summaryrefslogtreecommitdiff
path: root/sys/src/9/port/pgrp.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/port/pgrp.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/port/pgrp.c')
-rwxr-xr-xsys/src/9/port/pgrp.c320
1 files changed, 320 insertions, 0 deletions
diff --git a/sys/src/9/port/pgrp.c b/sys/src/9/port/pgrp.c
new file mode 100755
index 000000000..22fc78b56
--- /dev/null
+++ b/sys/src/9/port/pgrp.c
@@ -0,0 +1,320 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+enum {
+ Whinesecs = 10, /* frequency of out-of-resources printing */
+};
+
+static Ref pgrpid;
+static Ref mountid;
+
+void
+pgrpnote(ulong noteid, char *a, long n, int flag)
+{
+ Proc *p, *ep;
+ char buf[ERRMAX];
+
+ if(n >= ERRMAX-1)
+ error(Etoobig);
+
+ memmove(buf, a, n);
+ buf[n] = 0;
+ p = proctab(0);
+ ep = p+conf.nproc;
+ for(; p < ep; p++) {
+ if(p->state == Dead)
+ continue;
+ if(up != p && p->noteid == noteid && p->kp == 0) {
+ qlock(&p->debug);
+ if(p->pid == 0 || p->noteid != noteid){
+ qunlock(&p->debug);
+ continue;
+ }
+ if(!waserror()) {
+ postnote(p, 0, buf, flag);
+ poperror();
+ }
+ qunlock(&p->debug);
+ }
+ }
+}
+
+Pgrp*
+newpgrp(void)
+{
+ Pgrp *p;
+
+ p = smalloc(sizeof(Pgrp));
+ p->ref = 1;
+ p->pgrpid = incref(&pgrpid);
+ return p;
+}
+
+Rgrp*
+newrgrp(void)
+{
+ Rgrp *r;
+
+ r = smalloc(sizeof(Rgrp));
+ r->ref = 1;
+ return r;
+}
+
+void
+closergrp(Rgrp *r)
+{
+ if(decref(r) == 0)
+ free(r);
+}
+
+void
+closepgrp(Pgrp *p)
+{
+ Mhead **h, **e, *f, *next;
+
+ if(decref(p) != 0)
+ return;
+
+ qlock(&p->debug);
+ wlock(&p->ns);
+ p->pgrpid = -1;
+
+ e = &p->mnthash[MNTHASH];
+ for(h = p->mnthash; h < e; h++) {
+ for(f = *h; f; f = next) {
+ wlock(&f->lock);
+ cclose(f->from);
+ mountfree(f->mount);
+ f->mount = nil;
+ next = f->hash;
+ wunlock(&f->lock);
+ putmhead(f);
+ }
+ }
+ wunlock(&p->ns);
+ qunlock(&p->debug);
+ free(p);
+}
+
+void
+pgrpinsert(Mount **order, Mount *m)
+{
+ Mount *f;
+
+ m->order = 0;
+ if(*order == 0) {
+ *order = m;
+ return;
+ }
+ for(f = *order; f; f = f->order) {
+ if(m->mountid < f->mountid) {
+ m->order = f;
+ *order = m;
+ return;
+ }
+ order = &f->order;
+ }
+ *order = m;
+}
+
+/*
+ * pgrpcpy MUST preserve the mountid allocation order of the parent group
+ */
+void
+pgrpcpy(Pgrp *to, Pgrp *from)
+{
+ int i;
+ Mount *n, *m, **link, *order;
+ Mhead *f, **tom, **l, *mh;
+
+ wlock(&from->ns);
+ order = 0;
+ tom = to->mnthash;
+ for(i = 0; i < MNTHASH; i++) {
+ l = tom++;
+ for(f = from->mnthash[i]; f; f = f->hash) {
+ rlock(&f->lock);
+ mh = newmhead(f->from);
+ *l = mh;
+ l = &mh->hash;
+ link = &mh->mount;
+ for(m = f->mount; m; m = m->next) {
+ n = newmount(mh, m->to, m->mflag, m->spec);
+ m->copy = n;
+ pgrpinsert(&order, m);
+ *link = n;
+ link = &n->next;
+ }
+ runlock(&f->lock);
+ }
+ }
+ /*
+ * Allocate mount ids in the same sequence as the parent group
+ */
+ lock(&mountid);
+ for(m = order; m; m = m->order)
+ m->copy->mountid = mountid.ref++;
+ unlock(&mountid);
+ wunlock(&from->ns);
+}
+
+Fgrp*
+dupfgrp(Fgrp *f)
+{
+ Fgrp *new;
+ Chan *c;
+ int i;
+
+ new = smalloc(sizeof(Fgrp));
+ if(f == nil){
+ new->fd = smalloc(DELTAFD*sizeof(Chan*));
+ new->nfd = DELTAFD;
+ new->ref = 1;
+ return new;
+ }
+
+ lock(f);
+ /* Make new fd list shorter if possible, preserving quantization */
+ new->nfd = f->maxfd+1;
+ i = new->nfd%DELTAFD;
+ if(i != 0)
+ new->nfd += DELTAFD - i;
+ new->fd = malloc(new->nfd*sizeof(Chan*));
+ if(new->fd == nil){
+ unlock(f);
+ free(new);
+ error("no memory for fgrp");
+ }
+ new->ref = 1;
+
+ new->maxfd = f->maxfd;
+ for(i = 0; i <= f->maxfd; i++) {
+ if(c = f->fd[i]){
+ incref(c);
+ new->fd[i] = c;
+ }
+ }
+ unlock(f);
+
+ return new;
+}
+
+void
+closefgrp(Fgrp *f)
+{
+ int i;
+ Chan *c;
+
+ if(f == 0)
+ return;
+
+ if(decref(f) != 0)
+ return;
+
+ /*
+ * If we get into trouble, forceclosefgrp
+ * will bail us out.
+ */
+ up->closingfgrp = f;
+ for(i = 0; i <= f->maxfd; i++)
+ if(c = f->fd[i]){
+ f->fd[i] = nil;
+ cclose(c);
+ }
+ up->closingfgrp = nil;
+
+ free(f->fd);
+ free(f);
+}
+
+/*
+ * Called from sleep because up is in the middle
+ * of closefgrp and just got a kill ctl message.
+ * This usually means that up has wedged because
+ * of some kind of deadly embrace with mntclose
+ * trying to talk to itself. To break free, hand the
+ * unclosed channels to the close queue. Once they
+ * are finished, the blocked cclose that we've
+ * interrupted will finish by itself.
+ */
+void
+forceclosefgrp(void)
+{
+ int i;
+ Chan *c;
+ Fgrp *f;
+
+ if(up->procctl != Proc_exitme || up->closingfgrp == nil){
+ print("bad forceclosefgrp call");
+ return;
+ }
+
+ f = up->closingfgrp;
+ for(i = 0; i <= f->maxfd; i++)
+ if(c = f->fd[i]){
+ f->fd[i] = nil;
+ ccloseq(c);
+ }
+}
+
+
+Mount*
+newmount(Mhead *mh, Chan *to, int flag, char *spec)
+{
+ Mount *m;
+
+ m = smalloc(sizeof(Mount));
+ m->to = to;
+ m->head = mh;
+ incref(to);
+ m->mountid = incref(&mountid);
+ m->mflag = flag;
+ if(spec != 0)
+ kstrdup(&m->spec, spec);
+
+ return m;
+}
+
+void
+mountfree(Mount *m)
+{
+ Mount *f;
+
+ while(m) {
+ f = m->next;
+ cclose(m->to);
+ m->mountid = 0;
+ free(m->spec);
+ free(m);
+ m = f;
+ }
+}
+
+void
+resrcwait(char *reason)
+{
+ ulong now;
+ char *p;
+ static ulong lastwhine;
+
+ if(up == 0)
+ panic("resrcwait");
+
+ p = up->psstate;
+ if(reason) {
+ up->psstate = reason;
+ now = seconds();
+ /* don't tie up the console with complaints */
+ if(now - lastwhine > Whinesecs) {
+ lastwhine = now;
+ print("%s\n", reason);
+ }
+ }
+
+ tsleep(&up->sleep, return0, 0, 300);
+ up->psstate = p;
+}