]>
git.ipfire.org Git - thirdparty/bird.git/blob - nest/locks.c
4 * (c) 1999 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
11 #include "nest/bird.h"
12 #include "lib/resource.h"
13 #include "nest/locks.h"
14 #include "nest/iface.h"
16 static list olock_list
;
17 static event
*olock_event
;
20 olock_same(struct object_lock
*x
, struct object_lock
*y
)
24 x
->iface
== y
->iface
&&
26 ipa_equal(x
->addr
, y
->addr
);
30 olock_free(resource
*r
)
32 struct object_lock
*q
, *l
= (struct object_lock
*) r
;
35 DBG("olock: Freeing %p\n", l
);
38 case OLOCK_STATE_FREE
:
40 case OLOCK_STATE_LOCKED
:
41 case OLOCK_STATE_EVENT
:
46 DBG("olock: -> %p becomes locked\n", n
);
47 q
= SKIP_BACK(struct object_lock
, n
, n
);
49 add_tail_list(&l
->waiters
, &q
->waiters
);
50 q
->state
= OLOCK_STATE_EVENT
;
51 add_head(&olock_list
, n
);
52 ev_schedule(olock_event
);
55 case OLOCK_STATE_WAITING
:
64 olock_dump(resource
*r
)
66 struct object_lock
*l
= (struct object_lock
*) r
;
67 static char *olock_states
[] = { "free", "locked", "waiting", "event" };
69 debug("(%d:%s:%I:%d) [%s]\n", l
->type
, (l
->iface
? l
->iface
->name
: "?"), l
->addr
, l
->port
, olock_states
[l
->state
]);
70 if (!EMPTY_LIST(l
->waiters
))
74 static struct resclass olock_class
= {
76 sizeof(struct object_lock
),
84 struct object_lock
*l
= ralloc(p
, &olock_class
);
86 l
->state
= OLOCK_STATE_FREE
;
87 init_list(&l
->waiters
);
92 olock_acquire(struct object_lock
*l
)
95 struct object_lock
*q
;
97 WALK_LIST(n
, olock_list
)
99 q
= SKIP_BACK(struct object_lock
, n
, n
);
100 if (olock_same(q
, l
))
102 l
->state
= OLOCK_STATE_WAITING
;
103 add_tail(&q
->waiters
, &l
->n
);
104 DBG("olock: %p waits\n", l
);
108 DBG("olock: %p acquired immediately\n", l
);
109 l
->state
= OLOCK_STATE_EVENT
;
110 add_head(&olock_list
, &l
->n
);
111 ev_schedule(olock_event
);
115 olock_run_event(void *unused
)
118 struct object_lock
*q
;
120 DBG("olock: Processing events\n");
123 n
= HEAD(olock_list
);
126 q
= SKIP_BACK(struct object_lock
, n
, n
);
127 if (q
->state
!= OLOCK_STATE_EVENT
)
129 DBG("olock: %p locked\n", q
);
130 q
->state
= OLOCK_STATE_LOCKED
;
132 add_tail(&olock_list
, &q
->n
);
141 DBG("olock: init\n");
142 init_list(&olock_list
);
143 olock_event
= ev_new(&root_pool
);
144 olock_event
->hook
= olock_run_event
;