1#include <barrelfish/notificator.h>
2#include <barrelfish/dispatch.h>
3#include <barrelfish/dispatcher_arch.h>
4#include <barrelfish/waitset_chan.h>
5#include <include/waitset_chan_priv.h>
6
7/// Dequeue the element from the notificator queue
8// static void dequeue(struct notificator **queue,
9//                             struct notificator *element)
10// {
11//     if (element->next == element) {
12//         assert(element->prev == element);
13//         assert(*queue == element);
14//         *queue = NULL;
15//     } else {
16//         element->prev->next = element->next;
17//         element->next->prev = element->prev;
18//         if (*queue == element) {
19//             *queue = element->next;
20//         }
21//     }
22//     element->prev = element->next = NULL;
23// }
24
25/// Enqueue the element on the notificator queue
26static void enqueue(struct notificator **queue,
27                            struct notificator *element)
28{
29    if (*queue == NULL) {
30        *queue = element;
31        element->next = element->prev = element;
32    } else {
33        element->next = *queue;
34        element->prev = (*queue)->prev;
35        element->next->prev = element;
36        element->prev->next = element;
37    }
38}
39
40void notificator_init(struct notificator *notificator, void *object,
41    check_notification_fn_type can_read, check_notification_fn_type can_write)
42{
43    notificator->prev = NULL;
44    notificator->next = NULL;
45    notificator->object = object;
46    notificator->can_read = can_read;
47    notificator->can_write = can_write;
48
49    waitset_chanstate_init(&notificator->ready_to_read, CHANTYPE_OTHER);
50    notificator->ready_to_read.persistent = true;
51    waitset_chanstate_init(&notificator->ready_to_write, CHANTYPE_OTHER);
52    notificator->ready_to_write.persistent = true;
53
54    dispatcher_handle_t handle = disp_disable();
55    enqueue(&get_dispatcher_generic(handle)->notificators, notificator);
56    disp_enable(handle);
57}
58
59void check_notificators_disabled(dispatcher_handle_t handle)
60{
61    struct dispatcher_generic *dp = get_dispatcher_generic(handle);
62    struct notificator *n;
63
64    if (!dp->notificators)
65        return;
66    n = dp->notificators;
67    do {
68        if (n->can_read(n->object)) {
69            if (waitset_chan_is_registered(&n->ready_to_read)) {
70                // debug_printf("triggering\n");
71                errval_t err = waitset_chan_trigger_disabled(&n->ready_to_read, handle);
72                assert(err_is_ok(err)); // should not fail
73            }
74        }
75        if (n->can_write(n->object)) {
76            if (waitset_chan_is_registered(&n->ready_to_write)) {
77                // debug_printf("triggering\n");
78                errval_t err = waitset_chan_trigger_disabled(&n->ready_to_write, handle);
79                assert(err_is_ok(err)); // should not fail
80            }
81        }
82        n = n->next;
83    } while (n != dp->notificators);
84}
85