Beispiel #1
0
/*
 * operation_process -- processes registered operations
 *
 * The order of processing is important: persistent, transient.
 * This is because the transient entries that reside on persistent memory might
 * require write to a location that is currently occupied by a valid persistent
 * state but becomes a transient state after operation is processed.
 */
void
operation_process(struct operation_context *ctx)
{
	struct operation_entry *e;

	/*
	 * If there's exactly one persistent entry there's no need to involve
	 * the redo log. We can simply assign the value, the operation will be
	 * atomic.
	 */
	if (ctx->nentries[ENTRY_PERSISTENT] == 1) {
		e = &ctx->entries[ENTRY_PERSISTENT][0];

		VALGRIND_ADD_TO_TX(e->ptr, sizeof(uint64_t));

		PM_EQU((*e->ptr), (e->value));
		pmemobj_persist(ctx->pop, e->ptr, sizeof(uint64_t));

		VALGRIND_REMOVE_FROM_TX(e->ptr, sizeof(uint64_t));
	} else if (ctx->nentries[ENTRY_PERSISTENT] != 0) {
		operation_process_persistent_redo(ctx);
	}

	for (size_t i = 0; i < ctx->nentries[ENTRY_TRANSIENT]; ++i) {
		e = &ctx->entries[ENTRY_TRANSIENT][i];
		PM_EQU((*e->ptr), (e->value));
		/*
		 * Just in case that the entry was transient but in reality
		 * the variable is on persistent memory. This is true for
		 * chunk footers.
		 */
		VALGRIND_SET_CLEAN(e->ptr, sizeof(e->value));
	}
}
Beispiel #2
0
int
main(int argc, char *argv[])
{
	START(argc, argv, "obj_cpp_cond_var");

	if (argc != 2)
		UT_FATAL("usage: %s file-name", argv[0]);

	const char *path = argv[1];

	nvobj::pool<struct root> pop;

	try {
		pop = nvobj::pool<struct root>::create(
			path, LAYOUT, PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR);
	} catch (pmem::pool_error &pe) {
		UT_FATAL("!pool::create: %s %s", pe.what(), path);
	}

	cond_zero_test(pop);

	std::vector<reader_type> notify_functions(
		{reader_mutex, reader_mutex_pred, reader_lock, reader_lock_pred,
		 reader_mutex_until, reader_mutex_until_pred, reader_lock_until,
		 reader_lock_until_pred, reader_mutex_for,
		 reader_mutex_for_pred, reader_lock_for, reader_lock_for_pred});

	for (auto func : notify_functions) {
		int reset_value = 42;

		mutex_test(pop, true, false, write_notify, func);
		pop.get_root()->counter = reset_value;

		mutex_test(pop, true, true, write_notify, func);
		pop.get_root()->counter = reset_value;
	}

	std::vector<reader_type> not_notify_functions(
		{reader_mutex_until, reader_mutex_until_pred, reader_lock_until,
		 reader_lock_until_pred, reader_mutex_for,
		 reader_mutex_for_pred, reader_lock_for, reader_lock_for_pred});

	for (auto func : not_notify_functions) {
		int reset_value = 42;

		mutex_test(pop, false, false, write_notify, func);
		pop.get_root()->counter = reset_value;

		mutex_test(pop, false, true, write_notify, func);
		pop.get_root()->counter = reset_value;
	}

	/* pmemcheck related persist */
	pmemobj_persist(pop.get_handle(), &(pop.get_root()->counter),
			sizeof(pop.get_root()->counter));

	pop.close();

	DONE(nullptr);
}
Beispiel #3
0
int
main(int argc, char *argv[])
{
	if (argc != 2) {
		printf("usage: %s file-name\n", argv[0]);
		return 1;
	}

	PMEMobjpool *pop = pmemobj_create(argv[1], LAYOUT_NAME,
				PMEMOBJ_MIN_POOL, 0666);

	if (pop == NULL) {
		perror("pmemobj_create");
		return 1;
	}

	PMEMoid root = pmemobj_root(pop, sizeof(struct my_root));
	struct my_root *rootp = pmemobj_direct(root);

	char buf[MAX_BUF_LEN];
	if (scanf("%9s", buf) == EOF) {
		fprintf(stderr, "EOF\n");
		return 1;
	}

	rootp->len = strlen(buf);
	pmemobj_persist(pop, &rootp->len, sizeof(rootp->len));

	pmemobj_memcpy_persist(pop, rootp->buf, buf, rootp->len);

	pmemobj_close(pop);

	return 0;
}
static void
dummy_node_constructor(PMEMobjpool *pop, void *ptr, void *arg)
{
	struct dummy_node *n = ptr;
	int *test_val = arg;
	n->value = *test_val;
	pmemobj_persist(pop, &n->value, sizeof (n->value));
}
int
main(int argc, char *argv[])
{
	START(argc, argv, "obj_cpp_mutex_posix");

	if (argc != 2)
		UT_FATAL("usage: %s file-name", argv[0]);

	const char *path = argv[1];

	nvobj::pool<struct root> pop;

	try {
		pop = nvobj::pool<struct root>::create(
			path, LAYOUT, PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR);
	} catch (nvml::pool_error &pe) {
		UT_FATAL("!pool::create: %s %s", pe.what(), path);
	}

	timed_mtx_test(pop, increment_pint);
	UT_ASSERTeq(pop.get_root()->counter, num_threads * num_ops);

	timed_mtx_test(pop, decrement_pint);
	UT_ASSERTeq(pop.get_root()->counter, 0);

	timed_mtx_test(pop, trylock_test);
	UT_ASSERTeq(pop.get_root()->counter, num_threads);

	/* loop the next two tests */
	loop = true;

	timed_mtx_test(pop, trylock_until_test);
	UT_ASSERTeq(pop.get_root()->counter, 0);

	timed_mtx_test(pop, trylock_for_test);
	UT_ASSERTeq(pop.get_root()->counter, num_threads);

	loop = false;

	pop.get_root()->pmutex.lock();

	timed_mtx_test(pop, trylock_until_test);
	UT_ASSERTeq(pop.get_root()->counter, num_threads);

	timed_mtx_test(pop, trylock_for_test);
	UT_ASSERTeq(pop.get_root()->counter, num_threads);

	pop.get_root()->pmutex.unlock();

	/* pmemcheck related persist */
	pmemobj_persist(pop.get_handle(), &(pop.get_root()->counter),
			sizeof(pop.get_root()->counter));

	pop.close();

	DONE(NULL);
}
Beispiel #6
0
static int
dummy_node_constructor(PMEMobjpool *pop, void *ptr, void *arg)
{
	struct dummy_node *n = (struct dummy_node *)ptr;
	int *test_val = (int *)arg;
	n->value = *test_val;
	pmemobj_persist(pop, &n->value, sizeof(n->value));

	return 0;
}
Beispiel #7
0
/*
 * create_log_entry -- (internal) constructor for the log entry
 */
static int
create_log_entry(PMEMobjpool *pop, void *ptr, void *arg)
{
	struct log *logptr = ptr;
	struct create_args *carg = arg;
	logptr->size = carg->size;
	pmemobj_persist(pop, &logptr->size, sizeof(logptr->size));
	pmemobj_memcpy_persist(pop, logptr->data, carg->src, carg->size);

	return 0;
}
Beispiel #8
0
int
obj_constructor(PMEMobjpool *pop, void *ptr, void *arg)
{
	auto *arg_pack = static_cast<std::tuple<Args...> *>(arg);

	typedef typename make_index_sequence<Args...>::type index;
	try {
		create_object<T>(ptr, index(), *arg_pack);
	} catch (...) {
		return -1;
	}

	pmemobj_persist(pop, ptr, sizeof(T));

	return 0;
}
Beispiel #9
0
int
array_constructor(PMEMobjpool *pop, void *ptr, void *arg)
{
	std::size_t N = *static_cast<std::size_t *>(arg);

	T *tptr = static_cast<T *>(ptr);
	try {
		for (std::size_t i = 0; i < N; ++i)
			::new (tptr + i) T();
	} catch (...) {
		return -1;
	}

	pmemobj_persist(pop, ptr, sizeof(T) * N);

	return 0;
}
Beispiel #10
0
int
main(int argc, char *argv[])
{
	START(argc, argv, "obj_cpp_shared_mutex");

	if (argc != 2)
		UT_FATAL("usage: %s file-name", argv[0]);

	const char *path = argv[1];

	nvobj::pool<root> pop;

	try {
		pop = nvobj::pool<root>::create(path, LAYOUT, PMEMOBJ_MIN_POOL,
						S_IWUSR | S_IRUSR);
	} catch (nvml::pool_error &pe) {
		UT_FATAL("!pool::create: %s %s", pe.what(), path);
	}

	int expected = num_threads * num_ops * 2;
	mutex_test(pop, writer, reader);
	UT_ASSERTeq(pop.get_root()->counter, expected);

	/* trylocks are not tested as exhaustively */
	expected -= num_threads * 2;
	mutex_test(pop, writer_trylock, reader_trylock);
	UT_ASSERTeq(pop.get_root()->counter, expected);

	/* pmemcheck related persist */
	pmemobj_persist(pop.get_handle(), &(pop.get_root()->counter),
			sizeof(pop.get_root()->counter));

	pop.close();

	DONE(NULL);
}
Beispiel #11
0
	void
	persist(const persistent_ptr<Y> &ptr) noexcept
	{
		pmemobj_persist(this->pop, &ptr, sizeof(ptr));
	}
Beispiel #12
0
	void
	persist(const p<Y> &prop) noexcept
	{
		pmemobj_persist(this->pop, &prop, sizeof(Y));
	}
Beispiel #13
0
	/**
	 * Performs persist operation on a given chunk of memory.
	 *
	 * @param[in] addr address of memory chunk
	 * @param[in] len size of memory chunk
	 */
	void
	persist(const void *addr, size_t len) noexcept
	{
		pmemobj_persist(this->pop, addr, len);
	}
Beispiel #14
0
int
main(int argc, char *argv[])
{
	START(argc, argv, "obj_pvector");
	if (argc != 2)
		UT_FATAL("usage: %s [file]", argv[0]);

	const char *path = argv[1];

	PMEMobjpool *pop;
	if ((pop = pmemobj_create(path, "obj_pvector",
			PMEMOBJ_MIN_POOL * 3, S_IWUSR | S_IRUSR)) == NULL)
		UT_FATAL("!pmemobj_create: %s", path);

	PMEMoid root = pmemobj_root(pop, sizeof(struct test_root));
	struct test_root *r = (struct test_root *)pmemobj_direct(root);
	UT_ASSERTne(r, NULL);

	struct pvector_context *ctx = pvector_new(pop, &r->vec);

	uint64_t *val = pvector_push_back(ctx);
	*val = 5;

	val = pvector_push_back(ctx);
	*val = 10;

	val = pvector_push_back(ctx);
	*val = 15;

	uint64_t v;

	int n = 0;
	for (v = pvector_first(ctx); v != 0; v = pvector_next(ctx)) {
		if (n == 0)
			UT_ASSERTeq(v, 5);
		if (n == 1)
			UT_ASSERTeq(v, 10);
		if (n == 2)
			UT_ASSERTeq(v, 15);
		if (n == 3)
			UT_ASSERT(0);

		n++;
	}

	uint64_t removed = pvector_pop_back(ctx, NULL);
	UT_ASSERTeq(removed, 15);

	n = 0;
	for (v = pvector_first(ctx); v != 0; v = pvector_next(ctx)) {
		if (n == 0)
			UT_ASSERTeq(v, 5);
		if (n == 1)
			UT_ASSERTeq(v, 10);
		if (n == 3)
			UT_ASSERT(0);
		n++;
	}

	while (pvector_pop_back(ctx, vec_zero_entry) != 0)
		;

	pvector_delete(ctx);

	ctx = pvector_new(pop, &r->vec);
	for (int i = 0; i < PVECTOR_INSERT_VALUES; ++i) {
		val = pvector_push_back(ctx);
		UT_ASSERTne(val, NULL);
		*val = i;
		pmemobj_persist(pop, val, sizeof(*val));
	}

	n = 0;
	for (v = pvector_first(ctx); v != 0; v = pvector_next(ctx)) {
		UT_ASSERTeq(v, n);
		n++;
	}

	n = 0;
	for (int i = PVECTOR_INSERT_VALUES - 1; i >= 0; --i) {
		v = pvector_pop_back(ctx, NULL);
		UT_ASSERTeq(v, i);
	}

	UT_ASSERTeq(pvector_first(ctx), 0);

	pvector_delete(ctx);

	pmemobj_close(pop);

	DONE(NULL);
}