Skip to content

Commit

Permalink
masync: add memset operation for the thread data mover
Browse files Browse the repository at this point in the history
  • Loading branch information
damian committed Apr 11, 2022
1 parent 3095e0a commit 968209b
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 4 deletions.
5 changes: 3 additions & 2 deletions doc/data_mover_threads_get_vdm.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@ Thread data mover implementation supports following operations:

* **vdm_memcpy**(3) - memory copy operation
* **vdm_memmove**(3) - memory move operation
* **vdm_memset**(3) - memory set operation

# RETURN VALUE #

The **data_mover_threads_get_vdm**() function returns a pointer to *struct vdm* structure.

# SEE ALSO #

**vdm_memcpy**(3), **vdm_memmove**(3), **miniasync**(7),
**miniasync_vdm_threads**(7) and **<https://pmem.io>**
**vdm_memcpy**(3), **vdm_memmove**(3), **vdm_memset**(3),
**miniasync**(7), **miniasync_vdm_threads**(7) and **<https://pmem.io>**
3 changes: 2 additions & 1 deletion doc/miniasync_vdm_threads.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Thread data mover supports following operations:

* **vdm_memcpy**(3) - memory copy operation
* **vdm_memmove**(3) - memory move operation
* **vdm_memset**(3) - memory set operation

Thread data mover supports following notifer types:

Expand All @@ -78,5 +79,5 @@ struct vdm_memcpy_future memcpy_fut =

**data_mover_threads_default**(3), **data_mover_threads_get_vdm**(3),
**data_mover_threads_new**(3), **vdm_memcpy**(3), **vdm_memmove**(3),
**miniasync**(7), **miniasync_future**(7),
**vdm_memset**(3), **miniasync**(7), **miniasync_future**(7),
**miniasync_vdm**(7) and **<https://pmem.io>**
28 changes: 27 additions & 1 deletion src/data_mover_threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
struct data_mover_threads_op_fns {
memcpy_fn op_memcpy;
memmove_fn op_memmove;
memset_fn op_memset;
};

struct data_mover_threads {
Expand Down Expand Up @@ -67,9 +68,22 @@ void data_mover_threads_set_memmove_fn(struct data_mover_threads *dmt,
dmt->op_fns.op_memmove = op_memmove;
}

/*
* Standard implementation of memset used if none was specified by the user.
*/
void *std_memset(void *str, int c, size_t n, unsigned flags) {
return memset(str, c, n);
}

void data_mover_threads_set_memset_fn(struct data_mover_threads *dmt,
memset_fn op_memset) {
dmt->op_fns.op_memset = op_memset;
}

static struct data_mover_threads_op_fns op_fns_default = {
.op_memcpy = std_memcpy,
.op_memmove = std_memmove
.op_memmove = std_memmove,
.op_memset = std_memset,
};

/*
Expand All @@ -95,6 +109,13 @@ data_mover_threads_do_operation(struct data_mover_threads_data *data,
op_memmove(mdata->dest,
mdata->src, mdata->n, (unsigned)mdata->flags);
} break;
case VDM_OPERATION_MEMSET: {
struct vdm_operation_data_memset *mdata
= &data->op.data.memset;
memset_fn op_memset = dmt->op_fns.op_memset;
op_memset(mdata->str,
mdata->c, mdata->n, (unsigned)mdata->flags);
} break;
default:
ASSERT(0); /* unreachable */
break;
Expand Down Expand Up @@ -202,6 +223,11 @@ data_mover_threads_operation_delete(void *data,
output->output.memmove.dest =
operation->data.memmove.dest;
break;
case VDM_OPERATION_MEMSET:
output->type = VDM_OPERATION_MEMSET;
output->output.memset.str =
operation->data.memset.str;
break;
default:
ASSERT(0);
}
Expand Down
4 changes: 4 additions & 0 deletions src/include/libminiasync/data_mover_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ typedef void *(*memcpy_fn)(void *dst, const void *src,
size_t n, unsigned flags);
typedef void *(*memmove_fn)(void *dst, const void *src,
size_t n, unsigned flags);
typedef void *(*memset_fn)(void *str, int c, size_t n,
unsigned flags);

struct data_mover_threads;
struct data_mover_threads *data_mover_threads_new(size_t nthreads,
Expand All @@ -25,6 +27,8 @@ void data_mover_threads_set_memcpy_fn(struct data_mover_threads *dmt,
memcpy_fn op_memcpy);
void data_mover_threads_set_memmove_fn(struct data_mover_threads *dmt,
memmove_fn op_memmove);
void data_mover_threads_set_memset_fn(struct data_mover_threads *dmt,
memset_fn op_memset);

#ifdef __cplusplus
}
Expand Down
8 changes: 8 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ set(SOURCES_VDM_OPERATION_FUTURE_POLL
set(SOURCES_MEMMOVE_THREADS_TEST
memmove_threads/memmove_threads.c)

set(SOURCES_MEMSET_THREADS_TEST
memset_threads/memset_threads.c)

add_custom_target(tests)

add_flag(-Wall)
Expand Down Expand Up @@ -105,6 +108,10 @@ add_link_executable(memmove_threads
"${SOURCES_MEMMOVE_THREADS_TEST}"
"${LIBS_BASIC}")

add_link_executable(memset_threads
"${SOURCES_MEMSET_THREADS_TEST}"
"${LIBS_BASIC}")

# add test using test function defined in the ctest_helpers.cmake file
test("dummy" "dummy" test_dummy none)
test("dummy_drd" "dummy" test_dummy drd)
Expand All @@ -119,6 +126,7 @@ test("memmove_sync" "memmove_sync" test_memmove_sync none)
test("vdm" "vdm" test_vdm none)
test("memset_sync" "memset_sync" test_memset_sync none)
test("memmove_threads" "memmove_threads" test_memmove_threads none)
test("memset_threads" "memset_threads" test_memset_threads none)

# add tests running examples only if they are built
if(BUILD_EXAMPLES)
Expand Down
135 changes: 135 additions & 0 deletions tests/memset_threads/memset_threads.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// SPDX-License-Identifier: BSD-3-Clause
/* Copyright 2022, Intel Corporation */

#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "libminiasync.h"
#include "core/os.h"
#include "test_helpers.h"

int
test_thread_memset_single(size_t str_len)
{
int ret = 0;
unsigned seed = (unsigned)time(NULL);
fprintf(stdout, "seed: %u\n", seed);
struct runtime *r = runtime_new();
struct data_mover_threads *dmt = data_mover_threads_default();

if (dmt == NULL) {
runtime_delete(r);
return 1;
}

struct vdm *vdm = data_mover_threads_get_vdm(dmt);

char *buf_a = malloc(str_len);

if (buf_a == NULL)
UT_FATAL("buffer out of memory");

char symbol = (char)os_rand_r(&seed) % 256;

struct vdm_operation_future test_memset_fut =
vdm_memset(vdm, buf_a, symbol, str_len, 0);

struct future *future_memset = FUTURE_AS_RUNNABLE(&test_memset_fut);

runtime_wait(r, future_memset);

for (size_t i = 0; i < str_len; i++) {
UT_ASSERTeq(buf_a[i], symbol);
}

free(buf_a);

runtime_delete(r);
data_mover_threads_delete(dmt);

return ret;
}

int
test_thread_memset_multiple(size_t str_len)
{
int ret = 0;
unsigned seed = (unsigned)time(NULL);
fprintf(stdout, "seed: %u\n", seed);
struct runtime *r = runtime_new();
struct data_mover_threads *dmt = data_mover_threads_default();

if (dmt == NULL) {
fprintf(stderr,
"error while creating synchronous data mover");
runtime_delete(r);
return 1;
}

struct vdm *vdm = data_mover_threads_get_vdm(dmt);

char *buf_a = malloc(str_len);
char *buf_b = malloc(str_len);

if (!buf_a || !buf_b)
UT_FATAL("buffers out of memory");

char symbol_first = (char)os_rand_r(&seed) % 256;
char symbol_second = (char)os_rand_r(&seed) % 256;

struct future **futures = malloc(sizeof(struct future *) * 4);
if (futures == NULL)
UT_FATAL("futures out of memory");

struct vdm_operation_future memmove_fut_symbol_f_to_a =
vdm_memset(vdm, buf_a, symbol_first, str_len / 2, 0);

struct vdm_operation_future memmove_fut_symbol_s_to_a =
vdm_memset(vdm, buf_a + str_len / 2, symbol_second,
str_len / 2, 0);

struct vdm_operation_future memmove_fut_symbol_s_to_b =
vdm_memset(vdm, buf_b, symbol_second, str_len / 2, 0);

struct vdm_operation_future memmove_fut_symbol_f_to_b =
vdm_memset(vdm, buf_b + str_len / 2, symbol_first,
str_len / 2, 0);

futures[0] = FUTURE_AS_RUNNABLE(&memmove_fut_symbol_f_to_a);
futures[1] = FUTURE_AS_RUNNABLE(&memmove_fut_symbol_s_to_a);
futures[2] = FUTURE_AS_RUNNABLE(&memmove_fut_symbol_s_to_b);
futures[3] = FUTURE_AS_RUNNABLE(&memmove_fut_symbol_f_to_b);

runtime_wait_multiple(r, futures, 4);

for (size_t i = 0; i < str_len / 2; i++) {
UT_ASSERTeq(buf_a[i], symbol_first);
UT_ASSERTeq(buf_b[i], symbol_second);
}

for (size_t i = str_len / 2; i < str_len; i++) {
UT_ASSERTeq(buf_a[i], symbol_second);
UT_ASSERTeq(buf_b[i], symbol_first);
}

free(buf_a);
free(buf_b);
free(futures);

runtime_delete(r);
data_mover_threads_delete(dmt);

return ret;
}

int
main(void)
{
return
test_thread_memset_single(100000000) ||
test_thread_memset_single(300000000) ||
test_thread_memset_single(500000000) ||
test_thread_memset_multiple(100000000) ||
test_thread_memset_multiple(300000000) ||
test_thread_memset_multiple(500000000);
}
11 changes: 11 additions & 0 deletions tests/memset_threads/test_memset_threads.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright 2022, Intel Corporation

include(${SRC_DIR}/cmake/test_helpers.cmake)

setup()

execute(0 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${BUILD}/memset_threads)
execute_assert_pass(${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${BUILD}/memset_threads)

cleanup()

0 comments on commit 968209b

Please sign in to comment.