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 170Sigor@sysoev.ru #define \ 181Sigor@sysoev.ru nxt_fiber_enqueue(thr, task, fib) \ 194Sigor@sysoev.ru nxt_work_queue_add(&(thr)->engine->fast_work_queue, \ 201Sigor@sysoev.ru nxt_fiber_switch_handler, task, fib, NULL) 210Sigor@sysoev.ru 220Sigor@sysoev.ru 230Sigor@sysoev.ru nxt_fiber_main_t * 240Sigor@sysoev.ru nxt_fiber_main_create(nxt_event_engine_t *engine) 250Sigor@sysoev.ru { 260Sigor@sysoev.ru nxt_fiber_main_t *fm; 270Sigor@sysoev.ru 280Sigor@sysoev.ru fm = nxt_zalloc(sizeof(nxt_fiber_main_t)); 290Sigor@sysoev.ru if (nxt_slow_path(fm == NULL)) { 300Sigor@sysoev.ru return NULL; 310Sigor@sysoev.ru } 320Sigor@sysoev.ru 331Sigor@sysoev.ru fm->engine = engine; 340Sigor@sysoev.ru fm->stack_size = 512 * 1024 - nxt_pagesize; 350Sigor@sysoev.ru fm->idle = NULL; 360Sigor@sysoev.ru 370Sigor@sysoev.ru return fm; 380Sigor@sysoev.ru } 390Sigor@sysoev.ru 400Sigor@sysoev.ru 410Sigor@sysoev.ru nxt_int_t 420Sigor@sysoev.ru nxt_fiber_create(nxt_fiber_start_t start, void *data, size_t stack) 430Sigor@sysoev.ru { 440Sigor@sysoev.ru int ret; 450Sigor@sysoev.ru jmp_buf parent; 460Sigor@sysoev.ru nxt_fid_t fid; 470Sigor@sysoev.ru nxt_fiber_t *fib; 480Sigor@sysoev.ru nxt_thread_t *thr; 490Sigor@sysoev.ru nxt_fiber_main_t *fm; 500Sigor@sysoev.ru 510Sigor@sysoev.ru thr = nxt_thread(); 520Sigor@sysoev.ru fm = thr->engine->fibers; 530Sigor@sysoev.ru 540Sigor@sysoev.ru fid = ++fm->fid; 550Sigor@sysoev.ru 560Sigor@sysoev.ru if (fid == 0) { 570Sigor@sysoev.ru fid = ++fm->fid; 580Sigor@sysoev.ru } 590Sigor@sysoev.ru 600Sigor@sysoev.ru fib = fm->idle; 610Sigor@sysoev.ru 620Sigor@sysoev.ru if (fib != NULL) { 630Sigor@sysoev.ru fm->idle = fib->next; 640Sigor@sysoev.ru fib->fid = fid; 650Sigor@sysoev.ru fib->start = start; 660Sigor@sysoev.ru fib->data = data; 670Sigor@sysoev.ru fib->main = fm; 680Sigor@sysoev.ru 691Sigor@sysoev.ru fib->task.thread = thr; 701Sigor@sysoev.ru fib->task.log = thr->log; 711Sigor@sysoev.ru fib->task.ident = nxt_task_next_ident(); 721Sigor@sysoev.ru 731Sigor@sysoev.ru nxt_debug(&fib->task, "fiber create cached: %PF", fib->fid); 741Sigor@sysoev.ru 751Sigor@sysoev.ru nxt_fiber_enqueue(thr, &fm->engine->task, fib); 761Sigor@sysoev.ru 770Sigor@sysoev.ru return NXT_OK; 780Sigor@sysoev.ru } 790Sigor@sysoev.ru 800Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber create"); 810Sigor@sysoev.ru 820Sigor@sysoev.ru fib = nxt_malloc(sizeof(nxt_fiber_t)); 830Sigor@sysoev.ru if (nxt_slow_path(fib == NULL)) { 840Sigor@sysoev.ru return NXT_ERROR; 850Sigor@sysoev.ru } 860Sigor@sysoev.ru 870Sigor@sysoev.ru fib->fid = fid; 880Sigor@sysoev.ru fib->start = start; 890Sigor@sysoev.ru fib->data = data; 900Sigor@sysoev.ru fib->stack_size = fm->stack_size; 910Sigor@sysoev.ru fib->main = fm; 920Sigor@sysoev.ru 931Sigor@sysoev.ru fib->task.thread = thr; 941Sigor@sysoev.ru fib->task.log = thr->log; 951Sigor@sysoev.ru fib->task.ident = nxt_task_next_ident(); 961Sigor@sysoev.ru 971Sigor@sysoev.ru fib->stack = nxt_fiber_create_stack(&fib->task, fib); 980Sigor@sysoev.ru 990Sigor@sysoev.ru if (nxt_fast_path(fib->stack != NULL)) { 1000Sigor@sysoev.ru 1010Sigor@sysoev.ru if (_setjmp(parent) != 0) { 1020Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber create: %PF", fib->fid); 1030Sigor@sysoev.ru return NXT_OK; 1040Sigor@sysoev.ru } 1050Sigor@sysoev.ru 1060Sigor@sysoev.ru nxt_fiber_switch_stack(fib, &parent); 1070Sigor@sysoev.ru /* It does not return if the switch was successful. */ 1080Sigor@sysoev.ru } 1090Sigor@sysoev.ru 1100Sigor@sysoev.ru ret = munmap(fib->stack - nxt_pagesize, fib->stack_size + nxt_pagesize); 1110Sigor@sysoev.ru 1120Sigor@sysoev.ru if (nxt_slow_path(ret != 0)) { 1130Sigor@sysoev.ru nxt_log_alert(thr->log, "munmap() failed %E", nxt_errno); 1140Sigor@sysoev.ru } 1150Sigor@sysoev.ru 1160Sigor@sysoev.ru nxt_free(fib); 1170Sigor@sysoev.ru 1180Sigor@sysoev.ru return NXT_ERROR; 1190Sigor@sysoev.ru } 1200Sigor@sysoev.ru 1210Sigor@sysoev.ru 1220Sigor@sysoev.ru #if (NXT_LINUX) 1230Sigor@sysoev.ru 1240Sigor@sysoev.ru static char * 1251Sigor@sysoev.ru nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib) 1260Sigor@sysoev.ru { 1270Sigor@sysoev.ru char *s; 1280Sigor@sysoev.ru size_t size; 1290Sigor@sysoev.ru 1300Sigor@sysoev.ru size = fib->stack_size + nxt_pagesize; 1310Sigor@sysoev.ru 1320Sigor@sysoev.ru s = mmap(NULL, size, PROT_READ | PROT_WRITE, 1330Sigor@sysoev.ru MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, -1, 0); 1340Sigor@sysoev.ru 1350Sigor@sysoev.ru if (nxt_slow_path(s == MAP_FAILED)) { 1361Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "fiber stack " 1371Sigor@sysoev.ru "mmap(%uz, MAP_PRIVATE|MAP_ANON|MAP_GROWSDOWN) failed %E", 1381Sigor@sysoev.ru size, nxt_errno); 1391Sigor@sysoev.ru 1400Sigor@sysoev.ru return NULL; 1410Sigor@sysoev.ru } 1420Sigor@sysoev.ru 1430Sigor@sysoev.ru if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) { 1441Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 1451Sigor@sysoev.ru "fiber stack mprotect(%uz, PROT_NONE) failed %E", 1461Sigor@sysoev.ru size, nxt_errno); 1471Sigor@sysoev.ru 1480Sigor@sysoev.ru return NULL; 1490Sigor@sysoev.ru } 1500Sigor@sysoev.ru 1510Sigor@sysoev.ru s += nxt_pagesize; 1520Sigor@sysoev.ru 1531Sigor@sysoev.ru nxt_debug(task, "fiber stack mmap: %p", s); 1540Sigor@sysoev.ru 1550Sigor@sysoev.ru return s; 1560Sigor@sysoev.ru } 1570Sigor@sysoev.ru 1580Sigor@sysoev.ru #else /* Generic version. */ 1590Sigor@sysoev.ru 1600Sigor@sysoev.ru static char * 1611Sigor@sysoev.ru nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib) 1620Sigor@sysoev.ru { 1630Sigor@sysoev.ru char *s; 1640Sigor@sysoev.ru size_t size; 1650Sigor@sysoev.ru 1660Sigor@sysoev.ru size = fib->stack_size + nxt_pagesize; 1670Sigor@sysoev.ru 1680Sigor@sysoev.ru s = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); 1690Sigor@sysoev.ru 1700Sigor@sysoev.ru if (nxt_slow_path(s == MAP_FAILED)) { 1711Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 1721Sigor@sysoev.ru "fiber stack mmap(%uz, MAP_PRIVATE|MAP_ANON) failed %E", 1731Sigor@sysoev.ru size, nxt_errno); 1741Sigor@sysoev.ru 1750Sigor@sysoev.ru return NULL; 1760Sigor@sysoev.ru } 1770Sigor@sysoev.ru 1780Sigor@sysoev.ru if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) { 1791Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 1801Sigor@sysoev.ru "fiber stack mprotect(%uz, PROT_NONE) failed %E", 1811Sigor@sysoev.ru size, nxt_errno); 1821Sigor@sysoev.ru 1830Sigor@sysoev.ru return NULL; 1840Sigor@sysoev.ru } 1850Sigor@sysoev.ru 1860Sigor@sysoev.ru s += nxt_pagesize; 1870Sigor@sysoev.ru 1881Sigor@sysoev.ru nxt_debug(task, "fiber stack mmap: %p", s); 1890Sigor@sysoev.ru 1900Sigor@sysoev.ru return s; 1910Sigor@sysoev.ru } 1920Sigor@sysoev.ru 1930Sigor@sysoev.ru #endif 1940Sigor@sysoev.ru 1950Sigor@sysoev.ru 1960Sigor@sysoev.ru #if (NXT_LINUX && NXT_64BIT) 1970Sigor@sysoev.ru 1980Sigor@sysoev.ru /* 1990Sigor@sysoev.ru * Linux 64-bit ucontext version. 64-bit glibc makecontext() passes 2000Sigor@sysoev.ru * pointers as signed int's. The bug has been fixed in glibc 2.8. 2010Sigor@sysoev.ru */ 2020Sigor@sysoev.ru 2030Sigor@sysoev.ru static void nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph, 2040Sigor@sysoev.ru uint32_t pl); 2050Sigor@sysoev.ru 2060Sigor@sysoev.ru 2070Sigor@sysoev.ru static void 2080Sigor@sysoev.ru nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent) 2090Sigor@sysoev.ru { 2100Sigor@sysoev.ru ucontext_t uc; 2110Sigor@sysoev.ru 2121Sigor@sysoev.ru nxt_debug(&fib->task, "fiber switch to stack: %p", fib->stack); 2130Sigor@sysoev.ru 2140Sigor@sysoev.ru if (nxt_slow_path(getcontext(&uc) != 0)) { 2151Sigor@sysoev.ru nxt_log(&fib->task, NXT_LOG_CRIT, "getcontext() failed"); 2160Sigor@sysoev.ru return; 2170Sigor@sysoev.ru } 2180Sigor@sysoev.ru 2190Sigor@sysoev.ru uc.uc_link = NULL; 2200Sigor@sysoev.ru uc.uc_stack.ss_sp = fib->stack; 2210Sigor@sysoev.ru uc.uc_stack.ss_size = fib->stack_size; 2220Sigor@sysoev.ru 2230Sigor@sysoev.ru makecontext(&uc, (void (*)(void)) nxt_fiber_trampoline, 4, 2240Sigor@sysoev.ru (uint32_t) ((uintptr_t) fib >> 32), 2250Sigor@sysoev.ru (uint32_t) ((uintptr_t) fib & 0xffffffff), 2260Sigor@sysoev.ru (uint32_t) ((uintptr_t) parent >> 32), 2270Sigor@sysoev.ru (uint32_t) ((uintptr_t) parent & 0xffffffff)); 2280Sigor@sysoev.ru 2290Sigor@sysoev.ru setcontext(&uc); 2300Sigor@sysoev.ru 2311Sigor@sysoev.ru nxt_log(&fib->task, NXT_LOG_CRIT, "setcontext() failed"); 2320Sigor@sysoev.ru } 2330Sigor@sysoev.ru 2340Sigor@sysoev.ru 2350Sigor@sysoev.ru static void 2360Sigor@sysoev.ru nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph, uint32_t pl) 2370Sigor@sysoev.ru { 2381Sigor@sysoev.ru jmp_buf *parent; 2391Sigor@sysoev.ru nxt_task_t *task; 2401Sigor@sysoev.ru nxt_fiber_t *fib; 2410Sigor@sysoev.ru 2420Sigor@sysoev.ru fib = (nxt_fiber_t *) (((uintptr_t) fh << 32) + fl); 2430Sigor@sysoev.ru parent = (jmp_buf *) (((uintptr_t) ph << 32) + pl); 2440Sigor@sysoev.ru 2451Sigor@sysoev.ru task = &fib->task; 2460Sigor@sysoev.ru 2470Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 2481Sigor@sysoev.ru nxt_debug(task, "fiber return to parent stack"); 2490Sigor@sysoev.ru 2501Sigor@sysoev.ru nxt_fiber_enqueue(task->thread, task, fib); 2511Sigor@sysoev.ru 2520Sigor@sysoev.ru _longjmp(*parent, 1); 2531Sigor@sysoev.ru 2540Sigor@sysoev.ru nxt_unreachable(); 2550Sigor@sysoev.ru } 2560Sigor@sysoev.ru 2571Sigor@sysoev.ru nxt_debug(task, "fiber start"); 2580Sigor@sysoev.ru 2590Sigor@sysoev.ru fib->start(fib->data); 2600Sigor@sysoev.ru 2611Sigor@sysoev.ru nxt_fiber_exit(task, &fib->main->fiber, NULL); 2621Sigor@sysoev.ru 2630Sigor@sysoev.ru nxt_unreachable(); 2640Sigor@sysoev.ru } 2650Sigor@sysoev.ru 2660Sigor@sysoev.ru #elif (NXT_HAVE_UCONTEXT) 2670Sigor@sysoev.ru 2680Sigor@sysoev.ru /* Generic ucontext version. */ 2690Sigor@sysoev.ru 2700Sigor@sysoev.ru static void nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent); 2710Sigor@sysoev.ru 2720Sigor@sysoev.ru 2730Sigor@sysoev.ru static void 2740Sigor@sysoev.ru nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent) 2750Sigor@sysoev.ru { 2760Sigor@sysoev.ru ucontext_t uc; 2770Sigor@sysoev.ru 2781Sigor@sysoev.ru nxt_debug(&fib->task, "fiber switch to stack: %p", fib->stack); 2790Sigor@sysoev.ru 2800Sigor@sysoev.ru if (nxt_slow_path(getcontext(&uc) != 0)) { 2811Sigor@sysoev.ru nxt_log(&fib->task, NXT_LOG_CRIT, "getcontext() failed"); 2820Sigor@sysoev.ru return; 2830Sigor@sysoev.ru } 2840Sigor@sysoev.ru 2850Sigor@sysoev.ru uc.uc_link = NULL; 2860Sigor@sysoev.ru uc.uc_stack.ss_sp = fib->stack; 2870Sigor@sysoev.ru uc.uc_stack.ss_size = fib->stack_size; 2880Sigor@sysoev.ru 2890Sigor@sysoev.ru makecontext(&uc, (void (*)(void)) nxt_fiber_trampoline, 2, fib, parent); 2900Sigor@sysoev.ru 2910Sigor@sysoev.ru setcontext(&uc); 2920Sigor@sysoev.ru 2930Sigor@sysoev.ru #if !(NXT_SOLARIS) 2940Sigor@sysoev.ru /* Solaris declares setcontext() as __NORETURN. */ 2950Sigor@sysoev.ru 2961Sigor@sysoev.ru nxt_log(&fib->task, NXT_LOG_CRIT, "setcontext() failed"); 2970Sigor@sysoev.ru #endif 2980Sigor@sysoev.ru } 2990Sigor@sysoev.ru 3000Sigor@sysoev.ru 3010Sigor@sysoev.ru static void 3020Sigor@sysoev.ru nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent) 3030Sigor@sysoev.ru { 3041Sigor@sysoev.ru nxt_task_t *task; 3050Sigor@sysoev.ru 3061Sigor@sysoev.ru task = &fib->task; 3070Sigor@sysoev.ru 3080Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 3091Sigor@sysoev.ru nxt_debug(task, "fiber return to parent stack"); 3100Sigor@sysoev.ru 3111Sigor@sysoev.ru nxt_fiber_enqueue(task->thread, task, fib); 3121Sigor@sysoev.ru 3130Sigor@sysoev.ru _longjmp(*parent, 1); 3141Sigor@sysoev.ru 3150Sigor@sysoev.ru nxt_unreachable(); 3160Sigor@sysoev.ru } 3170Sigor@sysoev.ru 3181Sigor@sysoev.ru nxt_debug(task, "fiber start"); 3190Sigor@sysoev.ru 3200Sigor@sysoev.ru fib->start(fib->data); 3210Sigor@sysoev.ru 3221Sigor@sysoev.ru nxt_fiber_exit(task, &fib->main->fiber, NULL); 3231Sigor@sysoev.ru 3240Sigor@sysoev.ru nxt_unreachable(); 3250Sigor@sysoev.ru } 3260Sigor@sysoev.ru 3270Sigor@sysoev.ru #else 3280Sigor@sysoev.ru 3290Sigor@sysoev.ru #error No ucontext(3) interface. 3300Sigor@sysoev.ru 3310Sigor@sysoev.ru #endif 3320Sigor@sysoev.ru 3330Sigor@sysoev.ru 3340Sigor@sysoev.ru static void 3351Sigor@sysoev.ru nxt_fiber_switch_handler(nxt_task_t *task, void *obj, void *data) 3360Sigor@sysoev.ru { 3370Sigor@sysoev.ru nxt_fiber_t *fib; 3380Sigor@sysoev.ru 3390Sigor@sysoev.ru fib = obj; 3400Sigor@sysoev.ru 3411Sigor@sysoev.ru nxt_fiber_switch(task, fib); 3420Sigor@sysoev.ru nxt_unreachable(); 3430Sigor@sysoev.ru } 3440Sigor@sysoev.ru 3450Sigor@sysoev.ru 3460Sigor@sysoev.ru static void 3471Sigor@sysoev.ru nxt_fiber_switch(nxt_task_t *task, nxt_fiber_t *fib) 3480Sigor@sysoev.ru { 3491Sigor@sysoev.ru nxt_debug(task, "fiber switch: %PF", fib->fid); 3500Sigor@sysoev.ru 3511Sigor@sysoev.ru task->thread->fiber = fib; 3521Sigor@sysoev.ru 3530Sigor@sysoev.ru _longjmp(fib->jmp, 1); 3541Sigor@sysoev.ru 3550Sigor@sysoev.ru nxt_unreachable(); 3560Sigor@sysoev.ru } 3570Sigor@sysoev.ru 3580Sigor@sysoev.ru 3590Sigor@sysoev.ru nxt_fiber_t * 3600Sigor@sysoev.ru nxt_fiber_self(nxt_thread_t *thr) 3610Sigor@sysoev.ru { 3620Sigor@sysoev.ru return (nxt_fast_path(thr != NULL)) ? thr->fiber : NULL; 3630Sigor@sysoev.ru } 3640Sigor@sysoev.ru 3650Sigor@sysoev.ru 3660Sigor@sysoev.ru void 3671Sigor@sysoev.ru nxt_fiber_yield(nxt_task_t *task) 3680Sigor@sysoev.ru { 3691Sigor@sysoev.ru nxt_fiber_t *fib; 3700Sigor@sysoev.ru 3711Sigor@sysoev.ru fib = task->thread->fiber; 3720Sigor@sysoev.ru 3730Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 3740Sigor@sysoev.ru 3751Sigor@sysoev.ru nxt_debug(task, "fiber yield"); 3760Sigor@sysoev.ru 3771Sigor@sysoev.ru nxt_fiber_enqueue(task->thread, &fib->main->engine->task, fib); 3781Sigor@sysoev.ru 3791Sigor@sysoev.ru nxt_fiber_switch(task, &fib->main->fiber); 3801Sigor@sysoev.ru 3810Sigor@sysoev.ru nxt_unreachable(); 3820Sigor@sysoev.ru } 3830Sigor@sysoev.ru 3841Sigor@sysoev.ru nxt_debug(task, "fiber yield return"); 3850Sigor@sysoev.ru } 3860Sigor@sysoev.ru 3870Sigor@sysoev.ru 3880Sigor@sysoev.ru void 3891Sigor@sysoev.ru nxt_fiber_sleep(nxt_task_t *task, nxt_msec_t timeout) 3900Sigor@sysoev.ru { 3911Sigor@sysoev.ru nxt_fiber_t *fib; 3920Sigor@sysoev.ru 3931Sigor@sysoev.ru fib = task->thread->fiber; 3940Sigor@sysoev.ru 3954Sigor@sysoev.ru fib->timer.work_queue = &task->thread->engine->fast_work_queue; 3960Sigor@sysoev.ru fib->timer.handler = nxt_fiber_timer_handler; 3970Sigor@sysoev.ru fib->timer.log = &nxt_main_log; 3980Sigor@sysoev.ru 3991Sigor@sysoev.ru task = &fib->task; 4001Sigor@sysoev.ru 401*6Sigor@sysoev.ru nxt_timer_add(task->thread->engine, &fib->timer, timeout); 4020Sigor@sysoev.ru 4030Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 4040Sigor@sysoev.ru 4051Sigor@sysoev.ru nxt_debug(task, "fiber sleep: %T", timeout); 4060Sigor@sysoev.ru 4071Sigor@sysoev.ru nxt_fiber_switch(task, &fib->main->fiber); 4081Sigor@sysoev.ru 4090Sigor@sysoev.ru nxt_unreachable(); 4100Sigor@sysoev.ru } 4110Sigor@sysoev.ru 4121Sigor@sysoev.ru nxt_debug(task, "fiber sleep return"); 4130Sigor@sysoev.ru } 4140Sigor@sysoev.ru 4150Sigor@sysoev.ru 4160Sigor@sysoev.ru static void 4171Sigor@sysoev.ru nxt_fiber_timer_handler(nxt_task_t *task, void *obj, void *data) 4180Sigor@sysoev.ru { 419*6Sigor@sysoev.ru nxt_fiber_t *fib; 420*6Sigor@sysoev.ru nxt_timer_t *ev; 4210Sigor@sysoev.ru 4220Sigor@sysoev.ru ev = obj; 4230Sigor@sysoev.ru 4241Sigor@sysoev.ru nxt_debug(task, "fiber timer handler"); 4250Sigor@sysoev.ru 426*6Sigor@sysoev.ru fib = nxt_timer_data(ev, nxt_fiber_t, timer); 4270Sigor@sysoev.ru 4281Sigor@sysoev.ru nxt_fiber_switch(task, fib); 4291Sigor@sysoev.ru 4300Sigor@sysoev.ru nxt_unreachable(); 4310Sigor@sysoev.ru } 4320Sigor@sysoev.ru 4330Sigor@sysoev.ru 4340Sigor@sysoev.ru void 4351Sigor@sysoev.ru nxt_fiber_wait(nxt_task_t *task) 4360Sigor@sysoev.ru { 4371Sigor@sysoev.ru nxt_fiber_t *fib; 4380Sigor@sysoev.ru 4391Sigor@sysoev.ru fib = task->thread->fiber; 4400Sigor@sysoev.ru 4410Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 4421Sigor@sysoev.ru nxt_debug(task, "fiber wait"); 4430Sigor@sysoev.ru 4441Sigor@sysoev.ru nxt_fiber_switch(task, &fib->main->fiber); 4451Sigor@sysoev.ru 4460Sigor@sysoev.ru nxt_unreachable(); 4470Sigor@sysoev.ru } 4480Sigor@sysoev.ru 4491Sigor@sysoev.ru nxt_debug(task, "fiber wait return"); 4500Sigor@sysoev.ru } 4510Sigor@sysoev.ru 4520Sigor@sysoev.ru 4530Sigor@sysoev.ru void 4541Sigor@sysoev.ru nxt_fiber_exit(nxt_task_t *task, nxt_fiber_t *next, void *data) 4550Sigor@sysoev.ru { 4561Sigor@sysoev.ru nxt_fiber_t *fib; 4570Sigor@sysoev.ru 4581Sigor@sysoev.ru fib = task->thread->fiber; 4590Sigor@sysoev.ru 4601Sigor@sysoev.ru nxt_debug(task, "fiber exit"); 4610Sigor@sysoev.ru 4620Sigor@sysoev.ru /* TODO: limit idle fibers. */ 4630Sigor@sysoev.ru fib->next = fib->main->idle; 4640Sigor@sysoev.ru fib->main->idle = fib; 4650Sigor@sysoev.ru 4661Sigor@sysoev.ru nxt_fiber_switch(task, next); 4671Sigor@sysoev.ru 4680Sigor@sysoev.ru nxt_unreachable(); 4690Sigor@sysoev.ru } 470