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

Comparing libcoro/coro.c (file contents):
Revision 1.68 by root, Sun Mar 6 06:26:21 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_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
118# if CORO_ASM 123# if CORO_ASM
119 124
120 #if __arm__ && \ 125 #if __arm__ && \
121 (defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \ 126 (defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \
122 || defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__ \ 127 || defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__ \
123 || __ARCH_ARCH == 7) 128 || __ARM_ARCH == 7)
124 #define CORO_ARM 1 129 #define CORO_ARM 1
125 #endif 130 #endif
126 131
127 #if _WIN32 || __CYGWIN__ 132 #if _WIN32 || __CYGWIN__
128 #define CORO_WIN_TIB 1 133 #define CORO_WIN_TIB 1
500 coro_func func; 505 coro_func func;
501 void *arg; 506 void *arg;
502 coro_context *self, *main; 507 coro_context *self, *main;
503}; 508};
504 509
505static pthread_t null_tid;
506
507/* I'd so love to cast pthread_mutex_unlock to void (*)(void *)... */
508static void
509mutex_unlock_wrapper (void *arg)
510{
511 pthread_mutex_unlock ((pthread_mutex_t *)arg);
512}
513
514static void * 510static void *
515coro_init (void *args_) 511coro_init (void *args_)
516{ 512{
517 struct coro_init_args *args = (struct coro_init_args *)args_; 513 struct coro_init_args *args = (struct coro_init_args *)args_;
518 coro_func func = args->func; 514 coro_func func = args->func;
519 void *arg = args->arg; 515 void *arg = args->arg;
520 516
521 pthread_mutex_lock (&coro_mutex);
522
523 /* we try to be good citizens and use deferred cancellation and cleanup handlers */
524 pthread_cleanup_push (mutex_unlock_wrapper, &coro_mutex);
525 coro_transfer (args->self, args->main); 517 coro_transfer (args->self, args->main);
526 func (arg); 518 func (arg);
527 pthread_cleanup_pop (1);
528 519
529 return 0; 520 return 0;
530} 521}
531 522
532void 523void
533coro_transfer (coro_context *prev, coro_context *next) 524coro_transfer (coro_context *prev, coro_context *next)
534{ 525{
526 pthread_mutex_lock (&coro_mutex);
527
528 next->flags = 1;
535 pthread_cond_signal (&next->cv); 529 pthread_cond_signal (&next->cv);
530
531 prev->flags = 0;
532
533 while (!prev->flags)
536 pthread_cond_wait (&prev->cv, &coro_mutex); 534 pthread_cond_wait (&prev->cv, &coro_mutex);
537#if __FreeBSD__ /* freebsd is of course broken and needs manual testcancel calls... yay... */ 535
538 pthread_testcancel (); 536 if (prev->flags == 2)
539#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);
540} 545}
541 546
542void 547void
543coro_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)
544{ 549{
547 552
548 if (!once) 553 if (!once)
549 { 554 {
550 once = 1; 555 once = 1;
551 556
552 pthread_mutex_lock (&coro_mutex);
553 pthread_cond_init (&nctx.cv, 0); 557 pthread_cond_init (&nctx.cv, 0);
554 null_tid = pthread_self ();
555 } 558 }
556 559
557 pthread_cond_init (&ctx->cv, 0); 560 pthread_cond_init (&ctx->cv, 0);
558 561
559 if (coro) 562 if (coro)
560 { 563 {
561 pthread_attr_t attr; 564 pthread_attr_t attr;
562 struct coro_init_args args; 565 struct coro_init_args args;
566 pthread_t id;
563 567
564 args.func = coro; 568 args.func = coro;
565 args.arg = arg; 569 args.arg = arg;
566 args.self = ctx; 570 args.self = ctx;
567 args.main = &nctx; 571 args.main = &nctx;
575 pthread_attr_setstacksize (&attr, (size_t)ssize); 579 pthread_attr_setstacksize (&attr, (size_t)ssize);
576#else 580#else
577 pthread_attr_setstack (&attr, sptr, (size_t)ssize); 581 pthread_attr_setstack (&attr, sptr, (size_t)ssize);
578#endif 582#endif
579 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS); 583 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
580 pthread_create (&ctx->id, &attr, coro_init, &args); 584 pthread_create (&id, &attr, coro_init, &args);
581 585
582 coro_transfer (args.main, args.self); 586 coro_transfer (args.main, args.self);
583 } 587 }
584 else
585 ctx->id = null_tid;
586} 588}
587 589
588void 590void
589coro_destroy (coro_context *ctx) 591coro_destroy (coro_context *ctx)
590{ 592{
591 if (!pthread_equal (ctx->id, null_tid)) 593 pthread_mutex_lock (&coro_mutex);
592 { 594 ctx->flags = 2;
593 pthread_cancel (ctx->id); 595 pthread_cond_signal (&ctx->cv);
594 pthread_mutex_unlock (&coro_mutex); 596 pthread_mutex_unlock (&coro_mutex);
595 pthread_join (ctx->id, 0);
596 pthread_mutex_lock (&coro_mutex);
597 }
598
599 pthread_cond_destroy (&ctx->cv);
600} 597}
601 598
602/*****************************************************************************/ 599/*****************************************************************************/
603/* fiber backend */ 600/* fiber backend */
604/*****************************************************************************/ 601/*****************************************************************************/

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines