int main() { int el, t; struct cfifo f; cfifo_init(&f, sizeof(int), 5); /* Initialization assertions */ assert(f.cap == 5); assert(f.h == 0); assert(f.len == 0); assert(f.sz == sizeof(int)); assert(f.ptr != 0); assert(cfifo_isempty(&f)); assert(!cfifo_isfull(&f)); /* After one push */ el = 1, cfifo_push(&f, &el); assert(f.len == 1); assert(!cfifo_isempty(&f)); assert(!cfifo_isfull(&f)); /* After one pop */ cfifo_pop(&f, &t); assert(el == t); assert(f.len == 0); assert(f.h == 1); assert(cfifo_isempty(&f)); /* Push until full */ el = 1, cfifo_push(&f, &el); el = 2, cfifo_push(&f, &el); el = 3, cfifo_push(&f, &el); el = 4, cfifo_push(&f, &el); el = 5, cfifo_push(&f, &el); assert(cfifo_isfull(&f)); assert(!cfifo_isempty(&f)); /* Push to overwrite head */ el = 6, cfifo_push(&f, &el); assert(cfifo_isfull(&f)); assert(!cfifo_isempty(&f)); /* Pop until empty */ cfifo_pop(&f, &el), assert(el == 2); cfifo_pop(&f, &el), assert(el == 3); cfifo_pop(&f, &el), assert(el == 4); cfifo_pop(&f, &el), assert(el == 5); cfifo_pop(&f, &el), assert(el == 6); assert(cfifo_isempty(&f)); assert(!cfifo_isfull(&f)); cfifo_free(&f); return 0; }
// Function responsible for the workers on current TM node. void *worker(void *ptr) { int my_rank = COMM_get_rank_id(); int task_id, j_id=0; // j_id = journal id for current thread. struct tm_thread_data *d = (struct tm_thread_data *) ptr; struct byte_array * task; struct result_node * result; uint64_t buffer; struct j_entry * entry; workerid = d->id; void* (*worker_new) (int, char **); worker_new = dlsym(d->handle, "spits_worker_new"); void (*execute_pit) (void *, struct byte_array *, struct byte_array *); execute_pit = dlsym(d->handle, "spits_worker_run"); void* (*worker_free) (void *); worker_free = dlsym(d->handle, "spits_worker_free"); void *user_data = worker_new ? worker_new(d->argc, d->argv) : NULL; if(TM_KEEP_JOURNAL > 0) { j_id = JOURNAL_get_id(d->dia, 'W'); } sem_wait (&d->tcount); // wait for the first task to arrive. while (d->running) { pthread_mutex_lock(&d->tlock); // Get a new task. cfifo_pop(&d->f, &task); pthread_mutex_unlock(&d->tlock); // Warn the Task Manager about the new space available. sem_post(&d->sem); byte_array_unpack64(task, &buffer); task_id = (int) buffer; debug("[worker] Received TASK %d", task_id); //_byte_array_pack64(task, (uint64_t) task_id); // Put it back, might use in execute_pit. result = (struct result_node *) malloc(sizeof(struct result_node)); byte_array_init(&result->ba, 10); byte_array_pack64(&result->ba, task_id); // Pack the ID in the result byte_array. byte_array_pack64(&result->ba, my_rank); if(TM_KEEP_JOURNAL > 0) { entry = JOURNAL_new_entry(d->dia, j_id); entry->action = 'P'; gettimeofday(&entry->start, NULL); } debug("[--WORKER] task: %d", task); debug("[--WORKER] &result->ba: %d", &result->ba); execute_pit(user_data, task, &result->ba); // Do the computation. if(TM_KEEP_JOURNAL > 0) { gettimeofday(&entry->end, NULL); } byte_array_free(task); // Free memory used in task and pointer. free(task); // For now, each pointer is allocated in master thread. debug("Appending task %d.", task_id); pthread_mutex_lock(&d->rlock); // Pack the result to send it later. result->next = d->results; result->before = NULL; result->task_id = task_id; if(d->results != NULL) { d->results->before = result; } d->results = result; if(d->is_blocking_flush==1) { if(TM_NO_WAIT_FINAL_FLUSH > 0) { sem_post(&d->no_wait_sem); } else { d->bf_remaining_tasks--; if(d->bf_remaining_tasks==0) { pthread_mutex_unlock(&d->bf_mutex); } } } pthread_mutex_unlock(&d->rlock); sem_wait (&d->tcount); // wait for the next task to arrive. } if (worker_free) { worker_free(user_data); } //free(result); pthread_exit(NULL); }