From e2a086865596cb2d6532726a3d1c7d5f4cb8b307 Mon Sep 17 00:00:00 2001 From: qwx Date: Fri, 24 Jan 2025 03:38:29 +0100 Subject: [PATCH] posix: initialize rwlocks, prefer plain mutexes where applicable fixes crashes on macos with ineffectual rwlocks causing memory corruption. --- cmd/awkext.c | 12 +++++++----- cmd/cmd.c | 18 ++++++++--------- fs/em.c | 17 +++++++++-------- graph/graph.c | 28 --------------------------- graph/graph.h | 2 -- posix/threads.c | 7 +++++++ posix/threads.h | 51 ++++++++++++++++++++++++++++++++++++++++++++----- util/print.c | 10 +++++----- 8 files changed, 83 insertions(+), 62 deletions(-) diff --git a/cmd/awkext.c b/cmd/awkext.c index 7b2f290..d7d7135 100644 --- a/cmd/awkext.c +++ b/cmd/awkext.c @@ -45,7 +45,8 @@ struct Tab{ }; static tabmap *map; static Tab *tabs; -static RWLock buflock, tablock; +static RWLock tablock; +static QLock buflock; /* FIXME: can replace with awk array and lookup */ int @@ -329,10 +330,10 @@ fnloadbatch(void) { Val *v, *vs, *ve; - wlock(&buflock); + qlock(&buflock); vs = valbuf; valbuf = nil; - wunlock(&buflock); + qunlock(&buflock); for(v=vs, ve=v+dylen(v); vtab, v->type, v->id, v->val); dyfree(vs); @@ -345,9 +346,9 @@ pushval(int tab, int type, ioff id, V val) Val v; v = (Val){tab, type, id, val}; - wlock(&buflock); + qlock(&buflock); dypush(valbuf, v); - wunlock(&buflock); + qunlock(&buflock); if(dylen(valbuf) >= 64*1024){ pushcmd("loadbatch()"); flushcmd(); @@ -613,6 +614,7 @@ initext(void) [TCL] = {"CL", "nodecolor", 1}, }, *pp; + initrwlock(&tablock); map = tab_init(); for(pp=sptags; ppname, pp->nodeidx); diff --git a/cmd/cmd.c b/cmd/cmd.c index 936f458..588cea0 100644 --- a/cmd/cmd.c +++ b/cmd/cmd.c @@ -8,15 +8,15 @@ #include "cmd.h" static File *cmdfs; -RWLock cmdlock; +static QLock cmdlock; void killcmd(void) { - wlock(&cmdlock); + qlock(&cmdlock); freefs(cmdfs); cmdfs = nil; - wunlock(&cmdlock); + qunlock(&cmdlock); close(outfd[1]); outfd[1] = -1; close(infd[1]); @@ -26,13 +26,13 @@ killcmd(void) void flushcmd(void) { - wlock(&cmdlock); + qlock(&cmdlock); if(cmdfs == nil){ - wunlock(&cmdlock); + qunlock(&cmdlock); return; } flushfs(cmdfs); - wunlock(&cmdlock); + qunlock(&cmdlock); } static void @@ -42,13 +42,13 @@ sendcmd(char *cmd) n = strlen(cmd); DPRINT(Debugcmd, "> [%d][%s]", n, cmd); - wlock(&cmdlock); + qlock(&cmdlock); if(cmdfs == nil){ - wunlock(&cmdlock); + qunlock(&cmdlock); return; } writefs(cmdfs, cmd, n); - wunlock(&cmdlock); + qunlock(&cmdlock); } void diff --git a/fs/em.c b/fs/em.c index 48bab47..af53867 100644 --- a/fs/em.c +++ b/fs/em.c @@ -58,13 +58,13 @@ struct EM{ int ref; char flags; int infd; - RWLock l; + QLock l; Bank **banks; Page *cur; }; static int swapfd = -1; static Bank **banks; -static RWLock elock; +static QLock elock; static EM **etab, *emstrbuf; static Page pused = {.lleft = &pused, .lright = &pused}; static uvlong poolsz = Poolsz; @@ -112,7 +112,7 @@ cleanup(void *) if(swapfd < 0) return; - wlock(&elock); + qlock(&elock); close(swapfd); swapfd = -1; for(em=etab; empaddr = dylen(banks) << Ashift; bank->em = em; - wlock(&elock); + qlock(&elock); dypush(banks, bank); - wunlock(&elock); - wlock(&em->l); + qunlock(&elock); + qlock(&em->l); dyinsert(em->banks, i, bank); - wunlock(&em->l); + qunlock(&em->l); new = 1; }else if((p = bank->pt[PAGE(off)]) == nil) new = 1; @@ -241,6 +241,7 @@ feedpages(void) pl = emalloc(n * sizeof *pl); memreallyfree -= n; for(p=pl, pe=p+n; pl); p->lright = p + 1; p->lleft = p - 1; } diff --git a/graph/graph.c b/graph/graph.c index 3d85b45..28dc8d3 100644 --- a/graph/graph.c +++ b/graph/graph.c @@ -11,8 +11,6 @@ Node *nodes; ioff *edges; Super *supers; -static RWLock *locks; - void setattr(int type, ioff id, V val) { @@ -102,42 +100,16 @@ str2idx(char *s) return id; } -void -lockgraph(Graph *g, int w) -{ - RWLock *l; - - l = locks + (g - graphs); - if(w) - wlock(l); - else - rlock(l); -} - -void -unlockgraph(Graph *g, int w) -{ - RWLock *l; - - l = locks + (g - graphs); - if(w) - wunlock(l); - else - runlock(l); -} - Graph * initgraph(int type) { int n; Graph g = {0}, *gp; - RWLock l = {0}; n = dylen(graphs); g.type = type; g.nfirst = dylen(nodes); dypush(graphs, g); - dypush(locks, l); gp = graphs + n; return gp; } diff --git a/graph/graph.h b/graph/graph.h index 7d16cc1..d86df77 100644 --- a/graph/graph.h +++ b/graph/graph.h @@ -6,6 +6,4 @@ ioff newnode(Graph*, char*); ioff newedge(Graph*, ioff, ioff, int, int, char*, ushort*); void explode(ioff); ioff str2idx(char*); -void lockgraph(Graph*, int); -void unlockgraph(Graph*, int); Graph* initgraph(int); diff --git a/posix/threads.c b/posix/threads.c index 243e484..58d0ef4 100644 --- a/posix/threads.c +++ b/posix/threads.c @@ -102,6 +102,13 @@ killthread(Thread *th) pthread_cancel(th->p); } +void +initrwlock(RWLock *l) +{ + if(pthread_rwlock_init(l, NULL) != 0) + sysfatal("pthread_rwlock_init: %s", error()); +} + Channel * chancreate(int elsize, int nel) { diff --git a/posix/threads.h b/posix/threads.h index 1eb18a0..7068444 100644 --- a/posix/threads.h +++ b/posix/threads.h @@ -3,7 +3,6 @@ extern int mainstacksize; -typedef pthread_rwlock_t RWLock; typedef struct chan_t Channel; Channel* chancreate(int, int); @@ -16,7 +15,49 @@ ulong nbrecvul(Channel*); void* nbrecvp(Channel*); #define sendp chan_send -#define rlock pthread_rwlock_rdlock -#define runlock pthread_rwlock_unlock -#define wlock pthread_rwlock_wrlock -#define wunlock pthread_rwlock_unlock +typedef pthread_mutex_t QLock; +typedef pthread_rwlock_t RWLock; + +void initrwlock(RWLock*); + +static inline void +rlock(RWLock *l) +{ + if(pthread_rwlock_rdlock(l) != 0) + sysfatal("pthread_rwlock_rdlock: %s", error()); +} + +static inline void +wlock(RWLock *l) +{ + if(pthread_rwlock_wrlock(l) != 0) + sysfatal("pthread_rwlock_wrlock: %s", error()); +} + +static inline void +wunlock(RWLock *l) +{ + if(pthread_rwlock_unlock(l) != 0) + sysfatal("pthread_rwlock_unlock: %s", error()); +} + +static inline void +runlock(RWLock *l) +{ + if(pthread_rwlock_unlock(l) != 0) + sysfatal("pthread_rwlock_unlock: %s", error()); +} + +static inline void +qlock(QLock *l) +{ + if(pthread_mutex_lock(l) != 0) + sysfatal("pthread_mutex_lock: %s", error()); +} + +static inline void +qunlock(QLock *l) +{ + if(pthread_mutex_unlock(l) != 0) + sysfatal("pthread_mutex_unlock: %s", error()); +} diff --git a/util/print.c b/util/print.c index c58e143..30dbe28 100644 --- a/util/print.c +++ b/util/print.c @@ -7,7 +7,7 @@ char logbuf[8192], lastmsg[3][64], iserrmsg[3]; int nlog, logsz; static char *lp = logbuf; -static RWLock llock; +static QLock llock; static inline void writelog(char *s, int iserr) @@ -49,9 +49,9 @@ writelog(char *s, int iserr) void logmsg(char *s) { - wlock(&llock); + qlock(&llock); writelog(s, 0); - wunlock(&llock); + qunlock(&llock); if(!onscreen) warn("%s", s); } @@ -59,9 +59,9 @@ logmsg(char *s) void logerr(char *s) { - wlock(&llock); + qlock(&llock); writelog(s, 1); - wunlock(&llock); + qunlock(&llock); warn("%s", s); }