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