#include "unittest.h"
#define LAYOUT "obj_async_postcommit"
#define OIDS_PER_WORKER 10000
#define OIDS_PER_TX 10
struct worker_args {
PMEMobjpool *pop;
PMEMoid *oids;
};
static void *
worker(void *args)
{
struct worker_args *wa = args;
int freed = 0;
do {
TX_BEGIN(wa->pop) {
for (int i = 0; i < OIDS_PER_TX; ++i) {
pmemobj_tx_free(wa->oids[freed++]);
}
} TX_ONABORT {
UT_ASSERT(0);
} TX_END
} while (freed != OIDS_PER_WORKER);
return NULL;
}
static void *
postcommit_worker(void *arg)
{
PMEMobjpool *pop = (PMEMobjpool *)arg;
int ret = pmemobj_ctl_get(pop, "tx.post_commit.worker", pop);
UT_ASSERTeq(ret, 0);
return NULL;
}
static void
run_test(PMEMobjpool *pop, int nworkers_pc, int nworkers, int qdepth)
{
os_thread_t *th_pc = MALLOC(sizeof(*th_pc) * nworkers_pc);
int ret = pmemobj_ctl_set(pop, "tx.post_commit.queue_depth", &qdepth);
UT_ASSERTeq(ret, 0);
for (int i = 0; i < nworkers_pc; ++i) {
PTHREAD_CREATE(&th_pc[i],
NULL, postcommit_worker, pop);
}
os_thread_t *th = MALLOC(sizeof(*th) * nworkers);
struct worker_args *args = MALLOC(sizeof(*args) * nworkers);
for (int i = 0; i < nworkers; ++i) {
args[i].pop = pop;
args[i].oids = MALLOC(sizeof(PMEMoid) * OIDS_PER_WORKER);
for (int j = 0; j < OIDS_PER_WORKER; ++j) {
int ret = pmemobj_alloc(pop,
&args[i].oids[j], 1, 1, NULL, NULL);
UT_ASSERTeq(ret, 0);
}
}
for (int i = 0; i < nworkers; ++i) {
PTHREAD_CREATE(&th[i], NULL, worker, &args[i]);
}
for (int i = 0; i < nworkers; ++i) {
PTHREAD_JOIN(&th[i], NULL);
FREE(args[i].oids);
}
ret = pmemobj_ctl_get(pop, "tx.post_commit.stop", pop);
UT_ASSERTeq(ret, 0);
for (int i = 0; i < nworkers_pc; ++i)
PTHREAD_JOIN(&th_pc[i], NULL);
FREE(args);
FREE(th);
FREE(th_pc);
}
int
main(int argc, char *argv[])
{
START(argc, argv, "obj_async_postcommit");
if (argc != 2)
UT_FATAL("usage: %s file-name", argv[0]);
const char *path = argv[1];
PMEMobjpool *pop;
if ((pop = pmemobj_create(path, LAYOUT, PMEMOBJ_MIN_POOL * 10,
S_IWUSR | S_IRUSR)) == NULL)
UT_FATAL("!pmemobj_create: %s", path);
run_test(pop, 0, 2, 0);
run_test(pop, 1, 2, 128);
run_test(pop, 4, 4, 512);
run_test(pop, 1, 4, 1024);
run_test(pop, 0, 2, 0);
pmemobj_close(pop);
DONE(NULL);
}