Add rump-based test cases for threadpool(9).
This commit is contained in:
parent
c40d4bbfb3
commit
77118773d1
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.799 2018/12/24 16:58:54 thorpej Exp $
|
||||
# $NetBSD: mi,v 1.800 2018/12/24 21:42:05 thorpej Exp $
|
||||
#
|
||||
# Note: don't delete entries from here - mark them as "obsolete" instead.
|
||||
#
|
||||
@ -3468,6 +3468,7 @@
|
||||
./usr/tests/rump/rumpkern/t_modlinkset tests-rump-tests atf,rump
|
||||
./usr/tests/rump/rumpkern/t_signals tests-rump-tests atf,rump
|
||||
./usr/tests/rump/rumpkern/t_sp tests-rump-tests atf,rump
|
||||
./usr/tests/rump/rumpkern/t_threadpool tests-rump-tests atf,rump
|
||||
./usr/tests/rump/rumpkern/t_threads tests-rump-tests atf,rump
|
||||
./usr/tests/rump/rumpkern/t_tsleep tests-rump-tests atf,rump
|
||||
./usr/tests/rump/rumpkern/t_vm tests-rump-tests atf,rump
|
||||
|
@ -1,10 +1,11 @@
|
||||
# $NetBSD: Makefile,v 1.6 2017/09/29 12:42:36 maya Exp $
|
||||
# $NetBSD: Makefile,v 1.7 2018/12/24 21:42:05 thorpej Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
LIB= kernspace
|
||||
SRCS= thread.c busypage.c tsleep.c alloc.c lockme.c workqueue.c sendsig.c
|
||||
SRCS= thread.c threadpool.c busypage.c tsleep.c alloc.c lockme.c \
|
||||
workqueue.c sendsig.c
|
||||
|
||||
RUMPTOP=${NETBSDSRCDIR}/sys/rump
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: kernspace.h,v 1.6 2017/12/28 07:10:25 ozaki-r Exp $ */
|
||||
/* $NetBSD: kernspace.h,v 1.7 2018/12/24 21:42:05 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 2010, 2018 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -46,4 +46,10 @@ void rumptest_workqueue_wait(void);
|
||||
void rumptest_sendsig(char *);
|
||||
void rumptest_localsig(int);
|
||||
|
||||
void rumptest_threadpool_unbound_lifecycle(void);
|
||||
void rumptest_threadpool_percpu_lifecycle(void);
|
||||
void rumptest_threadpool_unbound_schedule(void);
|
||||
void rumptest_threadpool_percpu_schedule(void);
|
||||
void rumptest_threadpool_job_cancel(void);
|
||||
|
||||
#endif /* _TESTS_RUMP_KERNSPACE_KERNSPACE_H_ */
|
||||
|
234
tests/rump/kernspace/threadpool.c
Normal file
234
tests/rump/kernspace/threadpool.c
Normal file
@ -0,0 +1,234 @@
|
||||
/* $NetBSD: threadpool.c,v 1.1 2018/12/24 21:42:05 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2018 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: threadpool.c,v 1.1 2018/12/24 21:42:05 thorpej Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/threadpool.h>
|
||||
|
||||
#include "kernspace.h"
|
||||
|
||||
void
|
||||
rumptest_threadpool_unbound_lifecycle(void)
|
||||
{
|
||||
threadpool_t *pool0, *pool1, *pool2;
|
||||
int error;
|
||||
|
||||
error = threadpool_get(&pool0, PRI_NONE);
|
||||
KASSERT(error == 0);
|
||||
|
||||
error = threadpool_get(&pool1, PRI_NONE);
|
||||
KASSERT(error == 0);
|
||||
|
||||
KASSERT(pool0 == pool1);
|
||||
|
||||
error = threadpool_get(&pool2, PRI_KERNEL_RT);
|
||||
KASSERT(error == 0);
|
||||
|
||||
KASSERT(pool0 != pool2);
|
||||
|
||||
threadpool_put(pool0, PRI_NONE);
|
||||
threadpool_put(pool1, PRI_NONE);
|
||||
threadpool_put(pool2, PRI_KERNEL_RT);
|
||||
}
|
||||
|
||||
void
|
||||
rumptest_threadpool_percpu_lifecycle(void)
|
||||
{
|
||||
threadpool_percpu_t *pcpu0, *pcpu1, *pcpu2;
|
||||
int error;
|
||||
|
||||
error = threadpool_percpu_get(&pcpu0, PRI_NONE);
|
||||
KASSERT(error == 0);
|
||||
|
||||
error = threadpool_percpu_get(&pcpu1, PRI_NONE);
|
||||
KASSERT(error == 0);
|
||||
|
||||
KASSERT(pcpu0 == pcpu1);
|
||||
|
||||
error = threadpool_percpu_get(&pcpu2, PRI_KERNEL_RT);
|
||||
KASSERT(error == 0);
|
||||
|
||||
KASSERT(pcpu0 != pcpu2);
|
||||
|
||||
threadpool_percpu_put(pcpu0, PRI_NONE);
|
||||
threadpool_percpu_put(pcpu1, PRI_NONE);
|
||||
threadpool_percpu_put(pcpu2, PRI_KERNEL_RT);
|
||||
}
|
||||
|
||||
struct test_job_data {
|
||||
kmutex_t mutex;
|
||||
kcondvar_t cond;
|
||||
unsigned int count;
|
||||
threadpool_job_t job;
|
||||
};
|
||||
|
||||
#define FINAL_COUNT 12345
|
||||
|
||||
static void
|
||||
test_job_func_schedule(threadpool_job_t *job)
|
||||
{
|
||||
struct test_job_data *data =
|
||||
container_of(job, struct test_job_data, job);
|
||||
|
||||
mutex_enter(&data->mutex);
|
||||
KASSERT(data->count != FINAL_COUNT);
|
||||
data->count++;
|
||||
cv_broadcast(&data->cond);
|
||||
threadpool_job_done(job);
|
||||
mutex_exit(&data->mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
test_job_func_cancel(threadpool_job_t *job)
|
||||
{
|
||||
struct test_job_data *data =
|
||||
container_of(job, struct test_job_data, job);
|
||||
|
||||
mutex_enter(&data->mutex);
|
||||
data->count = 1;
|
||||
cv_broadcast(&data->cond);
|
||||
while (data->count != FINAL_COUNT - 1)
|
||||
cv_wait(&data->cond, &data->mutex);
|
||||
data->count = FINAL_COUNT;
|
||||
cv_broadcast(&data->cond);
|
||||
threadpool_job_done(job);
|
||||
mutex_exit(&data->mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
init_test_job_data(struct test_job_data *data, threadpool_job_fn_t fn)
|
||||
{
|
||||
mutex_init(&data->mutex, MUTEX_DEFAULT, IPL_NONE);
|
||||
cv_init(&data->cond, "testjob");
|
||||
threadpool_job_init(&data->job, fn, &data->mutex, "testjob");
|
||||
data->count = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
fini_test_job_data(struct test_job_data *data)
|
||||
{
|
||||
threadpool_job_destroy(&data->job);
|
||||
cv_destroy(&data->cond);
|
||||
mutex_destroy(&data->mutex);
|
||||
}
|
||||
|
||||
void
|
||||
rumptest_threadpool_unbound_schedule(void)
|
||||
{
|
||||
struct test_job_data data;
|
||||
threadpool_t *pool;
|
||||
int error;
|
||||
|
||||
error = threadpool_get(&pool, PRI_NONE);
|
||||
KASSERT(error == 0);
|
||||
|
||||
init_test_job_data(&data, test_job_func_schedule);
|
||||
|
||||
mutex_enter(&data.mutex);
|
||||
while (data.count != FINAL_COUNT) {
|
||||
threadpool_schedule_job(pool, &data.job);
|
||||
error = cv_timedwait(&data.cond, &data.mutex, hz * 2);
|
||||
KASSERT(error != EWOULDBLOCK);
|
||||
}
|
||||
mutex_exit(&data.mutex);
|
||||
|
||||
fini_test_job_data(&data);
|
||||
|
||||
threadpool_put(pool, PRI_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
rumptest_threadpool_percpu_schedule(void)
|
||||
{
|
||||
struct test_job_data data;
|
||||
threadpool_percpu_t *pcpu;
|
||||
threadpool_t *pool;
|
||||
int error;
|
||||
|
||||
error = threadpool_percpu_get(&pcpu, PRI_NONE);
|
||||
KASSERT(error == 0);
|
||||
|
||||
pool = threadpool_percpu_ref(pcpu);
|
||||
|
||||
init_test_job_data(&data, test_job_func_schedule);
|
||||
|
||||
mutex_enter(&data.mutex);
|
||||
while (data.count != FINAL_COUNT) {
|
||||
threadpool_schedule_job(pool, &data.job);
|
||||
error = cv_timedwait(&data.cond, &data.mutex, hz * 2);
|
||||
KASSERT(error != EWOULDBLOCK);
|
||||
}
|
||||
mutex_exit(&data.mutex);
|
||||
|
||||
fini_test_job_data(&data);
|
||||
|
||||
threadpool_percpu_put(pcpu, PRI_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
rumptest_threadpool_job_cancel(void)
|
||||
{
|
||||
struct test_job_data data;
|
||||
threadpool_t *pool;
|
||||
int error;
|
||||
bool rv;
|
||||
|
||||
error = threadpool_get(&pool, PRI_NONE);
|
||||
KASSERT(error == 0);
|
||||
|
||||
init_test_job_data(&data, test_job_func_cancel);
|
||||
|
||||
mutex_enter(&data.mutex);
|
||||
threadpool_schedule_job(pool, &data.job);
|
||||
while (data.count == 0)
|
||||
cv_wait(&data.cond, &data.mutex);
|
||||
KASSERT(data.count == 1);
|
||||
|
||||
/* Job is already running (and is not finished); this shold fail. */
|
||||
rv = threadpool_cancel_job_async(pool, &data.job);
|
||||
KASSERT(rv == false);
|
||||
|
||||
data.count = FINAL_COUNT - 1;
|
||||
cv_broadcast(&data.cond);
|
||||
|
||||
/* Now wait for the job to finish. */
|
||||
threadpool_cancel_job(pool, &data.job);
|
||||
KASSERT(data.count == FINAL_COUNT);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.16 2017/09/29 12:42:37 maya Exp $
|
||||
# $NetBSD: Makefile,v 1.17 2018/12/24 21:42:05 thorpej Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
@ -11,6 +11,7 @@ TESTS_C+= t_modcmd
|
||||
TESTS_C+= t_modlinkset
|
||||
TESTS_C+= t_signals
|
||||
TESTS_C+= t_threads
|
||||
TESTS_C+= t_threadpool
|
||||
TESTS_C+= t_tsleep
|
||||
TESTS_C+= t_workqueue
|
||||
TESTS_C+= t_vm
|
||||
|
138
tests/rump/rumpkern/t_threadpool.c
Normal file
138
tests/rump/rumpkern/t_threadpool.c
Normal file
@ -0,0 +1,138 @@
|
||||
/* $NetBSD: t_threadpool.c,v 1.1 2018/12/24 21:42:05 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2018 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
#include "h_macros.h"
|
||||
#include "../kernspace/kernspace.h"
|
||||
|
||||
ATF_TC(threadpool_unbound_lifecycle);
|
||||
ATF_TC_HEAD(threadpool_unbound_lifecycle, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Tests unbound threadpool lifecycle");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(threadpool_unbound_lifecycle, tc)
|
||||
{
|
||||
|
||||
rump_init();
|
||||
|
||||
rump_schedule();
|
||||
rumptest_threadpool_unbound_lifecycle(); /* panics if fails */
|
||||
rump_unschedule();
|
||||
}
|
||||
|
||||
ATF_TC(threadpool_percpu_lifecycle);
|
||||
ATF_TC_HEAD(threadpool_percpu_lifecycle, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr", "Tests percpu threadpool lifecycle");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(threadpool_percpu_lifecycle, tc)
|
||||
{
|
||||
|
||||
rump_init();
|
||||
|
||||
rump_schedule();
|
||||
rumptest_threadpool_percpu_lifecycle(); /* panics if fails */
|
||||
rump_unschedule();
|
||||
}
|
||||
|
||||
ATF_TC(threadpool_unbound_schedule);
|
||||
ATF_TC_HEAD(threadpool_unbound_schedule, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr",
|
||||
"Tests scheduling on unbound threadpools");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(threadpool_unbound_schedule, tc)
|
||||
{
|
||||
|
||||
rump_init();
|
||||
|
||||
rump_schedule();
|
||||
rumptest_threadpool_unbound_schedule(); /* panics if fails */
|
||||
rump_unschedule();
|
||||
}
|
||||
|
||||
ATF_TC(threadpool_percpu_schedule);
|
||||
ATF_TC_HEAD(threadpool_percpu_schedule, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr",
|
||||
"Tests scheduling on percpu threadpools");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(threadpool_percpu_schedule, tc)
|
||||
{
|
||||
|
||||
rump_init();
|
||||
|
||||
rump_schedule();
|
||||
rumptest_threadpool_percpu_schedule(); /* panics if fails */
|
||||
rump_unschedule();
|
||||
}
|
||||
|
||||
ATF_TC(threadpool_job_cancel);
|
||||
ATF_TC_HEAD(threadpool_job_cancel, tc)
|
||||
{
|
||||
|
||||
atf_tc_set_md_var(tc, "descr",
|
||||
"Tests synchronizing with job cancellation");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(threadpool_job_cancel, tc)
|
||||
{
|
||||
|
||||
rump_init();
|
||||
|
||||
rump_schedule();
|
||||
rumptest_threadpool_job_cancel(); /* panics if fails */
|
||||
rump_unschedule();
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
ATF_TP_ADD_TC(tp, threadpool_unbound_lifecycle);
|
||||
ATF_TP_ADD_TC(tp, threadpool_percpu_lifecycle);
|
||||
ATF_TP_ADD_TC(tp, threadpool_unbound_schedule);
|
||||
ATF_TP_ADD_TC(tp, threadpool_percpu_schedule);
|
||||
ATF_TP_ADD_TC(tp, threadpool_job_cancel);
|
||||
|
||||
return atf_no_error();
|
||||
}
|
Loading…
Reference in New Issue
Block a user