IBNOS
event.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Michael Müller
3  * Copyright (c) 2014, Sebastian Lackner
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include <process/event.h>
29 #include <process/object.h>
30 #include <memory/allocator.h>
31 #include <process/object.h>
32 #include <util/list.h>
33 #include <util/util.h>
34 
35 
44 static void __eventDestroy(struct object *obj);
45 static void __eventShutdown(struct object *obj, UNUSED uint32_t mode);
46 static int32_t __eventGetStatus(struct object *obj, UNUSED uint32_t mode);
47 static struct linkedList *__eventWait(struct object *obj, UNUSED uint32_t mode, uint32_t *result);
48 static void __eventSignal(struct object *obj, uint32_t result);
49 static bool __eventAttachObj(struct object *obj, struct object *subObj, uint32_t mode, uint32_t ident);
50 static bool __eventDetachObj(struct object *obj, uint32_t ident);
51 
52 static const struct objectFunctions eventFunctions =
53 {
54  __eventDestroy,
55  NULL, /* getMinHandle */
56  __eventShutdown,
57  __eventGetStatus,
58  __eventWait,
59  __eventSignal,
60  NULL, /* write */
61  NULL, /* read */
62  __eventAttachObj,
63  __eventDetachObj,
64 };
65 
66 static void __subEventSignal(struct object *obj, uint32_t result);
67 
68 static const struct objectFunctions subEventFunctions =
69 {
70  NULL, /* destroy */
71  NULL, /* getMinHandle */
72  NULL, /* shutdown */
73  NULL, /* getStatus */
74  NULL, /* wait */
75  __subEventSignal,
76  NULL, /* write */
77  NULL, /* read */
78  NULL, /* insert */
79  NULL, /* remove */
80 };
81 
93 {
94  struct event *e;
95 
96  /* allocate some new memory */
97  if (!(e = heapAlloc(sizeof(*e))))
98  return NULL;
99 
100  /* initialize general object info */
101  __objectInit(&e->obj, &eventFunctions);
102  ll_init(&e->waiters);
103  ll_init(&e->subEvents);
104  e->status = 0;
105  e->wakeupAll = wakeupAll;
106 
107  return e;
108 }
109 
115 static void __eventDestroy(struct object *obj)
116 {
117  struct event *e = objectContainer(obj, struct event, &eventFunctions);
118  struct subEvent *sub, *__sub;
119 
120  /* release other threads if the user destroys the object before they return */
121  queueWakeup(&e->waiters, true, -1);
122  assert(ll_empty(&e->waiters));
123 
124  LL_FOR_EACH_SAFE(sub, __sub, &e->subEvents, struct subEvent, entry_event)
125  {
126  if (sub->blocked)
127  ll_remove(&sub->obj.entry);
128  ll_remove(&sub->entry_event); /* not really necessary, as the memory is deallocated afterwards */
129  __objectRelease(sub->wait);
130 
131  sub->obj.functions = NULL;
132  heapFree(sub);
133  }
134 
135  /* release event memory */
136  e->obj.functions = NULL;
137  heapFree(e);
138 }
139 
149 static void __eventShutdown(struct object *obj, UNUSED uint32_t mode)
150 {
151  struct event *e = objectContainer(obj, struct event, &eventFunctions);
152  queueWakeup(&e->waiters, true, -1);
153 }
154 
167 static int32_t __eventGetStatus(struct object *obj, UNUSED uint32_t mode)
168 {
169  struct event *e = objectContainer(obj, struct event, &eventFunctions);
170  return e->status;
171 }
172 
186 static struct linkedList *__eventWait(struct object *obj, UNUSED uint32_t mode, uint32_t *result)
187 {
188  struct event *e = objectContainer(obj, struct event, &eventFunctions);
189  struct subEvent *sub;
190  struct linkedList *queue;
191 
192  LL_FOR_EACH(sub, &e->subEvents, struct subEvent, entry_event)
193  {
194  if (sub->blocked) continue;
195  assert(sub->event == e);
196 
197  e->status = 0;
198  queue = __objectWait(sub->wait, sub->waitMode, &e->status);
199  if (queue)
200  {
201  sub->blocked = true;
202  ll_add_after(queue, &sub->obj.entry);
203  }
204  else
205  {
206  *result = sub->identifier;
207  return NULL;
208  }
209  }
210 
211  return &e->waiters;
212 }
213 
220 static void __eventSignal(struct object *obj, uint32_t result)
221 {
222  struct event *e = objectContainer(obj, struct event, &eventFunctions);
223  e->status = 0;
224  queueWakeup(&e->waiters, e->wakeupAll, result);
225 }
226 
240 static bool __eventAttachObj(struct object *obj, struct object *subObj, uint32_t mode, uint32_t ident)
241 {
242  struct subEvent *sub;
243  struct event *e = objectContainer(obj, struct event, &eventFunctions);
244 
245  if (!(sub = heapAlloc(sizeof(*sub))))
246  return false;
247 
248  /* initialize general object info */
249  __objectInit(&sub->obj, &subEventFunctions);
250  sub->blocked = false;
251  sub->event = e;
252  ll_add_tail(&e->subEvents, &sub->entry_event);
253  sub->wait = __objectAddRef(subObj);
254  sub->waitMode = mode;
255  sub->identifier = ident;
256 
257  return true;
258 }
259 
268 static bool __eventDetachObj(struct object *obj, uint32_t ident)
269 {
270  struct event *e = objectContainer(obj, struct event, &eventFunctions);
271  struct subEvent *sub, *__sub;
272  bool success = false;
273 
274  LL_FOR_EACH_SAFE(sub, __sub, &e->subEvents, struct subEvent, entry_event)
275  {
276  if (sub->identifier == ident)
277  {
278  if (sub->blocked)
279  ll_remove(&sub->obj.entry);
280  ll_remove(&sub->entry_event);
281  __objectRelease(sub->wait);
282 
283  sub->obj.functions = NULL;
284  heapFree(sub);
285 
286  success = true;
287  }
288  }
289 
290  return success;
291 }
292 
299 static void __subEventSignal(struct object *obj, uint32_t result)
300 {
301  struct subEvent *s = objectContainer(obj, struct subEvent, &subEventFunctions);
302  struct event *e = s->event;
303  if (!s->blocked) return;
304 
305  s->blocked = false;
306  ll_remove(&s->obj.entry);
307 
308  /* wakeup objects waiting for the main event */
309  e->status = result;
310  queueWakeup(&e->waiters, e->wakeupAll, s->identifier);
311 }
312 
struct object * wait
Definition: event.h:60
bool blocked
Definition: event.h:55
struct linkedList subEvents
Definition: event.h:46
const struct objectFunctions * functions
Definition: object.h:72
void * heapAlloc(uint32_t length)
Allocates a block of kernel memory.
Definition: allocator.c:363
#define assert(ex)
Definition: util.h:61
#define UNUSED
Definition: util.h:39
Definition: event.h:41
void heapFree(void *addr)
Deallocates a block of kernel memory.
Definition: allocator.c:385
struct linkedList entry_event
Definition: event.h:58
struct event * event
Definition: event.h:57
struct event * eventCreate(bool wakeupAll)
Creates a new kernel event object.
Definition: event.c:92
struct object obj
Definition: event.h:54
uint32_t waitMode
Definition: event.h:61
#define objectContainer(p, type, functions)
Definition: object.h:66
struct object obj
Definition: event.h:43
struct linkedList entry
Definition: object.h:73
#define ll_add_tail
Definition: list.h:100
uint32_t identifier
Definition: event.h:63
uint32_t status
Definition: event.h:47
Definition: event.h:52
struct linkedList waiters
Definition: event.h:44
#define LL_FOR_EACH_SAFE(element, next_element, list, type, field)
Allows to iterate a linkedList similar to a for-loop (safe when deleting elements).
Definition: list.h:148
char mode[8]
Definition: filesystem.h:65
#define LL_FOR_EACH(element, list, type, field)
Allows to iterate a linkedList similar to a for-loop.
Definition: list.h:138
bool wakeupAll
Definition: event.h:49