static void nile_Process_run (nile_Process_t *p, nile_Thread_t *thread) { nile_Buffer_t *out; nile_prefetch (p->input.head); if (p->input.n > 1) nile_prefetch (p->input.head->next); nile_Process_activate (p, thread); out = nile_Buffer (p); if (!out) return (void) nile_Process_deactivate (p, NULL); if (nile_Process_quota_hit (p->consumer)) out->tag = NILE_TAG_QUOTA_HIT; if (p->prologue) { out = p->prologue (p, out); if (!out) return; p->prologue = NULL; } while (p->input.head) { out = p->body (p, NODE_TO_BUFFER (p->input.head), out); if (!out) return; nile_Process_pop_input (p); if (out->tag == NILE_TAG_OOM) return (void) nile_Process_deactivate (p, NULL); if (out->tag == NILE_TAG_QUOTA_HIT) return nile_Process_handle_backpressure (p, out); } nile_Process_handle_out_of_input (p, out); }
static void nile_Process_handle_out_of_input (nile_Process_t *p, nile_Buffer_t *out) { nile_Thread_t *thread = nile_Process_deactivate (p, out); if (nile_Process_block_on_producer (p)) return; else if (p->producer) thread->private_heap = nile_Process_schedule (p->producer, thread, thread->private_heap); else if (p->input.n) thread->private_heap = nile_Process_schedule (p, thread, thread->private_heap); else if (p->epilogue) { nile_Process_activate (p, thread); out = nile_Buffer (p); if (!out) return (void) nile_Process_deactivate (p, NULL); out = p->epilogue (p, out); if (!out) return; thread = nile_Process_deactivate (p, out); thread->private_heap = nile_Process_remove (p, thread, thread->private_heap); } else thread->private_heap = nile_Process_remove (p, thread, thread->private_heap); }
void nile_print_leaks (nile_Process_t *init) { int i; int n = 0; nile_Thread_t *t = nile_Process_deactivate (init, NULL); nile_Block_t *block = (nile_Block_t *) (t->threads + t->nthreads + 1); nile_Block_t *EOB = (nile_Block_t *) (t->memory + t->nbytes - sizeof (*block) + 1); int nblocks = EOB - block; // minus the init block for (i = 0; i < t->nthreads + 1; i++) n += nile_Heap_size (t->threads[i].private_heap) + nile_Heap_size (t->threads[i].public_heap); if (n != nblocks) { fprintf (stderr, "# blocks not in a heap: %d\n", nblocks - n); for (; block < EOB; block++) { nile_Node_t *nd = (nile_Node_t *) block; if (nd == &init->node) continue; if (nd->type == NILE_BUFFER_TYPE) fprintf (stderr, "LEAKED BUFFER : %p\n", nd); else if (nd->type == NILE_PROCESS_TYPE) fprintf (stderr, "LEAKED PROCESS: %p\n", nd); } } nile_Process_activate (init, t); }
void nile_sync (nile_Process_t *init) { int i; nile_Process_t *p; nile_Thread_t *liaison = nile_Process_deactivate (init, NULL); nile_Thread_t *worker = &liaison->threads[0]; nile_Thread_transfer_heaps (liaison, worker); for (i = 1; i < liaison->nthreads; i++) liaison->threads[i].sync = 1; if ((p = (nile_Process_t *) nile_Thread_steal_from_q (worker))) nile_Thread_work (worker, p); while (worker->status == NILE_STATUS_OK) { p = (nile_Process_t *) nile_Thread_steal (worker, nile_Thread_steal_from_q); if (p) nile_Thread_work (worker, p); else if (nile_Sleep_is_quiescent (worker->sleep)) break; else nile_Sleep_doze (1000); } for (i = 1; i < liaison->nthreads; i++) liaison->threads[i].sync = 0; nile_Thread_transfer_heaps (worker, liaison); nile_Process_activate (init, liaison); }
nile_Process_t * nile_startup (char *memory, int nbytes, int nthreads) { int i; nile_Process_t *init; nile_Sleep_t *sleep; nile_Thread_t *threads; nile_Block_t *block, *EOB; nile_Process_t boot; #ifdef NILE_DISABLE_THREADS nthreads = 1; #endif if ((size_t) nbytes < CACHE_LINE_SIZE + sizeof (*sleep) + sizeof (*threads) * (nthreads + 1)) return NULL; sleep = (nile_Sleep_t *) (((size_t) memory + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1)); nile_Sleep_init (sleep, nthreads); threads = (nile_Thread_t *) (sleep + 1); for (i = 0; i < nthreads + 1; i++) nile_Thread (i, threads, nthreads, sleep, memory, nbytes); block = (nile_Block_t *) (threads + nthreads + 1); EOB = (nile_Block_t *) (memory + nbytes - sizeof (*block) + 1); while (block < EOB) for (i = 1; i < nthreads + 1 && block < EOB; i++, block++) nile_Heap_push (&threads[i].public_heap, block); for (i = 1; i < nthreads; i++) nile_OSThread_spawn (&threads[i].osthread, nile_Thread_main, &threads[i]); nile_Process_activate (&boot, &threads[nthreads]); init = nile_Process (&boot, 0, 0, NULL, NULL, NULL); nile_Process_deactivate (&boot, NULL); if (init) nile_Process_activate (init, &threads[nthreads]); return init; }
void nile_sync (nile_Process_t *init) { int i; nile_Process_t *p; nile_Thread_t *liaison = nile_Process_deactivate (init, NULL); nile_Thread_t *worker = &liaison->threads[0]; nile_Thread_transfer_heaps (liaison, worker); for (i = 1; i < liaison->nthreads; i++) liaison->threads[i].sync = 1; if ((p = nile_Thread_steal_from_q (worker))) nile_Thread_work (worker, p); while (worker->status == NILE_STATUS_OK && (p = nile_Thread_steal (worker, nile_Thread_steal_from_q))) nile_Thread_work (worker, p); nile_Sleep_wait_for_quiecent (liaison->sleep); for (i = 1; i < liaison->nthreads; i++) liaison->threads[i].sync = 0; nile_Thread_transfer_heaps (worker, liaison); nile_Process_activate (init, liaison); }