summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nest/locks.c59
-rw-r--r--nest/locks.h4
-rw-r--r--proto/babel/babel.c10
-rw-r--r--proto/bgp/bgp.c10
-rw-r--r--proto/ospf/iface.c10
-rw-r--r--proto/radv/radv.c10
-rw-r--r--proto/rip/rip.c10
7 files changed, 57 insertions, 56 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);
}
diff --git a/nest/locks.h b/nest/locks.h
index 37026c68..0cb33db9 100644
--- a/nest/locks.h
+++ b/nest/locks.h
@@ -31,8 +31,7 @@ struct object_lock {
uint inst; /* ... instance ID */
struct iface *iface; /* ... interface */
struct iface *vrf; /* ... or VRF (if iface is unknown) */
- void (*hook)(struct object_lock *); /* Called when the lock succeeds */
- void *data; /* User data */
+ event event; /* Enqueued when the lock succeeds */
/* ... internal to lock manager, don't touch ... */
node n; /* Node in list of olocks */
int state; /* OLOCK_STATE_xxx */
@@ -50,6 +49,5 @@ void olock_init(void);
#define OLOCK_STATE_FREE 0
#define OLOCK_STATE_LOCKED 1
#define OLOCK_STATE_WAITING 2
-#define OLOCK_STATE_EVENT 3 /* waiting for unlock processing */
#endif
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index ad7981f6..e1b31e86 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1762,9 +1762,9 @@ babel_find_iface(struct babel_proto *p, struct iface *what)
}
static void
-babel_iface_locked(struct object_lock *lock)
+babel_iface_locked(void *_ifa)
{
- struct babel_iface *ifa = lock->data;
+ struct babel_iface *ifa = _ifa;
struct babel_proto *p = ifa->proto;
if (!babel_open_socket(ifa))
@@ -1819,8 +1819,10 @@ babel_add_iface(struct babel_proto *p, struct iface *new, struct babel_iface_con
lock->addr = IP6_BABEL_ROUTERS;
lock->port = ifa->cf->port;
lock->iface = ifa->iface;
- lock->hook = babel_iface_locked;
- lock->data = ifa;
+ lock->event = (event) {
+ .hook = babel_iface_locked,
+ .data = ifa,
+ };
olock_acquire(lock);
}
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 2e442e16..5b0569ae 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -1467,9 +1467,9 @@ bgp_feed_end(struct channel *C)
static void
-bgp_start_locked(struct object_lock *lock)
+bgp_start_locked(void *_p)
{
- struct bgp_proto *p = lock->data;
+ struct bgp_proto *p = _p;
const struct bgp_config *cf = p->cf;
if (p->p.proto_state != PS_START)
@@ -1574,8 +1574,10 @@ bgp_start(struct proto *P)
lock->iface = p->cf->iface;
lock->vrf = p->cf->iface ? NULL : p->p.vrf;
lock->type = OBJLOCK_TCP;
- lock->hook = bgp_start_locked;
- lock->data = p;
+ lock->event = (event) {
+ .hook = bgp_start_locked,
+ .data = p,
+ };
/* For dynamic BGP, we use inst 1 to avoid collisions with regular BGP */
if (bgp_is_dynamic(p))
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 84c53aa1..c7a6d3d4 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -484,9 +484,9 @@ ospf_iface_find(struct ospf_proto *p, struct iface *what)
}
static void
-ospf_iface_add(struct object_lock *lock)
+ospf_iface_add(void *_ifa)
{
- struct ospf_iface *ifa = lock->data;
+ struct ospf_iface *ifa = _ifa;
struct ospf_proto *p = ifa->oa->po;
/* Open socket if interface is not stub */
@@ -668,8 +668,10 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
lock->port = OSPF_PROTO;
lock->inst = ifa->instance_id;
lock->iface = iface;
- lock->data = ifa;
- lock->hook = ospf_iface_add;
+ lock->event = (event) {
+ .hook = ospf_iface_add,
+ .data = ifa,
+ };
olock_acquire(lock);
}
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index 8b547f6d..ee1da36c 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -263,9 +263,9 @@ radv_iface_find(struct radv_proto *p, struct iface *what)
}
static void
-radv_iface_add(struct object_lock *lock)
+radv_iface_add(void *_ifa)
{
- struct radv_iface *ifa = lock->data;
+ struct radv_iface *ifa = _ifa;
struct radv_proto *p = ifa->ra;
if (! radv_sk_open(ifa))
@@ -302,8 +302,10 @@ radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_conf
lock->type = OBJLOCK_IP;
lock->port = ICMPV6_PROTO;
lock->iface = iface;
- lock->data = ifa;
- lock->hook = radv_iface_add;
+ lock->event = (event) {
+ .hook = radv_iface_add,
+ .data = ifa,
+ };
ifa->lock = lock;
olock_acquire(lock);
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index ca218846..93b0d528 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -656,9 +656,9 @@ rip_iface_update_bfd(struct rip_iface *ifa)
static void
-rip_iface_locked(struct object_lock *lock)
+rip_iface_locked(void *_ifa)
{
- struct rip_iface *ifa = lock->data;
+ struct rip_iface *ifa = _ifa;
struct rip_proto *p = ifa->rip;
if (!rip_open_socket(ifa))
@@ -720,8 +720,10 @@ rip_add_iface(struct rip_proto *p, struct iface *iface, struct rip_iface_config
lock->type = OBJLOCK_UDP;
lock->port = ic->port;
lock->iface = iface;
- lock->data = ifa;
- lock->hook = rip_iface_locked;
+ lock->event = (event) {
+ .hook = rip_iface_locked,
+ .data = ifa,
+ };
ifa->lock = lock;
olock_acquire(lock);