plan 9 kernel history: overview | file list | diff list

1992/0623/port/devenv.c (diff list | history)

1992/0622/sys/src/9/port/devenv.c:7,481992/0623/sys/src/9/port/devenv.c:7,20 (short | long | prev | next)
1990/0227    
 
#include	"devtab.h" 
 
struct Envval 
1992/0623    
enum 
1990/0227    
{ 
1991/1018    
	Envval	*next;		/* for hashing & easy deletion from hash list */ 
	Envval	*prev; 
	ulong	len;		/* length of val that is valid */ 
	int	ref; 
	char	*val; 
1992/0623    
	Maxenvsize = 16300, 
1990/0227    
}; 
 
1991/1018    
enum{ 
	MAXENV	= (BY2PG - sizeof(Envval)), 
	EVHASH	= 64, 
	EVFREE	= 16, 
	ALIGN	= 16, 
}; 
1990/0227    
                 
struct 
{ 
1991/1018    
	Envval	*free[EVFREE+1]; 
	char	*block;			/* the free page we are allocating from */ 
	char	*lim;			/* end of block */ 
1991/1022    
	int	npage;			/* total pages gotten from newpage() */ 
1990/0227    
}envalloc; 
                 
1991/1018    
QLock	evlock; 
Envval	evhash[EVHASH]; 
char	*evscratch;		/* for constructing the contents of a file */ 
1990/0227    
                 
1991/1018    
Envval	*newev(char*, ulong); 
Envval	*evalloc(ulong); 
void	evfree(Envval*); 
                 
1990/0227    
void 
envreset(void) 
{ 
1992/0622    
	evscratch = xalloc(BY2PG); 
1990/0227    
} 
 
void 
1992/0622/sys/src/9/port/devenv.c:54,771992/0623/sys/src/9/port/devenv.c:26,47
1990/0227    
envgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) 
{ 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e; 
1990/0227    
	int ans; 
1992/0623    
	Evalue *e; 
1990/0227    
 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
1991/0705    
	if(s >= eg->nenv) 
1990/0227    
		ans = -1; 
	else{ 
1991/1018    
		e = &eg->etab[s]; 
		if(!e->name) 
1990/0227    
			ans = 0; 
		else{ 
1992/0331    
			devdir(c, (Qid){s+1, (ulong)e->name}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp); 
1990/0227    
			ans = 1; 
		} 
1992/0623    
	qlock(eg); 
 
	for(e = eg->entries; e && s; e = e->link) 
		s--; 
 
	if(e == 0) { 
		qunlock(eg); 
		return -1; 
1990/0227    
	} 
1991/1018    
	qunlock(&eg->ev); 
1990/0227    
	return ans; 
1992/0623    
 
	devdir(c, (Qid){e->path, 0}, e->name, e->len, eve, 0666, dp); 
	qunlock(eg); 
	return 1; 
1990/0227    
} 
 
Chan* 
1992/0622/sys/src/9/port/devenv.c:103,1321992/0623/sys/src/9/port/devenv.c:73,103
1990/0227    
envopen(Chan *c, int omode) 
{ 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e; 
	int mode; 
1990/0227    
                 
1991/1018    
	mode = openmode(omode); 
1992/0623    
	Evalue *e; 
	 
	eg = u->p->egrp; 
1991/1018    
	if(c->qid.path & CHDIR){ 
		if(omode != OREAD) 
1990/11211    
			error(Eperm); 
1991/1018    
	}else{ 
1991/0705    
		eg = u->p->egrp; 
1991/1018    
		qlock(&eg->ev); 
		e = &eg->etab[c->qid.path-1]; 
		if(!e->name){ 
			qunlock(&eg->ev); 
1992/0623    
	} 
	else { 
		qlock(eg); 
		for(e = eg->entries; e; e = e->link) 
			if(e->path == c->qid.path) 
				break; 
 
		if(e == 0) { 
			qunlock(eg); 
1991/1018    
			error(Enonexist); 
1990/0227    
		} 
1991/1018    
		if(omode == (OWRITE|OTRUNC) && e->val){ 
			qlock(&evlock); 
			evfree(e->val); 
			qunlock(&evlock); 
			e->val = 0; 
1992/0623    
		if(omode == (OWRITE|OTRUNC) && e->value) { 
			free(e->value); 
			e->value = 0; 
			e->len = 0; 
1990/0227    
		} 
1991/1018    
		qunlock(&eg->ev); 
1992/0623    
		qunlock(eg); 
1990/0227    
	} 
1991/1018    
	c->mode = mode; 
1992/0623    
	c->mode = openmode(omode); 
1990/0227    
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
1992/0622/sys/src/9/port/devenv.c:136,1741992/0623/sys/src/9/port/devenv.c:107,142
1990/0227    
envcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e, *ne; 
1990/0227    
	int i; 
1992/0623    
	Evalue *e; 
1990/0227    
 
1990/11211    
	if(c->qid.path != CHDIR) 
		error(Eperm); 
1992/0623    
 
1991/1018    
	omode = openmode(omode); 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
	e = eg->etab; 
	ne = 0; 
	for(i = 0; i < eg->nenv; i++, e++) 
		if(e->name == 0) 
			ne = e; 
		else if(strcmp(e->name->val, name) == 0){ 
			qunlock(&eg->ev); 
			error(Einuse); 
		} 
	if(ne) 
		e = ne; 
	else if(eg->nenv == conf.npgenv){ 
		qunlock(&eg->ev); 
1991/1105    
		print("out of egroup envs\n"); 
1990/11211    
		error(Enoenv); 
1992/0623    
 
	qlock(eg); 
	if(waserror()) { 
		qunlock(eg); 
		nexterror(); 
1990/0227    
	} 
1991/1018    
	i = e - eg->etab + 1; 
	e->val = 0; 
	qlock(&evlock); 
	e->name = newev(name, strlen(name)+1); 
	qunlock(&evlock); 
	if(i > eg->nenv) 
		eg->nenv = i; 
	qunlock(&eg->ev); 
	c->qid = (Qid){i, 0}; 
1992/0623    
 
	for(e = eg->entries; e; e = e->link) 
		if(strcmp(e->name, name) == 0) 
			error(Einuse); 
 
	e = smalloc(sizeof(Evalue)); 
	e->name = smalloc(strlen(name)+1); 
	strcpy(e->name, name); 
 
	e->path = ++eg->path; 
	e->link = eg->entries; 
	eg->entries = e; 
	c->qid = (Qid){e->path, 0}; 
	 
	qunlock(eg); 
	poperror(); 
 
1990/0227    
	c->offset = 0; 
1991/1018    
	c->mode = omode; 
1990/0227    
	c->flag |= COPEN; 
1992/0622/sys/src/9/port/devenv.c:178,1961992/0623/sys/src/9/port/devenv.c:146,177
1990/0227    
envremove(Chan *c) 
{ 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e; 
1992/0623    
	Evalue *e, **l; 
1990/0227    
 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eperm); 
1992/0623    
 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
	e = &eg->etab[c->qid.path-1]; 
	if(!e->name){ 
		qunlock(&eg->ev); 
1992/0623    
	qlock(eg); 
 
	l = &eg->entries; 
	for(e = *l; e; e = e->link) { 
		if(e->path == c->qid.path) 
			break; 
		l = &e->link; 
	} 
 
	if(e == 0) { 
		qunlock(eg); 
1990/11211    
		error(Enonexist); 
1990/0227    
	} 
	envpgclose(e); 
1991/1018    
	qunlock(&eg->ev); 
1992/0623    
 
	*l = e->link; 
	qunlock(eg); 
	free(e->name); 
	if(e->value) 
		free(e->value); 
	free(e); 
1990/0227    
} 
 
void 
1992/0622/sys/src/9/port/devenv.c:206,2601992/0623/sys/src/9/port/devenv.c:187,219
1991/1115    
	USED(c); 
1991/1018    
} 
1990/0227    
 
1991/1018    
void 
envpgcopy(Env *t, Env *f) 
{ 
	qlock(&evlock); 
	if(t->name = f->name) 
		t->name->ref++; 
	if(t->val = f->val) 
		t->val->ref++; 
	qunlock(&evlock); 
1990/0227    
} 
                 
void 
envpgclose(Env *e) 
{ 
1991/1018    
	qlock(&evlock); 
	if(e->name) 
		evfree(e->name); 
	if(e->val) 
		evfree(e->val); 
	e->name = e->val = 0; 
	qunlock(&evlock); 
1990/0227    
} 
                 
long 
1991/1018    
envread(Chan *c, void *a, long n, ulong offset) 
1990/0227    
{ 
1991/1018    
	Egrp *eg; 
1990/0227    
	Env *e; 
	Envval *ev; 
	long vn; 
1992/0623    
	Evalue *e; 
1990/0227    
 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return devdirread(c, a, n, 0, 0, envgen); 
1992/0623    
 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
	e = &eg->etab[c->qid.path-1]; 
	if(!e->name){ 
		qunlock(&eg->ev); 
1992/0623    
	qlock(eg); 
	for(e = eg->entries; e; e = e->link) 
		if(e->path == c->qid.path) 
			break; 
 
	if(e == 0) { 
		qunlock(eg); 
1991/1018    
		error(Enonexist); 
1990/0227    
	} 
	ev = e->val; 
1991/1018    
	vn = ev ? ev->len : 0; 
	if(offset + n > vn) 
1991/0411    
		n = vn - offset; 
1992/0623    
 
	if(offset + n > e->len) 
		n = e->len - offset; 
1990/0227    
	if(n <= 0) 
		n = 0; 
	else 
1991/1018    
		memmove(a, ev->val + offset, n); 
	qunlock(&eg->ev); 
1992/0623    
		memmove(a, e->value+offset, n); 
	qunlock(eg); 
1990/0227    
	return n; 
} 
 
1992/0622/sys/src/9/port/devenv.c:261,4111992/0623/sys/src/9/port/devenv.c:220,259
1990/0227    
long 
1991/1018    
envwrite(Chan *c, void *a, long n, ulong offset) 
1990/0227    
{ 
1992/0623    
	char *s; 
	int vend; 
1991/1018    
	Egrp *eg; 
1990/0227    
	Env *e; 
	Envval *ev; 
1991/1018    
	ulong olen; 
1992/0623    
	Evalue *e; 
1990/0227    
 
	if(n <= 0) 
		return 0; 
1991/1121    
	olen = (offset + n + ALIGN - 1) & ~(ALIGN - 1); 
	if(olen > MAXENV) 
1992/0623    
 
	vend = offset+n; 
	if(vend > Maxenvsize) 
1991/1018    
		error(Etoobig); 
1992/0623    
 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
	e = &eg->etab[c->qid.path-1]; 
	if(!e->name){ 
		qunlock(&eg->ev); 
1992/0623    
	qlock(eg); 
	for(e = eg->entries; e; e = e->link) 
		if(e->path == c->qid.path) 
			break; 
 
	if(e == 0) { 
		qunlock(eg); 
1991/1018    
		error(Enonexist); 
1990/0227    
	} 
	ev = e->val; 
1991/1018    
	olen = ev ? ev->len : 0; 
	qlock(&evlock); 
	if(offset == 0 && n >= olen) 
		e->val = newev(a, n); 
	else{ 
		if(olen > offset) 
			olen = offset; 
		if(ev) 
			memmove(evscratch, ev->val, olen); 
		if(olen < offset) 
			memset(evscratch + olen, '\0', offset - olen); 
		memmove(evscratch + offset, a, n); 
		e->val = newev(evscratch, offset + n); 
	} 
	if(ev) 
		evfree(ev); 
	qunlock(&evlock); 
	qunlock(&eg->ev); 
1990/0227    
	return n; 
} 
 
1991/1018    
/* 
 * called with evlock qlocked 
 */ 
Envval * 
newev(char *s, ulong n) 
1990/0227    
{ 
	Envval *ev; 
1991/1018    
	uchar *t; 
	int h; 
1990/0227    
                 
1991/1018    
	h = 0; 
	for(t = (uchar*)s; t - (uchar*)s < n; t++) 
		h = (h << 1) ^ *t; 
	h &= EVHASH - 1; 
	for(ev = evhash[h].next; ev; ev = ev->next) 
		if(ev->len == n && memcmp(ev->val, s, n) == 0){ 
			ev->ref++; 
			return ev; 
		} 
	ev = evalloc(n); 
	ev->len = n; 
	memmove(ev->val, s, n); 
	if(ev->next = evhash[h].next) 
		ev->next->prev = ev; 
	evhash[h].next = ev; 
	ev->prev = &evhash[h]; 
	return ev; 
} 
                 
/* 
 * called only from newev 
 */ 
Envval * 
evalloc(ulong n) 
{ 
	Envval *ev, **p; 
	char *b, *lim; 
	ulong size; 
                 
1991/1121    
	size = (n + ALIGN - 1) & ~(ALIGN - 1); 
	n = (size - 1) / ALIGN; 
1991/1018    
	p = &envalloc.free[n < EVFREE ? n : EVFREE]; 
	for(ev = *p; ev; ev = *p){ 
		if(ev->len == size){ 
			*p = ev->next; 
			ev->ref = 1; 
			return ev; 
		} 
		p = &ev->next; 
1992/0623    
	if(vend > e->len) { 
		s = smalloc(offset+n); 
		memmove(s, e->value, e->len); 
		if(e->value) 
			free(e->value); 
		e->value = s; 
		e->len = vend; 
1991/1018    
	} 
                 
	/* 
	 * make sure we have enough space to allocate the buffer. 
	 * if not, use the remaining space for the smallest buffers 
	 */ 
	if(size > MAXENV) 
		panic("evalloc"); 
	b = envalloc.block; 
	lim = envalloc.lim; 
	if(!b || lim < b + size + sizeof *ev){ 
		p = &envalloc.free[0]; 
		while(lim >= b + ALIGN + sizeof *ev){ 
			ev = (Envval*)b; 
			ev->len = ALIGN; 
			ev->val = b + sizeof *ev; 
			ev->next = *p; 
			*p = ev; 
			b += ALIGN + sizeof *ev; 
		} 
		b = (char*)VA(kmap(newpage(0, 0, 0))); 
1991/1022    
		envalloc.npage++; 
1991/1018    
		envalloc.lim = b + BY2PG; 
	} 
1991/1022    
	                 
1991/1018    
	ev = (Envval*)b; 
	ev->val = b + sizeof *ev; 
	ev->ref = 1; 
	envalloc.block = b + size + sizeof *ev; 
	return ev; 
} 
                 
/* 
 * called with evlock qlocked 
 */ 
void 
evfree(Envval *ev) 
{ 
	int n; 
                 
	if(--ev->ref > 0) 
		return; 
                 
	if(ev->prev) 
		ev->prev->next = ev->next; 
1991/1024    
	else 
		panic("evfree"); 
1991/1018    
	if(ev->next) 
		ev->next->prev = ev->prev; 
	n = (ev->len + ALIGN - 1) & ~(ALIGN - 1); 
	ev->len = n; 
	n = (n - 1) / ALIGN; 
	if(n > EVFREE) 
		n = EVFREE; 
	ev->next = envalloc.free[n]; 
1991/1024    
	ev->prev = 0; 
1991/1018    
	envalloc.free[n] = ev; 
1992/0623    
	memmove(e->value+offset, a, n); 
	qunlock(eg); 
	return n; 
1991/1022    
} 
 
1991/0927    
/* 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)