ram_reply_t ramtra_pop(void **ptr_arg, ramtra_trash_t *trash_arg) { void *p = NULL; ram_reply_t e = RAM_REPLY_INSANE; RAM_FAIL_NOTNULL(ptr_arg); *ptr_arg = NULL; RAM_FAIL_NOTNULL(trash_arg); RAM_FAIL_TRAP(rammtx_wait(&trash_arg->ramtrat_mutex)); p = RAMSLST_NEXT(&trash_arg->ramtrat_items); e = ramslst_remove(&trash_arg->ramtrat_items); trash_arg->ramtrat_size -= (RAM_REPLY_OK == e); /* if i fail to quit the mutex, the process can't continue meaningfully. */ RAM_FAIL_PANIC(rammtx_quit(&trash_arg->ramtrat_mutex)); if (RAM_REPLY_OK == e || RAM_REPLY_NOTFOUND == e) { *ptr_arg = p; return e; } else { RAM_FAIL_TRAP(e); /* i shouldn't be able to get here, since 'e' is known to not be RAM_REPLY_OK. */ return RAM_REPLY_INSANE; } }
ram_reply_t ramlin_waitonbarrier(ramlin_barrier_t *barrier_arg) { ram_reply_t e = RAM_REPLY_INSANE; RAM_FAIL_NOTNULL(barrier_arg); RAM_FAIL_TRAP(rammtx_wait(&barrier_arg->ramlinb_mutex)); e = ramlin_waitonbarrier2(barrier_arg); /* there's no point in continuing if i fail to release the mutex. */ /* TODO: ..._quitmutex() looks like it might be a candidate to succeed- * or-die. */ RAM_FAIL_PANIC(rammtx_quit(&barrier_arg->ramlinb_mutex)); return e; }
ram_reply_t ramtra_push(ramtra_trash_t *trash_arg, void *ptr_arg) { ram_reply_t e = RAM_REPLY_INSANE; RAM_FAIL_NOTNULL(trash_arg); RAM_FAIL_NOTNULL(ptr_arg); RAM_FAIL_TRAP(rammtx_wait(&trash_arg->ramtrat_mutex)); e = ramslst_insert((ramslst_slist_t *)ptr_arg, &trash_arg->ramtrat_items); trash_arg->ramtrat_size += (RAM_REPLY_OK == e); /* if i fail to quit the mutex, the process can't continue meaningfully. */ RAM_FAIL_PANIC(rammtx_quit(&trash_arg->ramtrat_mutex)); RAM_FAIL_TRAP(e); return RAM_REPLY_OK; }
ram_reply_t ramtra_size(size_t *size_arg, ramtra_trash_t *trash_arg) { size_t sz = 0; RAM_FAIL_NOTNULL(size_arg); *size_arg = 0; RAM_FAIL_NOTNULL(trash_arg); RAM_FAIL_TRAP(rammtx_wait(&trash_arg->ramtrat_mutex)); sz = trash_arg->ramtrat_size; /* if i fail to quit the mutex, the process can't continue meaningfully. */ RAM_FAIL_PANIC(rammtx_quit(&trash_arg->ramtrat_mutex)); *size_arg = sz; return RAM_REPLY_OK; }
ram_reply_t ramtest_next(size_t *next_arg, ramtest_test_t *test_arg) { size_t i = 0; size_t j = 0; RAM_FAIL_NOTNULL(next_arg); RAM_FAIL_NOTNULL(test_arg); j = test_arg->ramtestt_params.ramtestp_alloccount; RAM_FAIL_TRAP(rammtx_wait(&test_arg->ramtestt_mtx)); i = test_arg->ramtestt_nextrec; if (i < j) ++test_arg->ramtestt_nextrec; RAM_FAIL_PANIC(rammtx_quit(&test_arg->ramtestt_mtx)); *next_arg = i; return RAM_REPLY_OK; }
ram_reply_t ramtra_foreach(ramtra_trash_t *trash_arg, ramtra_foreach_t func_arg, void *context_arg) { ram_reply_t e = RAM_REPLY_INSANE; ramtra_foreachadaptor_t fea = {0}; RAM_FAIL_NOTNULL(trash_arg); RAM_FAIL_NOTNULL(func_arg); fea.ramtrafea_function = func_arg; fea.ramtrafea_context = context_arg; RAM_FAIL_TRAP(rammtx_wait(&trash_arg->ramtrat_mutex)); /* i don't include the first element in 'ramtrat_items' because it is a sentinel and doesn't * actually hold a trashed pointer. */ e = ramslst_foreach(RAMSLST_NEXT(&trash_arg->ramtrat_items), &ramtra_foreachadaptor, &fea); /* if i fail to quit the mutex, the process can't continue meaningfully. */ RAM_FAIL_PANIC(rammtx_quit(&trash_arg->ramtrat_mutex)); RAM_FAIL_TRAP(e); return RAM_REPLY_OK; }
ram_reply_t ramtest_thread2(ramtest_test_t *test_arg, size_t threadidx_arg) { size_t i = 0; ram_reply_t e = RAM_REPLY_INSANE; int cachedflag = 0; ramtest_allocdesc_t cached = {0}; RAM_FAIL_NOTNULL(test_arg); RAM_FAIL_EXPECT(RAM_REPLY_RANGEFAIL, threadidx_arg < test_arg->ramtestt_params.ramtestp_threadcount); while ((RAM_REPLY_OK == (e = ramtest_next(&i, test_arg))) && i < test_arg->ramtestt_params.ramtestp_alloccount) { ramtest_allocrec_t *info = NULL; ramtest_allocdesc_t condemned = {0}; info = &test_arg->ramtestt_records[test_arg->ramtestt_sequence[i]]; /* i don't want to allocate while i'm holding the allocation record * mutex, so i'll prepare an allocation ahead of time. */ if (!cachedflag) { RAM_FAIL_TRAP(ramtest_alloc(&cached, test_arg, threadidx_arg)); } /* there's actually a race condition between the call to * *ramtest_next()* and this point. the worst that could happen * (i think) is that the first thread to draw a given record's index * might end up being the deallocating thread. */ RAM_FAIL_TRAP(rammtx_wait(&info->ramtestar_mtx)); /* if there's a pointer stored in *info->ramtestar_desc.ramtestad_ptr* * we'll assume we're the allocating thread. otherwise, we need to * deallocate. */ if (NULL == info->ramtestar_desc.ramtestad_ptr) { info->ramtestar_desc = cached; /* i signal to the next loop iteration that i'll need a new * allocation. */ cachedflag = 0; } else condemned = info->ramtestar_desc; RAM_FAIL_PANIC(rammtx_quit(&info->ramtestar_mtx)); /* if i have a condemned pointer, i need to deallocate it. */ if (condemned.ramtestad_ptr != NULL) { RAM_FAIL_TRAP(ramtest_dealloc(&condemned, test_arg, threadidx_arg)); condemned.ramtestad_ptr = NULL; } RAM_FAIL_TRAP(test_arg->ramtestt_params.ramtestp_check( test_arg->ramtestt_params.ramtestp_extra, threadidx_arg)); } RAM_FAIL_TRAP(test_arg->ramtestt_params.ramtestp_flush( test_arg->ramtestt_params.ramtestp_extra, threadidx_arg)); RAM_FAIL_TRAP(test_arg->ramtestt_params.ramtestp_check( test_arg->ramtestt_params.ramtestp_extra, threadidx_arg)); return RAM_REPLY_OK; }