0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-03 07:31:54 +00:00

Co-routines moved to a separate module with sysdep implementation

This commit is contained in:
Martin Mares 2017-07-18 23:01:06 +02:00
parent fd3d15b6b5
commit 774121633f
7 changed files with 160 additions and 119 deletions

22
lib/coroutine.h Normal file
View File

@ -0,0 +1,22 @@
/*
* BIRD Coroutines
*
* (c) 2017 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_COROUTINE_H_
#define _BIRD_COROUTINE_H_
// The structure is completely opaque, implemented by sysdep
typedef struct coroutine coroutine;
coroutine *coro_new(struct pool *pool, void (*entry_point)(void *arg), void *arg);
void coro_suspend(void);
void coro_resume(coroutine *c);
struct birdsock;
int coro_sk_read(struct birdsock *s);
#endif

View File

@ -66,8 +66,8 @@
#include "nest/bird.h" #include "nest/bird.h"
#include "nest/cli.h" #include "nest/cli.h"
#include "conf/conf.h" #include "conf/conf.h"
#include "lib/coroutine.h"
#include "lib/string.h" #include "lib/string.h"
#include "sysdep/unix/unix.h" // FIXME
pool *cli_pool; pool *cli_pool;

View File

@ -1,4 +1,4 @@
src := io.c krt.c log.c main.c random.c src := io.c krt.c log.c main.c random.c coroutine.c
obj := $(src-o-files) obj := $(src-o-files)
$(all-daemon) $(all-daemon)
$(cf-local) $(cf-local)

135
sysdep/unix/coroutine.c Normal file
View File

@ -0,0 +1,135 @@
/*
* BIRD Coroutines
*
* (c) 2017 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdlib.h>
#include <ucontext.h>
#include "nest/bird.h"
#include "lib/coroutine.h"
#include "lib/resource.h"
#include "lib/socket.h"
#include "sysdep/unix/unix.h"
struct coroutine {
resource r;
ucontext_t ctx;
void *stack;
void (*entry_point)(void *arg);
void *arg;
};
static ucontext_t *main_context;
static coroutine *coro_current; // NULL for main context
#define CORO_STACK_SIZE 65536
static void
coro_free(resource *r)
{
coroutine *c = (coroutine *) r;
xfree(c->stack);
}
static void
coro_dump(resource *r UNUSED)
{
debug("\n");
}
static size_t
coro_memsize(resource *r)
{
coroutine *c = (coroutine *) r;
return sizeof(*c) + CORO_STACK_SIZE + 2*ALLOC_OVERHEAD;
}
static struct resclass coro_class = {
.name = "Coroutine",
.size = sizeof(struct coroutine),
.free = coro_free,
.dump = coro_dump,
.memsize = coro_memsize,
};
static void
coro_do_start(void)
{
ASSERT(coro_current);
coro_current->entry_point(coro_current->arg);
bug("Coroutine returned unexpectedly");
}
struct coroutine *
coro_new(pool *p, void (*entry_point)(void *), void *arg)
{
if (!main_context)
{
main_context = xmalloc(sizeof(*main_context));
if (getcontext(main_context) < 0)
bug("getcontext() failed");
}
coroutine *c = ralloc(p, &coro_class);
c->entry_point = entry_point;
c->arg = arg;
if (getcontext(&c->ctx) < 0)
bug("getcontext() failed");
c->stack = xmalloc(CORO_STACK_SIZE);
c->ctx.uc_stack.ss_sp = c->stack;
c->ctx.uc_stack.ss_size = CORO_STACK_SIZE;
makecontext(&c->ctx, coro_do_start, 0);
return c;
}
void
coro_suspend(void)
{
ASSERT(coro_current);
ASSERT(main_context);
coroutine *c = coro_current;
coro_current = NULL;
swapcontext(&c->ctx, main_context);
ASSERT(coro_current == c);
}
void
coro_resume(coroutine *c)
{
ASSERT(!coro_current);
coro_current = c;
swapcontext(main_context, &c->ctx);
ASSERT(!coro_current);
}
/* Coroutine-based I/O */
static int
coro_sk_rx_hook(sock *sk, uint size UNUSED)
{
ASSERT(sk->rx_coroutine);
ASSERT(!coro_current);
coro_resume(sk->rx_coroutine);
return 0;
}
int
coro_sk_read(sock *s)
{
ASSERT(coro_current);
s->rx_coroutine = coro_current;
s->rx_hook = coro_sk_rx_hook;
coro_suspend();
s->rx_hook = NULL;
return s->rpos - s->rbuf;
}

View File

@ -2665,113 +2665,3 @@ test_old_bird(char *path)
die("I found another BIRD running."); die("I found another BIRD running.");
close(fd); close(fd);
} }
/* EXPERIMENTAL: Support for coroutines */
#include <ucontext.h>
struct coroutine {
resource r;
ucontext_t ctx;
void *stack;
void (*entry_point)(void *arg);
void *arg;
};
static ucontext_t *main_context;
static coroutine *coro_current; // NULL for main context
static void
coro_free(resource *r)
{
coroutine *c = (coroutine *) r;
xfree(c->stack);
}
static void
coro_dump(resource *r UNUSED)
{
debug("\n");
}
static struct resclass coro_class = {
.name = "Coroutine",
.size = sizeof(struct coroutine),
.free = coro_free,
.dump = coro_dump,
// FIXME: Implement memsize
};
static void
coro_do_start(void)
{
ASSERT(coro_current);
coro_current->entry_point(coro_current->arg);
bug("Coroutine returned unexpectedly");
}
struct coroutine *
coro_new(pool *p, void (*entry_point)(void *), void *arg)
{
if (!main_context)
{
main_context = xmalloc(sizeof(*main_context));
if (getcontext(main_context) < 0)
bug("getcontext() failed");
}
coroutine *c = ralloc(p, &coro_class);
c->entry_point = entry_point;
c->arg = arg;
if (getcontext(&c->ctx) < 0)
bug("getcontext() failed");
c->stack = xmalloc(65536);
c->ctx.uc_stack.ss_sp = c->stack;
c->ctx.uc_stack.ss_size = 65536;
makecontext(&c->ctx, coro_do_start, 0);
return c;
}
// Return to main context
void
coro_suspend(void)
{
ASSERT(coro_current);
ASSERT(main_context);
coroutine *c = coro_current;
coro_current = NULL;
swapcontext(&c->ctx, main_context);
ASSERT(coro_current == c);
}
// Resume context
void
coro_resume(coroutine *c)
{
ASSERT(!coro_current);
coro_current = c;
swapcontext(main_context, &c->ctx);
ASSERT(!coro_current);
}
static int
coro_sk_rx_hook(sock *sk, uint size UNUSED)
{
ASSERT(sk->rx_coroutine);
ASSERT(!coro_current);
coro_resume(sk->rx_coroutine);
return 0;
}
int
coro_sk_read(sock *s)
{
ASSERT(coro_current);
s->rx_coroutine = coro_current;
s->rx_hook = coro_sk_rx_hook;
coro_suspend();
s->rx_hook = NULL;
return s->rpos - s->rbuf;
}

View File

@ -23,6 +23,7 @@
#include <libgen.h> #include <libgen.h>
#include "nest/bird.h" #include "nest/bird.h"
#include "lib/coroutine.h"
#include "lib/lists.h" #include "lib/lists.h"
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/socket.h" #include "lib/socket.h"

View File

@ -102,13 +102,6 @@ int sk_open_unix(struct birdsock *s, char *name);
void *tracked_fopen(struct pool *, char *name, char *mode); void *tracked_fopen(struct pool *, char *name, char *mode);
void test_old_bird(char *path); void test_old_bird(char *path);
/* Co-routines */
typedef struct coroutine coroutine;
coroutine *coro_new(struct pool *pool, void (*entry_point)(void *arg), void *arg);
void coro_suspend(void);
void coro_resume(coroutine *c);
int coro_sk_read(struct birdsock *s);
/* krt.c bits */ /* krt.c bits */
void krt_io_init(void); void krt_io_init(void);