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