mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-18 17:18:42 +00:00
Moved the thread starting code to IO loop code
This commit is contained in:
parent
00f6b162c9
commit
e858dce757
29
lib/coro.h
29
lib/coro.h
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* BIRD Coroutines
|
||||
*
|
||||
* (c) 2017 Martin Mares <mj@ucw.cz>
|
||||
* (c) 2020-2021 Maria Matejka <mq@jmq.cz>
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#ifndef _BIRD_CORO_H_
|
||||
#define _BIRD_CORO_H_
|
||||
|
||||
#include "lib/resource.h"
|
||||
|
||||
/* A completely opaque coroutine handle. */
|
||||
struct coroutine;
|
||||
|
||||
/* Coroutines are independent threads bound to pools.
|
||||
* You request a coroutine by calling coro_run().
|
||||
* It is forbidden to free a running coroutine from outside.
|
||||
* The running coroutine must free itself by rfree() before returning.
|
||||
*/
|
||||
struct coroutine *coro_run(pool *, void (*entry)(void *), void *data);
|
||||
|
||||
/* Get self. */
|
||||
extern _Thread_local struct coroutine *this_coro;
|
||||
|
||||
|
||||
#endif
|
@ -32,7 +32,6 @@
|
||||
|
||||
#include "nest/bird.h"
|
||||
|
||||
#include "lib/coro.h"
|
||||
#include "lib/heap.h"
|
||||
#include "lib/resource.h"
|
||||
#include "lib/timer.h"
|
||||
@ -117,7 +116,7 @@ tm_set_in_tl(timer *t, btime when, struct timeloop *local_timeloop)
|
||||
|
||||
t->loop = local_timeloop;
|
||||
|
||||
if ((t->index == 1) && (local_timeloop->coro != this_coro))
|
||||
if (t->index == 1)
|
||||
birdloop_ping(local_timeloop->loop);
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,6 @@ struct timeloop
|
||||
BUFFER_(timer *) timers;
|
||||
struct domain_generic *domain;
|
||||
struct birdloop *loop;
|
||||
struct coroutine *coro;
|
||||
};
|
||||
|
||||
#define TLOCK_TIMER_ASSERT(loop) ASSERT_DIE((loop)->domain && DG_IS_LOCKED((loop)->domain))
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "lib/event.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/string.h"
|
||||
#include "lib/coro.h"
|
||||
#include "conf/conf.h"
|
||||
#include "nest/rt.h"
|
||||
#include "nest/iface.h"
|
||||
|
@ -134,7 +134,7 @@ struct proto {
|
||||
u32 debug; /* Debugging flags */
|
||||
u32 mrtdump; /* MRTDump flags */
|
||||
uint active_channels; /* Number of active channels */
|
||||
uint active_coroutines; /* Number of active coroutines */
|
||||
uint active_loops; /* Number of active IO loops */
|
||||
byte net_type; /* Protocol network type (NET_*), 0 for undefined */
|
||||
byte disabled; /* Manually disabled */
|
||||
byte vrf_set; /* Related VRF instance (above) is defined */
|
||||
@ -342,7 +342,7 @@ void proto_notify_state(struct proto *p, unsigned state);
|
||||
*/
|
||||
|
||||
static inline int proto_is_inactive(struct proto *p)
|
||||
{ return (p->active_channels == 0) && (p->active_coroutines == 0); }
|
||||
{ return (p->active_channels == 0) && (p->active_loops == 0); }
|
||||
|
||||
|
||||
/*
|
||||
|
@ -1984,7 +1984,7 @@ rt_export_stopped(void *data)
|
||||
/* Reporting the hook as finished. */
|
||||
CALL(tab->done, hook);
|
||||
|
||||
/* Free the hook together with its coroutine. */
|
||||
/* Free the hook. */
|
||||
rfree(hook->pool);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
src := alloc.c io.c io-loop.c krt.c log.c main.c random.c coroutine.c
|
||||
src := alloc.c io.c io-loop.c krt.c log.c main.c random.c domain.c
|
||||
obj := $(src-o-files)
|
||||
$(all-daemon)
|
||||
$(cf-local)
|
||||
|
@ -1,7 +1,6 @@
|
||||
/*
|
||||
* BIRD Coroutines
|
||||
* BIRD Locking
|
||||
*
|
||||
* (c) 2017 Martin Mares <mj@ucw.cz>
|
||||
* (c) 2020 Maria Matejka <mq@jmq.cz>
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
@ -17,18 +16,11 @@
|
||||
|
||||
#include "lib/birdlib.h"
|
||||
#include "lib/locking.h"
|
||||
#include "lib/coro.h"
|
||||
#include "lib/resource.h"
|
||||
#include "lib/timer.h"
|
||||
|
||||
#include "conf/conf.h"
|
||||
|
||||
#define CORO_STACK_SIZE 65536
|
||||
|
||||
/*
|
||||
* Implementation of coroutines based on POSIX threads
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
@ -122,71 +114,3 @@ void do_unlock(struct domain_generic *dg, struct domain_generic **lsp)
|
||||
dg->prev = NULL;
|
||||
pthread_mutex_unlock(&dg->mutex);
|
||||
}
|
||||
|
||||
/* Coroutines */
|
||||
struct coroutine {
|
||||
resource r;
|
||||
pthread_t id;
|
||||
pthread_attr_t attr;
|
||||
void (*entry)(void *);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static _Thread_local _Bool coro_cleaned_up = 0;
|
||||
|
||||
static void coro_free(resource *r)
|
||||
{
|
||||
struct coroutine *c = (void *) r;
|
||||
ASSERT_DIE(pthread_equal(pthread_self(), c->id));
|
||||
pthread_attr_destroy(&c->attr);
|
||||
coro_cleaned_up = 1;
|
||||
}
|
||||
|
||||
static struct resclass coro_class = {
|
||||
.name = "Coroutine",
|
||||
.size = sizeof(struct coroutine),
|
||||
.free = coro_free,
|
||||
};
|
||||
|
||||
_Thread_local struct coroutine *this_coro = NULL;
|
||||
|
||||
static void *coro_entry(void *p)
|
||||
{
|
||||
struct coroutine *c = p;
|
||||
|
||||
ASSERT_DIE(c->entry);
|
||||
|
||||
this_coro = c;
|
||||
|
||||
c->entry(c->data);
|
||||
ASSERT_DIE(coro_cleaned_up);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct coroutine *coro_run(pool *p, void (*entry)(void *), void *data)
|
||||
{
|
||||
ASSERT_DIE(entry);
|
||||
ASSERT_DIE(p);
|
||||
|
||||
struct coroutine *c = ralloc(p, &coro_class);
|
||||
|
||||
c->entry = entry;
|
||||
c->data = data;
|
||||
|
||||
int e = 0;
|
||||
|
||||
if (e = pthread_attr_init(&c->attr))
|
||||
die("pthread_attr_init() failed: %M", e);
|
||||
|
||||
if (e = pthread_attr_setstacksize(&c->attr, CORO_STACK_SIZE))
|
||||
die("pthread_attr_setstacksize(%u) failed: %M", CORO_STACK_SIZE, e);
|
||||
|
||||
if (e = pthread_attr_setdetachstate(&c->attr, PTHREAD_CREATE_DETACHED))
|
||||
die("pthread_attr_setdetachstate(PTHREAD_CREATE_DETACHED) failed: %M", e);
|
||||
|
||||
if (e = pthread_create(&c->id, &c->attr, coro_entry, c))
|
||||
die("pthread_create() failed: %M", e);
|
||||
|
||||
return 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
|
||||
*/
|
||||
@ -132,11 +133,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 +145,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
|
||||
@ -336,7 +345,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 +366,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 +414,10 @@ void
|
||||
birdloop_free(struct birdloop *loop)
|
||||
{
|
||||
ASSERT_DIE(loop->links == 0);
|
||||
ASSERT_DIE(pthread_equal(pthread_self(), loop->thread_id));
|
||||
|
||||
pthread_attr_destroy(&loop->thread_attr);
|
||||
|
||||
domain_free(loop->time.domain);
|
||||
rfree(loop->pool);
|
||||
}
|
||||
@ -423,6 +448,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,7 +498,7 @@ birdloop_unlink(struct birdloop *loop)
|
||||
loop->links--;
|
||||
}
|
||||
|
||||
static void
|
||||
static void *
|
||||
birdloop_main(void *arg)
|
||||
{
|
||||
struct birdloop *loop = arg;
|
||||
@ -532,6 +564,8 @@ birdloop_main(void *arg)
|
||||
|
||||
birdloop_leave(loop);
|
||||
loop->stopped(loop->stop_data);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,9 +21,13 @@ struct birdloop
|
||||
u8 poll_changed;
|
||||
u8 close_scheduled;
|
||||
|
||||
uint ping_pending;
|
||||
_Atomic u32 ping_sent;
|
||||
int wakeup_fds[2];
|
||||
|
||||
pthread_t thread_id;
|
||||
pthread_attr_t thread_attr;
|
||||
|
||||
uint links;
|
||||
|
||||
void (*stopped)(void *data);
|
||||
|
@ -36,10 +36,10 @@ static FILE *dbgf;
|
||||
static list *current_log_list;
|
||||
static char *current_syslog_name; /* NULL -> syslog closed */
|
||||
|
||||
static _Atomic uint max_coro_id = ATOMIC_VAR_INIT(1);
|
||||
static _Thread_local uint this_coro_id;
|
||||
static _Atomic uint max_thread_id = ATOMIC_VAR_INIT(1);
|
||||
static _Thread_local uint this_thread_id;
|
||||
|
||||
#define THIS_CORO_ID (this_coro_id ?: (this_coro_id = atomic_fetch_add_explicit(&max_coro_id, 1, memory_order_acq_rel)))
|
||||
#define THIS_THREAD_ID (this_thread_id ?: (this_thread_id = atomic_fetch_add_explicit(&max_thread_id, 1, memory_order_acq_rel)))
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
@ -183,7 +183,7 @@ log_commit(int class, buffer *buf)
|
||||
l->pos += msg_len;
|
||||
}
|
||||
|
||||
fprintf(l->fh, "%s [%04x] <%s> ", tbuf, THIS_CORO_ID, class_names[class]);
|
||||
fprintf(l->fh, "%s [%04x] <%s> ", tbuf, THIS_THREAD_ID, class_names[class]);
|
||||
}
|
||||
fputs(buf->start, l->fh);
|
||||
fputc('\n', l->fh);
|
||||
@ -329,7 +329,7 @@ debug(const char *msg, ...)
|
||||
sec = dbg_time.tv_sec - dbg_time_start.tv_sec - 1;
|
||||
}
|
||||
|
||||
int n = bsnprintf(pos, max, "%u.%09u: [%04x] ", sec, nsec, THIS_CORO_ID);
|
||||
int n = bsnprintf(pos, max, "%u.%09u: [%04x] ", sec, nsec, THIS_THREAD_ID);
|
||||
pos += n;
|
||||
max -= n;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user