int fiber_sleep(uint32_t seconds, uint32_t useconds) { if(!fiber_loop) { fiber_do_real_sleep(seconds, useconds); return FIBER_SUCCESS; } //this code should really use ev_timer_init(), but ev_timer_init has compile warnings. ev_timer timer_event = {}; ev_set_cb(&timer_event, &timer_trigger); const double sleep_time = seconds + useconds * 0.000001; timer_event.at = sleep_time; timer_event.repeat = 0; fiber_spinlock_lock(&fiber_loop_spinlock); fiber_manager_t* const manager = fiber_manager_get(); fiber_t* const this_fiber = manager->current_fiber; timer_event.data = this_fiber; ev_timer_start(fiber_loop, &timer_event); this_fiber->state = FIBER_STATE_WAITING; manager->spinlock_to_unlock = &fiber_loop_spinlock; fiber_manager_yield(manager); return FIBER_SUCCESS; }
int fiber_wait_for_event(int fd, uint32_t events) { ev_io fd_event = {}; int poll_events = 0; if(events & FIBER_POLL_IN) { poll_events |= EV_READ; } if(events & FIBER_POLL_OUT) { poll_events |= EV_WRITE; } //this code should really use ev_io_init(), but ev_io_init has compile warnings. ev_set_cb(&fd_event, &fd_ready); ev_io_set(&fd_event, fd, poll_events); fiber_spinlock_lock(&fiber_loop_spinlock); fiber_manager_t* const manager = fiber_manager_get(); manager->event_wait_count += 1; fiber_t* const this_fiber = manager->current_fiber; fd_event.data = this_fiber; ev_io_start(fiber_loop, &fd_event); this_fiber->state = FIBER_STATE_WAITING; manager->spinlock_to_unlock = &fiber_loop_spinlock; fiber_manager_yield(manager); return FIBER_SUCCESS; }
void fiber_manager_wait_in_queue(fiber_manager_t* manager, mpsc_fifo_t* fifo) { assert(manager); assert(fifo); fiber_t* const this_fiber = manager->current_fiber; assert(this_fiber->state == FIBER_STATE_RUNNING); assert(this_fiber->mpsc_node); this_fiber->state = FIBER_STATE_WAITING; manager->mpsc_to_push.fifo = fifo; manager->mpsc_to_push.node = this_fiber->mpsc_node; manager->mpsc_to_push.node->data = this_fiber; this_fiber->mpsc_node = NULL; fiber_manager_yield(manager); }
static void* fiber_manager_thread_func(void* param) { /* set the thread local, then start running fibers */ #ifdef USE_COMPILER_THREAD_LOCAL fiber_the_manager = (fiber_manager_t*)param; #else if(!pthread_setspecific_func) { pthread_setspecific_func = (pthread_setspecific_function)fiber_load_symbol("pthread_setspecific"); } const int ret = pthread_setspecific_func(fiber_manager_key, param); if(ret) { assert(0 && "pthread_setspecific() failed!"); abort(); } #endif while(1) { /* always call fiber_manager_get(), because this *thread* fiber will actually switch threads */ fiber_manager_yield(fiber_manager_get()); } return NULL; }