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 * 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 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 * 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 * 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 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 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 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 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 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 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 * 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 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 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 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 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 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