devenv: avoid indirection, keep Evalue's allocated in an array

avoid the indirection for envlookup() by allocating Evalue structs
together in an array. remove unused link field in Evalue.
This commit is contained in:
cinap_lenrek 2015-08-02 21:39:33 +02:00
parent 29a53a52fd
commit 37e4ce0ea7
2 changed files with 70 additions and 74 deletions

View file

@ -7,6 +7,7 @@
enum enum
{ {
DELTAENV = 32,
Maxenvsize = 16300, Maxenvsize = 16300,
}; };
@ -18,12 +19,12 @@ static Egrp confegrp; /* global environment group containing the kernel configur
static Evalue* static Evalue*
envlookup(Egrp *eg, char *name, ulong qidpath) envlookup(Egrp *eg, char *name, ulong qidpath)
{ {
Evalue *e; Evalue *e, *ee;
int i;
for(i=0; i<eg->nent; i++){ e = eg->ent;
e = eg->ent[i]; for(ee = e + eg->nent; e < ee; e++){
if(e->qid.path == qidpath || (name != nil && name[0] == e->name[0] && strcmp(e->name, name) == 0)) if(e->qid.path == qidpath
|| (name != nil && name[0] == e->name[0] && strcmp(e->name, name) == 0))
return e; return e;
} }
return nil; return nil;
@ -42,12 +43,12 @@ envgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
eg = envgrp(c); eg = envgrp(c);
rlock(eg); rlock(eg);
e = nil;
if(name != nil) if(name != nil)
e = envlookup(eg, name, -1); e = envlookup(eg, name, -1);
else if(s < eg->nent) else if(s < eg->nent)
e = eg->ent[s]; e = &eg->ent[s];
else
e = nil;
if(e == nil || name != nil && (strlen(e->name) >= sizeof(up->genbuf))) { if(e == nil || name != nil && (strlen(e->name) >= sizeof(up->genbuf))) {
runlock(eg); runlock(eg);
return -1; return -1;
@ -141,7 +142,6 @@ envcreate(Chan *c, char *name, int omode, ulong)
{ {
Egrp *eg; Egrp *eg;
Evalue *e; Evalue *e;
Evalue **ent;
if(c->qid.type != QTDIR || !envwriteable(c)) if(c->qid.type != QTDIR || !envwriteable(c))
error(Eperm); error(Eperm);
@ -151,7 +151,6 @@ envcreate(Chan *c, char *name, int omode, ulong)
omode = openmode(omode); omode = openmode(omode);
eg = envgrp(c); eg = envgrp(c);
wlock(eg); wlock(eg);
if(waserror()) { if(waserror()) {
wunlock(eg); wunlock(eg);
@ -161,22 +160,23 @@ envcreate(Chan *c, char *name, int omode, ulong)
if(envlookup(eg, name, -1) != nil) if(envlookup(eg, name, -1) != nil)
error(Eexist); error(Eexist);
e = smalloc(sizeof(Evalue)); if(eg->nent == eg->ment){
Evalue *tmp;
eg->ment += DELTAENV;
if((tmp = realloc(eg->ent, sizeof(eg->ent[0])*eg->ment)) == nil){
eg->ment -= DELTAENV;
error(Enomem);
}
eg->ent = tmp;
}
eg->vers++;
e = &eg->ent[eg->nent++];
e->value = nil;
e->len = 0;
e->name = smalloc(strlen(name)+1); e->name = smalloc(strlen(name)+1);
strcpy(e->name, name); strcpy(e->name, name);
mkqid(&e->qid, ++eg->path, 0, QTFILE);
if(eg->nent == eg->ment){
eg->ment += 32;
ent = smalloc(sizeof(eg->ent[0])*eg->ment);
if(eg->nent)
memmove(ent, eg->ent, sizeof(eg->ent[0])*eg->nent);
free(eg->ent);
eg->ent = ent;
}
e->qid.path = ++eg->path;
e->qid.vers = 0;
eg->vers++;
eg->ent[eg->nent++] = e;
c->qid = e->qid; c->qid = e->qid;
wunlock(eg); wunlock(eg);
@ -191,31 +191,28 @@ envcreate(Chan *c, char *name, int omode, ulong)
static void static void
envremove(Chan *c) envremove(Chan *c)
{ {
int i;
Egrp *eg; Egrp *eg;
Evalue *e; Evalue *e, *ee;
if(c->qid.type & QTDIR || !envwriteable(c)) if(c->qid.type & QTDIR || !envwriteable(c))
error(Eperm); error(Eperm);
eg = envgrp(c); eg = envgrp(c);
wlock(eg); wlock(eg);
e = nil; e = eg->ent;
for(i=0; i<eg->nent; i++){ for(ee = e + eg->nent; e < ee; e++){
if(eg->ent[i]->qid.path == c->qid.path){ if(e->qid.path == c->qid.path){
e = eg->ent[i]; free(e->name);
free(e->value);
*e = ee[-1];
eg->nent--; eg->nent--;
eg->ent[i] = eg->ent[eg->nent];
eg->vers++; eg->vers++;
break; wunlock(eg);
return;
} }
} }
wunlock(eg); wunlock(eg);
if(e == nil) error(Enonexist);
error(Enonexist);
free(e->name);
free(e->value);
free(e);
} }
static void static void
@ -242,12 +239,14 @@ envread(Chan *c, void *a, long n, vlong off)
eg = envgrp(c); eg = envgrp(c);
rlock(eg); rlock(eg);
e = envlookup(eg, nil, c->qid.path); if(waserror()){
if(e == nil) {
runlock(eg); runlock(eg);
error(Enonexist); nexterror();
} }
e = envlookup(eg, nil, c->qid.path);
if(e == nil)
error(Enonexist);
if(offset >= e->len || e->value == nil) if(offset >= e->len || e->value == nil)
n = 0; n = 0;
else if(offset + n > e->len) else if(offset + n > e->len)
@ -256,7 +255,9 @@ envread(Chan *c, void *a, long n, vlong off)
n = 0; n = 0;
else else
memmove(a, e->value+offset, n); memmove(a, e->value+offset, n);
runlock(eg); runlock(eg);
poperror();
return n; return n;
} }
@ -276,30 +277,30 @@ envwrite(Chan *c, void *a, long n, vlong off)
eg = envgrp(c); eg = envgrp(c);
wlock(eg); wlock(eg);
e = envlookup(eg, nil, c->qid.path); if(waserror()){
if(e == nil) {
wunlock(eg); wunlock(eg);
error(Enonexist); nexterror();
} }
e = envlookup(eg, nil, c->qid.path);
if(e == nil)
error(Enonexist);
len = offset+n; len = offset+n;
if(len > e->len) { if(len > e->len) {
s = malloc(len); s = realloc(e->value, len);
if(s == nil){ if(s == nil)
wunlock(eg);
error(Enomem); error(Enomem);
} memset(s+offset, 0, n);
if(e->value != nil){
memmove(s, e->value, e->len);
free(e->value);
}
e->value = s; e->value = s;
e->len = len; e->len = len;
} }
memmove(e->value+offset, a, n); memmove(e->value+offset, a, n);
e->qid.vers++; e->qid.vers++;
eg->vers++; eg->vers++;
wunlock(eg); wunlock(eg);
poperror();
return n; return n;
} }
@ -327,15 +328,14 @@ Dev envdevtab = {
void void
envcpy(Egrp *to, Egrp *from) envcpy(Egrp *to, Egrp *from)
{ {
int i; Evalue *e, *ee, *ne;
Evalue *ne, *e;
rlock(from); rlock(from);
to->ment = (from->nent+31)&~31; to->ment = ROUND(from->nent, DELTAENV);
to->ent = smalloc(to->ment*sizeof(to->ent[0])); to->ent = smalloc(to->ment*sizeof(to->ent[0]));
for(i=0; i<from->nent; i++){ ne = to->ent;
e = from->ent[i]; e = from->ent;
ne = smalloc(sizeof(Evalue)); for(ee = e + from->nent; e < ee; e++, ne++){
ne->name = smalloc(strlen(e->name)+1); ne->name = smalloc(strlen(e->name)+1);
strcpy(ne->name, e->name); strcpy(ne->name, e->name);
if(e->value != nil){ if(e->value != nil){
@ -343,8 +343,7 @@ envcpy(Egrp *to, Egrp *from)
memmove(ne->value, e->value, e->len); memmove(ne->value, e->value, e->len);
ne->len = e->len; ne->len = e->len;
} }
ne->qid.path = ++to->path; mkqid(&ne->qid, ++to->path, 0, QTFILE);
to->ent[i] = ne;
} }
to->nent = from->nent; to->nent = from->nent;
runlock(from); runlock(from);
@ -353,15 +352,13 @@ envcpy(Egrp *to, Egrp *from)
void void
closeegrp(Egrp *eg) closeegrp(Egrp *eg)
{ {
int i; Evalue *e, *ee;
Evalue *e;
if(decref(eg) == 0){ if(decref(eg) == 0){
for(i=0; i<eg->nent; i++){ e = eg->ent;
e = eg->ent[i]; for(ee = e + eg->nent; e < ee; e++){
free(e->name); free(e->name);
free(e->value); free(e->value);
free(e);
} }
free(eg->ent); free(eg->ent);
free(eg); free(eg);
@ -406,9 +403,9 @@ char *
getconfenv(void) getconfenv(void)
{ {
Egrp *eg = &confegrp; Egrp *eg = &confegrp;
Evalue *e; Evalue *e, *ee;
char *p, *q; char *p, *q;
int i, n; int n;
rlock(eg); rlock(eg);
if(waserror()) { if(waserror()) {
@ -418,16 +415,16 @@ getconfenv(void)
/* determine size */ /* determine size */
n = 0; n = 0;
for(i=0; i<eg->nent; i++){ e = eg->ent;
e = eg->ent[i]; for(ee = e+eg->nent; e<ee; e++)
n += strlen(e->name) + e->len + 2; n += strlen(e->name) + e->len + 2;
}
p = malloc(n + 1); p = malloc(n + 1);
if(p == nil) if(p == nil)
error(Enomem); error(Enomem);
q = p; q = p;
for(i=0; i<eg->nent; i++){ e = eg->ent;
e = eg->ent[i]; for(ee = e + eg->nent; e < ee; e++){
strcpy(q, e->name); strcpy(q, e->name);
q += strlen(q) + 1; q += strlen(q) + 1;
memmove(q, e->value, e->len); memmove(q, e->value, e->len);
@ -437,7 +434,7 @@ getconfenv(void)
} }
*q = '\0'; *q = '\0';
poperror();
runlock(eg); runlock(eg);
poperror();
return p; return p;
} }

View file

@ -495,7 +495,7 @@ struct Egrp
{ {
Ref; Ref;
RWlock; RWlock;
Evalue **ent; Evalue *ent;
int nent; int nent;
int ment; int ment;
ulong path; /* qid.path of next Evalue to be allocated */ ulong path; /* qid.path of next Evalue to be allocated */
@ -507,7 +507,6 @@ struct Evalue
char *name; char *name;
char *value; char *value;
int len; int len;
Evalue *link;
Qid qid; Qid qid;
}; };