From b2d0c991b3fb4274b56a2f688c5f9ace0d8a201f Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Wed, 21 Oct 2015 23:31:08 +0300 Subject: [PATCH] arm: fiber.cc -> fiber.c --- src/CMakeLists.txt | 2 +- src/cbus.c | 6 +++- src/coio.cc | 2 +- src/coio.h | 4 +-- src/exception.cc | 14 ++++++++ src/exception.h | 16 +++++++++ src/{fiber.cc => fiber.c} | 71 ++++++++++++++++++++++----------------- src/fiber.h | 65 +++++++++++++++++++++-------------- src/main.cc | 2 +- src/trigger.h | 8 +++++ test/unit/coio.cc | 5 +-- test/unit/coio.result | 2 -- test/unit/fiber.cc | 2 +- test/unit/fiber_stress.cc | 2 +- test/unit/ipc.cc | 3 +- test/unit/ipc_stress.cc | 2 +- test/unit/rmean.cc | 2 +- 17 files changed, 135 insertions(+), 73 deletions(-) rename src/{fiber.cc => fiber.c} (94%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 22cbcc2c13..312a1da5bf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -59,7 +59,7 @@ set (core_sources diag.c say.c memory.c - fiber.cc + fiber.c cbus.c exception.cc coro.c diff --git a/src/cbus.c b/src/cbus.c index 5cb62944e4..04c0e33049 100644 --- a/src/cbus.c +++ b/src/cbus.c @@ -308,7 +308,11 @@ cpipe_fiber_pool_cb(ev_loop *loop, struct ev_async *watcher, struct fiber, state); fiber_call(f); } else if (! cpipe_fiber_pool_needs_throttling(pool)) { - f = fiber_new(pool->name, cpipe_fiber_pool_f); + f = fiber_new_nothrow(pool->name, cpipe_fiber_pool_f); + if (f == NULL) { + error_log(diag_last_error(&fiber()->diag)); + break; + } fiber_start(f, pool); } else { /** diff --git a/src/coio.cc b/src/coio.cc index 7406d3f43c..ac480a63a8 100644 --- a/src/coio.cc +++ b/src/coio.cc @@ -631,7 +631,7 @@ coio_service_on_accept(struct evio_service *evio_service, void coio_service_init(struct coio_service *service, const char *name, - void (*handler)(va_list ap), void *handler_param) + fiber_func handler, void *handler_param) { evio_service_init(loop(), &service->evio_service, name, coio_service_on_accept, service); diff --git a/src/coio.h b/src/coio.h index f43811c9e1..c27bcf09be 100644 --- a/src/coio.h +++ b/src/coio.h @@ -42,7 +42,7 @@ struct coio_service { struct evio_service evio_service; /* Fiber function. */ - void (*handler)(va_list ap); + fiber_func handler; /** Passed to the created fiber. */ void *handler_param; }; @@ -160,7 +160,7 @@ coio_recvfrom_timeout(struct ev_io *coio, void *buf, size_t sz, int flags, void coio_service_init(struct coio_service *service, const char *name, - void (*handler)(va_list ap), void *handler_param); + fiber_func handler, void *handler_param); /** Wait until the service binds to the port. */ void diff --git a/src/exception.cc b/src/exception.cc index 0c739b6037..8d242458b6 100644 --- a/src/exception.cc +++ b/src/exception.cc @@ -34,6 +34,8 @@ #include <string.h> #include <errno.h> +#include "fiber.h" + extern "C" { static void @@ -176,6 +178,17 @@ TimedOut::TimedOut(const char *file, unsigned line) m_errno = ETIMEDOUT; } +const struct type type_FiberCancelException = + make_type("FiberCancelException", &type_Exception); + +void +FiberCancelException::log() +{ + say_info("fiber `%s' has been cancelled", + fiber_name(fiber())); + say_info("fiber `%s': exiting", fiber_name(fiber())); +} + void exception_init() { @@ -188,3 +201,4 @@ exception_init() /* A special workaround for out_of_memory static init */ out_of_memory.refs = 1; } + diff --git a/src/exception.h b/src/exception.h index 810ecf2f66..04c8a53c89 100644 --- a/src/exception.h +++ b/src/exception.h @@ -92,6 +92,22 @@ class TimedOut: public SystemError { virtual void raise() { throw this; } }; +extern const struct type type_FiberCancelException; +/** + * This is thrown by fiber_* API calls when the fiber is + * cancelled. + */ +class FiberCancelException: public Exception { +public: + FiberCancelException(const char *file, unsigned line) + : Exception(&type_FiberCancelException, file, line) { + /* Nothing */ + } + + virtual void log(); + virtual void raise() { throw this; } +}; + /** * Initialize the exception subsystem. */ diff --git a/src/fiber.cc b/src/fiber.c similarity index 94% rename from src/fiber.cc rename to src/fiber.c index cc1891181e..89d3e31d56 100644 --- a/src/fiber.cc +++ b/src/fiber.c @@ -40,6 +40,8 @@ #include "trigger.h" #include "third_party/pmatomic.h" +static void (*fiber_invoke)(fiber_func f, va_list ap); + /* * Defines a handler to be executed on exit from cord's thread func, * accessible via cord()->on_exit (normally NULL). It is used to @@ -62,9 +64,6 @@ static struct cord main_cord; __thread struct cord *cord_ptr = NULL; pthread_t main_thread_id; -const struct type type_FiberCancelException = - make_type("FiberCancelException", &type_Exception); - static void update_last_stack_frame(struct fiber *fiber) { @@ -210,14 +209,14 @@ fiber_join(struct fiber *fiber) fiber_yield(); } assert(fiber_is_dead(fiber)); + bool fiber_was_cancelled = fiber->flags & FIBER_IS_CANCELLED; /* The fiber is already dead. */ fiber_recycle(fiber); /* Move exception to the caller */ diag_move(&fiber->diag, &fiber()->diag); - struct error *e = diag_last_error(&fiber()->diag); /** Don't bother with propagation of FiberCancelException */ - if (e != NULL && type_cast(FiberCancelException, e) != NULL) + if (fiber_was_cancelled) diag_clear(&fiber()->diag); } @@ -252,9 +251,10 @@ struct fiber_watcher_data { }; static void -fiber_schedule_timeout(ev_loop * /* loop */, +fiber_schedule_timeout(ev_loop *loop, ev_timer *watcher, int revents) { + (void) loop; (void) revents; assert(fiber() == &cord()->sched); @@ -309,8 +309,10 @@ fiber_sleep(ev_tstamp delay) } void -fiber_schedule_cb(ev_loop * /* loop */, ev_watcher *watcher, int /* revents */) +fiber_schedule_cb(ev_loop *loop, ev_watcher *watcher, int revents) { + (void) loop; + (void) revents; assert(fiber() == &cord()->sched); fiber_call((struct fiber *) watcher->data); } @@ -330,8 +332,9 @@ fiber_schedule_list(struct rlist *list) } static void -fiber_schedule_wakeup(ev_loop * /* loop */, ev_async *watcher, int revents) +fiber_schedule_wakeup(ev_loop *loop, ev_async *watcher, int revents) { + (void) loop; (void) watcher; (void) revents; struct cord *cord = cord(); @@ -339,9 +342,13 @@ fiber_schedule_wakeup(ev_loop * /* loop */, ev_async *watcher, int revents) } static void -fiber_schedule_idle(ev_loop * /* loop */, ev_idle * /* watcher */, - int /* revents */) -{} +fiber_schedule_idle(ev_loop *loop, ev_idle *watcher, + int revents) +{ + (void) loop; + (void) watcher; + (void) revents; +} struct fiber * @@ -411,20 +418,14 @@ fiber_loop(void *data __attribute__((unused))) struct fiber *fiber = fiber(); assert(fiber != NULL && fiber->f != NULL && fiber->fid != 0); - try { - fiber->f(fiber->f_data); - /* - * Make sure a leftover exception does not - * propagate up to the joiner. - */ - diag_clear(&fiber->diag); - } catch (struct error *e) { + fiber_invoke(fiber->f, fiber->f_data); + struct error *e = diag_last_error(&fiber->diag); + if (e != NULL && !(fiber->flags & FIBER_IS_JOINABLE)) { /* * For joinable fibers, it's the business * of the caller to deal with the error. */ - if (! (fiber->flags & FIBER_IS_JOINABLE)) - error_log(e); + error_log(e); } fiber->flags |= FIBER_IS_DEAD; while (! rlist_empty(&fiber->wake)) { @@ -472,7 +473,7 @@ fiber_get_key(struct fiber *fiber, enum fiber_key key); * completes. */ struct fiber * -fiber_new(const char *name, void (*f) (va_list)) +fiber_new_nothrow(const char *name, fiber_func f) { struct cord *cord = cord(); struct fiber *fiber = NULL; @@ -482,11 +483,19 @@ fiber_new(const char *name, void (*f) (va_list)) struct fiber, link); rlist_move_entry(&cord->alive, fiber, link); } else { - fiber = (struct fiber *) mempool_alloc0(&cord->fiber_pool); + fiber = (struct fiber *) + mempool_alloc_nothrow(&cord->fiber_pool); + if (fiber == NULL) { + diag_set(OutOfMemory, sizeof(struct fiber), + "fiber pool", "fiber"); + return NULL; + } + memset(fiber, 0, sizeof(struct fiber)); if (tarantool_coro_create(&fiber->coro, &cord->slabc, fiber_loop, NULL)) { - diag_raise(); + mempool_free(&cord->fiber_pool, fiber); + return NULL; } region_create(&fiber->gc, &cord->slabc); @@ -774,8 +783,10 @@ cord_cojoin(struct cord *cord) } void -break_ev_loop_f(struct trigger * /* trigger */, void * /* event */) +break_ev_loop_f(struct trigger *trigger, void *event) { + (void) trigger; + (void) event; ev_break(loop(), EVBREAK_ALL); } @@ -791,13 +802,10 @@ cord_costart_thread_func(void *arg) { struct costart_ctx ctx = *(struct costart_ctx *) arg; free(arg); - struct fiber *f; - try { - f = fiber_new("main", ctx.run); - } catch (...) { + struct fiber *f = fiber_new_nothrow("main", ctx.run); + if (f == NULL) return NULL; - } struct trigger break_ev_loop = { RLIST_LINK_INITIALIZER, break_ev_loop_f, NULL, NULL @@ -854,8 +862,9 @@ cord_is_main() } void -fiber_init(void) +fiber_init(void (*invoke)(fiber_func f, va_list ap)) { + fiber_invoke = invoke; main_thread_id = pthread_self(); cord() = &main_cord; cord_init("main"); diff --git a/src/fiber.h b/src/fiber.h index 5b9655748d..a209e5a479 100644 --- a/src/fiber.h +++ b/src/fiber.h @@ -96,7 +96,7 @@ enum fiber_key { FIBER_KEY_MAX = 5 }; -typedef void(*fiber_func)(va_list); +typedef void (*fiber_func)(va_list); struct fiber { struct tarantool_coro coro; @@ -136,7 +136,7 @@ struct fiber { * You can safely ignore all offset_of-related warnings. * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31488 */ - void (*f) (va_list); + fiber_func f; va_list f_data; /** Fiber local storage */ void *fls[FIBER_KEY_MAX]; @@ -266,11 +266,14 @@ cord_set_name(const char *name); bool cord_is_main(); -void fiber_init(void); -void fiber_free(void); +void +fiber_init(void (*fiber_invoke)(fiber_func f, va_list ap)); + +void +fiber_free(void); struct fiber * -fiber_new(const char *name, fiber_func f); +fiber_new_nothrow(const char *name, fiber_func f); void fiber_set_name(struct fiber *fiber, const char *name); @@ -414,29 +417,15 @@ fiber_time64(void) return (uint64_t) ( ev_now(loop()) * 1000000 + 0.5 ); } +inline void +fiber_c_invoke(fiber_func f, va_list ap) +{ + return f(ap); +} + #if defined(__cplusplus) } /* extern "C" */ -/** - * This is thrown by fiber_* API calls when the fiber is - * cancelled. - */ -extern const struct type type_FiberCancelException; -class FiberCancelException: public Exception { -public: - FiberCancelException(const char *file, unsigned line) - : Exception(&type_FiberCancelException, file, line) { - /* Nothing */ - } - - virtual void log() const { - say_info("fiber `%s' has been cancelled", - fiber_name(fiber())); - say_info("fiber `%s': exiting", fiber_name(fiber())); - } - virtual void raise() { throw this; } -}; - /* * Test if this fiber is in a cancellable state and was indeed * cancelled, and raise an exception (FiberCancelException) if @@ -456,7 +445,6 @@ fiber_testcancel(void) tnt_raise(FiberCancelException); } - static inline void diag_raise(void) { @@ -465,6 +453,31 @@ diag_raise(void) error_raise(e); } +static inline struct fiber * +fiber_new(const char *name, fiber_func func) +{ + struct fiber *f = fiber_new_nothrow(name, func); + if (f == NULL) { + diag_raise(); + assert(false); + } + return f; +} + +inline void +fiber_cxx_invoke(fiber_func f, va_list ap) +{ + try { + f(ap); + /* + * Make sure a leftover exception does not + * propagate up to the joiner. + */ + diag_clear(&fiber()->diag); + } catch (struct error *e) { + } +} + #endif /* defined(__cplusplus) */ #endif /* TARANTOOL_FIBER_H_INCLUDED */ diff --git a/src/main.cc b/src/main.cc index f2007b4af5..ccce27a44d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -631,7 +631,7 @@ main(int argc, char **argv) exception_init(); - fiber_init(); + fiber_init(fiber_cxx_invoke); /* Init iobuf library with default readahead */ iobuf_init(); coeio_init(); diff --git a/src/trigger.h b/src/trigger.h index bd67f604d0..51b2506a65 100644 --- a/src/trigger.h +++ b/src/trigger.h @@ -31,10 +31,15 @@ * SUCH DAMAGE. */ #include "salad/rlist.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ /** * Type of the callback which may be invoked * on an event. */ +struct trigger; typedef void (*trigger_f)(struct trigger *trigger, void *event); typedef void (*trigger_f0)(struct trigger *trigger); @@ -105,5 +110,8 @@ trigger_destroy(struct rlist *list) trigger->destroy(trigger); } } +#if defined(__cplusplus) +} /* extern "C" */ +#endif /* defined(__cplusplus) */ #endif /* INCLUDES_TARANTOOL_TRIGGER_H */ diff --git a/test/unit/coio.cc b/test/unit/coio.cc index aeb1154692..e1f2a6a0ab 100644 --- a/test/unit/coio.cc +++ b/test/unit/coio.cc @@ -15,7 +15,8 @@ touch_f(va_list ap) fail_unless(rc == 1); fflush(f); fiber_sleep(0.01); - fiber_testcancel(); + if (fiber_is_cancelled()) + return; } } @@ -63,7 +64,7 @@ main_f(va_list ap) int main() { memory_init(); - fiber_init(); + fiber_init(fiber_cxx_invoke); struct fiber *test = fiber_new("coio_stat", main_f); fiber_wakeup(test); ev_run(loop(), 0); diff --git a/test/unit/coio.result b/test/unit/coio.result index 392e2807f9..b8391a50c6 100644 --- a/test/unit/coio.result +++ b/test/unit/coio.result @@ -1,5 +1,3 @@ -(null): fiber `touch' has been cancelled -(null): fiber `touch': exiting *** stat_timeout_test *** *** stat_timeout_test: done *** *** stat_notify_test *** diff --git a/test/unit/fiber.cc b/test/unit/fiber.cc index dc87e311bf..99918c32cc 100644 --- a/test/unit/fiber.cc +++ b/test/unit/fiber.cc @@ -105,7 +105,7 @@ main_f(va_list ap) int main() { memory_init(); - fiber_init(); + fiber_init(fiber_cxx_invoke); struct fiber *main = fiber_new("main", main_f); fiber_wakeup(main); ev_run(loop(), 0); diff --git a/test/unit/fiber_stress.cc b/test/unit/fiber_stress.cc index 2afcb382f3..ed7e4dcd5f 100644 --- a/test/unit/fiber_stress.cc +++ b/test/unit/fiber_stress.cc @@ -32,7 +32,7 @@ void benchmark_f(va_list ap) int main() { memory_init(); - fiber_init(); + fiber_init(fiber_cxx_invoke); struct fiber *benchmark = fiber_new("benchmark", benchmark_f); fiber_wakeup(benchmark); ev_run(loop(), 0); diff --git a/test/unit/ipc.cc b/test/unit/ipc.cc index c475e84cad..8d69de03c0 100644 --- a/test/unit/ipc.cc +++ b/test/unit/ipc.cc @@ -8,7 +8,6 @@ int status; void ipc_basic() { - header(); plan(10); @@ -83,7 +82,7 @@ void main_f(va_list /* ap */) int main() { memory_init(); - fiber_init(); + fiber_init(fiber_c_invoke); struct fiber *main= fiber_new("main", main_f); fiber_wakeup(main); ev_run(loop(), 0); diff --git a/test/unit/ipc_stress.cc b/test/unit/ipc_stress.cc index c5812bbf90..78d44fa3fb 100644 --- a/test/unit/ipc_stress.cc +++ b/test/unit/ipc_stress.cc @@ -45,7 +45,7 @@ void main_f(va_list ap) int main() { memory_init(); - fiber_init(); + fiber_init(fiber_c_invoke); struct fiber *main= fiber_new("main", main_f); fiber_wakeup(main); ev_run(loop(), 0); diff --git a/test/unit/rmean.cc b/test/unit/rmean.cc index 797d12dda1..a2fbb65c1f 100644 --- a/test/unit/rmean.cc +++ b/test/unit/rmean.cc @@ -46,7 +46,7 @@ int main() printf("Stat. 2 names, timer simulation\n"); memory_init(); - fiber_init(); + fiber_init(fiber_c_invoke); struct rmean *st; const char *name[] = {"EV1", "EV2"}; -- GitLab