ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libcoro/coro.c
(Generate patch)

Comparing libcoro/coro.c (file contents):
Revision 1.66 by root, Fri Dec 7 14:21:09 2012 UTC vs.
Revision 1.73 by root, Tue Aug 14 15:46:03 2018 UTC

88 volatile void *arg = coro_init_arg; 88 volatile void *arg = coro_init_arg;
89 89
90 coro_transfer (new_coro, create_coro); 90 coro_transfer (new_coro, create_coro);
91 91
92#if __GCC_HAVE_DWARF2_CFI_ASM && __amd64 92#if __GCC_HAVE_DWARF2_CFI_ASM && __amd64
93 /*asm (".cfi_startproc");*/
93 asm (".cfi_undefined rip"); 94 /*asm (".cfi_undefined rip");*/
94#endif 95#endif
95 96
96 func ((void *)arg); 97 func ((void *)arg);
98
99#if __GCC_HAVE_DWARF2_CFI_ASM && __amd64
100 /*asm (".cfi_endproc");*/
101#endif
97 102
98 /* the new coro returned. bad. just abort() for now */ 103 /* the new coro returned. bad. just abort() for now */
99 abort (); 104 abort ();
100} 105}
101 106
114} 119}
115 120
116# endif 121# endif
117 122
118# if CORO_ASM 123# if CORO_ASM
124
125 #if __arm__ && \
126 (defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \
127 || defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__ \
128 || __ARM_ARCH == 7)
129 #define CORO_ARM 1
130 #endif
119 131
120 #if _WIN32 || __CYGWIN__ 132 #if _WIN32 || __CYGWIN__
121 #define CORO_WIN_TIB 1 133 #define CORO_WIN_TIB 1
122 #endif 134 #endif
123 135
204 "\tpopq %rbp\n" 216 "\tpopq %rbp\n"
205 #endif 217 #endif
206 "\tpopq %rcx\n" 218 "\tpopq %rcx\n"
207 "\tjmpq *%rcx\n" 219 "\tjmpq *%rcx\n"
208 220
209 #elif __i386 221 #elif __i386__
210 222
211 #define NUM_SAVED 4 223 #define NUM_SAVED 4
212 "\tpushl %ebp\n" 224 "\tpushl %ebp\n"
213 "\tpushl %ebx\n" 225 "\tpushl %ebx\n"
214 "\tpushl %esi\n" 226 "\tpushl %esi\n"
232 "\tpopl %ebx\n" 244 "\tpopl %ebx\n"
233 "\tpopl %ebp\n" 245 "\tpopl %ebp\n"
234 "\tpopl %ecx\n" 246 "\tpopl %ecx\n"
235 "\tjmpl *%ecx\n" 247 "\tjmpl *%ecx\n"
236 248
249 #elif CORO_ARM /* untested, what about thumb, neon, iwmmxt? */
250
251 #if __ARM_PCS_VFP
252 "\tvpush {d8-d15}\n"
253 #define NUM_SAVED (9 + 8 * 2)
254 #else
255 #define NUM_SAVED 9
256 #endif
257 "\tpush {r4-r11,lr}\n"
258 "\tstr sp, [r0]\n"
259 "\tldr sp, [r1]\n"
260 "\tpop {r4-r11,lr}\n"
261 #if __ARM_PCS_VFP
262 "\tvpop {d8-d15}\n"
263 #endif
264 "\tmov r15, lr\n"
265
266 #elif __mips__ && 0 /* untested, 32 bit only */
267
268 #define NUM_SAVED (12 + 8 * 2)
269 /* TODO: n64/o64, lw=>ld */
270
271 "\t.set nomips16\n"
272 "\t.frame $sp,112,$31\n"
273 #if __mips_soft_float
274 "\taddiu $sp,$sp,-44\n"
275 #else
276 "\taddiu $sp,$sp,-112\n"
277 "\ts.d $f30,88($sp)\n"
278 "\ts.d $f28,80($sp)\n"
279 "\ts.d $f26,72($sp)\n"
280 "\ts.d $f24,64($sp)\n"
281 "\ts.d $f22,56($sp)\n"
282 "\ts.d $f20,48($sp)\n"
283 #endif
284 "\tsw $28,40($sp)\n"
285 "\tsw $31,36($sp)\n"
286 "\tsw $fp,32($sp)\n"
287 "\tsw $23,28($sp)\n"
288 "\tsw $22,24($sp)\n"
289 "\tsw $21,20($sp)\n"
290 "\tsw $20,16($sp)\n"
291 "\tsw $19,12($sp)\n"
292 "\tsw $18,8($sp)\n"
293 "\tsw $17,4($sp)\n"
294 "\tsw $16,0($sp)\n"
295 "\tsw $sp,0($4)\n"
296 "\tlw $sp,0($5)\n"
297 #if !__mips_soft_float
298 "\tl.d $f30,88($sp)\n"
299 "\tl.d $f28,80($sp)\n"
300 "\tl.d $f26,72($sp)\n"
301 "\tl.d $f24,64($sp)\n"
302 "\tl.d $f22,56($sp)\n"
303 "\tl.d $f20,48($sp)\n"
304 #endif
305 "\tlw $28,40($sp)\n"
306 "\tlw $31,36($sp)\n"
307 "\tlw $fp,32($sp)\n"
308 "\tlw $23,28($sp)\n"
309 "\tlw $22,24($sp)\n"
310 "\tlw $21,20($sp)\n"
311 "\tlw $20,16($sp)\n"
312 "\tlw $19,12($sp)\n"
313 "\tlw $18,8($sp)\n"
314 "\tlw $17,4($sp)\n"
315 "\tlw $16,0($sp)\n"
316 "\tj $31\n"
317 #if __mips_soft_float
318 "\taddiu $sp,$sp,44\n"
319 #else
320 "\taddiu $sp,$sp,112\n"
321 #endif
322
237 #else 323 #else
238 #error unsupported architecture 324 #error unsupported architecture
239 #endif 325 #endif
240 ); 326 );
241 327
311 sigprocmask (SIG_SETMASK, &osig, 0); 397 sigprocmask (SIG_SETMASK, &osig, 0);
312 398
313# elif CORO_LOSER 399# elif CORO_LOSER
314 400
315 coro_setjmp (ctx->env); 401 coro_setjmp (ctx->env);
316 #if __CYGWIN__ && __i386 402 #if __CYGWIN__ && __i386__
317 ctx->env[8] = (long) coro_init; 403 ctx->env[8] = (long) coro_init;
318 ctx->env[7] = (long) ((char *)sptr + ssize) - sizeof (long); 404 ctx->env[7] = (long) ((char *)sptr + ssize) - sizeof (long);
319 #elif __CYGWIN__ && __x86_64 405 #elif __CYGWIN__ && __x86_64__
320 ctx->env[7] = (long) coro_init; 406 ctx->env[7] = (long) coro_init;
321 ctx->env[6] = (long) ((char *)sptr + ssize) - sizeof (long); 407 ctx->env[6] = (long) ((char *)sptr + ssize) - sizeof (long);
322 #elif defined __MINGW32__ 408 #elif defined __MINGW32__
323 ctx->env[5] = (long) coro_init; 409 ctx->env[5] = (long) coro_init;
324 ctx->env[4] = (long) ((char *)sptr + ssize) - sizeof (long); 410 ctx->env[4] = (long) ((char *)sptr + ssize) - sizeof (long);
345 ctx->env[0].__jmpbuf[0].__aregs[0] = (long int)coro_init; 431 ctx->env[0].__jmpbuf[0].__aregs[0] = (long int)coro_init;
346 ctx->env[0].__jmpbuf[0].__sp = (int *) ((char *)sptr + ssize) - sizeof (long); 432 ctx->env[0].__jmpbuf[0].__sp = (int *) ((char *)sptr + ssize) - sizeof (long);
347 #elif defined (__GNU_LIBRARY__) && defined (__i386__) 433 #elif defined (__GNU_LIBRARY__) && defined (__i386__)
348 ctx->env[0].__jmpbuf[0].__pc = (char *) coro_init; 434 ctx->env[0].__jmpbuf[0].__pc = (char *) coro_init;
349 ctx->env[0].__jmpbuf[0].__sp = (void *) ((char *)sptr + ssize) - sizeof (long); 435 ctx->env[0].__jmpbuf[0].__sp = (void *) ((char *)sptr + ssize) - sizeof (long);
350 #elif defined (__GNU_LIBRARY__) && defined (__amd64__) 436 #elif defined (__GNU_LIBRARY__) && defined (__x86_64__)
351 ctx->env[0].__jmpbuf[JB_PC] = (long) coro_init; 437 ctx->env[0].__jmpbuf[JB_PC] = (long) coro_init;
352 ctx->env[0].__jmpbuf[0].__sp = (void *) ((char *)sptr + ssize) - sizeof (long); 438 ctx->env[0].__jmpbuf[0].__sp = (void *) ((char *)sptr + ssize) - sizeof (long);
353 #else 439 #else
354 #error "linux libc or architecture not supported" 440 #error "linux libc or architecture not supported"
355 #endif 441 #endif
360 ctx->env[JB_PC] = (__uint64_t)coro_init; 446 ctx->env[JB_PC] = (__uint64_t)coro_init;
361 ctx->env[JB_SP] = (__uint64_t)STACK_ADJUST_PTR (sptr, ssize) - sizeof (long); 447 ctx->env[JB_SP] = (__uint64_t)STACK_ADJUST_PTR (sptr, ssize) - sizeof (long);
362 448
363# elif CORO_ASM 449# elif CORO_ASM
364 450
451 #if __i386__ || __x86_64__
365 ctx->sp = (void **)(ssize + (char *)sptr); 452 ctx->sp = (void **)(ssize + (char *)sptr);
366 *--ctx->sp = (void *)abort; /* needed for alignment only */ 453 *--ctx->sp = (void *)abort; /* needed for alignment only */
367 *--ctx->sp = (void *)coro_init; 454 *--ctx->sp = (void *)coro_init;
368
369 #if CORO_WIN_TIB 455 #if CORO_WIN_TIB
370 *--ctx->sp = 0; /* ExceptionList */ 456 *--ctx->sp = 0; /* ExceptionList */
371 *--ctx->sp = (char *)sptr + ssize; /* StackBase */ 457 *--ctx->sp = (char *)sptr + ssize; /* StackBase */
372 *--ctx->sp = sptr; /* StackLimit */ 458 *--ctx->sp = sptr; /* StackLimit */
459 #endif
460 #elif CORO_ARM
461 /* return address stored in lr register, don't push anything */
462 #else
463 #error unsupported architecture
373 #endif 464 #endif
374 465
375 ctx->sp -= NUM_SAVED; 466 ctx->sp -= NUM_SAVED;
376 memset (ctx->sp, 0, sizeof (*ctx->sp) * NUM_SAVED); 467 memset (ctx->sp, 0, sizeof (*ctx->sp) * NUM_SAVED);
468
469 #if __i386__ || __x86_64__
470 /* done already */
471 #elif CORO_ARM
472 ctx->sp[0] = coro; /* r4 */
473 ctx->sp[1] = arg; /* r5 */
474 ctx->sp[8] = (char *)coro_init; /* lr */
475 #else
476 #error unsupported architecture
477 #endif
377 478
378# elif CORO_UCONTEXT 479# elif CORO_UCONTEXT
379 480
380 getcontext (&(ctx->uc)); 481 getcontext (&(ctx->uc));
381 482
404 coro_func func; 505 coro_func func;
405 void *arg; 506 void *arg;
406 coro_context *self, *main; 507 coro_context *self, *main;
407}; 508};
408 509
409static pthread_t null_tid;
410
411/* I'd so love to cast pthread_mutex_unlock to void (*)(void *)... */
412static void
413mutex_unlock_wrapper (void *arg)
414{
415 pthread_mutex_unlock ((pthread_mutex_t *)arg);
416}
417
418static void * 510static void *
419coro_init (void *args_) 511coro_init (void *args_)
420{ 512{
421 struct coro_init_args *args = (struct coro_init_args *)args_; 513 struct coro_init_args *args = (struct coro_init_args *)args_;
422 coro_func func = args->func; 514 coro_func func = args->func;
423 void *arg = args->arg; 515 void *arg = args->arg;
424 516
425 pthread_mutex_lock (&coro_mutex);
426
427 /* we try to be good citizens and use deferred cancellation and cleanup handlers */
428 pthread_cleanup_push (mutex_unlock_wrapper, &coro_mutex);
429 coro_transfer (args->self, args->main); 517 coro_transfer (args->self, args->main);
430 func (arg); 518 func (arg);
431 pthread_cleanup_pop (1);
432 519
433 return 0; 520 return 0;
434} 521}
435 522
436void 523void
437coro_transfer (coro_context *prev, coro_context *next) 524coro_transfer (coro_context *prev, coro_context *next)
438{ 525{
526 pthread_mutex_lock (&coro_mutex);
527
528 next->flags = 1;
439 pthread_cond_signal (&next->cv); 529 pthread_cond_signal (&next->cv);
530
531 prev->flags = 0;
532
533 while (!prev->flags)
440 pthread_cond_wait (&prev->cv, &coro_mutex); 534 pthread_cond_wait (&prev->cv, &coro_mutex);
441#if __FreeBSD__ /* freebsd is of course broken and needs manual testcancel calls... yay... */ 535
442 pthread_testcancel (); 536 if (prev->flags == 2)
443#endif 537 {
538 pthread_mutex_unlock (&coro_mutex);
539 pthread_cond_destroy (&prev->cv);
540 pthread_detach (pthread_self ());
541 pthread_exit (0);
542 }
543
544 pthread_mutex_unlock (&coro_mutex);
444} 545}
445 546
446void 547void
447coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, size_t ssize) 548coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, size_t ssize)
448{ 549{
451 552
452 if (!once) 553 if (!once)
453 { 554 {
454 once = 1; 555 once = 1;
455 556
456 pthread_mutex_lock (&coro_mutex);
457 pthread_cond_init (&nctx.cv, 0); 557 pthread_cond_init (&nctx.cv, 0);
458 null_tid = pthread_self ();
459 } 558 }
460 559
461 pthread_cond_init (&ctx->cv, 0); 560 pthread_cond_init (&ctx->cv, 0);
462 561
463 if (coro) 562 if (coro)
464 { 563 {
465 pthread_attr_t attr; 564 pthread_attr_t attr;
466 struct coro_init_args args; 565 struct coro_init_args args;
566 pthread_t id;
467 567
468 args.func = coro; 568 args.func = coro;
469 args.arg = arg; 569 args.arg = arg;
470 args.self = ctx; 570 args.self = ctx;
471 args.main = &nctx; 571 args.main = &nctx;
479 pthread_attr_setstacksize (&attr, (size_t)ssize); 579 pthread_attr_setstacksize (&attr, (size_t)ssize);
480#else 580#else
481 pthread_attr_setstack (&attr, sptr, (size_t)ssize); 581 pthread_attr_setstack (&attr, sptr, (size_t)ssize);
482#endif 582#endif
483 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS); 583 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
484 pthread_create (&ctx->id, &attr, coro_init, &args); 584 pthread_create (&id, &attr, coro_init, &args);
485 585
486 coro_transfer (args.main, args.self); 586 coro_transfer (args.main, args.self);
487 } 587 }
488 else
489 ctx->id = null_tid;
490} 588}
491 589
492void 590void
493coro_destroy (coro_context *ctx) 591coro_destroy (coro_context *ctx)
494{ 592{
495 if (!pthread_equal (ctx->id, null_tid)) 593 pthread_mutex_lock (&coro_mutex);
496 { 594 ctx->flags = 2;
497 pthread_cancel (ctx->id); 595 pthread_cond_signal (&ctx->cv);
498 pthread_mutex_unlock (&coro_mutex); 596 pthread_mutex_unlock (&coro_mutex);
499 pthread_join (ctx->id, 0);
500 pthread_mutex_lock (&coro_mutex);
501 }
502
503 pthread_cond_destroy (&ctx->cv);
504} 597}
505 598
506/*****************************************************************************/ 599/*****************************************************************************/
507/* fiber backend */ 600/* fiber backend */
508/*****************************************************************************/ 601/*****************************************************************************/
600 693
601#if !CORO_MMAP 694#if !CORO_MMAP
602# undef CORO_GUARDPAGES 695# undef CORO_GUARDPAGES
603#endif 696#endif
604 697
605#if !__i386 && !__x86_64 && !__powerpc && !__m68k && !__alpha && !__mips && !__sparc64 698#if !__i386__ && !__x86_64__ && !__powerpc__ && !__arm__ && !__aarch64__ && !__m68k__ && !__alpha__ && !__mips__ && !__sparc64__
606# undef CORO_GUARDPAGES 699# undef CORO_GUARDPAGES
607#endif 700#endif
608 701
609#ifndef CORO_GUARDPAGES 702#ifndef CORO_GUARDPAGES
610# define CORO_GUARDPAGES 0 703# define CORO_GUARDPAGES 0
672 if (!base) 765 if (!base)
673 return 0; 766 return 0;
674 #endif 767 #endif
675 768
676 #if CORO_USE_VALGRIND 769 #if CORO_USE_VALGRIND
677 stack->valgrind_id = VALGRIND_STACK_REGISTER ((char *)base, (char *)ssze - CORO_GUARDPAGES * PAGESIZE); 770 stack->valgrind_id = VALGRIND_STACK_REGISTER ((char *)base, ((char *)base) + ssze - CORO_GUARDPAGES * PAGESIZE);
678 #endif 771 #endif
679 772
680 stack->sptr = base; 773 stack->sptr = base;
681 return 1; 774 return 1;
682 775

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines