1*0Sigor@sysoev.ru 2*0Sigor@sysoev.ru /* 3*0Sigor@sysoev.ru * Copyright (C) Igor Sysoev 4*0Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 5*0Sigor@sysoev.ru */ 6*0Sigor@sysoev.ru 7*0Sigor@sysoev.ru #include <nxt_main.h> 8*0Sigor@sysoev.ru 9*0Sigor@sysoev.ru 10*0Sigor@sysoev.ru static char *nxt_fiber_create_stack(nxt_fiber_t *fib); 11*0Sigor@sysoev.ru static void nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent); 12*0Sigor@sysoev.ru static void nxt_fiber_switch_handler(nxt_thread_t *thr, void *obj, 13*0Sigor@sysoev.ru void *data); 14*0Sigor@sysoev.ru static void nxt_fiber_switch(nxt_thread_t *thr, nxt_fiber_t *fib); 15*0Sigor@sysoev.ru static void nxt_fiber_timer_handler(nxt_thread_t *thr, void *obj, 16*0Sigor@sysoev.ru void *data); 17*0Sigor@sysoev.ru 18*0Sigor@sysoev.ru 19*0Sigor@sysoev.ru #define \ 20*0Sigor@sysoev.ru nxt_fiber_enqueue(thr, fib) \ 21*0Sigor@sysoev.ru nxt_thread_work_queue_add(thr, &(thr)->work_queue.main, \ 22*0Sigor@sysoev.ru nxt_fiber_switch_handler, fib, NULL, thr->log) 23*0Sigor@sysoev.ru 24*0Sigor@sysoev.ru 25*0Sigor@sysoev.ru nxt_fiber_main_t * 26*0Sigor@sysoev.ru nxt_fiber_main_create(nxt_event_engine_t *engine) 27*0Sigor@sysoev.ru { 28*0Sigor@sysoev.ru nxt_fiber_main_t *fm; 29*0Sigor@sysoev.ru 30*0Sigor@sysoev.ru fm = nxt_zalloc(sizeof(nxt_fiber_main_t)); 31*0Sigor@sysoev.ru if (nxt_slow_path(fm == NULL)) { 32*0Sigor@sysoev.ru return NULL; 33*0Sigor@sysoev.ru } 34*0Sigor@sysoev.ru 35*0Sigor@sysoev.ru fm->stack_size = 512 * 1024 - nxt_pagesize; 36*0Sigor@sysoev.ru fm->idle = NULL; 37*0Sigor@sysoev.ru 38*0Sigor@sysoev.ru return fm; 39*0Sigor@sysoev.ru } 40*0Sigor@sysoev.ru 41*0Sigor@sysoev.ru 42*0Sigor@sysoev.ru nxt_int_t 43*0Sigor@sysoev.ru nxt_fiber_create(nxt_fiber_start_t start, void *data, size_t stack) 44*0Sigor@sysoev.ru { 45*0Sigor@sysoev.ru int ret; 46*0Sigor@sysoev.ru jmp_buf parent; 47*0Sigor@sysoev.ru nxt_fid_t fid; 48*0Sigor@sysoev.ru nxt_fiber_t *fib; 49*0Sigor@sysoev.ru nxt_thread_t *thr; 50*0Sigor@sysoev.ru nxt_fiber_main_t *fm; 51*0Sigor@sysoev.ru 52*0Sigor@sysoev.ru thr = nxt_thread(); 53*0Sigor@sysoev.ru fm = thr->engine->fibers; 54*0Sigor@sysoev.ru 55*0Sigor@sysoev.ru fid = ++fm->fid; 56*0Sigor@sysoev.ru 57*0Sigor@sysoev.ru if (fid == 0) { 58*0Sigor@sysoev.ru fid = ++fm->fid; 59*0Sigor@sysoev.ru } 60*0Sigor@sysoev.ru 61*0Sigor@sysoev.ru fib = fm->idle; 62*0Sigor@sysoev.ru 63*0Sigor@sysoev.ru if (fib != NULL) { 64*0Sigor@sysoev.ru fm->idle = fib->next; 65*0Sigor@sysoev.ru fib->fid = fid; 66*0Sigor@sysoev.ru fib->start = start; 67*0Sigor@sysoev.ru fib->data = data; 68*0Sigor@sysoev.ru fib->main = fm; 69*0Sigor@sysoev.ru 70*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber create cached: %PF", fib->fid); 71*0Sigor@sysoev.ru nxt_fiber_enqueue(thr, fib); 72*0Sigor@sysoev.ru return NXT_OK; 73*0Sigor@sysoev.ru } 74*0Sigor@sysoev.ru 75*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber create"); 76*0Sigor@sysoev.ru 77*0Sigor@sysoev.ru fib = nxt_malloc(sizeof(nxt_fiber_t)); 78*0Sigor@sysoev.ru if (nxt_slow_path(fib == NULL)) { 79*0Sigor@sysoev.ru return NXT_ERROR; 80*0Sigor@sysoev.ru } 81*0Sigor@sysoev.ru 82*0Sigor@sysoev.ru fib->fid = fid; 83*0Sigor@sysoev.ru fib->start = start; 84*0Sigor@sysoev.ru fib->data = data; 85*0Sigor@sysoev.ru fib->stack_size = fm->stack_size; 86*0Sigor@sysoev.ru fib->main = fm; 87*0Sigor@sysoev.ru 88*0Sigor@sysoev.ru fib->stack = nxt_fiber_create_stack(fib); 89*0Sigor@sysoev.ru 90*0Sigor@sysoev.ru if (nxt_fast_path(fib->stack != NULL)) { 91*0Sigor@sysoev.ru 92*0Sigor@sysoev.ru if (_setjmp(parent) != 0) { 93*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber create: %PF", fib->fid); 94*0Sigor@sysoev.ru return NXT_OK; 95*0Sigor@sysoev.ru } 96*0Sigor@sysoev.ru 97*0Sigor@sysoev.ru nxt_fiber_switch_stack(fib, &parent); 98*0Sigor@sysoev.ru /* It does not return if the switch was successful. */ 99*0Sigor@sysoev.ru } 100*0Sigor@sysoev.ru 101*0Sigor@sysoev.ru ret = munmap(fib->stack - nxt_pagesize, fib->stack_size + nxt_pagesize); 102*0Sigor@sysoev.ru 103*0Sigor@sysoev.ru if (nxt_slow_path(ret != 0)) { 104*0Sigor@sysoev.ru nxt_log_alert(thr->log, "munmap() failed %E", nxt_errno); 105*0Sigor@sysoev.ru } 106*0Sigor@sysoev.ru 107*0Sigor@sysoev.ru nxt_free(fib); 108*0Sigor@sysoev.ru 109*0Sigor@sysoev.ru return NXT_ERROR; 110*0Sigor@sysoev.ru } 111*0Sigor@sysoev.ru 112*0Sigor@sysoev.ru 113*0Sigor@sysoev.ru #if (NXT_LINUX) 114*0Sigor@sysoev.ru 115*0Sigor@sysoev.ru static char * 116*0Sigor@sysoev.ru nxt_fiber_create_stack(nxt_fiber_t *fib) 117*0Sigor@sysoev.ru { 118*0Sigor@sysoev.ru char *s; 119*0Sigor@sysoev.ru size_t size; 120*0Sigor@sysoev.ru 121*0Sigor@sysoev.ru size = fib->stack_size + nxt_pagesize; 122*0Sigor@sysoev.ru 123*0Sigor@sysoev.ru s = mmap(NULL, size, PROT_READ | PROT_WRITE, 124*0Sigor@sysoev.ru MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, -1, 0); 125*0Sigor@sysoev.ru 126*0Sigor@sysoev.ru if (nxt_slow_path(s == MAP_FAILED)) { 127*0Sigor@sysoev.ru nxt_thread_log_alert("fiber stack " 128*0Sigor@sysoev.ru "mmap(%uz, MAP_PRIVATE|MAP_ANON|MAP_GROWSDOWN) failed %E", 129*0Sigor@sysoev.ru size, nxt_errno); 130*0Sigor@sysoev.ru return NULL; 131*0Sigor@sysoev.ru } 132*0Sigor@sysoev.ru 133*0Sigor@sysoev.ru if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) { 134*0Sigor@sysoev.ru nxt_thread_log_alert("fiber stack mprotect(%uz, PROT_NONE) failed %E", 135*0Sigor@sysoev.ru size, nxt_errno); 136*0Sigor@sysoev.ru return NULL; 137*0Sigor@sysoev.ru } 138*0Sigor@sysoev.ru 139*0Sigor@sysoev.ru s += nxt_pagesize; 140*0Sigor@sysoev.ru 141*0Sigor@sysoev.ru nxt_thread_log_debug("fiber stack mmap: %p", s); 142*0Sigor@sysoev.ru 143*0Sigor@sysoev.ru return s; 144*0Sigor@sysoev.ru } 145*0Sigor@sysoev.ru 146*0Sigor@sysoev.ru #else /* Generic version. */ 147*0Sigor@sysoev.ru 148*0Sigor@sysoev.ru static char * 149*0Sigor@sysoev.ru nxt_fiber_create_stack(nxt_fiber_t *fib) 150*0Sigor@sysoev.ru { 151*0Sigor@sysoev.ru char *s; 152*0Sigor@sysoev.ru size_t size; 153*0Sigor@sysoev.ru 154*0Sigor@sysoev.ru size = fib->stack_size + nxt_pagesize; 155*0Sigor@sysoev.ru 156*0Sigor@sysoev.ru s = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); 157*0Sigor@sysoev.ru 158*0Sigor@sysoev.ru if (nxt_slow_path(s == MAP_FAILED)) { 159*0Sigor@sysoev.ru nxt_thread_log_alert("fiber stack " 160*0Sigor@sysoev.ru "mmap(%uz, MAP_PRIVATE|MAP_ANON) failed %E", 161*0Sigor@sysoev.ru size, nxt_errno); 162*0Sigor@sysoev.ru return NULL; 163*0Sigor@sysoev.ru } 164*0Sigor@sysoev.ru 165*0Sigor@sysoev.ru if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) { 166*0Sigor@sysoev.ru nxt_thread_log_alert("fiber stack mprotect(%uz, PROT_NONE) failed %E", 167*0Sigor@sysoev.ru size, nxt_errno); 168*0Sigor@sysoev.ru return NULL; 169*0Sigor@sysoev.ru } 170*0Sigor@sysoev.ru 171*0Sigor@sysoev.ru s += nxt_pagesize; 172*0Sigor@sysoev.ru 173*0Sigor@sysoev.ru nxt_thread_log_debug("fiber stack mmap: %p", s); 174*0Sigor@sysoev.ru 175*0Sigor@sysoev.ru return s; 176*0Sigor@sysoev.ru } 177*0Sigor@sysoev.ru 178*0Sigor@sysoev.ru #endif 179*0Sigor@sysoev.ru 180*0Sigor@sysoev.ru 181*0Sigor@sysoev.ru #if (NXT_LINUX && NXT_64BIT) 182*0Sigor@sysoev.ru 183*0Sigor@sysoev.ru /* 184*0Sigor@sysoev.ru * Linux 64-bit ucontext version. 64-bit glibc makecontext() passes 185*0Sigor@sysoev.ru * pointers as signed int's. The bug has been fixed in glibc 2.8. 186*0Sigor@sysoev.ru */ 187*0Sigor@sysoev.ru 188*0Sigor@sysoev.ru static void nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph, 189*0Sigor@sysoev.ru uint32_t pl); 190*0Sigor@sysoev.ru 191*0Sigor@sysoev.ru 192*0Sigor@sysoev.ru static void 193*0Sigor@sysoev.ru nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent) 194*0Sigor@sysoev.ru { 195*0Sigor@sysoev.ru ucontext_t uc; 196*0Sigor@sysoev.ru 197*0Sigor@sysoev.ru nxt_thread_log_debug("fiber switch to stack: %p", fib->stack); 198*0Sigor@sysoev.ru 199*0Sigor@sysoev.ru if (nxt_slow_path(getcontext(&uc) != 0)) { 200*0Sigor@sysoev.ru nxt_thread_log_alert("getcontext() failed"); 201*0Sigor@sysoev.ru return; 202*0Sigor@sysoev.ru } 203*0Sigor@sysoev.ru 204*0Sigor@sysoev.ru uc.uc_link = NULL; 205*0Sigor@sysoev.ru uc.uc_stack.ss_sp = fib->stack; 206*0Sigor@sysoev.ru uc.uc_stack.ss_size = fib->stack_size; 207*0Sigor@sysoev.ru 208*0Sigor@sysoev.ru makecontext(&uc, (void (*)(void)) nxt_fiber_trampoline, 4, 209*0Sigor@sysoev.ru (uint32_t) ((uintptr_t) fib >> 32), 210*0Sigor@sysoev.ru (uint32_t) ((uintptr_t) fib & 0xffffffff), 211*0Sigor@sysoev.ru (uint32_t) ((uintptr_t) parent >> 32), 212*0Sigor@sysoev.ru (uint32_t) ((uintptr_t) parent & 0xffffffff)); 213*0Sigor@sysoev.ru 214*0Sigor@sysoev.ru setcontext(&uc); 215*0Sigor@sysoev.ru 216*0Sigor@sysoev.ru nxt_thread_log_alert("setcontext() failed"); 217*0Sigor@sysoev.ru } 218*0Sigor@sysoev.ru 219*0Sigor@sysoev.ru 220*0Sigor@sysoev.ru static void 221*0Sigor@sysoev.ru nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph, uint32_t pl) 222*0Sigor@sysoev.ru { 223*0Sigor@sysoev.ru jmp_buf *parent; 224*0Sigor@sysoev.ru nxt_fiber_t *fib; 225*0Sigor@sysoev.ru nxt_thread_t *thr; 226*0Sigor@sysoev.ru 227*0Sigor@sysoev.ru fib = (nxt_fiber_t *) (((uintptr_t) fh << 32) + fl); 228*0Sigor@sysoev.ru parent = (jmp_buf *) (((uintptr_t) ph << 32) + pl); 229*0Sigor@sysoev.ru 230*0Sigor@sysoev.ru thr = nxt_thread(); 231*0Sigor@sysoev.ru 232*0Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 233*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber return to parent stack"); 234*0Sigor@sysoev.ru 235*0Sigor@sysoev.ru nxt_fiber_enqueue(thr, fib); 236*0Sigor@sysoev.ru _longjmp(*parent, 1); 237*0Sigor@sysoev.ru nxt_unreachable(); 238*0Sigor@sysoev.ru } 239*0Sigor@sysoev.ru 240*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber start"); 241*0Sigor@sysoev.ru 242*0Sigor@sysoev.ru fib->start(fib->data); 243*0Sigor@sysoev.ru 244*0Sigor@sysoev.ru nxt_fiber_exit(&fib->main->fiber, NULL); 245*0Sigor@sysoev.ru nxt_unreachable(); 246*0Sigor@sysoev.ru } 247*0Sigor@sysoev.ru 248*0Sigor@sysoev.ru #elif (NXT_HAVE_UCONTEXT) 249*0Sigor@sysoev.ru 250*0Sigor@sysoev.ru /* Generic ucontext version. */ 251*0Sigor@sysoev.ru 252*0Sigor@sysoev.ru static void nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent); 253*0Sigor@sysoev.ru 254*0Sigor@sysoev.ru 255*0Sigor@sysoev.ru static void 256*0Sigor@sysoev.ru nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent) 257*0Sigor@sysoev.ru { 258*0Sigor@sysoev.ru ucontext_t uc; 259*0Sigor@sysoev.ru 260*0Sigor@sysoev.ru nxt_thread_log_debug("fiber switch to stack: %p", fib->stack); 261*0Sigor@sysoev.ru 262*0Sigor@sysoev.ru if (nxt_slow_path(getcontext(&uc) != 0)) { 263*0Sigor@sysoev.ru nxt_thread_log_alert("getcontext() failed"); 264*0Sigor@sysoev.ru return; 265*0Sigor@sysoev.ru } 266*0Sigor@sysoev.ru 267*0Sigor@sysoev.ru uc.uc_link = NULL; 268*0Sigor@sysoev.ru uc.uc_stack.ss_sp = fib->stack; 269*0Sigor@sysoev.ru uc.uc_stack.ss_size = fib->stack_size; 270*0Sigor@sysoev.ru 271*0Sigor@sysoev.ru makecontext(&uc, (void (*)(void)) nxt_fiber_trampoline, 2, fib, parent); 272*0Sigor@sysoev.ru 273*0Sigor@sysoev.ru setcontext(&uc); 274*0Sigor@sysoev.ru 275*0Sigor@sysoev.ru #if !(NXT_SOLARIS) 276*0Sigor@sysoev.ru /* Solaris declares setcontext() as __NORETURN. */ 277*0Sigor@sysoev.ru 278*0Sigor@sysoev.ru nxt_thread_log_alert("setcontext() failed"); 279*0Sigor@sysoev.ru #endif 280*0Sigor@sysoev.ru } 281*0Sigor@sysoev.ru 282*0Sigor@sysoev.ru 283*0Sigor@sysoev.ru static void 284*0Sigor@sysoev.ru nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent) 285*0Sigor@sysoev.ru { 286*0Sigor@sysoev.ru nxt_thread_t *thr; 287*0Sigor@sysoev.ru 288*0Sigor@sysoev.ru thr = nxt_thread(); 289*0Sigor@sysoev.ru 290*0Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 291*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber return to parent stack"); 292*0Sigor@sysoev.ru 293*0Sigor@sysoev.ru nxt_fiber_enqueue(thr, fib); 294*0Sigor@sysoev.ru _longjmp(*parent, 1); 295*0Sigor@sysoev.ru nxt_unreachable(); 296*0Sigor@sysoev.ru } 297*0Sigor@sysoev.ru 298*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber start"); 299*0Sigor@sysoev.ru 300*0Sigor@sysoev.ru fib->start(fib->data); 301*0Sigor@sysoev.ru 302*0Sigor@sysoev.ru nxt_fiber_exit(&fib->main->fiber, NULL); 303*0Sigor@sysoev.ru nxt_unreachable(); 304*0Sigor@sysoev.ru } 305*0Sigor@sysoev.ru 306*0Sigor@sysoev.ru #else 307*0Sigor@sysoev.ru 308*0Sigor@sysoev.ru #error No ucontext(3) interface. 309*0Sigor@sysoev.ru 310*0Sigor@sysoev.ru #endif 311*0Sigor@sysoev.ru 312*0Sigor@sysoev.ru 313*0Sigor@sysoev.ru static void 314*0Sigor@sysoev.ru nxt_fiber_switch_handler(nxt_thread_t *thr, void *obj, void *data) 315*0Sigor@sysoev.ru { 316*0Sigor@sysoev.ru nxt_fiber_t *fib; 317*0Sigor@sysoev.ru 318*0Sigor@sysoev.ru fib = obj; 319*0Sigor@sysoev.ru 320*0Sigor@sysoev.ru nxt_fiber_switch(thr, fib); 321*0Sigor@sysoev.ru nxt_unreachable(); 322*0Sigor@sysoev.ru } 323*0Sigor@sysoev.ru 324*0Sigor@sysoev.ru 325*0Sigor@sysoev.ru static void 326*0Sigor@sysoev.ru nxt_fiber_switch(nxt_thread_t *thr, nxt_fiber_t *fib) 327*0Sigor@sysoev.ru { 328*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber switch: %PF", fib->fid); 329*0Sigor@sysoev.ru 330*0Sigor@sysoev.ru thr->fiber = fib; 331*0Sigor@sysoev.ru _longjmp(fib->jmp, 1); 332*0Sigor@sysoev.ru nxt_unreachable(); 333*0Sigor@sysoev.ru } 334*0Sigor@sysoev.ru 335*0Sigor@sysoev.ru 336*0Sigor@sysoev.ru nxt_fiber_t * 337*0Sigor@sysoev.ru nxt_fiber_self(nxt_thread_t *thr) 338*0Sigor@sysoev.ru { 339*0Sigor@sysoev.ru return (nxt_fast_path(thr != NULL)) ? thr->fiber : NULL; 340*0Sigor@sysoev.ru } 341*0Sigor@sysoev.ru 342*0Sigor@sysoev.ru 343*0Sigor@sysoev.ru void 344*0Sigor@sysoev.ru nxt_fiber_yield(void) 345*0Sigor@sysoev.ru { 346*0Sigor@sysoev.ru nxt_fiber_t *fib; 347*0Sigor@sysoev.ru nxt_thread_t *thr; 348*0Sigor@sysoev.ru 349*0Sigor@sysoev.ru thr = nxt_thread(); 350*0Sigor@sysoev.ru fib = thr->fiber; 351*0Sigor@sysoev.ru 352*0Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 353*0Sigor@sysoev.ru 354*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber yield"); 355*0Sigor@sysoev.ru 356*0Sigor@sysoev.ru nxt_fiber_enqueue(thr, fib); 357*0Sigor@sysoev.ru nxt_fiber_switch(thr, &fib->main->fiber); 358*0Sigor@sysoev.ru nxt_unreachable(); 359*0Sigor@sysoev.ru } 360*0Sigor@sysoev.ru 361*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber yield return"); 362*0Sigor@sysoev.ru } 363*0Sigor@sysoev.ru 364*0Sigor@sysoev.ru 365*0Sigor@sysoev.ru void 366*0Sigor@sysoev.ru nxt_fiber_sleep(nxt_msec_t timeout) 367*0Sigor@sysoev.ru { 368*0Sigor@sysoev.ru nxt_fiber_t *fib; 369*0Sigor@sysoev.ru nxt_thread_t *thr; 370*0Sigor@sysoev.ru 371*0Sigor@sysoev.ru thr = nxt_thread(); 372*0Sigor@sysoev.ru fib = thr->fiber; 373*0Sigor@sysoev.ru 374*0Sigor@sysoev.ru fib->timer.work_queue = &thr->work_queue.main; 375*0Sigor@sysoev.ru fib->timer.handler = nxt_fiber_timer_handler; 376*0Sigor@sysoev.ru fib->timer.log = &nxt_main_log; 377*0Sigor@sysoev.ru 378*0Sigor@sysoev.ru nxt_event_timer_add(thr->engine, &fib->timer, timeout); 379*0Sigor@sysoev.ru 380*0Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 381*0Sigor@sysoev.ru 382*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber sleep: %T", timeout); 383*0Sigor@sysoev.ru 384*0Sigor@sysoev.ru nxt_fiber_switch(thr, &fib->main->fiber); 385*0Sigor@sysoev.ru nxt_unreachable(); 386*0Sigor@sysoev.ru } 387*0Sigor@sysoev.ru 388*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber sleep return"); 389*0Sigor@sysoev.ru } 390*0Sigor@sysoev.ru 391*0Sigor@sysoev.ru 392*0Sigor@sysoev.ru static void 393*0Sigor@sysoev.ru nxt_fiber_timer_handler(nxt_thread_t *thr, void *obj, void *data) 394*0Sigor@sysoev.ru { 395*0Sigor@sysoev.ru nxt_fiber_t *fib; 396*0Sigor@sysoev.ru nxt_event_timer_t *ev; 397*0Sigor@sysoev.ru 398*0Sigor@sysoev.ru ev = obj; 399*0Sigor@sysoev.ru 400*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber timer handler"); 401*0Sigor@sysoev.ru 402*0Sigor@sysoev.ru fib = nxt_event_timer_data(ev, nxt_fiber_t, timer); 403*0Sigor@sysoev.ru 404*0Sigor@sysoev.ru nxt_fiber_switch(thr, fib); 405*0Sigor@sysoev.ru nxt_unreachable(); 406*0Sigor@sysoev.ru } 407*0Sigor@sysoev.ru 408*0Sigor@sysoev.ru 409*0Sigor@sysoev.ru void 410*0Sigor@sysoev.ru nxt_fiber_wait(void) 411*0Sigor@sysoev.ru { 412*0Sigor@sysoev.ru nxt_fiber_t *fib; 413*0Sigor@sysoev.ru nxt_thread_t *thr; 414*0Sigor@sysoev.ru 415*0Sigor@sysoev.ru thr = nxt_thread(); 416*0Sigor@sysoev.ru fib = thr->fiber; 417*0Sigor@sysoev.ru 418*0Sigor@sysoev.ru if (_setjmp(fib->jmp) == 0) { 419*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber wait"); 420*0Sigor@sysoev.ru 421*0Sigor@sysoev.ru nxt_fiber_switch(thr, &fib->main->fiber); 422*0Sigor@sysoev.ru nxt_unreachable(); 423*0Sigor@sysoev.ru } 424*0Sigor@sysoev.ru 425*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber wait return"); 426*0Sigor@sysoev.ru } 427*0Sigor@sysoev.ru 428*0Sigor@sysoev.ru 429*0Sigor@sysoev.ru void 430*0Sigor@sysoev.ru nxt_fiber_exit(nxt_fiber_t *next, void *data) 431*0Sigor@sysoev.ru { 432*0Sigor@sysoev.ru nxt_fiber_t *fib; 433*0Sigor@sysoev.ru nxt_thread_t *thr; 434*0Sigor@sysoev.ru 435*0Sigor@sysoev.ru thr = nxt_thread(); 436*0Sigor@sysoev.ru fib = thr->fiber; 437*0Sigor@sysoev.ru 438*0Sigor@sysoev.ru nxt_log_debug(thr->log, "fiber exit"); 439*0Sigor@sysoev.ru 440*0Sigor@sysoev.ru /* TODO: limit idle fibers. */ 441*0Sigor@sysoev.ru fib->next = fib->main->idle; 442*0Sigor@sysoev.ru fib->main->idle = fib; 443*0Sigor@sysoev.ru 444*0Sigor@sysoev.ru nxt_fiber_switch(thr, next); 445*0Sigor@sysoev.ru nxt_unreachable(); 446*0Sigor@sysoev.ru } 447