1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
/* ifc.c - inter fiber communications
*
* Copyright (C) 2010 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 or later as
* published by the Free Software Foundation.
*
* See http://www.gnu.org/ for details.
*/
#include <libtf/atomic.h>
#include <libtf/fiber.h>
void tf_ifc_queue(void *fiber, struct tf_ifc *ifc, tf_ifc_handler_t handler)
{
struct tf_fiber *f = container_of(fiber, struct tf_fiber, data);
struct tf_ifc *old;
TF_BUG_ON(ifc->next != NULL);
ifc->handler = handler;
do {
old = f->pending_ifc;
ifc->next = old;
} while (!tf_atomic_cmpxchg(&f->pending_ifc, old, ifc));
tf_fiber_wakeup(f);
}
void tf_ifc_complete(void *fiber, struct tf_ifc *ifc, tf_ifc_handler_t handler)
{
ifc->sender = tf_vmach_get_current_fiber();
tf_ifc_queue(fiber, ifc, handler);
while (ifc->sender != NULL)
tf_fiber_schedule();
}
void tf_ifc_process_unordered(void)
{
struct tf_fiber *f = tf_vmach_get_current_fiber(), *s;
struct tf_ifc *pending, *ifc;
while (f->pending_ifc != NULL) {
pending = tf_atomic_xchg(&f->pending_ifc, NULL);
while (pending) {
ifc = pending;
pending = ifc->next;
ifc->handler(f->data, ifc);
s = ifc->sender;
ifc->next = NULL;
ifc->sender = NULL;
if (s != NULL)
tf_fiber_wakeup(s);
}
}
}
|