xref: /titanic_50/usr/src/test/util-tests/tests/workq/wqt.c (revision f3e7f55e73a39377d55a030f124cc86b3b66a9cc)
1*f3e7f55eSRobert Mustacchi /*
2*f3e7f55eSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*f3e7f55eSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*f3e7f55eSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*f3e7f55eSRobert Mustacchi  * 1.0 of the CDDL.
6*f3e7f55eSRobert Mustacchi  *
7*f3e7f55eSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*f3e7f55eSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*f3e7f55eSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*f3e7f55eSRobert Mustacchi  */
11*f3e7f55eSRobert Mustacchi 
12*f3e7f55eSRobert Mustacchi /*
13*f3e7f55eSRobert Mustacchi  * Copyright 2015 Joyent, Inc.
14*f3e7f55eSRobert Mustacchi  */
15*f3e7f55eSRobert Mustacchi 
16*f3e7f55eSRobert Mustacchi /*
17*f3e7f55eSRobert Mustacchi  * workq testing routines
18*f3e7f55eSRobert Mustacchi  *
19*f3e7f55eSRobert Mustacchi  * What we want to guarantee is that every function is executed exactly once. To
20*f3e7f55eSRobert Mustacchi  * that end we have the callback function basically increment a global in the
21*f3e7f55eSRobert Mustacchi  * test around a mutex.
22*f3e7f55eSRobert Mustacchi  */
23*f3e7f55eSRobert Mustacchi 
24*f3e7f55eSRobert Mustacchi #include <workq.h>
25*f3e7f55eSRobert Mustacchi #include <stdio.h>
26*f3e7f55eSRobert Mustacchi #include <errno.h>
27*f3e7f55eSRobert Mustacchi #include <string.h>
28*f3e7f55eSRobert Mustacchi #include <stdlib.h>
29*f3e7f55eSRobert Mustacchi #include <thread.h>
30*f3e7f55eSRobert Mustacchi #include <synch.h>
31*f3e7f55eSRobert Mustacchi 
32*f3e7f55eSRobert Mustacchi mutex_t wqt_lock = ERRORCHECKMUTEX;
33*f3e7f55eSRobert Mustacchi uintptr_t wqt_count;
34*f3e7f55eSRobert Mustacchi 
35*f3e7f55eSRobert Mustacchi const char *
_umem_debug_init()36*f3e7f55eSRobert Mustacchi _umem_debug_init()
37*f3e7f55eSRobert Mustacchi {
38*f3e7f55eSRobert Mustacchi 	return ("default,verbose");
39*f3e7f55eSRobert Mustacchi }
40*f3e7f55eSRobert Mustacchi 
41*f3e7f55eSRobert Mustacchi const char *
_umem_logging_init(void)42*f3e7f55eSRobert Mustacchi _umem_logging_init(void)
43*f3e7f55eSRobert Mustacchi {
44*f3e7f55eSRobert Mustacchi 	return ("fail,contents");
45*f3e7f55eSRobert Mustacchi }
46*f3e7f55eSRobert Mustacchi 
47*f3e7f55eSRobert Mustacchi void *
workq_alloc(size_t size)48*f3e7f55eSRobert Mustacchi workq_alloc(size_t size)
49*f3e7f55eSRobert Mustacchi {
50*f3e7f55eSRobert Mustacchi 	return (malloc(size));
51*f3e7f55eSRobert Mustacchi }
52*f3e7f55eSRobert Mustacchi 
53*f3e7f55eSRobert Mustacchi /*ARGSUSED*/
54*f3e7f55eSRobert Mustacchi void
workq_free(void * buf,size_t size)55*f3e7f55eSRobert Mustacchi workq_free(void *buf, size_t size)
56*f3e7f55eSRobert Mustacchi {
57*f3e7f55eSRobert Mustacchi 	free(buf);
58*f3e7f55eSRobert Mustacchi }
59*f3e7f55eSRobert Mustacchi 
60*f3e7f55eSRobert Mustacchi /*ARGSUSED*/
61*f3e7f55eSRobert Mustacchi int
wqt_fatal(void * item,void * arg)62*f3e7f55eSRobert Mustacchi wqt_fatal(void *item, void *arg)
63*f3e7f55eSRobert Mustacchi {
64*f3e7f55eSRobert Mustacchi 	return (-1);
65*f3e7f55eSRobert Mustacchi }
66*f3e7f55eSRobert Mustacchi 
67*f3e7f55eSRobert Mustacchi int
wqt_add(void * item,void * arg)68*f3e7f55eSRobert Mustacchi wqt_add(void *item, void *arg)
69*f3e7f55eSRobert Mustacchi {
70*f3e7f55eSRobert Mustacchi 	uintptr_t a = (uintptr_t)item;
71*f3e7f55eSRobert Mustacchi 
72*f3e7f55eSRobert Mustacchi 	mutex_enter(&wqt_lock);
73*f3e7f55eSRobert Mustacchi 	wqt_count += a;
74*f3e7f55eSRobert Mustacchi 	mutex_exit(&wqt_lock);
75*f3e7f55eSRobert Mustacchi 
76*f3e7f55eSRobert Mustacchi 	return (0);
77*f3e7f55eSRobert Mustacchi }
78*f3e7f55eSRobert Mustacchi 
79*f3e7f55eSRobert Mustacchi typedef struct wq_test {
80*f3e7f55eSRobert Mustacchi 	const char	*wq_desc;	/* test description/name */
81*f3e7f55eSRobert Mustacchi 	workq_proc_f	*wq_proc;	/* processing function */
82*f3e7f55eSRobert Mustacchi 	int		wq_rval;	/* workq_work return value */
83*f3e7f55eSRobert Mustacchi 	int		wq_uerr;	/* user error, if any */
84*f3e7f55eSRobert Mustacchi 	uintptr_t	wq_sum;		/* expected sum */
85*f3e7f55eSRobert Mustacchi 	void		**wq_args;	/* argument array */
86*f3e7f55eSRobert Mustacchi } wq_test_t;
87*f3e7f55eSRobert Mustacchi 
88*f3e7f55eSRobert Mustacchi static void *wqt_empty_args[] = { NULL };
89*f3e7f55eSRobert Mustacchi static void *wqt_single_args[] = { (void *)42, NULL };
90*f3e7f55eSRobert Mustacchi static void *wqt_double_args[] = { (void *)42, (void *)27, NULL };
91*f3e7f55eSRobert Mustacchi static void *wqt_wrap_args[] = {
92*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
93*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
94*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
95*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
96*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
97*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
98*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
99*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
100*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
101*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
102*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, NULL
103*f3e7f55eSRobert Mustacchi };
104*f3e7f55eSRobert Mustacchi static void *wqt_grow_args[] = {
105*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
106*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
107*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
108*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
109*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
110*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
111*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
112*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
113*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
114*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
115*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
116*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
117*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
118*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
119*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1,
120*f3e7f55eSRobert Mustacchi 	(void *)1, (void *)1, NULL
121*f3e7f55eSRobert Mustacchi };
122*f3e7f55eSRobert Mustacchi 
123*f3e7f55eSRobert Mustacchi static wq_test_t wq_tests[] = {
124*f3e7f55eSRobert Mustacchi 	{ "empty", wqt_add, 0, 0, NULL, wqt_empty_args },
125*f3e7f55eSRobert Mustacchi 	{ "single", wqt_add, 0, 0, 42, wqt_single_args },
126*f3e7f55eSRobert Mustacchi 	{ "double", wqt_add, 0, 0, 69, wqt_double_args },
127*f3e7f55eSRobert Mustacchi 	{ "wrap", wqt_add, 0, 0, 64, wqt_wrap_args },
128*f3e7f55eSRobert Mustacchi 	{ "grow", wqt_add, 0, 0, 92, wqt_grow_args },
129*f3e7f55eSRobert Mustacchi 	{ "fatal", wqt_fatal, WORKQ_UERROR, -1, -1, wqt_double_args }
130*f3e7f55eSRobert Mustacchi };
131*f3e7f55eSRobert Mustacchi 
132*f3e7f55eSRobert Mustacchi #define	NWQ_TESTS (sizeof (wq_tests) / sizeof (wq_test_t))
133*f3e7f55eSRobert Mustacchi 
134*f3e7f55eSRobert Mustacchi static void
wq_test_run(workq_t * wqp,wq_test_t * wqt)135*f3e7f55eSRobert Mustacchi wq_test_run(workq_t *wqp, wq_test_t *wqt)
136*f3e7f55eSRobert Mustacchi {
137*f3e7f55eSRobert Mustacchi 	int ret, err;
138*f3e7f55eSRobert Mustacchi 	void **itemp = wqt->wq_args;
139*f3e7f55eSRobert Mustacchi 
140*f3e7f55eSRobert Mustacchi 	while (*itemp != NULL) {
141*f3e7f55eSRobert Mustacchi 		if ((ret = workq_add(wqp, *itemp)) != 0) {
142*f3e7f55eSRobert Mustacchi 			(void) fprintf(stderr, "test %s: failed to add item: "
143*f3e7f55eSRobert Mustacchi 			    "%s\n", wqt->wq_desc, strerror(errno));
144*f3e7f55eSRobert Mustacchi 			exit(1);
145*f3e7f55eSRobert Mustacchi 		}
146*f3e7f55eSRobert Mustacchi 		itemp++;
147*f3e7f55eSRobert Mustacchi 	}
148*f3e7f55eSRobert Mustacchi 
149*f3e7f55eSRobert Mustacchi 	wqt_count = 0;
150*f3e7f55eSRobert Mustacchi 	ret = workq_work(wqp, wqt->wq_proc, NULL, &err);
151*f3e7f55eSRobert Mustacchi 	if (ret != wqt->wq_rval) {
152*f3e7f55eSRobert Mustacchi 		(void) fprintf(stderr, "test %s: got incorrect rval. "
153*f3e7f55eSRobert Mustacchi 		    "Expected %d, got %d (%d)\n", wqt->wq_desc, wqt->wq_rval,
154*f3e7f55eSRobert Mustacchi 		    ret, errno);
155*f3e7f55eSRobert Mustacchi 		exit(1);
156*f3e7f55eSRobert Mustacchi 	}
157*f3e7f55eSRobert Mustacchi 
158*f3e7f55eSRobert Mustacchi 	if (ret == WORKQ_UERROR && err != wqt->wq_uerr) {
159*f3e7f55eSRobert Mustacchi 		(void) fprintf(stderr, "test %s: got incorrect user error. "
160*f3e7f55eSRobert Mustacchi 		    "Expected %d, got %d\n", wqt->wq_desc, wqt->wq_uerr, err);
161*f3e7f55eSRobert Mustacchi 		exit(1);
162*f3e7f55eSRobert Mustacchi 	}
163*f3e7f55eSRobert Mustacchi 
164*f3e7f55eSRobert Mustacchi 	if (ret == 0 && wqt_count != wqt->wq_sum) {
165*f3e7f55eSRobert Mustacchi 		(void) fprintf(stderr, "test %s: got unexpected "
166*f3e7f55eSRobert Mustacchi 		    "result: %d, expected %d\n", wqt->wq_desc, wqt_count,
167*f3e7f55eSRobert Mustacchi 		    wqt->wq_sum);
168*f3e7f55eSRobert Mustacchi 		exit(1);
169*f3e7f55eSRobert Mustacchi 	}
170*f3e7f55eSRobert Mustacchi }
171*f3e7f55eSRobert Mustacchi 
172*f3e7f55eSRobert Mustacchi int
main(void)173*f3e7f55eSRobert Mustacchi main(void)
174*f3e7f55eSRobert Mustacchi {
175*f3e7f55eSRobert Mustacchi 	int ret, i, t;
176*f3e7f55eSRobert Mustacchi 	workq_t *wqp;
177*f3e7f55eSRobert Mustacchi 	int nthreads[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, -1 };
178*f3e7f55eSRobert Mustacchi 
179*f3e7f55eSRobert Mustacchi 	for (t = 0; nthreads[t] != -1; t++) {
180*f3e7f55eSRobert Mustacchi 		printf("Beginning tests with %d threads\n", nthreads[t]);
181*f3e7f55eSRobert Mustacchi 		if ((ret = workq_init(&wqp, nthreads[t])) != 0) {
182*f3e7f55eSRobert Mustacchi 			fprintf(stderr, "failed to init workq: %s\n",
183*f3e7f55eSRobert Mustacchi 			    strerror(errno));
184*f3e7f55eSRobert Mustacchi 			return (1);
185*f3e7f55eSRobert Mustacchi 		}
186*f3e7f55eSRobert Mustacchi 
187*f3e7f55eSRobert Mustacchi 		for (i = 0; i < NWQ_TESTS; i++) {
188*f3e7f55eSRobert Mustacchi 			wq_test_run(wqp, &wq_tests[i]);
189*f3e7f55eSRobert Mustacchi 		}
190*f3e7f55eSRobert Mustacchi 
191*f3e7f55eSRobert Mustacchi 		workq_fini(wqp);
192*f3e7f55eSRobert Mustacchi 	}
193*f3e7f55eSRobert Mustacchi 
194*f3e7f55eSRobert Mustacchi 
195*f3e7f55eSRobert Mustacchi 	return (0);
196*f3e7f55eSRobert Mustacchi }
197