Commit 5ec58612 authored by Maria Matejka's avatar Maria Matejka
Browse files

Conversion of events to coroutines

Instead of running the events in the main thread, we run them in their
separate threads as coroutines.

For now, there is still the_bird_lock which needs to be split to allow
concurrent thread execution.

Running an event directly is deprecated (there is one warning in BGP)
and should be removed in near future.

Re-scheduling an event from itself is deprecated as well. Instead, the
event should get to an appropriate cancellation point and call
ev_suspend() there. Conversion to this policy will be also made in near
future.
parent cde8e28b
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -481,8 +481,7 @@ config_timeout(timer *t UNUSED)
void
config_init(void)
{
  config_event = ev_new(&root_pool);
  config_event->hook = config_done;
  config_event = ev_new_init(&root_pool, config_done, NULL);

  config_timer = tm_new(&root_pool);
  config_timer->hook = config_timeout;
+7 −22
Original line number Diff line number Diff line
@@ -36,12 +36,6 @@ AC_ARG_ENABLE([memcheck],
  [enable_memcheck=yes]
)

AC_ARG_ENABLE([pthreads],
  [AS_HELP_STRING([--enable-pthreads], [enable POSIX threads support @<:@try@:>@])],
  [],
  [enable_pthreads=try]
)

AC_ARG_ENABLE([libssh],
  [AS_HELP_STRING([--enable-libssh], [enable LibSSH support in RPKI @<:@try@:>@])],
  [],
@@ -129,23 +123,15 @@ if test "$bird_cv_thread_local" = yes ; then
  AC_DEFINE([HAVE_THREAD_LOCAL], [1], [Define to 1 if _Thread_local is available])
fi

if test "$enable_pthreads" != no ; then
BIRD_CHECK_PTHREADS

if test "$bird_cv_lib_pthreads" = yes ; then
    AC_DEFINE([USE_PTHREADS], [1], [Define to 1 if pthreads are enabled])
  CFLAGS="$CFLAGS -pthread"
  LDFLAGS="$LDFLAGS -pthread"
    proto_bfd=bfd
  elif test "$enable_pthreads" = yes ; then
else
  AC_MSG_ERROR([POSIX threads not available.])
fi

  if test "$enable_pthreads" = try ; then
    enable_pthreads="$bird_cv_lib_pthreads"
  fi
fi

# This is assumed to be necessary for proper BIRD build
CFLAGS="$CFLAGS -fno-strict-aliasing -fno-strict-overflow"

@@ -304,7 +290,7 @@ if test "$enable_mpls_kernel" != no ; then
  fi
fi

all_protocols="$proto_bfd babel bgp mrt ospf perf pipe radv rip rpki static"
all_protocols="bfd babel bgp mrt ospf perf pipe radv rip rpki static"

all_protocols=`echo $all_protocols | sed 's/ /,/g'`

@@ -463,7 +449,6 @@ AC_MSG_RESULT([ Object directory: $objdir])
AC_MSG_RESULT([        Iproute2 directory:	$iproutedir])
AC_MSG_RESULT([        System configuration:	$sysdesc])
AC_MSG_RESULT([        Debugging:		$enable_debug])
AC_MSG_RESULT([        POSIX threads:		$enable_pthreads])
AC_MSG_RESULT([        Routing protocols:	$protocols])
AC_MSG_RESULT([        LibSSH support in RPKI:	$enable_libssh])
AC_MSG_RESULT([        Kernel MPLS support:	$enable_mpls_kernel])
+15 −5
Original line number Diff line number Diff line
@@ -95,7 +95,17 @@ struct filter_state {
};

_Thread_local static struct filter_state filter_state;
_Thread_local static struct filter_stack filter_stack;
_Thread_local static struct filter_stack *filter_stack = NULL;

static struct filter_stack *get_filter_stack(void)
{
  if (filter_stack)
    return filter_stack;

  filter_stack = ev_alloc(sizeof(struct filter_stack));

  return filter_stack;
}

void (*bt_assert_hook)(int result, const struct f_line_item *assert);

@@ -276,7 +286,7 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i

  /* Initialize the filter state */
  filter_state = (struct filter_state) {
    .stack = &filter_stack,
    .stack = get_filter_stack(),
    .rte = rte,
    .pool = tmp_pool,
    .flags = flags,
@@ -340,7 +350,7 @@ enum filter_return
f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool)
{
  filter_state = (struct filter_state) {
    .stack = &filter_stack,
    .stack = get_filter_stack(),
    .rte = rte,
    .pool = tmp_pool,
  };
@@ -363,7 +373,7 @@ enum filter_return
f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres)
{
  filter_state = (struct filter_state) {
    .stack = &filter_stack,
    .stack = get_filter_stack(),
    .pool = tmp_pool,
  };

@@ -383,7 +393,7 @@ f_eval_int(const struct f_line *expr)
{
  /* Called independently in parse-time to eval expressions */
  filter_state = (struct filter_state) {
    .stack = &filter_stack,
    .stack = get_filter_stack(),
    .pool = cfg_mem,
  };

+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#ifndef _BIRD_BIRDLIB_H_
#define _BIRD_BIRDLIB_H_

#include "sysdep/config.h"
#include "lib/alloca.h"

/* Ugly structure offset handling macros */
+12 −92
Original line number Diff line number Diff line
@@ -22,34 +22,28 @@
#include "nest/bird.h"
#include "lib/event.h"

event_list global_event_list;
extern _Thread_local struct timeloop *timeloop_current;

inline void
ev_postpone(event *e)
static void
ev_free(resource *r)
{
  event *e = (event *) r;

  if (ev_active(e))
    {
      rem_node(&e->n);
      e->n.next = NULL;
    }
    ev_cancel(e);
}

static void
ev_dump(resource *r)
static void ev_dump_res(resource *r)
{
  event *e = (event *) r;

  debug("(code %p, data %p, %s)\n",
	e->hook,
	e->data,
	e->n.next ? "scheduled" : "inactive");
  ev_dump(e);
}

static struct resclass ev_class = {
  "Event",
  sizeof(event),
  (void (*)(resource *)) ev_postpone,
  ev_dump,
  ev_free,
  ev_dump_res,
  NULL,
  NULL
};
@@ -65,81 +59,7 @@ event *
ev_new(pool *p)
{
  event *e = ralloc(p, &ev_class);
  e->timeloop = timeloop_current;
  e->coro = NULL;
  return e;
}

/**
 * ev_run - run an event
 * @e: an event
 *
 * This function explicitly runs the event @e (calls its hook
 * function) and removes it from an event list if it's linked to any.
 *
 * From the hook function, you can call ev_enqueue() or ev_schedule()
 * to re-add the event.
 */
inline void
ev_run(event *e)
{
  ev_postpone(e);
  e->hook(e->data);
}

/**
 * ev_enqueue - enqueue an event
 * @l: an event list
 * @e: an event
 *
 * ev_enqueue() stores the event @e to the specified event
 * list @l which can be run by calling ev_run_list().
 */
inline void
ev_enqueue(event_list *l, event *e)
{
  ev_postpone(e);
  add_tail(l, &e->n);
}

/**
 * ev_schedule - schedule an event
 * @e: an event
 *
 * This function schedules an event by enqueueing it to a system-wide
 * event list which is run by the platform dependent code whenever
 * appropriate.
 */
void
ev_schedule(event *e)
{
  ev_enqueue(&global_event_list, e);
}

void io_log_event(void *hook, void *data);

/**
 * ev_run_list - run an event list
 * @l: an event list
 *
 * This function calls ev_run() for all events enqueued in the list @l.
 */
int
ev_run_list(event_list *l)
{
  node *n;
  list tmp_list;

  init_list(&tmp_list);
  add_tail_list(&tmp_list, l);
  init_list(l);
  WALK_LIST_FIRST(n, tmp_list)
    {
      event *e = SKIP_BACK(event, n, n);

      /* This is ugly hack, we want to log just events executed from the main I/O loop */
      if (l == &global_event_list)
	io_log_event(e->hook, e->data);

      ev_run(e);
    }
  return !EMPTY_LIST(*l);
}
Loading