xref: /netbsd-src/tests/rump/kernspace/workqueue.c (revision 78e153c0eb7c01f6b2c9fa5714f1b47c07d65bbb)
1*78e153c0Sriastradh /*	$NetBSD: workqueue.c,v 1.10 2023/08/10 22:20:20 riastradh Exp $	*/
2aef814ffSmaya 
3aef814ffSmaya /*-
4aef814ffSmaya  * Copyright (c) 2017 The NetBSD Foundation, Inc.
5aef814ffSmaya  * All rights reserved.
6aef814ffSmaya  *
7aef814ffSmaya  * Redistribution and use in source and binary forms, with or without
8aef814ffSmaya  * modification, are permitted provided that the following conditions
9aef814ffSmaya  * are met:
10aef814ffSmaya  * 1. Redistributions of source code must retain the above copyright
11aef814ffSmaya  *    notice, this list of conditions and the following disclaimer.
12aef814ffSmaya  * 2. Redistributions in binary form must reproduce the above copyright
13aef814ffSmaya  *    notice, this list of conditions and the following disclaimer in the
14aef814ffSmaya  *    documentation and/or other materials provided with the distribution.
15aef814ffSmaya  *
16aef814ffSmaya  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17aef814ffSmaya  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18aef814ffSmaya  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19aef814ffSmaya  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20aef814ffSmaya  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21aef814ffSmaya  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22aef814ffSmaya  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23aef814ffSmaya  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24aef814ffSmaya  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25aef814ffSmaya  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26aef814ffSmaya  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27aef814ffSmaya  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28aef814ffSmaya  */
29aef814ffSmaya 
30aef814ffSmaya #include <sys/cdefs.h>
31aef814ffSmaya #if !defined(lint)
32*78e153c0Sriastradh __RCSID("$NetBSD: workqueue.c,v 1.10 2023/08/10 22:20:20 riastradh Exp $");
33aef814ffSmaya #endif /* !lint */
34aef814ffSmaya 
35aef814ffSmaya #include <sys/param.h>
36aef814ffSmaya #include <sys/condvar.h>
37aef814ffSmaya #include <sys/kernel.h>
38aef814ffSmaya #include <sys/kmem.h>
39aef814ffSmaya #include <sys/kthread.h>
40aef814ffSmaya #include <sys/mutex.h>
41aef814ffSmaya #include <sys/workqueue.h>
42aef814ffSmaya 
43aef814ffSmaya #include "kernspace.h"
44aef814ffSmaya 
45aef814ffSmaya struct test_softc {
46aef814ffSmaya 	kmutex_t mtx;
47aef814ffSmaya 	kcondvar_t cv;
48aef814ffSmaya 	struct workqueue *wq;
49aef814ffSmaya 	struct work wk;
50aef814ffSmaya 	int counter;
51f8e8b7bfSriastradh 	bool pause;
52aef814ffSmaya };
53aef814ffSmaya 
54aef814ffSmaya static void
rump_work1(struct work * wk,void * arg)55aef814ffSmaya rump_work1(struct work *wk, void *arg)
56aef814ffSmaya {
57aef814ffSmaya 	struct test_softc *sc = arg;
58aef814ffSmaya 
59aab7c675Sriastradh 	memset(wk, 0x5a, sizeof(*wk));
60aab7c675Sriastradh 
61f8e8b7bfSriastradh 	if (sc->pause)
62f8e8b7bfSriastradh 		kpause("tstwk1", /*intr*/false, /*timo*/2, /*lock*/NULL);
63f8e8b7bfSriastradh 
64aef814ffSmaya 	mutex_enter(&sc->mtx);
65aef814ffSmaya 	++sc->counter;
66aef814ffSmaya 	cv_broadcast(&sc->cv);
67aef814ffSmaya 	mutex_exit(&sc->mtx);
68aef814ffSmaya }
69aef814ffSmaya 
70bfde781fSozaki-r static struct test_softc *
create_sc(void)71bfde781fSozaki-r create_sc(void)
72aef814ffSmaya {
73aef814ffSmaya 	int rv;
74aef814ffSmaya 	struct test_softc *sc;
75aef814ffSmaya 
76aef814ffSmaya 	sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
77aef814ffSmaya 	mutex_init(&sc->mtx, MUTEX_DEFAULT, IPL_NONE);
78aef814ffSmaya 	cv_init(&sc->cv, "rumpwqcv");
79aef814ffSmaya 	rv = workqueue_create(&sc->wq, "rumpwq",
80aef814ffSmaya 	    rump_work1, sc, PRI_SOFTNET, IPL_SOFTNET, 0);
81aef814ffSmaya 	if (rv)
82aef814ffSmaya 		panic("workqueue creation failed: %d", rv);
83aef814ffSmaya 
84aef814ffSmaya 	sc->counter = 0;
85aef814ffSmaya 
86bfde781fSozaki-r 	return sc;
87bfde781fSozaki-r }
88bfde781fSozaki-r 
89bfde781fSozaki-r static void
destroy_sc(struct test_softc * sc)90bfde781fSozaki-r destroy_sc(struct test_softc *sc)
91bfde781fSozaki-r {
92bfde781fSozaki-r 
93bfde781fSozaki-r 	cv_destroy(&sc->cv);
94bfde781fSozaki-r 	mutex_destroy(&sc->mtx);
95bfde781fSozaki-r 	workqueue_destroy(sc->wq);
96bfde781fSozaki-r }
97bfde781fSozaki-r 
98bfde781fSozaki-r void
rumptest_workqueue1()99bfde781fSozaki-r rumptest_workqueue1()
100bfde781fSozaki-r {
101bfde781fSozaki-r 	struct test_softc *sc;
102bfde781fSozaki-r 
103bfde781fSozaki-r 	sc = create_sc();
104bfde781fSozaki-r 
105aef814ffSmaya #define ITERATIONS 12435
106bd910154Sozaki-r 	for (int i = 0; i < ITERATIONS; ++i) {
1071315c7eeSozaki-r 		int e;
108aef814ffSmaya 		mutex_enter(&sc->mtx);
109bf33e35aSozaki-r 		workqueue_enqueue(sc->wq, &sc->wk, NULL);
1101315c7eeSozaki-r 		e = cv_timedwait(&sc->cv, &sc->mtx, hz * 2);
1111315c7eeSozaki-r 		if (e != 0)
112bd910154Sozaki-r 			panic("cv_timedwait timed out (i=%d)", i);
113aef814ffSmaya 		mutex_exit(&sc->mtx);
114aef814ffSmaya 	}
115aef814ffSmaya 
116aef814ffSmaya 	KASSERT(sc->counter == ITERATIONS);
117aef814ffSmaya 
118bfde781fSozaki-r 	destroy_sc(sc);
119bfde781fSozaki-r #undef ITERATIONS
120aef814ffSmaya }
12161673e6eSozaki-r 
12261673e6eSozaki-r void
rumptest_workqueue_wait(void)12361673e6eSozaki-r rumptest_workqueue_wait(void)
12461673e6eSozaki-r {
12561673e6eSozaki-r 	struct test_softc *sc;
12661673e6eSozaki-r 	struct work dummy;
12761673e6eSozaki-r 
12861673e6eSozaki-r 	sc = create_sc();
12961673e6eSozaki-r 
13061673e6eSozaki-r #define ITERATIONS 12435
13161673e6eSozaki-r 	for (size_t i = 0; i < ITERATIONS; ++i) {
13261673e6eSozaki-r 		KASSERT(sc->counter == i);
13361673e6eSozaki-r 		workqueue_enqueue(sc->wq, &sc->wk, NULL);
13461673e6eSozaki-r 		workqueue_wait(sc->wq, &sc->wk);
13561673e6eSozaki-r 		KASSERT(sc->counter == (i + 1));
13661673e6eSozaki-r 	}
13761673e6eSozaki-r 
13861673e6eSozaki-r 	KASSERT(sc->counter == ITERATIONS);
13961673e6eSozaki-r 
14061673e6eSozaki-r 	/* Wait for a work that is not enqueued. Just return immediately. */
14161673e6eSozaki-r 	workqueue_wait(sc->wq, &dummy);
14261673e6eSozaki-r 
14361673e6eSozaki-r 	destroy_sc(sc);
14461673e6eSozaki-r #undef ITERATIONS
14561673e6eSozaki-r }
146f8e8b7bfSriastradh 
147f8e8b7bfSriastradh void
rumptest_workqueue_wait_pause(void)148f8e8b7bfSriastradh rumptest_workqueue_wait_pause(void)
149f8e8b7bfSriastradh {
150f8e8b7bfSriastradh 	struct test_softc *sc;
151f8e8b7bfSriastradh 	struct work dummy;
152f8e8b7bfSriastradh 
153f8e8b7bfSriastradh 	sc = create_sc();
154f8e8b7bfSriastradh 	sc->pause = true;
155f8e8b7bfSriastradh 
156f8e8b7bfSriastradh #define ITERATIONS 1
157f8e8b7bfSriastradh 	for (size_t i = 0; i < ITERATIONS; ++i) {
158f8e8b7bfSriastradh 		struct work wk;
159f8e8b7bfSriastradh 
160f8e8b7bfSriastradh 		KASSERT(sc->counter == i);
161f8e8b7bfSriastradh 		workqueue_enqueue(sc->wq, &wk, NULL);
162f8e8b7bfSriastradh 		workqueue_enqueue(sc->wq, &sc->wk, NULL);
163f8e8b7bfSriastradh 		kpause("tstwk2", /*intr*/false, /*timo*/1, /*lock*/NULL);
164f8e8b7bfSriastradh 		workqueue_wait(sc->wq, &sc->wk);
165*78e153c0Sriastradh 		workqueue_wait(sc->wq, &wk);
166*78e153c0Sriastradh 		KASSERT(sc->counter == (i + 2));
167f8e8b7bfSriastradh 	}
168f8e8b7bfSriastradh 
169*78e153c0Sriastradh 	KASSERT(sc->counter == 2*ITERATIONS);
170f8e8b7bfSriastradh 
171f8e8b7bfSriastradh 	/* Wait for a work that is not enqueued. Just return immediately. */
172f8e8b7bfSriastradh 	workqueue_wait(sc->wq, &dummy);
173f8e8b7bfSriastradh 
174f8e8b7bfSriastradh 	destroy_sc(sc);
175f8e8b7bfSriastradh #undef ITERATIONS
176f8e8b7bfSriastradh }
177