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