#include "lib/resource.h"
#include "lib/event.h"
#include "lib/socket.h"
+#include "lib/tlists.h"
extern struct birdloop main_birdloop;
void birdloop_init(void);
+/* What if a thread ends */
+struct bird_thread_end_callback {
+ TLIST_NODE(bird_thread_end, struct bird_thread_end_callback) n;
+
+ /* The hook runs locked on the resource level. DO NOT LOCK ANYTHING FROM THERE.
+ * If you need to lock, schedule an event from this hook. */
+ void (*hook)(struct bird_thread_end_callback *);
+};
+
+void bird_thread_end_register(struct bird_thread_end_callback *);
+void bird_thread_end_unregister(struct bird_thread_end_callback *);
+
#endif /* _BIRD_IO_LOOP_H_ */
static _Thread_local struct bird_thread *this_thread;
+#define TLIST_PREFIX bird_thread_end
+#define TLIST_TYPE struct bird_thread_end_callback
+#define TLIST_ITEM n
+#define TLIST_WANT_ADD_TAIL
+#define TLIST_WALK
+#include "lib/tlists.h"
+
+struct bird_thread_end_private {
+ DOMAIN(resource) lock;
+ struct bird_thread_end_private **locked_at;
+ TLIST_LIST(bird_thread_end) cbs;
+};
+
+typedef union bird_thread_end {
+ DOMAIN(resource) lock;
+ struct bird_thread_end_private priv;
+} bird_thread_end;
+
+static bird_thread_end bird_thread_end_public;
+
+LOBJ_UNLOCK_CLEANUP(bird_thread_end, resource);
+#define BIRD_THREAD_END_LOCKED(p) LOBJ_LOCKED(&bird_thread_end_public, p, bird_thread_end, resource)
+
+void
+bird_thread_end_register(struct bird_thread_end_callback *btec)
+{
+ BIRD_THREAD_END_LOCKED(p)
+ bird_thread_end_add_tail(&p->cbs, btec);
+}
+
+void
+bird_thread_end_unregister(struct bird_thread_end_callback *btec)
+{
+ BIRD_THREAD_END_LOCKED(p)
+ bird_thread_end_rem_node(&p->cbs, btec);
+}
+
static void
birdloop_set_thread(struct birdloop *loop, struct bird_thread *thr, struct birdloop_pickup_group *group)
{
ev_run_list(&this_thread->priority_events);
memset(&this_thread->priority_events, 0xa5, sizeof(this_thread->priority_events));
+ /* Run thread-stop hooks */
+ BIRD_THREAD_END_LOCKED(p)
+ WALK_TLIST(bird_thread_end, n, &p->cbs)
+ n->hook(n);
+
/* Drop loops including the thread dropper itself */
while (!EMPTY_LIST(thr->loops))
{
init_list(&group->threads);
}
+ bird_thread_end_public = (bird_thread_end) {
+ .lock = DOMAIN_NEW(resource),
+ };
+
wakeup_init(main_birdloop.thread);
main_birdloop.time.domain = the_bird_domain.the_bird;