static int bomp_thread_fn(void *xdata) { struct bomp_work *work_data = xdata; backend_set_numa(work_data->thread_id); bomp_set_tls(work_data); work_data->fn(work_data->data); /* Wait for the Barrier */ bomp_barrier_wait(work_data->barrier); return 0; }
void bomp_start_processing(void (*fn) (void *), void *data, unsigned nthreads) { /* Create Threads and ask them to process the function specified */ /* Let them die as soon as they are done */ unsigned i; struct bomp_work *xdata; struct bomp_barrier *barrier; g_thread_numbers = nthreads; char *memory = calloc(1, nthreads * sizeof(struct bomp_thread_local_data *) + sizeof(struct bomp_barrier) + nthreads * sizeof(struct bomp_work)); assert(memory != NULL); g_array_thread_local_data = (struct bomp_thread_local_data **)memory; memory += nthreads * sizeof(struct bomp_thread_local_data *); /* Create a barier for the work that will be carried out by the threads */ barrier = (struct bomp_barrier *)memory; memory += sizeof(struct bomp_barrier); bomp_barrier_init(barrier, nthreads); /* For main thread */ xdata = (struct bomp_work * )memory; memory += sizeof(struct bomp_work); xdata->fn = fn; xdata->data = data; xdata->thread_id = 0; xdata->barrier = barrier; bomp_set_tls(xdata); for (i = 1; i < nthreads; i++) { xdata = (struct bomp_work *)memory; memory += sizeof(struct bomp_work); xdata->fn = fn; xdata->data = data; xdata->thread_id = i; xdata->barrier = barrier; /* Create threads */ backend_run_func_on(i + THREAD_OFFSET, bomp_thread_fn, xdata); } }
void bomp_start_processing(void (*fn)(void *), void *data, coreid_t tid_start, coreid_t nthreads) { struct bomp_tls *tls = thread_get_tls(); debug_printf("bomp_start_processing(%p, %p, %u, %u)\n", fn, data, tid_start, nthreads); /* this function must only be called by the program and node masters */ assert(tls->role == BOMP_THREAD_ROLE_MASTER || tls->role == BOMP_THREAD_ROLE_NODE); /* add one to the tid_start as this will be our ID */ coreid_t tid_current = tid_start + 1; struct bomp_node *node; if (tls->role == BOMP_THREAD_ROLE_MASTER) { node = &tls->r.master.local; if (nthreads > (node->threads_max + 1)) { /* send the requests to the node masters */ nthreads -= (node->threads_max + 1); for (nodeid_t i = 0; i < tls->r.master.num_nodes; ++i) { coreid_t num = bomp_node_exec(&tls->r.master.nodes[i], fn, data, tid_start, nthreads); assert(num <= nthreads); tls->r.master.nodes_active++; nthreads -= num; tid_current += num; if (nthreads == 0) { break; } } nthreads += (node->threads_max); } } else if (tls->role == BOMP_THREAD_ROLE_NODE) { node = &tls->r.node; } debug_printf("nthreads=%u, max_threads=%u\n", nthreads, node->threads_max); assert((node->threads_max + 1)>= nthreads); struct omp_icv_task *icv = bomp_icv_get()->task; for (coreid_t i = 1; i < nthreads; ++i) { node->threads[i].icvt = icv; node->threads_active++; bomp_thread_exec(&node->threads[i], fn, data, tid_current); tid_current++; } /* set the local thread ID */ tls->thread_id = 0; return; #if 0 /* Create Threads and ask them to process the function specified */ /* Let them die as soon as they are done */ unsigned i; struct bomp_work *xdata; struct bomp_barrier *barrier; g_bomp_state->num_threads = nthreads; char *memory = calloc( 1, nthreads * sizeof(struct bomp_thread_local_data *) + sizeof(struct bomp_barrier) + nthreads * sizeof(struct bomp_work)); assert(memory != NULL); g_bomp_state->tld = (struct bomp_thread_local_data **) memory; memory += nthreads * sizeof(struct bomp_thread_local_data *); /* Create a barier for the work that will be carried out by the threads */ barrier = (struct bomp_barrier *) memory; memory += sizeof(struct bomp_barrier); bomp_barrier_init(barrier, nthreads); /* For main thread */ xdata = (struct bomp_work *) memory; memory += sizeof(struct bomp_work); xdata->fn = fn; xdata->data = data; xdata->thread_id = 0; xdata->barrier = barrier; bomp_set_tls(xdata); for (i = 1; i < nthreads; i++) { xdata = (struct bomp_work *) memory; memory += sizeof(struct bomp_work); xdata->fn = fn; xdata->data = data; xdata->thread_id = i; xdata->barrier = barrier; /* Create threads */ bomp_run_on(i * BOMP_DEFAULT_CORE_STRIDE + THREAD_OFFSET, bomp_thread_fn, xdata); } #endif }