summaryrefslogtreecommitdiff
path: root/sysdep/unix/io-loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep/unix/io-loop.c')
-rw-r--r--sysdep/unix/io-loop.c97
1 files changed, 84 insertions, 13 deletions
diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c
index c7cf4ad2..575e5403 100644
--- a/sysdep/unix/io-loop.c
+++ b/sysdep/unix/io-loop.c
@@ -17,7 +17,6 @@
#include "nest/bird.h"
#include "lib/buffer.h"
-#include "lib/coro.h"
#include "lib/lists.h"
#include "lib/resource.h"
#include "lib/event.h"
@@ -28,6 +27,8 @@
#include "sysdep/unix/io-loop.h"
#include "conf/conf.h"
+#define THREAD_STACK_SIZE 65536 /* To be lowered in near future */
+
/*
* Current thread context
*/
@@ -58,6 +59,31 @@ birdloop_inside(struct birdloop *loop)
return 0;
}
+void
+birdloop_flag(struct birdloop *loop, u32 flag)
+{
+ atomic_fetch_or_explicit(&loop->flags, flag, memory_order_acq_rel);
+ birdloop_ping(loop);
+}
+
+void
+birdloop_flag_set_handler(struct birdloop *loop, struct birdloop_flag_handler *fh)
+{
+ ASSERT_DIE(birdloop_inside(loop));
+ loop->flag_handler = fh;
+}
+
+static int
+birdloop_process_flags(struct birdloop *loop)
+{
+ if (!loop->flag_handler)
+ return 0;
+
+ u32 flags = atomic_exchange_explicit(&loop->flags, 0, memory_order_acq_rel);
+ loop->flag_handler->hook(loop->flag_handler, flags);
+ return !!flags;
+}
+
/*
* Wakeup code for birdloop
*/
@@ -132,11 +158,10 @@ wakeup_do_kick(struct birdloop *loop)
pipe_kick(loop->wakeup_fds[1]);
}
-void
-birdloop_ping(struct birdloop *loop)
+static inline void
+birdloop_do_ping(struct birdloop *loop)
{
- u32 ping_sent = atomic_fetch_add_explicit(&loop->ping_sent, 1, memory_order_acq_rel);
- if (ping_sent)
+ if (atomic_fetch_add_explicit(&loop->ping_sent, 1, memory_order_acq_rel))
return;
if (loop == birdloop_wakeup_masked)
@@ -145,6 +170,15 @@ birdloop_ping(struct birdloop *loop)
wakeup_do_kick(loop);
}
+void
+birdloop_ping(struct birdloop *loop)
+{
+ if (birdloop_inside(loop) && !loop->ping_pending)
+ loop->ping_pending++;
+ else
+ birdloop_do_ping(loop);
+}
+
/*
* Sockets
@@ -205,7 +239,7 @@ sk_stop(sock *s)
}
static inline uint sk_want_events(sock *s)
-{ return ((s->rx_hook && !ev_corked(s->cork)) ? POLLIN : 0) | ((s->ttx != s->tpos) ? POLLOUT : 0); }
+{ return (s->rx_hook ? POLLIN : 0) | ((s->ttx != s->tpos) ? POLLOUT : 0); }
/*
FIXME: this should be called from sock code
@@ -336,7 +370,7 @@ birdloop_init(void)
birdloop_enter_locked(&main_birdloop);
}
-static void birdloop_main(void *arg);
+static void *birdloop_main(void *arg);
struct birdloop *
birdloop_new(pool *pp, uint order, const char *name)
@@ -357,7 +391,19 @@ birdloop_new(pool *pp, uint order, const char *name)
timers_init(&loop->time, p);
sockets_init(loop);
- loop->time.coro = coro_run(p, birdloop_main, loop);
+ int e = 0;
+
+ if (e = pthread_attr_init(&loop->thread_attr))
+ die("pthread_attr_init() failed: %M", e);
+
+ if (e = pthread_attr_setstacksize(&loop->thread_attr, THREAD_STACK_SIZE))
+ die("pthread_attr_setstacksize(%u) failed: %M", THREAD_STACK_SIZE, e);
+
+ if (e = pthread_attr_setdetachstate(&loop->thread_attr, PTHREAD_CREATE_DETACHED))
+ die("pthread_attr_setdetachstate(PTHREAD_CREATE_DETACHED) failed: %M", e);
+
+ if (e = pthread_create(&loop->thread_id, &loop->thread_attr, birdloop_main, loop))
+ die("pthread_create() failed: %M", e);
birdloop_leave(loop);
@@ -393,6 +439,11 @@ void
birdloop_free(struct birdloop *loop)
{
ASSERT_DIE(loop->links == 0);
+ ASSERT_DIE(pthread_equal(pthread_self(), loop->thread_id));
+
+ rcu_birdloop_stop(&loop->rcu);
+ pthread_attr_destroy(&loop->thread_attr);
+
domain_free(loop->time.domain);
rfree(loop->pool);
}
@@ -423,6 +474,13 @@ birdloop_leave_locked(struct birdloop *loop)
/* Check the current context */
ASSERT_DIE(birdloop_current == loop);
+ /* Send pending pings */
+ if (loop->ping_pending)
+ {
+ loop->ping_pending = 0;
+ birdloop_do_ping(loop);
+ }
+
/* Restore the old context */
birdloop_current = loop->prev_loop;
}
@@ -466,20 +524,24 @@ birdloop_unlink(struct birdloop *loop)
loop->links--;
}
-static void
+static void *
birdloop_main(void *arg)
{
struct birdloop *loop = arg;
timer *t;
int rv, timeout;
+ rcu_birdloop_start(&loop->rcu);
+
btime loop_begin = current_time();
+ tmp_init(loop->pool);
+
birdloop_enter(loop);
while (1)
{
timers_fire(&loop->time, 0);
- if (ev_run_list(&loop->event_list))
+ if (birdloop_process_flags(loop) + ev_run_list(&loop->event_list))
timeout = 0;
else if (t = timers_first(&loop->time))
timeout = (tm_remains(t) TO_MS) + 1;
@@ -523,13 +585,22 @@ birdloop_main(void *arg)
/* Flush remaining events */
ASSERT_DIE(!ev_run_list(&loop->event_list));
- /* No timers allowed */
- ASSERT_DIE(timers_count(&loop->time) == 0);
+ /* Drop timers */
+ while (t = timers_first(&loop->time))
+ tm_stop(t);
+
+ /* No sockets allowed */
ASSERT_DIE(EMPTY_LIST(loop->sock_list));
ASSERT_DIE(loop->sock_num == 0);
birdloop_leave(loop);
loop->stopped(loop->stop_data);
-}
+ return NULL;
+}
+void
+birdloop_yield(void)
+{
+ usleep(100);
+}