summaryrefslogtreecommitdiff
path: root/lib9/lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib9/lock.c')
-rw-r--r--lib9/lock.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/lib9/lock.c b/lib9/lock.c
new file mode 100644
index 00000000..48b5d8c2
--- /dev/null
+++ b/lib9/lock.c
@@ -0,0 +1,141 @@
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+void
+lock(Lock *l)
+{
+ int i;
+
+ if(_tas(&l->val) == 0)
+ return;
+ for(i=0; i<100; i++){
+ if(_tas(&l->val) == 0)
+ return;
+ osyield();
+ }
+ for(i=1;; i++){
+ if(_tas(&l->val) == 0)
+ return;
+ osmillisleep(i*10);
+ if(i > 100){
+ osyield();
+ i = 1;
+ }
+ }
+}
+
+int
+canlock(Lock *l)
+{
+ return _tas(&l->val) == 0;
+}
+
+void
+unlock(Lock *l)
+{
+ l->val = 0;
+}
+
+void
+qlock(QLock *q)
+{
+ Proc *p;
+
+ lock(&q->use);
+ if(!q->locked) {
+ q->locked = 1;
+ unlock(&q->use);
+ return;
+ }
+ p = q->tail;
+ if(p == 0)
+ q->head = up;
+ else
+ p->qnext = up;
+ q->tail = up;
+ up->qnext = 0;
+ unlock(&q->use);
+ osblock();
+}
+
+int
+canqlock(QLock *q)
+{
+ if(!canlock(&q->use))
+ return 0;
+ if(q->locked){
+ unlock(&q->use);
+ return 0;
+ }
+ q->locked = 1;
+ unlock(&q->use);
+ return 1;
+}
+
+void
+qunlock(QLock *q)
+{
+ Proc *p;
+
+ lock(&q->use);
+ p = q->head;
+ if(p) {
+ q->head = p->qnext;
+ if(q->head == 0)
+ q->tail = 0;
+ unlock(&q->use);
+ osready(p);
+ return;
+ }
+ q->locked = 0;
+ unlock(&q->use);
+}
+
+void
+rlock(RWlock *l)
+{
+ qlock(&l->x); /* wait here for writers and exclusion */
+ lock(&l->l);
+ l->readers++;
+ canqlock(&l->k); /* block writers if we are the first reader */
+ unlock(&l->l);
+ qunlock(&l->x);
+}
+
+/* same as rlock but punts if there are any writers waiting */
+int
+canrlock(RWlock *l)
+{
+ if (!canqlock(&l->x))
+ return 0;
+ lock(&l->l);
+ l->readers++;
+ canqlock(&l->k); /* block writers if we are the first reader */
+ unlock(&l->l);
+ qunlock(&l->x);
+ return 1;
+}
+
+void
+runlock(RWlock *l)
+{
+ lock(&l->l);
+ if(--l->readers == 0) /* last reader out allows writers */
+ qunlock(&l->k);
+ unlock(&l->l);
+}
+
+void
+wlock(RWlock *l)
+{
+ qlock(&l->x); /* wait here for writers and exclusion */
+ qlock(&l->k); /* wait here for last reader */
+}
+
+void
+wunlock(RWlock *l)
+{
+ qunlock(&l->k);
+ qunlock(&l->x);
+}