diff --git a/src/fiber.cc b/src/fiber.cc index ff02fb3132cd68813f52c43e722e95b4ce9d872b..111aaca7da0c9b4f106119fa603df2b6810263cd 100644 --- a/src/fiber.cc +++ b/src/fiber.cc @@ -105,12 +105,12 @@ fiber_wakeup(struct fiber *f) if (rlist_empty(&cord->ready)) { /* * ev_feed_event() is possibly faster, - * but custom event gets scheduled in the + * but EV_CUSTOM event gets scheduled in the * same event loop iteration, which can - * produce unfair scheduling (see the case of + * produce unfair scheduling, (see the case of * fiber_sleep(0)) */ - ev_async_send(cord->loop, &cord->wakeup_event); + ev_feed_event(cord->loop, &cord->wakeup_event, EV_CUSTOM); } rlist_move_tail_entry(&cord->ready, f, state); } @@ -293,13 +293,11 @@ fiber_yield_timeout(ev_tstamp delay) void fiber_sleep(ev_tstamp delay) { - if (delay == 0) { - /* Faster than starting and stopping a timer. */ - fiber_wakeup(fiber()); - fiber_yield(); - } else { - fiber_yield_timeout(delay); - } + /* + * We don't use fiber_wakeup() here to ensure there is + * no infinite wakeup loop in case of fiber_sleep(0). + */ + fiber_yield_timeout(delay); fiber_testcancel(); } diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 1b8d8c0088382ebae013631316a7096d65211fc8..4833461371e482ad674f8222e01a20de7945ca46 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -65,6 +65,9 @@ target_link_libraries(fiber.test core) add_executable(fiber_stress.test fiber_stress.cc) target_link_libraries(fiber_stress.test core) +add_executable(ipc.test ipc.cc ${CMAKE_SOURCE_DIR}/src/ipc.cc) +target_link_libraries(ipc.test core) + add_executable(coio.test coio.cc unit.c ${CMAKE_SOURCE_DIR}/src/sio.cc ${CMAKE_SOURCE_DIR}/src/evio.cc diff --git a/test/unit/ipc.cc b/test/unit/ipc.cc new file mode 100644 index 0000000000000000000000000000000000000000..c5812bbf90744b73442b3bea481480c995dea721 --- /dev/null +++ b/test/unit/ipc.cc @@ -0,0 +1,55 @@ +#include "memory.h" +#include "fiber.h" +#include "ipc.h" +#include "unit.h" + +enum { + ITERATIONS = 100000, +}; + +void +push_f(va_list ap) +{ + struct ipc_channel *channel = va_arg(ap, struct ipc_channel *); + + for (int i = 0; i < ITERATIONS; i++) + ipc_channel_put(channel, NULL); +} + +void +pop_f(va_list ap) +{ + struct ipc_channel *channel = va_arg(ap, struct ipc_channel *); + + for (int i = 0; i < ITERATIONS; i++) + (void) ipc_channel_get(channel); +} + +void main_f(va_list ap) +{ + header(); + struct fiber *push = fiber_new("push_f", push_f); + fiber_set_joinable(push, true); + struct fiber *pop = fiber_new("pop_f", pop_f); + fiber_set_joinable(pop, true); + struct ipc_channel *channel = ipc_channel_new(1); + fiber_start(push, channel); + fiber_start(pop, channel); + fiber_join(push); + fiber_join(pop); + ipc_channel_delete(channel); + ev_break(loop(), EVBREAK_ALL); + footer(); +} + +int main() +{ + memory_init(); + fiber_init(); + struct fiber *main= fiber_new("main", main_f); + fiber_wakeup(main); + ev_run(loop(), 0); + fiber_free(); + memory_free(); + return 0; +} diff --git a/test/unit/ipc.result b/test/unit/ipc.result new file mode 100644 index 0000000000000000000000000000000000000000..f3398fb9c7731397e2535321288bd427198fba1e --- /dev/null +++ b/test/unit/ipc.result @@ -0,0 +1,3 @@ + *** main_f *** + *** main_f: done *** + \ No newline at end of file