pgrp.c 4.6 KB

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