Statistics
| Branch: | Revision:

iof-bird-daemon / nest / locks.c @ ccdc3397

History | View | Annotate | Download (2.84 KB)

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

    
18
static list olock_list;
19
static event *olock_event;
20

    
21
static inline int
22
olock_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

    
31
static void
32
olock_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

    
65
static void
66
olock_dump(resource *r)
67
{
68
  struct object_lock *l = (struct object_lock *) r;
69
  static char *olock_states[] = { "free", "locked", "waiting", "event" };
70

    
71
  debug("(%d:%s:%I:%d) [%s]", l->type, (l->iface ? l->iface->name : "?"), l->addr, l->port, olock_states[l->state]);
72
  if (!EMPTY_LIST(l->waiters))
73
    debug(" [wanted]\n");
74
}
75

    
76
static struct resclass olock_class = {
77
  "ObjLock",
78
  sizeof(struct object_lock),
79
  olock_free,
80
  olock_dump
81
};
82

    
83
struct object_lock *
84
olock_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

    
93
void
94
olock_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

    
116
int
117
olock_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

    
140
void
141
olock_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
}