diff options
Diffstat (limited to 'nest/locks.c')
-rw-r--r-- | nest/locks.c | 59 |
1 files changed, 26 insertions, 33 deletions
diff --git a/nest/locks.c b/nest/locks.c index 812a6534..e378fb1f 100644 --- a/nest/locks.c +++ b/nest/locks.c @@ -37,7 +37,6 @@ #include "nest/iface.h" static list olock_list; -static event *olock_event; static inline int olock_same(struct object_lock *x, struct object_lock *y) @@ -54,7 +53,8 @@ olock_same(struct object_lock *x, struct object_lock *y) static void olock_free(resource *r) { - struct object_lock *q, *l = (struct object_lock *) r; + /* Called externally from rfree() */ + struct object_lock *l = SKIP_BACK(struct object_lock, r, r); node *n; DBG("olock: Freeing %p\n", l); @@ -63,21 +63,35 @@ olock_free(resource *r) case OLOCK_STATE_FREE: break; case OLOCK_STATE_LOCKED: - case OLOCK_STATE_EVENT: + /* Remove myself from the olock_list */ rem_node(&l->n); + + /* Maybe the notification is still pending. */ + ev_postpone(&l->event); + + /* Get new lock candidate */ n = HEAD(l->waiters); - if (n->next) + if (NODE_VALID(n)) { - DBG("olock: -> %p becomes locked\n", n); - q = SKIP_BACK(struct object_lock, n, n); + struct object_lock *q = SKIP_BACK(struct object_lock, n, n); + + /* Remove this candidate from waiters list */ rem_node(n); + + /* Move waiter lists */ + DBG("olock: -> %p becomes locked\n", n); add_tail_list(&q->waiters, &l->waiters); - q->state = OLOCK_STATE_EVENT; + + /* Add the new olock to olock_list */ add_head(&olock_list, n); - ev_schedule(olock_event); + + /* Inform */ + q->state = OLOCK_STATE_LOCKED; + ev_schedule(&q->event); } break; case OLOCK_STATE_WAITING: + /* Remove from the waiters list */ rem_node(&l->n); break; default: @@ -148,36 +162,16 @@ olock_acquire(struct object_lock *l) l->state = OLOCK_STATE_WAITING; add_tail(&q->waiters, &l->n); DBG("olock: %p waits\n", l); + return; } } + DBG("olock: %p acquired immediately\n", l); - l->state = OLOCK_STATE_EVENT; add_head(&olock_list, &l->n); - ev_schedule(olock_event); -} -static void -olock_run_event(void *unused UNUSED) -{ - node *n; - struct object_lock *q; - - DBG("olock: Processing events\n"); - for(;;) - { - n = HEAD(olock_list); - if (!n->next) - break; - q = SKIP_BACK(struct object_lock, n, n); - if (q->state != OLOCK_STATE_EVENT) - break; - DBG("olock: %p locked\n", q); - q->state = OLOCK_STATE_LOCKED; - rem_node(&q->n); - add_tail(&olock_list, &q->n); - q->hook(q); - } + l->state = OLOCK_STATE_LOCKED; + ev_schedule(&l->event); } /** @@ -191,5 +185,4 @@ olock_init(void) { DBG("olock: init\n"); init_list(&olock_list); - olock_event = ev_new_init(&root_pool, olock_run_event, NULL); } |