Skip to content

Commit

Permalink
Merge pull request #6035 from janekmi/core_log_threshold-mt
Browse files Browse the repository at this point in the history
common: core_log_set/get_threshold MT unit tests
  • Loading branch information
janekmi committed Mar 6, 2024
2 parents ddf59f0 + 3e5569d commit 2edad18
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 20 deletions.
27 changes: 7 additions & 20 deletions src/core/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ _Atomic
void *Core_log_function_context;

/* threshold levels */
#ifdef ATOMIC_OPERATIONS_SUPPORTED
_Atomic
#endif /* ATOMIC_OPERATIONS_SUPPORTED */
enum core_log_level Core_log_threshold[] = {
CORE_LOG_THRESHOLD_DEFAULT,
CORE_LOG_THRESHOLD_AUX_DEFAULT
Expand Down Expand Up @@ -114,6 +111,7 @@ core_log_lib_info(void)
CORE_LOG_HARK("compiled with libndctl 63+");
#endif
}

/*
* core_log_set_function -- set the log function pointer either to
* a user-provided function pointer or to the default logging function.
Expand Down Expand Up @@ -164,21 +162,15 @@ core_log_set_threshold(enum core_log_threshold threshold,
if (level < CORE_LOG_LEVEL_HARK || level > CORE_LOG_LEVEL_DEBUG)
return EINVAL;

#ifdef ATOMIC_OPERATIONS_SUPPORTED
atomic_store_explicit(&Log_threshold[threshold], level,
__ATOMIC_SEQ_CST);
return 0;
#else
enum core_log_level level_old;
while (EAGAIN == core_log_get_threshold(threshold, &level_old))
;
(void) core_log_get_threshold(threshold, &level_old);

if (__sync_bool_compare_and_swap(&Core_log_threshold[threshold],
level_old, level))
return 0;
else
if (!__sync_bool_compare_and_swap(&Core_log_threshold[threshold],
level_old, level)) {
return EAGAIN;
#endif /* ATOMIC_OPERATIONS_SUPPORTED */
}

return 0;
}

/*
Expand All @@ -195,12 +187,7 @@ core_log_get_threshold(enum core_log_threshold threshold,
if (level == NULL)
return EINVAL;

#ifdef ATOMIC_OPERATIONS_SUPPORTED
*level = atomic_load_explicit(&Log_threshold[threshold],
__ATOMIC_SEQ_CST);
#else
*level = Core_log_threshold[threshold];
#endif /* ATOMIC_OPERATIONS_SUPPORTED */

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions src/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ OTHER_TESTS = \
core_log_internal\
core_log_default_function\
core_log_max\
core_log_mt\
checksum\
compat_incompat_features\
ctl_prefault\
Expand Down
1 change: 1 addition & 0 deletions src/test/core_log_mt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
core_log_mt
12 changes: 12 additions & 0 deletions src/test/core_log_mt/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright 2024, Intel Corporation

TARGET = core_log_mt
OBJS = core_log_mt.o

BUILD_STATIC_DEBUG=n
BUILD_STATIC_NONDEBUG=n

LIBPMEMCORE=nondebug

include ../Makefile.inc
45 changes: 45 additions & 0 deletions src/test/core_log_mt/TESTS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!../env.py
# SPDX-License-Identifier: BSD-3-Clause
# Copyright 2024, Intel Corporation
#


import testframework as t
from testframework import granularity as g


@g.require_granularity(g.ANY)
@t.require_build('nondebug')
class CORE_LOG_MT(t.BaseTest):
test_type = t.Short

def run(self, ctx):
ctx.exec('core_log_mt', self.test_case)


class THRESHOLD(CORE_LOG_MT):
test_case = 'test_threshold'


class THRESHOLD_AUX(CORE_LOG_MT):
test_case = 'test_threshold_aux'


@t.require_valgrind_enabled('helgrind')
class TEST0(THRESHOLD):
pass


@t.require_valgrind_enabled('drd')
class TEST1(THRESHOLD):
pass


@t.require_valgrind_enabled('helgrind')
class TEST2(THRESHOLD_AUX):
pass


@t.require_valgrind_enabled('drd')
class TEST3(THRESHOLD_AUX):
pass
105 changes: 105 additions & 0 deletions src/test/core_log_mt/core_log_mt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// SPDX-License-Identifier: BSD-3-Clause
/* Copyright 2024, Intel Corporation */

/*
* core_log_internal.c -- unit test to CORE_LOG_...
*/

#include "unittest.h"
#include "log_internal.h"

#define NO_ARGS_CONSUMED 0

#define THREADS_IN_GROUP 10
#define TOTAL_THREADS (THREADS_IN_GROUP * 2)
#define OP_REDO 4096

struct test_threshold_helper_ctx {
enum core_log_threshold threshold;
enum core_log_level level;
} threshold_helper_ [TOTAL_THREADS];

static void *
test_threshold_helper_set(void *arg)
{
struct test_threshold_helper_ctx *ctx =
(struct test_threshold_helper_ctx *)arg;
for (int i = 0; i < OP_REDO; ++i) {
core_log_set_threshold(ctx->threshold, ctx->level);
}
return NULL;
}

static void *
test_threshold_helper_get(void *arg)
{
struct test_threshold_helper_ctx *ctx =
(struct test_threshold_helper_ctx *)arg;
for (int i = 0; i < OP_REDO; ++i) {
core_log_get_threshold(ctx->threshold, &ctx->level);
}
(void) ctx->level;
return NULL;
}

static void
test_threshold_helper(enum core_log_threshold threshold)
{
os_thread_t threads[TOTAL_THREADS];

/* core_log_set_threshold() threads */
for (int idx = 0; idx < THREADS_IN_GROUP; idx++) {
threshold_helper_[idx].threshold = threshold;
threshold_helper_[idx].level =
(enum core_log_level)(idx % CORE_LOG_LEVEL_MAX);
THREAD_CREATE(&threads[idx], 0, test_threshold_helper_set,
(void *)&threshold_helper_[idx]);
}

/* core_log_get_threshold() threads */
for (int idx = THREADS_IN_GROUP; idx < TOTAL_THREADS; idx++) {
threshold_helper_[idx].threshold = threshold;
THREAD_CREATE(&threads[idx], 0, test_threshold_helper_get,
(void *)&threshold_helper_[idx]);
}

for (int idx = 0; idx < TOTAL_THREADS; idx++) {
void *retval;
THREAD_JOIN(&threads[idx], &retval);
}
}

/* Run core_log_set/get_threshold(CORE_LOG_THRESHOLD, ...) in parallel. */
static int
test_threshold(const struct test_case *tc, int argc, char *argv[])
{
test_threshold_helper(CORE_LOG_THRESHOLD);
return NO_ARGS_CONSUMED;
}

/* Run core_log_set/get_threshold(CORE_LOG_THRESHOLD_AUX, ...) in parallel. */
static int
test_threshold_aux(const struct test_case *tc, int argc, char *argv[])
{
test_threshold_helper(CORE_LOG_THRESHOLD_AUX);
return NO_ARGS_CONSUMED;
}

/*
* A Valgrind tool external to the test binary is assumed to monitor
* the execution and assess synchronisation correctness.
*/
static struct test_case test_cases[] = {
TEST_CASE(test_threshold),
TEST_CASE(test_threshold_aux),
};

#define NTESTS ARRAY_SIZE(test_cases)

int
main(int argc, char *argv[])
{
START(argc, argv, "core_log_mt");
TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS);
DONE(NULL);
}

0 comments on commit 2edad18

Please sign in to comment.