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; }
co_thread_t co_thread_init(size_t stack_size, size_t lwm, size_t hwm) { cothread_ctx* tctx = (cothread_ctx*)malloc(sizeof(cothread_ctx)); if(tctx == NULL) return 0; memset(tctx, 0, sizeof(cothread_ctx)); tctx->co_stack_size = stack_size; tctx->low_watermark = lwm; tctx->high_watermark = hwm; coroutine* c = malloc_coroutine(); tctx->co_main = c; tctx->co_curr = c; if(init_main_coroutine(c) == 0) { for(size_t i=0; i<lwm; ++i) { c = create_coroutine(tctx, tctx->co_stack_size); if(c == NULL) break; c->status = co_stat_null; bd_push_front(&(tctx->co_cache_list), &c->node); } return tctx; } co_thread_cleanup(tctx); return 0; }
void *WorkerThread(void *arg) { workerctx_t *wc = (workerctx_t *)arg; #ifdef HAVE___THREAD workerctx_cur = wc; #else /* HAVE___THREAD */ /* set pointer to worker context as TSD */ pthread_setspecific(workerctx_key, wc); #endif /* HAVE___THREAD */ //FIXME #ifdef USE_MCTX_PCL assert(0 == co_thread_init()); wc->mctx = co_current(); #endif wc->terminate = 0; wc->current_task = NULL; LpelThreadAssign(wc->wid + 1); // 0 is for the master WorkerLoop(wc); #ifdef USE_LOGGING /* cleanup monitoring */ if (wc->mon && MON_CB(worker_destroy)) { MON_CB(worker_destroy)(wc->mon); } #endif #ifdef USE_MCTX_PCL co_thread_cleanup(); #endif return NULL; }
void *WrapperThread(void *arg) { workerctx_t *wp = (workerctx_t *)arg; #ifdef HAVE___THREAD workerctx_cur = wp; #else /* HAVE___THREAD */ /* set pointer to worker context as TSD */ pthread_setspecific(workerctx_key, wp); #endif /* HAVE___THREAD */ #ifdef USE_MCTX_PCL assert(0 == co_thread_init()); wp->mctx = co_current(); #endif LpelThreadAssign(wp->wid); WrapperLoop(wp); addFreeWrapper(wp); #ifdef USE_MCTX_PCL co_thread_cleanup(); #endif return NULL; }
/** * Cleans the LPEL up * - wait for the workers to finish * - free the data structures of worker threads */ void LpelCleanup(void) { /* Cleanup workers */ LpelWorkersCleanup(); /* Cleanup hardware info */ LpelHwLocCleanup(); #ifdef USE_MCTX_PCL /* cleanup machine context for main thread */ co_thread_cleanup(); #endif }
void *MasterThread(void *arg) { masterctx_t *master = (masterctx_t *)arg; num_workers = master->num_workers; //#ifdef HAVE___THREAD // workerctx_cur = ms; //#else /* HAVE___THREAD */ // /* set pointer to worker context as TSD */ // pthread_setspecific(workerctx_key, ms); //#endif /* HAVE___THREAD */ //FIXME #ifdef USE_MCTX_PCL assert(0 == co_thread_init()); master->mctx = co_current(); #endif /* assign to cores */ master->terminate = 0; LpelThreadAssign(LPEL_MAP_MASTER); // master loop, no monitor for master MasterLoop(master); // master terminated, now terminate worker workermsg_t msg; msg.type = WORKER_MSG_TERMINATE; LpelWorkerBroadcast(&msg); #ifdef USE_MCTX_PCL co_thread_cleanup(); #endif return NULL; }
void coopth_done(void) { int i, tt, itd, it; struct coopth_thrdata_t *thdata = NULL; it = _coopth_is_in_thread_nowarn(); itd = it; // assert(!it || is_detached()); if (it) { thdata = co_get_data(co_current()); assert(thdata); /* unfortunately the shutdown can run from signal handler - * in this case we can be in a joinable thread interrupted * by signal, and there is no way to leave that thread. */ if (!is_detached()) itd = 0; } /* there is no safe way to delete joinable threads without joining, * so print error only if there are also detached threads left */ if (threads_total > threads_joinable + itd) error("Coopth: not all detached threads properly shut down\n"); again: tt = threads_total; for (i = 0; i < threads_active; i++) { int tid = active_tids[i]; struct coopth_t *thr = &coopthreads[tid]; struct coopth_per_thread_t *pth = current_thr(thr); /* dont cancel own thread */ if (thdata && *thdata->tid == tid) continue; if (!pth->data.attached) { error("\ttid=%i state=%i name=\"%s\" off=%#x\n", tid, pth->st.state, thr->name, thr->off); do_cancel(thr, pth); assert(threads_total == tt - 1); /* retry the loop as the array changed */ goto again; } else { g_printf("\ttid=%i state=%i name=%s off=%#x\n", tid, pth->st.state, thr->name, thr->off); } } /* at this point all detached threads should be killed, * except perhaps current one */ assert(threads_total == threads_joinable + itd); for (i = 0; i < coopth_num; i++) { struct coopth_t *thr = &coopthreads[i]; int j; /* dont free own thread */ if (thdata && *thdata->tid == i) continue; for (j = thr->cur_thr; j < thr->max_thr; j++) { struct coopth_per_thread_t *pth = &thr->pth[j]; munmap(pth->stack, pth->stk_size); } } if (!threads_total) co_thread_cleanup(); else g_printf("coopth: leaked %i threads\n", threads_total); }
/** * Thread function for workers (and wrappers) */ static void *WorkerThread( void *arg) { workerctx_t *wc = (workerctx_t *)arg; lpel_task_t *t; #ifdef HAVE___THREAD workerctx_cur = wc; #else /* HAVE___THREAD */ /* set pointer to worker context as TSD */ pthread_setspecific(workerctx_key, wc); #endif /* HAVE___THREAD */ #ifdef USE_MCTX_PCL int res = co_thread_init(); assert( 0 == res); wc->mctx = co_current(); #endif wc->current_task = NULL; /* no task marked for deletion */ wc->marked_del = NULL; /* assign to cores */ LpelThreadAssign( wc->wid); /*******************************************************/ if ( wc->wid >= 0) { WorkerLoop( wc); } else { WrapperLoop( wc); } /*******************************************************/ #ifdef USE_LOGGING /* cleanup monitoring */ if (wc->mon && MON_CB(worker_destroy)) { MON_CB(worker_destroy)(wc->mon); } #endif /* destroy all the free tasks */ while ((t = LpelPopTask(free, &wc->free_tasks))) { LpelTaskDestroy(t); } /* on a wrapper, we also can cleanup more*/ if (wc->wid < 0) { /* clean up the mailbox for the worker */ LpelMailboxDestroy(wc->mailbox); /* free the worker context */ free( wc); } #ifdef USE_MCTX_PCL co_thread_cleanup(); #endif return NULL; }