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

Comparing libcoro/coro.c (file contents):
Revision 1.70 by root, Fri Nov 18 05:45:00 2016 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_startproc");*/
94 asm (".cfi_undefined rip"); 94 /*asm (".cfi_undefined rip");*/
95#endif 95#endif
96 96
97 func ((void *)arg); 97 func ((void *)arg);
98 98
99#if __GCC_HAVE_DWARF2_CFI_ASM && __amd64 99#if __GCC_HAVE_DWARF2_CFI_ASM && __amd64
100 asm (".cfi_endproc"); 100 /*asm (".cfi_endproc");*/
101#endif 101#endif
102 102
103 /* the new coro returned. bad. just abort() for now */ 103 /* the new coro returned. bad. just abort() for now */
104 abort (); 104 abort ();
105} 105}
505 coro_func func; 505 coro_func func;
506 void *arg; 506 void *arg;
507 coro_context *self, *main; 507 coro_context *self, *main;
508}; 508};
509 509
510static pthread_t null_tid;
511
512/* I'd so love to cast pthread_mutex_unlock to void (*)(void *)... */
513static void
514mutex_unlock_wrapper (void *arg)
515{
516 pthread_mutex_unlock ((pthread_mutex_t *)arg);
517}
518
519static void * 510static void *
520coro_init (void *args_) 511coro_init (void *args_)
521{ 512{
522 struct coro_init_args *args = (struct coro_init_args *)args_; 513 struct coro_init_args *args = (struct coro_init_args *)args_;
523 coro_func func = args->func; 514 coro_func func = args->func;
524 void *arg = args->arg; 515 void *arg = args->arg;
525 516
526 pthread_mutex_lock (&coro_mutex);
527
528 /* we try to be good citizens and use deferred cancellation and cleanup handlers */
529 pthread_cleanup_push (mutex_unlock_wrapper, &coro_mutex);
530 coro_transfer (args->self, args->main); 517 coro_transfer (args->self, args->main);
531 func (arg); 518 func (arg);
532 pthread_cleanup_pop (1);
533 519
534 return 0; 520 return 0;
535} 521}
536 522
537void 523void
538coro_transfer (coro_context *prev, coro_context *next) 524coro_transfer (coro_context *prev, coro_context *next)
539{ 525{
526 pthread_mutex_lock (&coro_mutex);
527
528 next->flags = 1;
540 pthread_cond_signal (&next->cv); 529 pthread_cond_signal (&next->cv);
530
531 prev->flags = 0;
532
533 while (!prev->flags)
541 pthread_cond_wait (&prev->cv, &coro_mutex); 534 pthread_cond_wait (&prev->cv, &coro_mutex);
542#if __FreeBSD__ /* freebsd is of course broken and needs manual testcancel calls... yay... */ 535
543 pthread_testcancel (); 536 if (prev->flags == 2)
544#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);
545} 545}
546 546
547void 547void
548coro_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)
549{ 549{
552 552
553 if (!once) 553 if (!once)
554 { 554 {
555 once = 1; 555 once = 1;
556 556
557 pthread_mutex_lock (&coro_mutex);
558 pthread_cond_init (&nctx.cv, 0); 557 pthread_cond_init (&nctx.cv, 0);
559 null_tid = pthread_self ();
560 } 558 }
561 559
562 pthread_cond_init (&ctx->cv, 0); 560 pthread_cond_init (&ctx->cv, 0);
563 561
564 if (coro) 562 if (coro)
565 { 563 {
566 pthread_attr_t attr; 564 pthread_attr_t attr;
567 struct coro_init_args args; 565 struct coro_init_args args;
566 pthread_t id;
568 567
569 args.func = coro; 568 args.func = coro;
570 args.arg = arg; 569 args.arg = arg;
571 args.self = ctx; 570 args.self = ctx;
572 args.main = &nctx; 571 args.main = &nctx;
580 pthread_attr_setstacksize (&attr, (size_t)ssize); 579 pthread_attr_setstacksize (&attr, (size_t)ssize);
581#else 580#else
582 pthread_attr_setstack (&attr, sptr, (size_t)ssize); 581 pthread_attr_setstack (&attr, sptr, (size_t)ssize);
583#endif 582#endif
584 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS); 583 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
585 pthread_create (&ctx->id, &attr, coro_init, &args); 584 pthread_create (&id, &attr, coro_init, &args);
586 585
587 coro_transfer (args.main, args.self); 586 coro_transfer (args.main, args.self);
588 } 587 }
589 else
590 ctx->id = null_tid;
591} 588}
592 589
593void 590void
594coro_destroy (coro_context *ctx) 591coro_destroy (coro_context *ctx)
595{ 592{
596 if (!pthread_equal (ctx->id, null_tid)) 593 pthread_mutex_lock (&coro_mutex);
597 { 594 ctx->flags = 2;
598 pthread_cancel (ctx->id); 595 pthread_cond_signal (&ctx->cv);
599 pthread_mutex_unlock (&coro_mutex); 596 pthread_mutex_unlock (&coro_mutex);
600 pthread_join (ctx->id, 0);
601 pthread_mutex_lock (&coro_mutex);
602 }
603
604 pthread_cond_destroy (&ctx->cv);
605} 597}
606 598
607/*****************************************************************************/ 599/*****************************************************************************/
608/* fiber backend */ 600/* fiber backend */
609/*****************************************************************************/ 601/*****************************************************************************/

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines