]> git.ipfire.org Git - thirdparty/bird.git/blame - nest/locks.c
Added missing newline in debug output.
[thirdparty/bird.git] / nest / locks.c
CommitLineData
f545d387
MM
1/*
2 * BIRD Object Locks
3 *
4 * (c) 1999 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9#include <stdio.h>
10
11#define LOCAL_DEBUG
12
13#include "nest/bird.h"
14#include "lib/resource.h"
15#include "nest/locks.h"
16#include "nest/iface.h"
17
18static list olock_list;
19static event *olock_event;
20
21static inline int
22olock_same(struct object_lock *x, struct object_lock *y)
23{
24 return
25 x->type == y->type &&
26 x->iface == y->iface &&
27 x->port == y->port &&
28 ipa_equal(x->addr, y->addr);
29}
30
31static void
32olock_free(resource *r)
33{
34 struct object_lock *q, *l = (struct object_lock *) r;
35 node *n;
36
37 DBG("olock: Freeing %p\n", l);
38 switch (l->state)
39 {
40 case OLOCK_STATE_FREE:
41 break;
42 case OLOCK_STATE_LOCKED:
43 case OLOCK_STATE_EVENT:
44 rem_node(&l->n);
45 n = HEAD(l->waiters);
46 if (n->next)
47 {
48 DBG("olock: -> %p becomes locked\n", n);
49 q = SKIP_BACK(struct object_lock, n, n);
50 rem_node(n);
51 add_tail_list(&l->waiters, &q->waiters);
52 q->state = OLOCK_STATE_EVENT;
53 add_head(&olock_list, n);
54 ev_schedule(olock_event);
55 }
56 break;
57 case OLOCK_STATE_WAITING:
58 rem_node(&l->n);
59 break;
60 default:
61 ASSERT(0);
62 }
63}
64
65static void
66olock_dump(resource *r)
67{
68 struct object_lock *l = (struct object_lock *) r;
69 static char *olock_states[] = { "free", "locked", "waiting", "event" };
70
267a2c0e 71 debug("(%d:%s:%I:%d) [%s]\n", l->type, (l->iface ? l->iface->name : "?"), l->addr, l->port, olock_states[l->state]);
f545d387
MM
72 if (!EMPTY_LIST(l->waiters))
73 debug(" [wanted]\n");
74}
75
76static struct resclass olock_class = {
77 "ObjLock",
78 sizeof(struct object_lock),
79 olock_free,
80 olock_dump
81};
82
83struct object_lock *
84olock_new(pool *p)
85{
86 struct object_lock *l = ralloc(p, &olock_class);
87
88 l->state = OLOCK_STATE_FREE;
89 init_list(&l->waiters);
90 return l;
91}
92
93void
94olock_acquire(struct object_lock *l)
95{
96 node *n;
97 struct object_lock *q;
98
99 WALK_LIST(n, olock_list)
100 {
101 q = SKIP_BACK(struct object_lock, n, n);
102 if (olock_same(q, l))
103 {
104 l->state = OLOCK_STATE_WAITING;
105 add_tail(&q->waiters, &l->n);
106 DBG("olock: %p waits\n", l);
107 return;
108 }
109 }
110 DBG("olock: %p acquired immediately\n", l);
111 l->state = OLOCK_STATE_EVENT;
112 add_head(&olock_list, &l->n);
113 ev_schedule(olock_event);
114}
115
116int
117olock_run_event(void *unused)
118{
119 node *n;
120 struct object_lock *q;
121
122 DBG("olock: Processing events\n");
123 for(;;)
124 {
125 n = HEAD(olock_list);
126 if (!n->next)
127 break;
128 q = SKIP_BACK(struct object_lock, n, n);
129 if (q->state != OLOCK_STATE_EVENT)
130 break;
131 DBG("olock: %p locked\n", q);
132 q->state = OLOCK_STATE_LOCKED;
133 rem_node(&q->n);
134 add_tail(&olock_list, &q->n);
135 q->hook(q);
136 }
137 return 0;
138}
139
140void
141olock_init(void)
142{
143 DBG("olock: init\n");
144 init_list(&olock_list);
145 olock_event = ev_new(&root_pool);
146 olock_event->hook = olock_run_event;
147}