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 * 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 * 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 * 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 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 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 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 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 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