]> git.ipfire.org Git - thirdparty/bird.git/blob - nest/locks.c
Removal of useless includes continues...
[thirdparty/bird.git] / nest / locks.c
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 #define LOCAL_DEBUG
10
11 #include "nest/bird.h"
12 #include "lib/resource.h"
13 #include "nest/locks.h"
14 #include "nest/iface.h"
15
16 static list olock_list;
17 static event *olock_event;
18
19 static inline int
20 olock_same(struct object_lock *x, struct object_lock *y)
21 {
22 return
23 x->type == y->type &&
24 x->iface == y->iface &&
25 x->port == y->port &&
26 ipa_equal(x->addr, y->addr);
27 }
28
29 static void
30 olock_free(resource *r)
31 {
32 struct object_lock *q, *l = (struct object_lock *) r;
33 node *n;
34
35 DBG("olock: Freeing %p\n", l);
36 switch (l->state)
37 {
38 case OLOCK_STATE_FREE:
39 break;
40 case OLOCK_STATE_LOCKED:
41 case OLOCK_STATE_EVENT:
42 rem_node(&l->n);
43 n = HEAD(l->waiters);
44 if (n->next)
45 {
46 DBG("olock: -> %p becomes locked\n", n);
47 q = SKIP_BACK(struct object_lock, n, n);
48 rem_node(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);
53 }
54 break;
55 case OLOCK_STATE_WAITING:
56 rem_node(&l->n);
57 break;
58 default:
59 ASSERT(0);
60 }
61 }
62
63 static void
64 olock_dump(resource *r)
65 {
66 struct object_lock *l = (struct object_lock *) r;
67 static char *olock_states[] = { "free", "locked", "waiting", "event" };
68
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))
71 debug(" [wanted]\n");
72 }
73
74 static struct resclass olock_class = {
75 "ObjLock",
76 sizeof(struct object_lock),
77 olock_free,
78 olock_dump
79 };
80
81 struct object_lock *
82 olock_new(pool *p)
83 {
84 struct object_lock *l = ralloc(p, &olock_class);
85
86 l->state = OLOCK_STATE_FREE;
87 init_list(&l->waiters);
88 return l;
89 }
90
91 void
92 olock_acquire(struct object_lock *l)
93 {
94 node *n;
95 struct object_lock *q;
96
97 WALK_LIST(n, olock_list)
98 {
99 q = SKIP_BACK(struct object_lock, n, n);
100 if (olock_same(q, l))
101 {
102 l->state = OLOCK_STATE_WAITING;
103 add_tail(&q->waiters, &l->n);
104 DBG("olock: %p waits\n", l);
105 return;
106 }
107 }
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);
112 }
113
114 int
115 olock_run_event(void *unused)
116 {
117 node *n;
118 struct object_lock *q;
119
120 DBG("olock: Processing events\n");
121 for(;;)
122 {
123 n = HEAD(olock_list);
124 if (!n->next)
125 break;
126 q = SKIP_BACK(struct object_lock, n, n);
127 if (q->state != OLOCK_STATE_EVENT)
128 break;
129 DBG("olock: %p locked\n", q);
130 q->state = OLOCK_STATE_LOCKED;
131 rem_node(&q->n);
132 add_tail(&olock_list, &q->n);
133 q->hook(q);
134 }
135 return 0;
136 }
137
138 void
139 olock_init(void)
140 {
141 DBG("olock: init\n");
142 init_list(&olock_list);
143 olock_event = ev_new(&root_pool);
144 olock_event->hook = olock_run_event;
145 }