pgrp.c 5.4 KB

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