Spdk/test/common/lib/ut_multithread.c
paul luse a6dbe3721e update Intel copyright notices
per Intel policy to include file commit date using git cmd
below.  The policy does not apply to non-Intel (C) notices.

git log --follow -C90% --format=%ad --date default <file> | tail -1

and then pull just the 4 digit year from the result.

Intel copyrights were not added to files where Intel either had
no contribution ot the contribution lacked substance (ie license
header updates, formatting changes, etc).  Contribution date used
"--follow -C95%" to get the most accurate date.

Note that several files in this patch didn't end the license/(c)
block with a blank comment line so these were added as the vast
majority of files do have this last blank line.  Simply there for
consistency.

Signed-off-by: paul luse <paul.e.luse@intel.com>
Change-Id: Id5b7ce4f658fe87132f14139ead58d6e285c04d4
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15192
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Community-CI: Mellanox Build Bot
2022-11-10 08:28:53 +00:00

186 lines
3.5 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2017 Intel Corporation.
* All rights reserved.
*/
#include "spdk_cunit.h"
#include "spdk/thread.h"
#include "spdk_internal/mock.h"
#include "common/lib/test_env.c"
static uint32_t g_ut_num_threads;
int allocate_threads(int num_threads);
void free_threads(void);
void poll_threads(void);
bool poll_thread(uintptr_t thread_id);
bool poll_thread_times(uintptr_t thread_id, uint32_t max_polls);
struct ut_msg {
spdk_msg_fn fn;
void *ctx;
TAILQ_ENTRY(ut_msg) link;
};
struct ut_thread {
struct spdk_thread *thread;
struct spdk_io_channel *ch;
};
struct ut_thread *g_ut_threads;
#define INVALID_THREAD 0x1000
static uint64_t g_ut_thread_id = INVALID_THREAD;
static void
set_thread(uintptr_t thread_id)
{
g_ut_thread_id = thread_id;
if (thread_id == INVALID_THREAD) {
spdk_set_thread(NULL);
} else {
spdk_set_thread(g_ut_threads[thread_id].thread);
}
}
int
allocate_threads(int num_threads)
{
struct spdk_thread *thread;
uint32_t i;
spdk_thread_lib_init(NULL, 0);
g_ut_num_threads = num_threads;
g_ut_threads = calloc(num_threads, sizeof(*g_ut_threads));
assert(g_ut_threads != NULL);
for (i = 0; i < g_ut_num_threads; i++) {
set_thread(i);
thread = spdk_thread_create(NULL, NULL);
assert(thread != NULL);
g_ut_threads[i].thread = thread;
}
set_thread(INVALID_THREAD);
return 0;
}
void
free_threads(void)
{
uint32_t i, num_threads;
struct spdk_thread *thread;
for (i = 0; i < g_ut_num_threads; i++) {
set_thread(i);
thread = g_ut_threads[i].thread;
spdk_thread_exit(thread);
}
num_threads = g_ut_num_threads;
while (num_threads != 0) {
for (i = 0; i < g_ut_num_threads; i++) {
set_thread(i);
thread = g_ut_threads[i].thread;
if (thread == NULL) {
continue;
}
if (spdk_thread_is_exited(thread)) {
g_ut_threads[i].thread = NULL;
num_threads--;
spdk_thread_destroy(thread);
} else {
spdk_thread_poll(thread, 0, 0);
}
}
}
g_ut_num_threads = 0;
free(g_ut_threads);
g_ut_threads = NULL;
spdk_thread_lib_fini();
}
bool
poll_thread_times(uintptr_t thread_id, uint32_t max_polls)
{
bool busy = false;
struct ut_thread *thread = &g_ut_threads[thread_id];
uintptr_t original_thread_id;
uint32_t polls_executed = 0;
uint64_t now;
if (max_polls == 0) {
/* If max_polls is set to 0,
* poll until no operation is pending. */
return poll_thread(thread_id);
}
assert(thread_id != (uintptr_t)INVALID_THREAD);
assert(thread_id < g_ut_num_threads);
original_thread_id = g_ut_thread_id;
set_thread(INVALID_THREAD);
now = spdk_get_ticks();
while (polls_executed < max_polls) {
if (spdk_thread_poll(thread->thread, 1, now) > 0) {
busy = true;
}
now = spdk_thread_get_last_tsc(thread->thread);
polls_executed++;
}
set_thread(original_thread_id);
return busy;
}
bool
poll_thread(uintptr_t thread_id)
{
bool busy = false;
struct ut_thread *thread = &g_ut_threads[thread_id];
uintptr_t original_thread_id;
uint64_t now;
assert(thread_id != (uintptr_t)INVALID_THREAD);
assert(thread_id < g_ut_num_threads);
original_thread_id = g_ut_thread_id;
set_thread(INVALID_THREAD);
now = spdk_get_ticks();
while (spdk_thread_poll(thread->thread, 0, now) > 0) {
now = spdk_thread_get_last_tsc(thread->thread);
busy = true;
}
set_thread(original_thread_id);
return busy;
}
void
poll_threads(void)
{
while (true) {
bool busy = false;
for (uint32_t i = 0; i < g_ut_num_threads; i++) {
busy = busy || poll_thread(i);
}
if (!busy) {
break;
}
}
}