10Sigor@sysoev.ru
20Sigor@sysoev.ru /*
30Sigor@sysoev.ru * Copyright (C) Igor Sysoev
40Sigor@sysoev.ru * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru */
60Sigor@sysoev.ru
70Sigor@sysoev.ru #include <nxt_main.h>
80Sigor@sysoev.ru
90Sigor@sysoev.ru
101Sigor@sysoev.ru static char *nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib);
110Sigor@sysoev.ru static void nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent);
121Sigor@sysoev.ru static void nxt_fiber_switch_handler(nxt_task_t *task, void *obj, void *data);
131Sigor@sysoev.ru static void nxt_fiber_switch(nxt_task_t *task, nxt_fiber_t *fib);
141Sigor@sysoev.ru static void nxt_fiber_timer_handler(nxt_task_t *task, void *obj, void *data);
150Sigor@sysoev.ru
160Sigor@sysoev.ru
17*2084Salx.manpages@gmail.com #define nxt_fiber_enqueue(thr, task, fib) \
184Sigor@sysoev.ru nxt_work_queue_add(&(thr)->engine->fast_work_queue, \
191Sigor@sysoev.ru nxt_fiber_switch_handler, task, fib, NULL)
200Sigor@sysoev.ru
210Sigor@sysoev.ru
220Sigor@sysoev.ru nxt_fiber_main_t *
nxt_fiber_main_create(nxt_event_engine_t * engine)230Sigor@sysoev.ru nxt_fiber_main_create(nxt_event_engine_t *engine)
240Sigor@sysoev.ru {
250Sigor@sysoev.ru nxt_fiber_main_t *fm;
260Sigor@sysoev.ru
270Sigor@sysoev.ru fm = nxt_zalloc(sizeof(nxt_fiber_main_t));
280Sigor@sysoev.ru if (nxt_slow_path(fm == NULL)) {
290Sigor@sysoev.ru return NULL;
300Sigor@sysoev.ru }
310Sigor@sysoev.ru
321Sigor@sysoev.ru fm->engine = engine;
330Sigor@sysoev.ru fm->stack_size = 512 * 1024 - nxt_pagesize;
340Sigor@sysoev.ru fm->idle = NULL;
350Sigor@sysoev.ru
360Sigor@sysoev.ru return fm;
370Sigor@sysoev.ru }
380Sigor@sysoev.ru
390Sigor@sysoev.ru
400Sigor@sysoev.ru nxt_int_t
nxt_fiber_create(nxt_fiber_start_t start,void * data,size_t stack)410Sigor@sysoev.ru nxt_fiber_create(nxt_fiber_start_t start, void *data, size_t stack)
420Sigor@sysoev.ru {
430Sigor@sysoev.ru int ret;
440Sigor@sysoev.ru jmp_buf parent;
450Sigor@sysoev.ru nxt_fid_t fid;
460Sigor@sysoev.ru nxt_fiber_t *fib;
470Sigor@sysoev.ru nxt_thread_t *thr;
480Sigor@sysoev.ru nxt_fiber_main_t *fm;
490Sigor@sysoev.ru
500Sigor@sysoev.ru thr = nxt_thread();
510Sigor@sysoev.ru fm = thr->engine->fibers;
520Sigor@sysoev.ru
530Sigor@sysoev.ru fid = ++fm->fid;
540Sigor@sysoev.ru
550Sigor@sysoev.ru if (fid == 0) {
560Sigor@sysoev.ru fid = ++fm->fid;
570Sigor@sysoev.ru }
580Sigor@sysoev.ru
590Sigor@sysoev.ru fib = fm->idle;
600Sigor@sysoev.ru
610Sigor@sysoev.ru if (fib != NULL) {
620Sigor@sysoev.ru fm->idle = fib->next;
630Sigor@sysoev.ru fib->fid = fid;
640Sigor@sysoev.ru fib->start = start;
650Sigor@sysoev.ru fib->data = data;
660Sigor@sysoev.ru fib->main = fm;
670Sigor@sysoev.ru
681Sigor@sysoev.ru fib->task.thread = thr;
691Sigor@sysoev.ru fib->task.log = thr->log;
701Sigor@sysoev.ru fib->task.ident = nxt_task_next_ident();
711Sigor@sysoev.ru
721Sigor@sysoev.ru nxt_debug(&fib->task, "fiber create cached: %PF", fib->fid);
731Sigor@sysoev.ru
741Sigor@sysoev.ru nxt_fiber_enqueue(thr, &fm->engine->task, fib);
751Sigor@sysoev.ru
760Sigor@sysoev.ru return NXT_OK;
770Sigor@sysoev.ru }
780Sigor@sysoev.ru
790Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber create");
800Sigor@sysoev.ru
810Sigor@sysoev.ru fib = nxt_malloc(sizeof(nxt_fiber_t));
820Sigor@sysoev.ru if (nxt_slow_path(fib == NULL)) {
830Sigor@sysoev.ru return NXT_ERROR;
840Sigor@sysoev.ru }
850Sigor@sysoev.ru
860Sigor@sysoev.ru fib->fid = fid;
870Sigor@sysoev.ru fib->start = start;
880Sigor@sysoev.ru fib->data = data;
890Sigor@sysoev.ru fib->stack_size = fm->stack_size;
900Sigor@sysoev.ru fib->main = fm;
910Sigor@sysoev.ru
921Sigor@sysoev.ru fib->task.thread = thr;
931Sigor@sysoev.ru fib->task.log = thr->log;
941Sigor@sysoev.ru fib->task.ident = nxt_task_next_ident();
951Sigor@sysoev.ru
961Sigor@sysoev.ru fib->stack = nxt_fiber_create_stack(&fib->task, fib);
970Sigor@sysoev.ru
980Sigor@sysoev.ru if (nxt_fast_path(fib->stack != NULL)) {
990Sigor@sysoev.ru
1000Sigor@sysoev.ru if (_setjmp(parent) != 0) {
1010Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber create: %PF", fib->fid);
1020Sigor@sysoev.ru return NXT_OK;
1030Sigor@sysoev.ru }
1040Sigor@sysoev.ru
1050Sigor@sysoev.ru nxt_fiber_switch_stack(fib, &parent);
1060Sigor@sysoev.ru /* It does not return if the switch was successful. */
1070Sigor@sysoev.ru }
1080Sigor@sysoev.ru
1090Sigor@sysoev.ru ret = munmap(fib->stack - nxt_pagesize, fib->stack_size + nxt_pagesize);
1100Sigor@sysoev.ru
1110Sigor@sysoev.ru if (nxt_slow_path(ret != 0)) {
1120Sigor@sysoev.ru nxt_log_alert(thr->log, "munmap() failed %E", nxt_errno);
1130Sigor@sysoev.ru }
1140Sigor@sysoev.ru
1150Sigor@sysoev.ru nxt_free(fib);
1160Sigor@sysoev.ru
1170Sigor@sysoev.ru return NXT_ERROR;
1180Sigor@sysoev.ru }
1190Sigor@sysoev.ru
1200Sigor@sysoev.ru
1210Sigor@sysoev.ru #if (NXT_LINUX)
1220Sigor@sysoev.ru
1230Sigor@sysoev.ru static char *
nxt_fiber_create_stack(nxt_task_t * task,nxt_fiber_t * fib)1241Sigor@sysoev.ru nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib)
1250Sigor@sysoev.ru {
1260Sigor@sysoev.ru char *s;
1270Sigor@sysoev.ru size_t size;
1280Sigor@sysoev.ru
1290Sigor@sysoev.ru size = fib->stack_size + nxt_pagesize;
1300Sigor@sysoev.ru
1310Sigor@sysoev.ru s = mmap(NULL, size, PROT_READ | PROT_WRITE,
1320Sigor@sysoev.ru MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, -1, 0);
1330Sigor@sysoev.ru
1340Sigor@sysoev.ru if (nxt_slow_path(s == MAP_FAILED)) {
135564Svbart@nginx.com nxt_alert(task, "fiber stack "
136564Svbart@nginx.com "mmap(%uz, MAP_PRIVATE|MAP_ANON|MAP_GROWSDOWN) failed %E",
137564Svbart@nginx.com size, nxt_errno);
1381Sigor@sysoev.ru
1390Sigor@sysoev.ru return NULL;
1400Sigor@sysoev.ru }
1410Sigor@sysoev.ru
1420Sigor@sysoev.ru if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) {
143564Svbart@nginx.com nxt_alert(task, "fiber stack mprotect(%uz, PROT_NONE) failed %E",
144564Svbart@nginx.com size, nxt_errno);
1451Sigor@sysoev.ru
1460Sigor@sysoev.ru return NULL;
1470Sigor@sysoev.ru }
1480Sigor@sysoev.ru
1490Sigor@sysoev.ru s += nxt_pagesize;
1500Sigor@sysoev.ru
1511Sigor@sysoev.ru nxt_debug(task, "fiber stack mmap: %p", s);
1520Sigor@sysoev.ru
1530Sigor@sysoev.ru return s;
1540Sigor@sysoev.ru }
1550Sigor@sysoev.ru
1560Sigor@sysoev.ru #else /* Generic version. */
1570Sigor@sysoev.ru
1580Sigor@sysoev.ru static char *
nxt_fiber_create_stack(nxt_task_t * task,nxt_fiber_t * fib)1591Sigor@sysoev.ru nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib)
1600Sigor@sysoev.ru {
1610Sigor@sysoev.ru char *s;
1620Sigor@sysoev.ru size_t size;
1630Sigor@sysoev.ru
1640Sigor@sysoev.ru size = fib->stack_size + nxt_pagesize;
1650Sigor@sysoev.ru
1660Sigor@sysoev.ru s = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1670Sigor@sysoev.ru
1680Sigor@sysoev.ru if (nxt_slow_path(s == MAP_FAILED)) {
169564Svbart@nginx.com nxt_alert(task, "fiber stack mmap(%uz, MAP_PRIVATE|MAP_ANON) failed %E",
170564Svbart@nginx.com size, nxt_errno);
1711Sigor@sysoev.ru
1720Sigor@sysoev.ru return NULL;
1730Sigor@sysoev.ru }
1740Sigor@sysoev.ru
1750Sigor@sysoev.ru if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) {
176564Svbart@nginx.com nxt_alert(task, "fiber stack mprotect(%uz, PROT_NONE) failed %E",
177564Svbart@nginx.com size, nxt_errno);
1781Sigor@sysoev.ru
1790Sigor@sysoev.ru return NULL;
1800Sigor@sysoev.ru }
1810Sigor@sysoev.ru
1820Sigor@sysoev.ru s += nxt_pagesize;
1830Sigor@sysoev.ru
1841Sigor@sysoev.ru nxt_debug(task, "fiber stack mmap: %p", s);
1850Sigor@sysoev.ru
1860Sigor@sysoev.ru return s;
1870Sigor@sysoev.ru }
1880Sigor@sysoev.ru
1890Sigor@sysoev.ru #endif
1900Sigor@sysoev.ru
1910Sigor@sysoev.ru
1920Sigor@sysoev.ru #if (NXT_LINUX && NXT_64BIT)
1930Sigor@sysoev.ru
1940Sigor@sysoev.ru /*
1950Sigor@sysoev.ru * Linux 64-bit ucontext version. 64-bit glibc makecontext() passes
1960Sigor@sysoev.ru * pointers as signed int's. The bug has been fixed in glibc 2.8.
1970Sigor@sysoev.ru */
1980Sigor@sysoev.ru
1990Sigor@sysoev.ru static void nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph,
2000Sigor@sysoev.ru uint32_t pl);
2010Sigor@sysoev.ru
2020Sigor@sysoev.ru
2030Sigor@sysoev.ru static void
nxt_fiber_switch_stack(nxt_fiber_t * fib,jmp_buf * parent)2040Sigor@sysoev.ru nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent)
2050Sigor@sysoev.ru {
2060Sigor@sysoev.ru ucontext_t uc;
2070Sigor@sysoev.ru
2081Sigor@sysoev.ru nxt_debug(&fib->task, "fiber switch to stack: %p", fib->stack);
2090Sigor@sysoev.ru
2100Sigor@sysoev.ru if (nxt_slow_path(getcontext(&uc) != 0)) {
211564Svbart@nginx.com nxt_alert(&fib->task, "getcontext() failed");
2120Sigor@sysoev.ru return;
2130Sigor@sysoev.ru }
2140Sigor@sysoev.ru
2150Sigor@sysoev.ru uc.uc_link = NULL;
2160Sigor@sysoev.ru uc.uc_stack.ss_sp = fib->stack;
2170Sigor@sysoev.ru uc.uc_stack.ss_size = fib->stack_size;
2180Sigor@sysoev.ru
2190Sigor@sysoev.ru makecontext(&uc, (void (*)(void)) nxt_fiber_trampoline, 4,
2200Sigor@sysoev.ru (uint32_t) ((uintptr_t) fib >> 32),
221611Svbart@nginx.com (uint32_t) ((uintptr_t) fib & 0xFFFFFFFF),
2220Sigor@sysoev.ru (uint32_t) ((uintptr_t) parent >> 32),
223611Svbart@nginx.com (uint32_t) ((uintptr_t) parent & 0xFFFFFFFF));
2240Sigor@sysoev.ru
2250Sigor@sysoev.ru setcontext(&uc);
2260Sigor@sysoev.ru
227564Svbart@nginx.com nxt_alert(&fib->task, "setcontext() failed");
2280Sigor@sysoev.ru }
2290Sigor@sysoev.ru
2300Sigor@sysoev.ru
2310Sigor@sysoev.ru static void
nxt_fiber_trampoline(uint32_t fh,uint32_t fl,uint32_t ph,uint32_t pl)2320Sigor@sysoev.ru nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph, uint32_t pl)
2330Sigor@sysoev.ru {
2341Sigor@sysoev.ru jmp_buf *parent;
2351Sigor@sysoev.ru nxt_task_t *task;
2361Sigor@sysoev.ru nxt_fiber_t *fib;
2370Sigor@sysoev.ru
2380Sigor@sysoev.ru fib = (nxt_fiber_t *) (((uintptr_t) fh << 32) + fl);
2390Sigor@sysoev.ru parent = (jmp_buf *) (((uintptr_t) ph << 32) + pl);
2400Sigor@sysoev.ru
2411Sigor@sysoev.ru task = &fib->task;
2420Sigor@sysoev.ru
2430Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) {
2441Sigor@sysoev.ru nxt_debug(task, "fiber return to parent stack");
2450Sigor@sysoev.ru
2461Sigor@sysoev.ru nxt_fiber_enqueue(task->thread, task, fib);
2471Sigor@sysoev.ru
2480Sigor@sysoev.ru _longjmp(*parent, 1);
2491Sigor@sysoev.ru
2500Sigor@sysoev.ru nxt_unreachable();
2510Sigor@sysoev.ru }
2520Sigor@sysoev.ru
2531Sigor@sysoev.ru nxt_debug(task, "fiber start");
2540Sigor@sysoev.ru
2550Sigor@sysoev.ru fib->start(fib->data);
2560Sigor@sysoev.ru
2571Sigor@sysoev.ru nxt_fiber_exit(task, &fib->main->fiber, NULL);
2581Sigor@sysoev.ru
2590Sigor@sysoev.ru nxt_unreachable();
2600Sigor@sysoev.ru }
2610Sigor@sysoev.ru
2620Sigor@sysoev.ru #elif (NXT_HAVE_UCONTEXT)
2630Sigor@sysoev.ru
2640Sigor@sysoev.ru /* Generic ucontext version. */
2650Sigor@sysoev.ru
2660Sigor@sysoev.ru static void nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent);
2670Sigor@sysoev.ru
2680Sigor@sysoev.ru
2690Sigor@sysoev.ru static void
nxt_fiber_switch_stack(nxt_fiber_t * fib,jmp_buf * parent)2700Sigor@sysoev.ru nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent)
2710Sigor@sysoev.ru {
2720Sigor@sysoev.ru ucontext_t uc;
2730Sigor@sysoev.ru
2741Sigor@sysoev.ru nxt_debug(&fib->task, "fiber switch to stack: %p", fib->stack);
2750Sigor@sysoev.ru
2760Sigor@sysoev.ru if (nxt_slow_path(getcontext(&uc) != 0)) {
277564Svbart@nginx.com nxt_alert(&fib->task, "getcontext() failed");
2780Sigor@sysoev.ru return;
2790Sigor@sysoev.ru }
2800Sigor@sysoev.ru
2810Sigor@sysoev.ru uc.uc_link = NULL;
2820Sigor@sysoev.ru uc.uc_stack.ss_sp = fib->stack;
2830Sigor@sysoev.ru uc.uc_stack.ss_size = fib->stack_size;
2840Sigor@sysoev.ru
2850Sigor@sysoev.ru makecontext(&uc, (void (*)(void)) nxt_fiber_trampoline, 2, fib, parent);
2860Sigor@sysoev.ru
2870Sigor@sysoev.ru setcontext(&uc);
2880Sigor@sysoev.ru
2890Sigor@sysoev.ru #if !(NXT_SOLARIS)
2900Sigor@sysoev.ru /* Solaris declares setcontext() as __NORETURN. */
2910Sigor@sysoev.ru
292564Svbart@nginx.com nxt_alert(&fib->task, "setcontext() failed");
2930Sigor@sysoev.ru #endif
2940Sigor@sysoev.ru }
2950Sigor@sysoev.ru
2960Sigor@sysoev.ru
2970Sigor@sysoev.ru static void
nxt_fiber_trampoline(nxt_fiber_t * fib,jmp_buf * parent)2980Sigor@sysoev.ru nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent)
2990Sigor@sysoev.ru {
3001Sigor@sysoev.ru nxt_task_t *task;
3010Sigor@sysoev.ru
3021Sigor@sysoev.ru task = &fib->task;
3030Sigor@sysoev.ru
3040Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) {
3051Sigor@sysoev.ru nxt_debug(task, "fiber return to parent stack");
3060Sigor@sysoev.ru
3071Sigor@sysoev.ru nxt_fiber_enqueue(task->thread, task, fib);
3081Sigor@sysoev.ru
3090Sigor@sysoev.ru _longjmp(*parent, 1);
3101Sigor@sysoev.ru
3110Sigor@sysoev.ru nxt_unreachable();
3120Sigor@sysoev.ru }
3130Sigor@sysoev.ru
3141Sigor@sysoev.ru nxt_debug(task, "fiber start");
3150Sigor@sysoev.ru
3160Sigor@sysoev.ru fib->start(fib->data);
3170Sigor@sysoev.ru
3181Sigor@sysoev.ru nxt_fiber_exit(task, &fib->main->fiber, NULL);
3191Sigor@sysoev.ru
3200Sigor@sysoev.ru nxt_unreachable();
3210Sigor@sysoev.ru }
3220Sigor@sysoev.ru
3230Sigor@sysoev.ru #else
3240Sigor@sysoev.ru
3250Sigor@sysoev.ru #error No ucontext(3) interface.
3260Sigor@sysoev.ru
3270Sigor@sysoev.ru #endif
3280Sigor@sysoev.ru
3290Sigor@sysoev.ru
3300Sigor@sysoev.ru static void
nxt_fiber_switch_handler(nxt_task_t * task,void * obj,void * data)3311Sigor@sysoev.ru nxt_fiber_switch_handler(nxt_task_t *task, void *obj, void *data)
3320Sigor@sysoev.ru {
3330Sigor@sysoev.ru nxt_fiber_t *fib;
3340Sigor@sysoev.ru
3350Sigor@sysoev.ru fib = obj;
3360Sigor@sysoev.ru
3371Sigor@sysoev.ru nxt_fiber_switch(task, fib);
3380Sigor@sysoev.ru nxt_unreachable();
3390Sigor@sysoev.ru }
3400Sigor@sysoev.ru
3410Sigor@sysoev.ru
3420Sigor@sysoev.ru static void
nxt_fiber_switch(nxt_task_t * task,nxt_fiber_t * fib)3431Sigor@sysoev.ru nxt_fiber_switch(nxt_task_t *task, nxt_fiber_t *fib)
3440Sigor@sysoev.ru {
3451Sigor@sysoev.ru nxt_debug(task, "fiber switch: %PF", fib->fid);
3460Sigor@sysoev.ru
3471Sigor@sysoev.ru task->thread->fiber = fib;
3481Sigor@sysoev.ru
3490Sigor@sysoev.ru _longjmp(fib->jmp, 1);
3501Sigor@sysoev.ru
3510Sigor@sysoev.ru nxt_unreachable();
3520Sigor@sysoev.ru }
3530Sigor@sysoev.ru
3540Sigor@sysoev.ru
3550Sigor@sysoev.ru nxt_fiber_t *
nxt_fiber_self(nxt_thread_t * thr)3560Sigor@sysoev.ru nxt_fiber_self(nxt_thread_t *thr)
3570Sigor@sysoev.ru {
3580Sigor@sysoev.ru return (nxt_fast_path(thr != NULL)) ? thr->fiber : NULL;
3590Sigor@sysoev.ru }
3600Sigor@sysoev.ru
3610Sigor@sysoev.ru
3620Sigor@sysoev.ru void
nxt_fiber_yield(nxt_task_t * task)3631Sigor@sysoev.ru nxt_fiber_yield(nxt_task_t *task)
3640Sigor@sysoev.ru {
3651Sigor@sysoev.ru nxt_fiber_t *fib;
3660Sigor@sysoev.ru
3671Sigor@sysoev.ru fib = task->thread->fiber;
3680Sigor@sysoev.ru
3690Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) {
3700Sigor@sysoev.ru
3711Sigor@sysoev.ru nxt_debug(task, "fiber yield");
3720Sigor@sysoev.ru
3731Sigor@sysoev.ru nxt_fiber_enqueue(task->thread, &fib->main->engine->task, fib);
3741Sigor@sysoev.ru
3751Sigor@sysoev.ru nxt_fiber_switch(task, &fib->main->fiber);
3761Sigor@sysoev.ru
3770Sigor@sysoev.ru nxt_unreachable();
3780Sigor@sysoev.ru }
3790Sigor@sysoev.ru
3801Sigor@sysoev.ru nxt_debug(task, "fiber yield return");
3810Sigor@sysoev.ru }
3820Sigor@sysoev.ru
3830Sigor@sysoev.ru
3840Sigor@sysoev.ru void
nxt_fiber_sleep(nxt_task_t * task,nxt_msec_t timeout)3851Sigor@sysoev.ru nxt_fiber_sleep(nxt_task_t *task, nxt_msec_t timeout)
3860Sigor@sysoev.ru {
3871Sigor@sysoev.ru nxt_fiber_t *fib;
3880Sigor@sysoev.ru
3891Sigor@sysoev.ru fib = task->thread->fiber;
3900Sigor@sysoev.ru
3914Sigor@sysoev.ru fib->timer.work_queue = &task->thread->engine->fast_work_queue;
3920Sigor@sysoev.ru fib->timer.handler = nxt_fiber_timer_handler;
3930Sigor@sysoev.ru fib->timer.log = &nxt_main_log;
3940Sigor@sysoev.ru
3951Sigor@sysoev.ru task = &fib->task;
3961Sigor@sysoev.ru
3976Sigor@sysoev.ru nxt_timer_add(task->thread->engine, &fib->timer, timeout);
3980Sigor@sysoev.ru
3990Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) {
4000Sigor@sysoev.ru
4011Sigor@sysoev.ru nxt_debug(task, "fiber sleep: %T", timeout);
4020Sigor@sysoev.ru
4031Sigor@sysoev.ru nxt_fiber_switch(task, &fib->main->fiber);
4041Sigor@sysoev.ru
4050Sigor@sysoev.ru nxt_unreachable();
4060Sigor@sysoev.ru }
4070Sigor@sysoev.ru
4081Sigor@sysoev.ru nxt_debug(task, "fiber sleep return");
4090Sigor@sysoev.ru }
4100Sigor@sysoev.ru
4110Sigor@sysoev.ru
4120Sigor@sysoev.ru static void
nxt_fiber_timer_handler(nxt_task_t * task,void * obj,void * data)4131Sigor@sysoev.ru nxt_fiber_timer_handler(nxt_task_t *task, void *obj, void *data)
4140Sigor@sysoev.ru {
4156Sigor@sysoev.ru nxt_fiber_t *fib;
4166Sigor@sysoev.ru nxt_timer_t *ev;
4170Sigor@sysoev.ru
4180Sigor@sysoev.ru ev = obj;
4190Sigor@sysoev.ru
4201Sigor@sysoev.ru nxt_debug(task, "fiber timer handler");
4210Sigor@sysoev.ru
4226Sigor@sysoev.ru fib = nxt_timer_data(ev, nxt_fiber_t, timer);
4230Sigor@sysoev.ru
4241Sigor@sysoev.ru nxt_fiber_switch(task, fib);
4251Sigor@sysoev.ru
4260Sigor@sysoev.ru nxt_unreachable();
4270Sigor@sysoev.ru }
4280Sigor@sysoev.ru
4290Sigor@sysoev.ru
4300Sigor@sysoev.ru void
nxt_fiber_wait(nxt_task_t * task)4311Sigor@sysoev.ru nxt_fiber_wait(nxt_task_t *task)
4320Sigor@sysoev.ru {
4331Sigor@sysoev.ru nxt_fiber_t *fib;
4340Sigor@sysoev.ru
4351Sigor@sysoev.ru fib = task->thread->fiber;
4360Sigor@sysoev.ru
4370Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) {
4381Sigor@sysoev.ru nxt_debug(task, "fiber wait");
4390Sigor@sysoev.ru
4401Sigor@sysoev.ru nxt_fiber_switch(task, &fib->main->fiber);
4411Sigor@sysoev.ru
4420Sigor@sysoev.ru nxt_unreachable();
4430Sigor@sysoev.ru }
4440Sigor@sysoev.ru
4451Sigor@sysoev.ru nxt_debug(task, "fiber wait return");
4460Sigor@sysoev.ru }
4470Sigor@sysoev.ru
4480Sigor@sysoev.ru
4490Sigor@sysoev.ru void
nxt_fiber_exit(nxt_task_t * task,nxt_fiber_t * next,void * data)4501Sigor@sysoev.ru nxt_fiber_exit(nxt_task_t *task, nxt_fiber_t *next, void *data)
4510Sigor@sysoev.ru {
4521Sigor@sysoev.ru nxt_fiber_t *fib;
4530Sigor@sysoev.ru
4541Sigor@sysoev.ru fib = task->thread->fiber;
4550Sigor@sysoev.ru
4561Sigor@sysoev.ru nxt_debug(task, "fiber exit");
4570Sigor@sysoev.ru
4580Sigor@sysoev.ru /* TODO: limit idle fibers. */
4590Sigor@sysoev.ru fib->next = fib->main->idle;
4600Sigor@sysoev.ru fib->main->idle = fib;
4610Sigor@sysoev.ru
4621Sigor@sysoev.ru nxt_fiber_switch(task, next);
4631Sigor@sysoev.ru
4640Sigor@sysoev.ru nxt_unreachable();
4650Sigor@sysoev.ru }
466