float DLODStaticObject::computeLODLevel(const Frustum<float>& frustum) const { if(isLODForced) return forcedLevel; HASSERT(cross(frustum.front().normal, frustum.rear().normal).length() == 0); HASSERT(frustum.front().normal.length() == 1); float totalDistance = abs(frustum.front().d - frustum.rear().d) / frustum.front().normal.length(); const matrix4f& worldToLocalR = getWorldToLocalR(); vector3f translation(worldToLocalR(3, 0), worldToLocalR(3, 1), worldToLocalR(3, 2)); float objectDistance = abs(dot(frustum.front().normal, translation) + frustum.front().d) / frustum.front().normal.length(); // fajnie się skraca dzięki temu odległość od punktu // głupie skalowanie... powinno jakoś wpływać na objectDistance, ale średnio działa, więc wyłączam //vector3f ox(1, 0, 0); // zakładam, że uniform scaling (jak nie uniform, to i tak nie bardzo wiem, co robić...) //float scaleX = (worldToLocalR * ox).length(); //objectDistance /= scaleX; uint maxValue = mesh->getNumLODLevels() - 1; // max possible value if(maxValue == 0) return 0; if(objectDistance > totalDistance) return maxValue; return floor(maxValue * objectDistance / totalDistance); }
void hclib_end_finish() { hclib_worker_state *ws = CURRENT_WS_INTERNAL; finish_t *current_finish = ws->current_finish; hclib_task_t *current_task = ws->curr_task; #ifdef VERBOSE fprintf(stderr, "hclib_end_finish: ending finish %p on worker %p\n", current_finish, CURRENT_WS_INTERNAL); #endif #ifdef HCLIB_STATS worker_stats[CURRENT_WS_INTERNAL->id].count_end_finishes++; #endif HASSERT(current_finish); HASSERT(current_finish->counter > 0); help_finish(current_finish); check_out_finish(current_finish->parent); // NULL check in check_out_finish #ifdef VERBOSE fprintf(stderr, "hclib_end_finish: out of finish, setting current finish " "of %p to %p from %p\n", CURRENT_WS_INTERNAL, current_finish->parent, current_finish); #endif // Don't reuse worker-state! (we might not be on the same worker anymore) ws = CURRENT_WS_INTERNAL; ws->current_finish = current_finish->parent; ws->curr_task = current_task; free(current_finish); }
CFileStream::CFileStream(const char *fileName, uint mode) { HASSERT(fileName != NULL); HASSERT((mode & ~(Read|Write|Append)) == 0); const char *strMode; if (mode & Read) if (mode & Write) if (mode & Append) strMode = "a+b"; else strMode = "w+b"; else strMode = "rb"; else if (mode & Write) if (mode & Append) strMode = "ab"; else strMode = "wb"; stream = fopen(fileName, strMode); if (!stream) RAISE(CRTError, "fopen"); isOwner = true; }
static void forasync_internal(void *user_fct_ptr, void *user_arg, int dim, const hclib_loop_domain_t *loop_domain, forasync_mode_t mode) { // All the sub-asyncs share async_def // The user loop code to execute hclib_task_t *user_def = (hclib_task_t *)calloc(1, sizeof(*user_def)); HASSERT(user_def); user_def->_fp = user_fct_ptr; user_def->args = user_arg; HASSERT(dim>0 && dim<4); // TODO put those somewhere as static async_fct_t fct_ptr_rec[3] = { forasync1D_recursive, forasync2D_recursive, forasync3D_recursive }; async_fct_t fct_ptr_flat[3] = { forasync1D_flat, forasync2D_flat, forasync3D_flat }; async_fct_t *fct_ptr = (mode == FORASYNC_MODE_RECURSIVE) ? fct_ptr_rec : fct_ptr_flat; if (dim == 1) { forasync1D_t forasync = {{user_def}, loop_domain[0]}; (fct_ptr[dim-1])((void *) &forasync); } else if (dim == 2) { forasync2D_t forasync = {{user_def}, {loop_domain[0], loop_domain[1]}}; (fct_ptr[dim-1])((void *) &forasync); } else if (dim == 3) { forasync3D_t forasync = {{user_def}, {loop_domain[0], loop_domain[1], loop_domain[2]}}; (fct_ptr[dim-1])((void *) &forasync); } }
/* * _help_finish_ctx is the function we switch to on a new context when * encountering an end finish to allow the current hardware thread to make * useful progress. */ static void _help_finish_ctx(LiteCtx *ctx) { /* * Set up previous context to be stolen when the finish completes (note that * the async must ESCAPE, otherwise this finish scope will deadlock on * itself). */ #ifdef VERBOSE printf("_help_finish_ctx: ctx = %p, ctx->arg = %p\n", ctx, ctx->arg); #endif finish_t *finish = ctx->arg1; hclib_task_t *starting_task = ctx->arg2; HASSERT(finish && starting_task); LiteCtx *hclib_finish_ctx = ctx->prev; hclib_task_t *task = (hclib_task_t *)calloc( 1, sizeof(*task)); HASSERT(task); task->_fp = _finish_ctx_resume; task->args = hclib_finish_ctx; /* * Create an async to handle the continuation after the finish, whose state * is captured in hclib_finish_ctx and whose execution is pending on * finish->finish_dep. */ spawn_escaping((hclib_task_t *)task, finish->finish_dep); // The task that is the body of the finish is now complete, so check it out. check_out_finish(finish); // keep workstealing until this context gets swapped out and destroyed core_work_loop(starting_task); // this function never returns HASSERT(0); // we should never return here }
/* * Generate two lists for all places and workers below the place pl in the HPT: * a list of places that are leaves in the tree (i.e. have no child places) and * a list of all workers in the HPT (which are implicitly leaves, by the * definition of a worker). * * This is done recursively to find all leaf places and workers in a global HPT. */ void find_leaf(place_t *pl, place_node_t **pl_list_cur, worker_node_t **wk_list_cur) { place_t *child = pl->child; if (child == NULL) { // Leaf, add it to the pl_list place_node_t *new_pl = (place_node_t *)malloc(sizeof(place_node_t)); HASSERT(new_pl); memset(new_pl, 0x00, sizeof(place_node_t)); new_pl->data = pl; (*pl_list_cur)->next = new_pl; *pl_list_cur = new_pl; } else { while (child != NULL) { find_leaf(child, pl_list_cur, wk_list_cur); child = child->nnext; } } hclib_worker_state *wk = pl->workers; while (wk != NULL) { // Add any workers to wk_list worker_node_t *new_ws = (worker_node_t *) malloc(sizeof(worker_node_t)); HASSERT(new_ws); memset(new_ws, 0x00, sizeof(worker_node_t)); new_ws->data = wk; (*wk_list_cur)->next = new_ws; *wk_list_cur = new_ws; wk = wk->next_worker; } }
void *hclib_allocate_at(place_t *pl, size_t nbytes, int flags) { HASSERT(pl); HASSERT(nbytes > 0); #ifdef VERBOSE fprintf(stderr, "hclib_allocate_at: pl=%p nbytes=%lu flags=%d, is_cpu? %s", pl, (unsigned long)nbytes, flags, is_cpu_place(pl) ? "true" : "false"); #ifdef HC_CUDA fprintf(stderr, ", is_nvgpu? %s, cuda_id=%d", is_nvgpu_place(pl) ? "true" : "false", pl->cuda_id); #endif fprintf(stderr, "\n"); #endif if (is_cpu_place(pl)) { #ifdef HC_CUDA if (flags & PHYSICAL) { void *ptr; const cudaError_t alloc_err = cudaMallocHost((void **)&ptr, nbytes); if (alloc_err != cudaSuccess) { #ifdef VERBOSE fprintf(stderr, "Physical allocation at CPU place failed with " "reason \"%s\"\n", cudaGetErrorString(alloc_err)); #endif return NULL; } else { hclib_memory_tree_insert(ptr, nbytes, &hclib_context->pinned_host_allocs); return ptr; } } #else HASSERT(flags == NONE); #endif return malloc(nbytes); #ifdef HC_CUDA } else if (is_nvgpu_place(pl)) { HASSERT(flags == NONE); void *ptr; HASSERT(pl->cuda_id >= 0); CHECK_CUDA(cudaSetDevice(pl->cuda_id)); const cudaError_t alloc_err = cudaMalloc((void **)&ptr, nbytes); if (alloc_err != cudaSuccess) { #ifdef VERBOSE fprintf(stderr, "Allocation at NVGPU place failed with reason " "\"%s\"\n", cudaGetErrorString(alloc_err)); #endif return NULL; } else { return ptr; } #endif } else { unsupported_place_type_err(pl); return NULL; // will never reach here } }
StackAllocator::StackAllocator(uint a_size, uint a_alignment) : size(a_size), alignment(a_alignment) { HASSERT(a_alignment > 0); HASSERT(!(a_alignment & (a_alignment - 1))); //true for powers of two void * new_begin = alignedAlloc(a_alignment, a_size); units.push_back(MemoryUnit(new_begin)); currentUnit = &units[0]; }
void help_finish(finish_t *finish) { /* * Creating a new context to switch to is necessary here because the * current context needs to become the continuation for this finish * (which will be switched back to by _finish_ctx_resume, for which an * async is created inside _help_finish_ctx). */ if (finish->counter == 1) { /* * Quick optimization: if no asyncs remain in this finish scope, just * return. finish counter will be 1 here because we haven't checked out * the main thread (this thread) yet. */ return; } hclib_worker_state *ws = CURRENT_WS_INTERNAL; hclib_task_t *need_to_swap_ctx = NULL; while (finish->counter > 1 && need_to_swap_ctx == NULL) { need_to_swap_ctx = find_and_run_task(ws, 0, &(finish->counter), 1, finish); } if (need_to_swap_ctx) { // create finish event hclib_promise_t *finish_promise = hclib_promise_create(); finish->finish_dep = &finish_promise->future; LiteCtx *currentCtx = get_curr_lite_ctx(); HASSERT(currentCtx); LiteCtx *newCtx = LiteCtx_create(_help_finish_ctx); newCtx->arg1 = finish; newCtx->arg2 = need_to_swap_ctx; #ifdef HCLIB_STATS worker_stats[CURRENT_WS_INTERNAL->id].count_ctx_creates++; #endif #ifdef VERBOSE printf("help_finish: newCtx = %p, newCtx->arg = %p\n", newCtx, newCtx->arg); #endif ctx_swap(currentCtx, newCtx, __func__); /* * destroy the context that resumed this one since it's now defunct * (there are no other handles to it, and it will never be resumed) */ LiteCtx_destroy(currentCtx->prev); hclib_promise_free(finish_promise); HASSERT(finish->counter == 0); } else { HASSERT(finish->counter == 1); } }
/* * Based on _help_finish_ctx, _help_wait is called to swap out the current * context when a thread waits on a future. */ void _help_wait(LiteCtx *ctx) { hclib_future_t *continuation_dep = ctx->arg1; hclib_task_t *starting_task = ctx->arg2; LiteCtx *wait_ctx = ctx->prev; hclib_task_t *task = calloc(1, sizeof(*task)); HASSERT(task); task->_fp = _finish_ctx_resume; // reuse _finish_ctx_resume task->args = wait_ctx; spawn_escaping((hclib_task_t *)task, continuation_dep); core_work_loop(starting_task); HASSERT(0); }
void BooksListWatcher::onWidthChanged() { HASSERT(sender() == iListView); HDEBUG(iListView->width()); // Width change will probably be followed by height change iResizeTimer->start(); }
void SkeletalAnimatedObject::addMesh(ref<SkinnedMesh> mesh) { HASSERT(mesh->skeleton == skeleton); m_Meshes.push_back(mesh); if (boundingVolume->growToContain(*mesh->boundingVolume)) growBV = true; }
void SkeletalAnimatedObject::removeMeshAt(uint index) { m_Meshes.erase(m_Meshes.begin() + index); HASSERT(m_Meshes.size() > 0); // jak będzie zaślepka, to dopiszę resztę. rebuildBV = true; }
unsigned hclib_register_dist_func(loop_dist_func func) { registered_dist_funcs = (loop_dist_func *)realloc(registered_dist_funcs, (n_registered_dist_funcs + 1) * sizeof(loop_dist_func)); HASSERT(registered_dist_funcs); registered_dist_funcs[n_registered_dist_funcs++] = func; return n_registered_dist_funcs - 1; }
place_t *generate_fake_hpt(uint32_t num_workers, place_t *** all_places, int *num_pl, int *nproc, hclib_worker_state ***all_workers, int *num_wk) { uint32_t i; place_t *pl = (place_t *)malloc(sizeof(place_t)); HASSERT(pl); memset(pl, 0x00, sizeof(place_t)); pl->id = 1; pl->type = MEM_PLACE; pl->ndeques = num_workers; hclib_worker_state *last = NULL; for (i = 0; i < num_workers; i++) { hclib_worker_state *worker = (hclib_worker_state *)malloc(sizeof( hclib_worker_state)); memset(worker, 0x00, sizeof(hclib_worker_state)); worker->id = 1; worker->pl = pl; if (pl->workers == NULL) pl->workers = worker; else last->next_worker = worker; last = worker; } return pl; }
void spawn_handler(hclib_task_t *task, hclib_locale_t *locale, hclib_future_t **futures, const int nfutures, const int escaping) { HASSERT(task); hclib_worker_state *ws = CURRENT_WS_INTERNAL; if (escaping) { // If escaping task, don't register with current finish set_current_finish(task, NULL); } else { check_in_finish(ws->current_finish); set_current_finish(task, ws->current_finish); } if (locale) { task->locale = locale; } if (nfutures > 0) { if (nfutures > MAX_NUM_WAITS) { fprintf(stderr, "Number of dependent futures (%d) exceeds limit of " "%d\n", nfutures, MAX_NUM_WAITS); exit(1); } memcpy(task->waiting_on, futures, nfutures * sizeof(hclib_future_t *)); task->waiting_on_index = -1; } #ifdef VERBOSE fprintf(stderr, "spawn_handler: task=%p escaping=%d\n", task, escaping); #endif try_schedule_async(task, ws); }
place_t *hclib_get_parent_place() { hclib_worker_state *ws = CURRENT_WS_INTERNAL; place_t *pl = ws->current->pl; HASSERT(pl != NULL); if (ws->hpt_path == NULL) return pl; return ws->hpt_path[pl->level - 1]; }
static void yield_helper(LiteCtx *ctx) { hclib_task_t *starting_task = ctx->arg1; HASSERT(starting_task); hclib_locale_t *locale = ctx->arg2; hclib_task_t *continuation = (hclib_task_t *)calloc(1, sizeof(*continuation)); HASSERT(continuation); continuation->_fp = _finish_ctx_resume; continuation->args = ctx->prev; spawn_escaping_at(locale, continuation, NULL); core_work_loop(starting_task); HASSERT(0); }
void hclib_start_finish() { hclib_worker_state *ws = CURRENT_WS_INTERNAL; finish_t *finish = (finish_t *)calloc(1, sizeof(*finish)); HASSERT(finish); /* * Set finish counter to 1 initially to emulate the main thread inside the * finish being a task registered on the finish. When we reach the * corresponding end_finish we set up the finish_dep for the continuation * and then decrement the counter from the main thread. This ensures that * anytime the counter reaches zero, it is safe to do a promise_put on the * finish_dep. If we initialized counter to zero here, any async inside the * finish could start and finish before the main thread reaches the * end_finish, decrementing the finish counter to zero when it completes. * This would make it harder to detect when all tasks within the finish have * completed, or just the tasks launched so far. */ finish->counter = 1; finish->parent = ws->current_finish; #if HCLIB_LITECTX_STRATEGY finish->finish_deps = NULL; #endif check_in_finish(finish->parent); // check_in_finish performs NULL check ws->current_finish = finish; #ifdef VERBOSE fprintf(stderr, "hclib_start_finish: entering finish for %p and setting its current finish " "from %p to %p\n", ws, finish->parent, ws->current_finish); #endif }
GenericGeometry<SkinVertex> * CLODSkinnedMesh::getGeometry(uint vsplits) { HASSERT(vsplits >= 0 && vsplits <= numVertexSplits); if(isCached && vsplits == lastVertexSplits) return tmpGeometry; else if(isCached) { int difference = vsplits - lastVertexSplits; // how much vsplits has to be perfomed (can be negative, in that case we have to reverse the operations) std::vector<uint> counters(geometry->getNumSubMeshes()); for(int i = 0; i < geometry->getNumSubMeshes(); i++) { const ExtendableSubMesh * sm = (ExtendableSubMesh *)(tmpGeometry->getSubMesh(i)); counters[i] = sm->getNumIndices(); } if(difference > 0) return moveForward(difference, counters); else return moveBackward(-difference, counters); } lastVertexSplits = 0; std::vector<uint> counters(geometry->getNumSubMeshes()); for(int i = 0; i < geometry->getNumSubMeshes(); i++) { const SubMesh * sm = geometry->getSubMesh(i); ExtendableSubMesh * extSubMesh = (ExtendableSubMesh *)(tmpGeometry->getSubMesh(i)); counters[i] = sm->getNumIndices(); // overwrite previous changes std::copy(sm->getIndices(), sm->getIndices() + sm->getNumIndices(), extSubMesh->getIndices()); } return moveForward(vsplits, counters);; }
// Based on help_finish void hclib_end_finish_nonblocking_helper(hclib_promise_t *event) { hclib_worker_state *ws = CURRENT_WS_INTERNAL; finish_t *current_finish = ws->current_finish; hclib_task_t *current_task = ws->curr_task; #ifdef HCLIB_STATS worker_stats[CURRENT_WS_INTERNAL->id].count_end_finishes_nonblocking++; #endif HASSERT(current_finish->counter > 0); // Based on help_finish current_finish->finish_dep = &event->future; // Check out this "task" from the current finish check_out_finish(current_finish); // Check out the current finish from its parent check_out_finish(current_finish->parent); ws = CURRENT_WS_INTERNAL; ws->current_finish = current_finish->parent; ws->curr_task = current_task; #ifdef VERBOSE fprintf(stderr, "hclib_end_finish_nonblocking_helper: out of finish, " "setting current finish of %p to %p from %p\n", CURRENT_WS_INTERNAL, current_finish->parent, current_finish); #endif }
void DDF_PUT(DDF_t* ddf, void* data) { int kind = ddf->kind; // 1. do a local put in all cases // incase the user breaks the single-assignment rule, an error will be thrown here hcpp::ddf_put(ddf, data); switch (kind) { case DDF_KIND_SHARED: // intra-node DDF implementation --> nothing else to do break; case DDF_KIND_DISTRIBUTED_OWNER: { // 2. copy the data from my private memory to shared memory in my portion of global address space copy_datum_from_private_to_globalAddress(ddf, data); break; } case DDF_KIND_DISTRIBUTED_REMOTE: { // 2. copy the data from my private memory to shared memory in my portion of global address space copy_datum_from_private_to_globalAddress(ddf, data); // 3. Initiate the put on remote node (home node) DDDF_t *myindex_dddf_array = (DDDF_t *) ddf; const int dest = myindex_dddf_array->home_rank; DDF_PUT_remote(myindex_dddf_array, dest); break; } default: printf("ERROR (DDF_PUT): Unknown DDF kind \n"); HASSERT(0); } }
uint CLODStaticObject::computeLODLevel(const Frustum<float>& frustum) const { if(isLODForced) return forcedVSplits; HASSERT(cross(frustum.front().normal, frustum.rear().normal).length() == 0); float totalDistance = abs(frustum.front().d - frustum.rear().d) / frustum.front().normal.length(); const matrix4f& worldToLocalR = getWorldToLocalR(); vector3f translation(worldToLocalR(3, 0), worldToLocalR(3, 1), worldToLocalR(3, 2)); float objectDistance = abs(dot(frustum.front().normal, translation) + frustum.front().d) / frustum.front().normal.length(); // fajnie się skraca dzięki temu odległość od punktu // głupie skalowanie... powinno jakoś wpływać na objectDistance, ale jakoś nie działa więc wyłączam //vector3f ox(1, 0, 0); // zakładam, że uniform scaling (jak nie uniform, to i tak nie bardzo wiem, co robić...) //float scaleX = (worldToLocalR * ox).length(); //objectDistance /= scaleX; uint value = mesh->getNumVertexSplits(); // legal values: integers in range [0, value] if(value == 0) return 0; if(objectDistance >= totalDistance) return 0; uint result = value - round((objectDistance / totalDistance) * value); return result; }
/*++ Routine Description: Clock interrupt handler for processor 0. Arguments: Interrupt ServiceContext TrapFrame Return Value: TRUE --*/ BOOLEAN HalpHandleDecrementerInterrupt( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext, IN PVOID TrapFrame ) { KIRQL OldIrql; static int recurse = FALSE; ULONG CpuId; HASSERT(!MSR(EE)); CpuId = GetCpuId(); // // Raise irql via updating the PCR // OldIrql = PCR->CurrentIrql; PCR->CurrentIrql = CLOCK2_LEVEL; RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]); WaitForRInterruptMask(CpuId); // // Reset DECREMENTER, accounting for interrupt latency. // HalpUpdateDecrementer(HalpClockCount); // // Call the kernel to update system time // KeUpdateSystemTime(TrapFrame,HalpCurrentTimeIncrement); HalpCurrentTimeIncrement = HalpNewTimeIncrement; if (!recurse) { // // In some circumstances the KdPollBreakIn can // take longer than a decrementer interrupt // to complete. This is do to a conflict // between DMA and PIO. For now, just avoid // recursing into the debugger check. // recurse = TRUE; if (KdDebuggerEnabled && KdPollBreakIn()) { HalpEnableInterrupts(); DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); HalpDisableInterrupts(); } recurse = FALSE; } // // Lower Irql to original value and enable interrupts // PCR->CurrentIrql = OldIrql; RInterruptMask(CpuId) = (Irql2Mask[OldIrql] & registeredInts[CpuId]); WaitForRInterruptMask(CpuId); return (TRUE); }
File::uptr File::map(const char *fileName, uint access, uint64 offset, size_t size, uint64 *fileSize) { struct HandleDeleter { typedef int pointer; void operator ()(pointer handle) const { if (handle != -1 && close(handle) != -1) RAISE(Exception, "close"); } }; HASSERT((access & ~(Read | Write | Copy)) == 0); int fflags = 0, prot = 0, mflags = MAP_SHARED; if (access & Read) { fflags = O_RDONLY; prot = PROT_READ; } if (access & Write) { prot |= PROT_WRITE; if (access & Copy) mflags = MAP_PRIVATE; else fflags = O_RDWR; } HASSERT(!(fflags & O_RDWR)); // TODO: QuickFix ze .. int file(open(fileName, fflags)); if (file == -1) RAISE(Exception, "open"); struct stat info; if (fstat(file, &info) == -1) RAISE(Exception, "fstat"); if (fileSize) *fileSize = info.st_size; //uptr data(mmap(nullptr, info.st_size, prot, mflags, file.get(), 0)); uptr data(malloc(info.st_size)); ::read(file, data.get(), info.st_size); //if (data.get() == MAP_FAILED) // RAISE(Exception, "mmap"); return data; }
void showStatsFooter() { HASSERT(benchmark_start_time_stats != 0); double dur = (((double)(mysecond()-benchmark_start_time_stats))/1000000) * 1000; //msec if(upcxx::global_myrank() == 0) { print_topology_information(); } runtime_statistics(dur); }
size_t CFileStream::read(void *buff, size_t size) { HASSERT(buff != NULL || size == 0); size_t result = fread(buff, 1, size, stream); if (ferror(stream)) RAISE(CRTError, "fread", ferror(stream)); return result; }
/* * Recursively copy a place and its entire subtree, incrementing num_pl every * time a new place is created and incrementing nproc every time a new worker is * created. */ place_t *clonePlace(place_t *pl, int *num_pl, int *nproc) { place_t *clone = (place_t *) malloc(sizeof(place_t)); HASSERT(clone); memset(clone, 0x00, sizeof(place_t)); clone->type = pl->type; clone->psize = pl->psize; clone->unitSize = pl->unitSize; clone->id = pl->id; clone->did = pl->did; clone->ndeques = pl->ndeques; clone->parent = pl->parent; place_t *child = pl->child; place_t *pllast = NULL; while (child != NULL) { place_t *tmp = clonePlace(child, num_pl, nproc); tmp->parent = clone; if (clone->child == NULL) clone->child = tmp; else pllast->nnext = tmp; pllast = tmp; child = child->nnext; } if (pllast != NULL) pllast->nnext = NULL; hclib_worker_state *ws = pl->workers; hclib_worker_state *wslast = NULL; while (ws != NULL) { hclib_worker_state *tmp = (hclib_worker_state *) malloc(sizeof( hclib_worker_state)); HASSERT(tmp); memset(tmp, 0x00, sizeof(hclib_worker_state)); tmp->pl = clone; tmp->did = ws->did; if (clone->workers == NULL) clone->workers = tmp; else wslast->next_worker = tmp; wslast = tmp; (*nproc) ++; ws = ws->next_worker; } if (wslast != NULL) wslast->next_worker = NULL; (*num_pl) ++; return clone; }
void SkeletonJoint::setName(const char * newName) { HASSERT(newName != NULL); if (strlen(newName) >= sizeof(name)) RAISE(Exception, format("SkeletonJoint name too long: '%s'", newName)); strcpy(name, newName); }
static void _hclib_finalize_ctx(LiteCtx *ctx) { hclib_end_finish(); // Signal shutdown to all worker threads hclib_signal_join(hc_context->nworkers); // Jump back to the system thread context for this worker ctx_swap(ctx, CURRENT_WS_INTERNAL->root_ctx, __func__); HASSERT(0); // Should never return here }