void *do_work() { // TODO All lock/unlock must be instrumented, regardless of whether the // critical sections have accesses to persistent locations NVM_LOCK(ready_lock); ready = 1; NVM_UNLOCK(ready_lock); int global_count = 0; int t = 0; while (1) { int val; int status = dequeue(&val); if (status) { ++global_count; } else if (t) { break; } NVM_LOCK(done_lock); t = done; NVM_UNLOCK(done_lock); } fprintf(stderr, "Total # items dequeued is %d\n", global_count); #ifdef NVM_STATS NVM_PrintStats(); #endif return 0; }
int dequeue(int *valp) { NVM_LOCK(*(Q->head_lock)); // note that not everything of type node_t is persistent // In the following statement, we have a transient pointer to // persistent data which is just fine. If there is a crash, the // transient pointer goes away. node_t *node = Q->head; node_t *new_head = node->next; if (new_head == NULL) { NVM_UNLOCK(*(Q->head_lock)); return 0; } *valp = new_head->val; #ifdef _FORCE_FAIL if (*valp == NUM_ITEMS / 4) exit(0); #endif NVM_STR2(Q->head, new_head, sizeof(node_t *) * 8); NVM_UNLOCK(*(Q->head_lock)); #if defined(_USE_MALLOC) free(node); #else nvm_free(node); #endif return 1; }
int main() { pthread_t thread; struct timeval tv_start; struct timeval tv_end; gettimeofday(&tv_start, NULL); NVM_Initialize(); queue_rgn_id = NVM_FindOrCreateRegion("queue", O_RDWR, NULL); initialize(); pthread_create(&thread, 0, (void *(*)(void *))do_work, 0); // wait for the child to be ready int t = 0; while (!t) { NVM_LOCK(ready_lock); t = ready; NVM_UNLOCK(ready_lock); } int i; for (i = 0; i < NUM_ITEMS; ++i) enqueue(i); NVM_LOCK(done_lock); done = 1; NVM_UNLOCK(done_lock); pthread_join(thread, NULL); NVM_CloseRegion(queue_rgn_id); #ifdef NVM_STATS NVM_PrintStats(); #endif NVM_Finalize(); fprintf(stderr, "Total # items enqueued is %d\n", NUM_ITEMS); gettimeofday(&tv_end, NULL); fprintf(stderr, "time elapsed %ld us\n", tv_end.tv_usec - tv_start.tv_usec + (tv_end.tv_sec - tv_start.tv_sec) * 1000000); return 0; }
void enqueue(int val) { node_t *node = #if defined(_USE_MALLOC) (node_t *)malloc(sizeof(node_t)); #else (node_t *)nvm_alloc(sizeof(node_t), queue_rgn_id); #endif assert(node); NVM_STR2(node->val, val, sizeof(int) * 8); NVM_STR2(node->next, NULL, sizeof(node_t *) * 8); NVM_LOCK(*(Q->tail_lock)); NVM_STR2(Q->tail->next, node, sizeof(node_t *) * 8); #ifdef _FORCE_FAIL if (val == NUM_ITEMS / 2) exit(0); #endif NVM_STR2(Q->tail, node, sizeof(node_t *) * 8); NVM_UNLOCK(*(Q->tail_lock)); }