pgrp.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. enum {
  8. Whinesecs = 10, /* frequency of out-of-resources printing */
  9. };
  10. static Ref pgrpid;
  11. static Ref mountid;
  12. void
  13. pgrpnote(ulong noteid, char *a, long n, int flag)
  14. {
  15. Proc *p, *ep;
  16. char buf[ERRMAX];
  17. if(n >= ERRMAX-1)
  18. error(Etoobig);
  19. memmove(buf, a, n);
  20. buf[n] = 0;
  21. p = proctab(0);
  22. ep = p+conf.nproc;
  23. for(; p < ep; p++) {
  24. if(p->state == Dead)
  25. continue;
  26. if(up != p && p->noteid == noteid && p->kp == 0) {
  27. qlock(&p->debug);
  28. if(p->pid == 0 || p->noteid != noteid){
  29. qunlock(&p->debug);
  30. continue;
  31. }
  32. if(!waserror()) {
  33. postnote(p, 0, buf, flag);
  34. poperror();
  35. }
  36. qunlock(&p->debug);
  37. }
  38. }
  39. }
  40. Pgrp*
  41. newpgrp(void)
  42. {
  43. Pgrp *p;
  44. p = smalloc(sizeof(Pgrp));
  45. p->ref = 1;
  46. p->pgrpid = incref(&pgrpid);
  47. return p;
  48. }
  49. Rgrp*
  50. newrgrp(void)
  51. {
  52. Rgrp *r;
  53. r = smalloc(sizeof(Rgrp));
  54. r->ref = 1;
  55. return r;
  56. }
  57. void
  58. closergrp(Rgrp *r)
  59. {
  60. if(decref(r) == 0)
  61. free(r);
  62. }
  63. void
  64. closepgrp(Pgrp *p)
  65. {
  66. Mhead **h, **e, *f, *next;
  67. if(decref(p) != 0)
  68. return;
  69. qlock(&p->debug);
  70. wlock(&p->ns);
  71. p->pgrpid = -1;
  72. e = &p->mnthash[MNTHASH];
  73. for(h = p->mnthash; h < e; h++) {
  74. for(f = *h; f; f = next) {
  75. wlock(&f->lock);
  76. cclose(f->from);
  77. mountfree(f->mount);
  78. f->mount = nil;
  79. next = f->hash;
  80. wunlock(&f->lock);
  81. putmhead(f);
  82. }
  83. }
  84. wunlock(&p->ns);
  85. qunlock(&p->debug);
  86. free(p);
  87. }
  88. void
  89. pgrpinsert(Mount **order, Mount *m)
  90. {
  91. Mount *f;
  92. m->order = 0;
  93. if(*order == 0) {
  94. *order = m;
  95. return;
  96. }
  97. for(f = *order; f; f = f->order) {
  98. if(m->mountid < f->mountid) {
  99. m->order = f;
  100. *order = m;
  101. return;
  102. }
  103. order = &f->order;
  104. }
  105. *order = m;
  106. }
  107. /*
  108. * pgrpcpy MUST preserve the mountid allocation order of the parent group
  109. */
  110. void
  111. pgrpcpy(Pgrp *to, Pgrp *from)
  112. {
  113. int i;
  114. Mount *n, *m, **link, *order;
  115. Mhead *f, **tom, **l, *mh;
  116. wlock(&from->ns);
  117. order = 0;
  118. tom = to->mnthash;
  119. for(i = 0; i < MNTHASH; i++) {
  120. l = tom++;
  121. for(f = from->mnthash[i]; f; f = f->hash) {
  122. rlock(&f->lock);
  123. mh = newmhead(f->from);
  124. *l = mh;
  125. l = &mh->hash;
  126. link = &mh->mount;
  127. for(m = f->mount; m; m = m->next) {
  128. n = newmount(mh, m->to, m->mflag, m->spec);
  129. m->copy = n;
  130. pgrpinsert(&order, m);
  131. *link = n;
  132. link = &n->next;
  133. }
  134. runlock(&f->lock);
  135. }
  136. }
  137. /*
  138. * Allocate mount ids in the same sequence as the parent group
  139. */
  140. lock(&mountid);
  141. for(m = order; m; m = m->order)
  142. m->copy->mountid = mountid.ref++;
  143. unlock(&mountid);
  144. wunlock(&from->ns);
  145. }
  146. Fgrp*
  147. dupfgrp(Fgrp *f)
  148. {
  149. Fgrp *new;
  150. Chan *c;
  151. int i;
  152. new = smalloc(sizeof(Fgrp));
  153. if(f == nil){
  154. new->fd = smalloc(DELTAFD*sizeof(Chan*));
  155. new->nfd = DELTAFD;
  156. new->ref = 1;
  157. return new;
  158. }
  159. lock(f);
  160. /* Make new fd list shorter if possible, preserving quantization */
  161. new->nfd = f->maxfd+1;
  162. i = new->nfd%DELTAFD;
  163. if(i != 0)
  164. new->nfd += DELTAFD - i;
  165. new->fd = malloc(new->nfd*sizeof(Chan*));
  166. if(new->fd == nil){
  167. unlock(f);
  168. free(new);
  169. error("no memory for fgrp");
  170. }
  171. new->ref = 1;
  172. new->maxfd = f->maxfd;
  173. for(i = 0; i <= f->maxfd; i++) {
  174. if(c = f->fd[i]){
  175. incref(c);
  176. new->fd[i] = c;
  177. }
  178. }
  179. unlock(f);
  180. return new;
  181. }
  182. void
  183. closefgrp(Fgrp *f)
  184. {
  185. int i;
  186. Chan *c;
  187. if(f == 0)
  188. return;
  189. if(decref(f) != 0)
  190. return;
  191. /*
  192. * If we get into trouble, forceclosefgrp
  193. * will bail us out.
  194. */
  195. up->closingfgrp = f;
  196. for(i = 0; i <= f->maxfd; i++)
  197. if(c = f->fd[i]){
  198. f->fd[i] = nil;
  199. cclose(c);
  200. }
  201. up->closingfgrp = nil;
  202. free(f->fd);
  203. free(f);
  204. }
  205. /*
  206. * Called from sleep because up is in the middle
  207. * of closefgrp and just got a kill ctl message.
  208. * This usually means that up has wedged because
  209. * of some kind of deadly embrace with mntclose
  210. * trying to talk to itself. To break free, hand the
  211. * unclosed channels to the close queue. Once they
  212. * are finished, the blocked cclose that we've
  213. * interrupted will finish by itself.
  214. */
  215. void
  216. forceclosefgrp(void)
  217. {
  218. int i;
  219. Chan *c;
  220. Fgrp *f;
  221. if(up->procctl != Proc_exitme || up->closingfgrp == nil){
  222. print("bad forceclosefgrp call");
  223. return;
  224. }
  225. f = up->closingfgrp;
  226. for(i = 0; i <= f->maxfd; i++)
  227. if(c = f->fd[i]){
  228. f->fd[i] = nil;
  229. ccloseq(c);
  230. }
  231. }
  232. Mount*
  233. newmount(Mhead *mh, Chan *to, int flag, char *spec)
  234. {
  235. Mount *m;
  236. m = smalloc(sizeof(Mount));
  237. m->to = to;
  238. m->head = mh;
  239. incref(to);
  240. m->mountid = incref(&mountid);
  241. m->mflag = flag;
  242. if(spec != 0)
  243. kstrdup(&m->spec, spec);
  244. return m;
  245. }
  246. void
  247. mountfree(Mount *m)
  248. {
  249. Mount *f;
  250. while(m) {
  251. f = m->next;
  252. cclose(m->to);
  253. m->mountid = 0;
  254. free(m->spec);
  255. free(m);
  256. m = f;
  257. }
  258. }
  259. void
  260. resrcwait(char *reason)
  261. {
  262. ulong now;
  263. char *p;
  264. static ulong lastwhine;
  265. if(up == 0)
  266. panic("resrcwait");
  267. p = up->psstate;
  268. if(reason) {
  269. up->psstate = reason;
  270. now = seconds();
  271. /* don't tie up the console with complaints */
  272. if(now - lastwhine > Whinesecs) {
  273. lastwhine = now;
  274. print("%s\n", reason);
  275. }
  276. }
  277. tsleep(&up->sleep, return0, 0, 300);
  278. up->psstate = p;
  279. }