void async_destroy(void) { assert(async_loop); co_delete(trampoline); trampoline = NULL; uv_loop_close(async_loop); memset(async_loop, 0, sizeof(async_loop)); // TODO: Not safe for various libco backends? #if defined(CORO_USE_VALGRIND) co_delete(master->fiber); memset(master, 0, sizeof(master)); #endif }
int main(int argc, char **argv) { pthread_t *thids; int i; if (co_thread_init() < 0) { perror("co_thread_init failed in main\n"); exit(-1); } task = co_create(count_inc, NULL, NULL, 4096); // launch worker threads thids = (pthread_t *) malloc(NUM_WORKERS * sizeof(pthread_t)); for (i = 0; i < NUM_WORKERS; i++) { int *arg = (int *) malloc( sizeof(int) ); *arg = i; if (pthread_create(&thids[i], NULL, worker, arg)) { perror("creating worker threads"); exit(-1); } } // join on finish for (i = 0; i < NUM_WORKERS; i++) pthread_join(thids[i], NULL); co_delete(task); co_thread_cleanup(); return 0; }
static void do_del_thread(struct coopth_t *thr, struct coopth_per_thread_t *pth) { int i; pth->st = ST(NONE); co_delete(pth->thread); thr->cur_thr--; if (thr->cur_thr == 0) { int found = 0; for (i = 0; i < threads_active; i++) { if (active_tids[i] == thr->tid) { assert(!found); found++; continue; } if (found) active_tids[i - 1] = active_tids[i]; } assert(found); threads_active--; } threads_total--; if (!pth->data.cancelled && !pth->data.left) do_call_post(thr, pth); }
int main() { printf("context-switching timing test\n\n"); time_t start, end; int i, t1, t2; start = clock(); for(thread::counter = 0, i = 0; i < Iterations; i++) { sub_timingtest(); } end = clock(); t1 = (int)difftime(end, start); printf("%2.3f seconds per 50 million subroutine calls (%d iterations)\n", (float)t1 / CLOCKS_PER_SEC, thread::counter); thread::x = co_active(); thread::y = co_create(65536, co_timingtest); start = clock(); for(thread::counter = 0, i = 0; i < Iterations; i++) { co_switch(thread::y); } end = clock(); co_delete(thread::y); t2 = (int)difftime(end, start); printf("%2.3f seconds per 100 million co_switch calls (%d iterations)\n", (float)t2 / CLOCKS_PER_SEC, thread::counter); printf("co_switch skew = %fx\n\n", (double)t2 / (double)t1); return 0; }
int32_t test_yieldmain() { args_t args; args.host_ = co_init(nullptr); args.a_ = co_create (args.host_, thread_a, 1024, nullptr, &args); args.b_ = co_create (args.host_, thread_b, 1024, nullptr, &args); co_yield(args.host_, args.a_); co_delete(args.a_); co_delete(args.b_); co_delete(args.host_); return 0; }
int main(){ char para[] = "MainCo"; Coroutine* co = co_create(MainCo, para); co_resume( co ); co_resume( co ); co_delete( co ); return 0; }
void retro_deinit(void) { if(emuThread) { co_delete(emuThread); emuThread = 0; } LOGI("Retro DeInit\n"); }
static void pam_auth_deinit(void* ctx) { struct pam_ctx_st * pctx = ctx; pam_end(pctx->ph, pctx->cr_ret); free(pctx->replies); str_clear(&pctx->msg); if (pctx->cr != NULL) co_delete(pctx->cr); talloc_free(pctx); }
static void del_helper(void **args) { for (;;) { if (args != helper_args) fatal("resume to deleted coroutine"); co_delete(co_current->caller); args = co_call(args[0], args[1]); } }
cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) { if(!co_running) co_running = &co_primary; ucontext_t *thread = (ucontext_t*)malloc(sizeof(ucontext_t)); if(thread) { if((!getcontext(thread) && !(thread->uc_stack.ss_sp = 0)) && (thread->uc_stack.ss_sp = malloc(heapsize))) { thread->uc_link = co_running; thread->uc_stack.ss_size = heapsize; makecontext(thread, coentry, 0); } else { co_delete((cothread_t)thread); thread = 0; } } return (cothread_t)thread; }
static void co_del_helper(void *data) { coroutine *cdh; for (;;) { cdh = co_dhelper; co_dhelper = NULL; co_delete(co_curr->caller); co_call((coroutine_t) cdh); if (!co_dhelper) { fprintf(stderr, "[PCL] Resume to delete helper coroutine: curr=%p\n", co_curr); exit(1); } } }
void Scheduler::init() { clock.cpu_freq = snes.region() == SNES::NTSC ? snes.config.cpu.ntsc_clock_rate : snes.config.cpu.pal_clock_rate; clock.smp_freq = snes.region() == SNES::NTSC ? snes.config.smp.ntsc_clock_rate : snes.config.smp.pal_clock_rate; clock.active = THREAD_CPU; clock.cpuppu = 0; clock.cpusmp = 0; clock.smpdsp = 0; if(thread_cpu) co_delete(thread_cpu); if(thread_smp) co_delete(thread_smp); if(thread_ppu) co_delete(thread_ppu); if(thread_dsp) co_delete(thread_dsp); thread_snes = co_active(); thread_cpu = co_create(65536 * sizeof(void*), threadentry_cpu); thread_smp = co_create(65536 * sizeof(void*), threadentry_smp); thread_ppu = co_create(65536 * sizeof(void*), threadentry_ppu); thread_dsp = co_create(65536 * sizeof(void*), threadentry_dsp); }
/** * Free the memory associated with the given thread. **/ inline static void free_thread( thread_t *t ) { static int iter = -1; iter++; pl_remove_pointer(threadlist, t); assert(t->state == ZOMBIE); t->state = GHOST; // just for good measure num_zombie_threads--; if( t != main_thread ) { co_delete( t->coro ); stack_return_chunk( t->stack_size_kb_log2, t->stack ); free( t ); } }
static void co_del_helper(void *data) { cothread_ctx *tctx; coroutine *cdh; for (;;) { tctx = co_get_thread_ctx(); cdh = tctx->co_dhelper; tctx->co_dhelper = NULL; co_delete(tctx->co_curr->caller); co_call((coroutine_t) cdh); if (tctx->co_dhelper == NULL) { fprintf(stderr, "[PCL] Resume to delete helper coroutine: curr=%p caller=%p\n", tctx->co_curr, tctx->co_curr->caller); exit(1); } } }
void function1(void* p) { char para[] = "Function2"; Coroutine* co = co_create(function2, para); int i = 0; int a[ N ]; for(i=0; i<N; ++i) a[ i ] = i; printf(" %s come...\n",p); printf(" %s pause...\n",p); co_pause(); printf(" %s back...\n",p); co_resume( co ); printf(" %s resume Function2...\n",p); co_resume( co ); printf(" %s has array\n",p); for(i=0; i<N; ++i) printf("%d ",a[ i ]); printf("\n"); printf(" %s terminated\n",p); co_delete( co ); co_terminate(); }
cothread_t co_create(unsigned int size, void (*coentry)(void)) { if(!co_running) co_running = &co_primary; cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct)); if(thread) { struct sigaction handler; struct sigaction old_handler; stack_t stack; stack_t old_stack; thread->coentry = thread->stack = 0; stack.ss_flags = 0; stack.ss_size = size; thread->stack = stack.ss_sp = malloc(size); if(stack.ss_sp && !sigaltstack(&stack, &old_stack)) { handler.sa_handler = springboard; handler.sa_flags = SA_ONSTACK; sigemptyset(&handler.sa_mask); creating = thread; if(!sigaction(SIGUSR1, &handler, &old_handler)) { if(!raise(SIGUSR1)) { thread->coentry = coentry; } sigaltstack(&old_stack, 0); sigaction(SIGUSR1, &old_handler, 0); } } if(thread->coentry != coentry) { co_delete(thread); thread = 0; } } return (cothread_t)thread; }
void MainCo(void* p) { printf("MainCo para: %s\n", (char *)p); char para[] = "Function1"; Coroutine* co = co_create(function1, para); int i = 0; int a[ N ]; for(i=0; i<N; ++i) a[ i ] = 5*i; printf("%s come...\n",p); printf("%s pause...\n",p); co_pause(); printf("%s back...\n",p); co_resume( co ); printf("%s resume Function1...\n",p); co_resume( co ); printf("%s has array\n",p); for(i=0; i<N; ++i) printf("%d ",a[ i ]); printf("\n"); printf("%s terminated\n",p); co_delete( co ); co_terminate(); }
static int eph_new_conn(int sfd, void *func) { struct eph_conn *conn = (struct eph_conn *)malloc(sizeof(struct eph_conn)); struct epoll_event ev; if (!conn) return -1; memset(conn, 0, sizeof(*conn)); DBL_INIT_LIST_HEAD(&conn->lnk); conn->sfd = sfd; conn->events = 0; conn->revents = 0; conn->nbytes = conn->rindex = 0; if (!(conn->co = co_create(func, conn, NULL, stksize))) { free(conn); return -1; } DBL_LIST_ADDT(&conn->lnk, &chash[sfd % chash_size]); ev.events = 0; ev.data.ptr = conn; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, sfd, &ev) < 0) { fprintf(stderr, "epoll set insertion error: fd=%d\n", sfd); DBL_LIST_DEL(&conn->lnk); co_delete(conn->co); free(conn); return -1; } ++numfds; co_call(conn->co); return 0; }
inline ~Processor() { if(thread) co_delete(thread); }
inline void create(void (*entrypoint)(), unsigned frequency) { if(thread) co_delete(thread); thread = co_create(65536 * sizeof(void*), entrypoint); this->frequency = frequency; clock = 0; }
inline ~Thread() { if(thread) co_delete(thread); }
static void run( jmp_buf jb, int depth ) { unsigned local [16]; memcpy( local, shared, sizeof local ); if ( depth > max_depth ) max_depth = depth; while ( 1 ) { co_switch( threads [0] ); switch ( rnd() & 7 ) { case 0: if ( depth > 0 ) { if ( rnd() & 1 ) #if STRESS_EXCEPTIONS throw 0; #else longjmp( jb, 1 ); #endif goto ret; } break; case 1: if ( depth < 50 ) { #if STRESS_EXCEPTIONS { try { run( jb, depth + 1 ); } catch ( ... ) { } } #else { jmp_buf jb2; if ( !setjmp( jb2 ) ) run( jb2, depth + 1 ); } #endif } break; case 2: { int i; for ( i = 0; i < max_threads; i++ ) { if ( !threads [i] ) { threads [i] = co_create( stack_size, entry ); assert( threads [i] ); break; } } break; } case 3: { int i = rnd() & (max_threads - 1); if ( i > 0 && threads [i] && threads [i] != co_active() ) { co_delete( threads [i] ); threads [i] = 0; } break; } case 4: case 5: case 6: case 7: { int n; for ( n = 10; n--; ) { unsigned r; r = rnd(); local [r & 15] += rnd(); r = rnd(); shared [r & 15] += rnd(); r = rnd(); local [r & 15] ^= shared [rnd() & 15]; r = rnd(); shared [r & 15] ^= local [rnd() & 15]; } break; } } { int i = rnd() & (max_threads - 1); if ( threads [i] && threads [i] != co_active() ) co_switch( threads [i] ); } } ret:; }