summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <petermikkelsen10@gmail.com>2024-02-11 15:18:27 +0000
committerPeter Mikkelsen <petermikkelsen10@gmail.com>2024-02-11 15:18:27 +0000
commit7aeae86d36a1a04e93bb4be2216cb735acfab714 (patch)
tree88d113a905ea73fb2f32cc43283bed3decae3e76 /main.c
parent7c6a945996a1d5510ff1412320ac7d07a0f82851 (diff)
More work
Diffstat (limited to 'main.c')
-rw-r--r--main.c124
1 files changed, 79 insertions, 45 deletions
diff --git a/main.c b/main.c
index a2bf780..59e9d0c 100644
--- a/main.c
+++ b/main.c
@@ -13,6 +13,8 @@
#define Eoffset "can't write to this file at non-zero offset"
#define Ebadctl "bad ctl message"
+QLock guilock = 0;
+
char *username;
enum {
@@ -88,19 +90,35 @@ mkpropqid(int proptag)
void
settype(GuiElement *g, int type)
{
+
GuiSpec spec = guispecs[type];
- free(g->props);
- g->type = type;
-
- g->nprops = spec.nprops;
- g->props = emalloc(sizeof(Prop) * spec.nprops);
+ int nprops = spec.nprops + nbaseprops;
+ /* Allocate the props before locking the gui element, as some of the
+ * allocations might cause this thread to block
+ */
+
+ Prop *props = emalloc(sizeof(Prop) * nprops);
+ for(int i = 0; i < nbaseprops; i++){
+ int tag = baseprops[i];
+ props[i].tag = tag;
+ props[i].val = propspecs[tag].def();
+ props[i].qid = mkpropqid(tag);
+ }
for(int i = 0; i < spec.nprops; i++){
int tag = spec.proptags[i];
- g->props[i].tag = tag;
- g->props[i].val = propspecs[tag].def();
- g->props[i].qid = mkpropqid(tag);
+ props[i+nbaseprops].tag = tag;
+ props[i+nbaseprops].val = propspecs[tag].def();
+ props[i+nbaseprops].qid = mkpropqid(tag);
}
+ wlock(&g->lock);
+ /* TODO: free old propvals */
+ free(g->props);
+ g->type = type;
+ g->nprops = nprops;
+ g->props = props;
+ wunlock(&g->lock);
+
updategui(0); /* redraw everything */
}
@@ -108,7 +126,6 @@ GuiElement *
newgui(GuiElement *parent)
{
GuiElement *g = emalloc(sizeof(GuiElement));
- memset(g, 0, sizeof(GuiElement));
g->parent = parent;
g->qid = mkqid(Qdir);
g->qclone = mkqid(Qclone);
@@ -118,9 +135,11 @@ newgui(GuiElement *parent)
if(parent){
g->id = parent->nchildren;
+ wlock(&parent->lock);
parent->nchildren++;
parent->children = erealloc(parent->children, parent->nchildren * sizeof(GuiElement *));
parent->children[g->id] = g;
+ wunlock(&parent->lock);
}
settype(g, Gcontainer);
@@ -137,10 +156,11 @@ findchild(GuiElement *g, char *name)
return nil;
}
- if(id < g->nchildren)
- return g->children[id];
+ rlock(&g->lock);
+ GuiElement *child = (id < g->nchildren) ? g->children[id] : nil;
+ runlock(&g->lock);
- return nil;
+ return child;
}
void
@@ -164,6 +184,7 @@ fswalk1(Fid *fid, char *name, Qid *qid)
{
GuiElement *g = fid->aux;
GuiElement *child;
+ char *err = nil;
switch(QID_TYPE(fid->qid)){
case Qdir:
@@ -174,41 +195,43 @@ fswalk1(Fid *fid, char *name, Qid *qid)
fid->aux = g->parent;
*qid = g->parent->qid;
}
- return nil;
- }else if(strcmp(name, "clone") == 0){
+ }else if(strcmp(name, "clone") == 0)
*qid = g->qclone;
- return nil;
- }else if(strcmp(name, "event") == 0){
+ else if(strcmp(name, "event") == 0)
*qid = g->qevent;
- return nil;
- }else if(strcmp(name, "type") == 0){
+ else if(strcmp(name, "type") == 0)
*qid = g->qtype;
- return nil;
- }else if(strcmp(name, "props") == 0){
+ else if(strcmp(name, "props") == 0)
*qid = g->qprops;
- return nil;
- }else if(child = findchild(g, name)){
+ else if(child = findchild(g, name)){
fid->aux = child;
*qid = child->qid;
- return nil;
- }
- return Eexist;
+ }else
+ err = Eexist;
+ break;
case Qprops:
- if(strcmp(name, "..") == 0){
+ if(strcmp(name, "..") == 0)
*qid = g->qid;
- return nil;
- }
- for(int i = 0; i < g->nprops; i++){
- PropSpec spec = propspecs[g->props[i].tag];
- if(strcmp(name, spec.name) == 0){
- *qid = g->props[i].qid;
- return nil;
+ else{
+ rlock(&g->lock);
+ int ok = 0;
+ for(int i = 0; i < g->nprops && ok == 0; i++){
+ PropSpec spec = propspecs[g->props[i].tag];
+ if(strcmp(name, spec.name) == 0){
+ *qid = g->props[i].qid;
+ ok = 1;
+ }
}
+ runlock(&g->lock);
+ if(!ok)
+ err = Eexist;
}
- return Eexist;
+ break;
default:
- return Enodir;
+ err = Enodir;
+ break;
}
+ return err;
}
char *
@@ -310,7 +333,10 @@ dirtreegen(int n, Dir *d, void *aux)
}else
n -= Fmax;
- if(g && n < g->nchildren){
+ rlock(&g->lock);
+ int done = n >= g->nchildren;
+
+ if(!done){
GuiElement *child = g->children[n];
d->mode = DMDIR|0555;
@@ -319,10 +345,10 @@ dirtreegen(int n, Dir *d, void *aux)
char buf[64];
snprint(buf, sizeof(buf), "%d", child->id);
d->name = estrdup9p(buf);
- return 0;
}
+ runlock(&g->lock);
- return -1;
+ return done ? -1 : 0;
}
int
@@ -334,14 +360,20 @@ proptreegen(int n, Dir *d, void *aux)
d->gid = estrdup9p(username);
d->muid = estrdup9p(username);
- if(n >= g->nprops)
- return -1;
+ int done;
+
+ rlock(&g->lock);
+ done = n >= g->nprops;
+
+ if(!done){
+ PropSpec spec = propspecs[g->props[n].tag];
+ d->mode = 0666;
+ d->name = estrdup9p(spec.name);
+ d->qid = g->props[n].qid;
+ }
+ runlock(&g->lock);
- PropSpec spec = propspecs[g->props[n].tag];
- d->mode = 0666;
- d->name = estrdup9p(spec.name);
- d->qid = g->props[n].qid;
- return 0;
+ return done ? -1 : 0;
}
void
@@ -365,7 +397,9 @@ fsread(Req *r)
readstr(r, "eveeent\n");
break;
case Qtype:
+ rlock(&g->lock);
snprint(buf, sizeof(buf), "%s\n", guispecs[g->type].name);
+ runlock(&g->lock);
readstr(r, buf);
break;
case Qprops: