static int chkskip(struct rnc_source *sp,int symc,int syms) { if(CUR(sp).sym!=symc) { error(0,sp,RNC_ER_SEXP,sp->fn,CUR(sp).line,CUR(sp).col,sym2str(symc),sym2str(CUR(sp).sym)); skipto(sp,syms); return 0; } else { return 1; } }
static int splat_taskq_test1_impl(struct file *file, void *arg, boolean_t prealloc) { taskq_t *tq; taskqid_t id; splat_taskq_arg_t tq_arg; taskq_ent_t tqe; taskq_init_ent(&tqe); splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' creating (%s dispatch)\n", SPLAT_TASKQ_TEST1_NAME, prealloc ? "prealloc" : "dynamic"); if ((tq = taskq_create(SPLAT_TASKQ_TEST1_NAME, 1, maxclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST1_NAME); return -EINVAL; } tq_arg.flag = 0; tq_arg.id = 0; tq_arg.file = file; tq_arg.name = SPLAT_TASKQ_TEST1_NAME; splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' function '%s' dispatching\n", tq_arg.name, sym2str(splat_taskq_test13_func)); if (prealloc) { taskq_dispatch_ent(tq, splat_taskq_test13_func, &tq_arg, TQ_SLEEP, &tqe); id = tqe.tqent_id; } else { id = taskq_dispatch(tq, splat_taskq_test13_func, &tq_arg, TQ_SLEEP); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' function '%s' dispatch failed\n", tq_arg.name, sym2str(splat_taskq_test13_func)); taskq_destroy(tq); return -EINVAL; } splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' waiting\n", tq_arg.name); taskq_wait(tq); splat_vprint(file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' destroying\n", tq_arg.name); taskq_destroy(tq); return (tq_arg.flag) ? 0 : -EINVAL; }
static void getrng(void) { int ircur=-1,i=0; int cc0; for(;;) { cc0=cc; getcc(); if(cc=='}') ircur=i; else if(cc=='>') {if(cc0=='=') {getcc(); break;}} /* use => as terminator */ else if(cc==-1) {error(ARX_ER_EXP,"=>",sym2str(SYM_EOF)); break;} value[i++]=cc; if(i==len_v) value=(char*)m_stretch(value,len_v=2*i,i,sizeof(char)); } if(ircur==-1) {error(ARX_ER_EXP,sym2str(SYM_RCUR),sym2str(SYM_EOF)); ircur=0;} value[ircur]='\0'; }
/* * Use the global system task queue with a single task, wait until task * completes, ensure task ran properly. */ static int splat_taskq_test3_impl(struct file *file, void *arg, boolean_t prealloc) { taskqid_t id; splat_taskq_arg_t *tq_arg; taskq_ent_t *tqe; int error; tq_arg = kmem_alloc(sizeof (splat_taskq_arg_t), KM_SLEEP); tqe = kmem_alloc(sizeof (taskq_ent_t), KM_SLEEP); taskq_init_ent(tqe); tq_arg->flag = 0; tq_arg->id = 0; tq_arg->file = file; tq_arg->name = SPLAT_TASKQ_TEST3_NAME; splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' function '%s' %s dispatch\n", tq_arg->name, sym2str(splat_taskq_test13_func), prealloc ? "prealloc" : "dynamic"); if (prealloc) { taskq_dispatch_ent(system_taskq, splat_taskq_test13_func, tq_arg, TQ_SLEEP, tqe); id = tqe->tqent_id; } else { id = taskq_dispatch(system_taskq, splat_taskq_test13_func, tq_arg, TQ_SLEEP); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' function '%s' dispatch failed\n", tq_arg->name, sym2str(splat_taskq_test13_func)); kmem_free(tqe, sizeof (taskq_ent_t)); kmem_free(tq_arg, sizeof (splat_taskq_arg_t)); return -EINVAL; } splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' waiting\n", tq_arg->name); taskq_wait(system_taskq); error = (tq_arg->flag) ? 0 : -EINVAL; kmem_free(tqe, sizeof (taskq_ent_t)); kmem_free(tq_arg, sizeof (splat_taskq_arg_t)); return (error); }
static int chkwd(struct rnc_source *sp) { if(0<=CUR(sp).sym&&CUR(sp).sym<=SYM_IDENT) { return 1; } else { error(0,sp,RNC_ER_SEXP,sp->fn,CUR(sp).line,CUR(sp).col,"identifier or keyword",sym2str(CUR(sp).sym)); return 0; } }
/* advance, join literal fragments and skip annotations and documentation comments */ static void getsym(struct rnc_source *sp) { advance(sp); for(;;) { switch(CUR(sp).sym) { case SYM_DOCUMENTATION: advance(sp); continue; case SYM_FOLLOW_ANNOTATION: advance(sp); if(CUR(sp).sym<0||CUR(sp).sym>SYM_QNAME) { error(0,sp,RNC_ER_SEXP,sp->fn,CUR(sp).line,CUR(sp).col,"identifier, prefixed name or keyword",sym2str(CUR(sp).sym)); while(CUR(sp).sym!=SYM_LSQU&&CUR(sp).sym!=SYM_EOF) advance(sp); } else { advance(sp); if(CUR(sp).sym!=SYM_LSQU) error(0,sp,RNC_ER_SEXP,sp->fn,CUR(sp).line,CUR(sp).col,sym2str(SYM_LSQU),sym2str(CUR(sp).sym)); } case SYM_LSQU: skipAnnotationContent(sp); continue; case SYM_LITERAL: /* alternatively, either a non-terminal, or a separate filter; - one more filtering layer is not worth the effort, - the non-terminal would later need extra buffer for concatenated strings. Since the concatenation is only applied to constants anyway, merging them into a single terminal looks appropriate. */ if(NXT(sp).sym==SYM_CONCAT) { sp->cur=!sp->cur; advance(sp); if(NXT(sp).sym!=SYM_LITERAL) { error(0,sp,RNC_ER_SEXP,sp->fn,NXT(sp).line,NXT(sp).col,sym2str(SYM_LITERAL),sym2str(NXT(sp).sym)); break; } { int newslen=strlen(CUR(sp).s)+strlen(NXT(sp).s)+1; if(newslen>CUR(sp).slen) realloc_s(&CUR(sp),newslen); } strcat(CUR(sp).s,NXT(sp).s); sp->cur=!sp->cur; advance(sp); continue; } break; } return; } }
/* * Create a taskq, queue a task, wait until task completes, ensure * task ran properly, cleanup taskq. */ static void splat_taskq_test13_func(void *arg) { splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg; ASSERT(tq_arg); splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST1_NAME, "Taskq '%s' function '%s' setting flag\n", tq_arg->name, sym2str(splat_taskq_test13_func)); tq_arg->flag = 1; }
/* * Use the global system task queue with a single task, wait until task * completes, ensure task ran properly. */ static int splat_taskq_test3_impl(struct file *file, void *arg, boolean_t prealloc) { taskqid_t id; splat_taskq_arg_t tq_arg; taskq_ent_t tqe; taskq_init_ent(&tqe); tq_arg.flag = 0; tq_arg.id = 0; tq_arg.file = file; tq_arg.name = SPLAT_TASKQ_TEST3_NAME; splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' function '%s' %s dispatch\n", tq_arg.name, sym2str(splat_taskq_test13_func), prealloc ? "prealloc" : "dynamic"); if (prealloc) { taskq_dispatch_ent(system_taskq, splat_taskq_test13_func, &tq_arg, TQ_SLEEP, &tqe); id = tqe.tqent_id; } else { id = taskq_dispatch(system_taskq, splat_taskq_test13_func, &tq_arg, TQ_SLEEP); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' function '%s' dispatch failed\n", tq_arg.name, sym2str(splat_taskq_test13_func)); return -EINVAL; } splat_vprint(file, SPLAT_TASKQ_TEST3_NAME, "Taskq '%s' waiting\n", tq_arg.name); taskq_wait(system_taskq); return (tq_arg.flag) ? 0 : -EINVAL; }
static void splat_taskq_test2_func2(void *arg) { splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg; ASSERT(tq_arg); splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' function '%s' flag = %d = %d + 1\n", tq_arg->name, tq_arg->id, sym2str(splat_taskq_test2_func2), tq_arg->flag + 1, tq_arg->flag); tq_arg->flag += 1; }
static void splat_taskq_test7_func(void *arg) { splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg; taskqid_t id; ASSERT(tq_arg); if (tq_arg->depth >= SPLAT_TASKQ_DEPTH_MAX) return; tq_arg->depth++; splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST7_NAME, "Taskq '%s' function '%s' dispatching (depth = %u)\n", tq_arg->name, sym2str(splat_taskq_test7_func), tq_arg->depth); if (tq_arg->tqe) { VERIFY(taskq_empty_ent(tq_arg->tqe)); taskq_dispatch_ent(tq_arg->tq, splat_taskq_test7_func, tq_arg, TQ_SLEEP, tq_arg->tqe); id = tq_arg->tqe->tqent_id; } else { id = taskq_dispatch(tq_arg->tq, splat_taskq_test7_func, tq_arg, TQ_SLEEP); } if (id == 0) { splat_vprint(tq_arg->file, SPLAT_TASKQ_TEST7_NAME, "Taskq '%s' function '%s' dispatch failed " "(depth = %u)\n", tq_arg->name, sym2str(splat_taskq_test7_func), tq_arg->depth); tq_arg->flag = -EINVAL; return; } }
static void getsym(void) { for(;;) { if(0<=cc&&cc<=' ') {getcc(); continue;} switch(cc) { case -1: sym=SYM_EOF; return; case '#': do getcc(); while(cc!='\n'&&cc!='\r'); getcc(); continue; case '{': if(sym==SYM_VALD||sym==SYM_NVAL) { getrng(); sym=SYM_RENG; } else { getcc(); sym=SYM_LCUR; } return; case '}': getcc(); sym=SYM_RCUR; return; case '!': getcc(); if(cc=='~') { getcc(); sym=SYM_NMTC; } else { if(getid()) { if(strcmp("valid",value)!=0) {error(ARX_ER_EXP,sym2str(SYM_NVAL),value);} sym=SYM_NVAL; } else {error(ARX_ER_SYN); sym=SYM_INVL;} } return; case '=': getcc(); switch(cc) { case '~': getcc(); sym=SYM_MTCH; return; case '>': getcc(); if(sym!=SYM_RGXP) error(ARX_ER_SYN); continue; default: sym=SYM_ASGN; return; } case '"': getq(); sym=SYM_LTRL; return; case '/': getq(); sym=SYM_RGXP; return; default: if(getid()) { sym=strcmp("grammars",value)==0?SYM_GRMS : strcmp("valid",value)==0?SYM_VALD:SYM_IDNT; } else {getcc(); error(ARX_ER_SYN); sym=SYM_INVL;} return; } } }
static void skipAnnotationContent(struct rnc_source *sp) { /* syntax of annotations is not checked; it is not a purpose of this parser to handle them anyway */ if(CUR(sp).sym==SYM_LSQU) { advance(sp); for(;;) { switch(CUR(sp).sym) { case SYM_RSQU: advance(sp); return; case SYM_LSQU: skipAnnotationContent(sp); break; case SYM_IDENT: case SYM_QNAME: /* keywords are in the default: clause */ case SYM_ASGN: case SYM_LITERAL: case SYM_CONCAT: advance(sp); break; default: if(0<=CUR(sp).sym&&CUR(sp).sym<NKWD) { /* keywords */ advance(sp); break; } else { error(0,sp,RNC_ER_SILL,sp->fn,CUR(sp).line,CUR(sp).col,sym2str(CUR(sp).sym)); return; } } } } }
static int splat_mutex_test3(struct file *file, void *arg) { mutex_priv_t mp; taskq_t *tq; int rc = 0; mp.mp_magic = SPLAT_MUTEX_TEST_MAGIC; mp.mp_file = file; mutex_init(&mp.mp_mtx, SPLAT_MUTEX_TEST_NAME, MUTEX_DEFAULT, NULL); if ((tq = taskq_create(SPLAT_MUTEX_TEST_NAME, 1, defclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Taskq '%s' " "create failed\n", SPLAT_MUTEX_TEST3_NAME); return -EINVAL; } mutex_enter(&mp.mp_mtx); /* Mutex should be owned by current */ if (!mutex_owned(&mp.mp_mtx)) { splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Unowned mutex " "should be owned by pid %d\n", current->pid); rc = -EINVAL; goto out_exit; } if (taskq_dispatch(tq, splat_mutex_owned, &mp, TQ_SLEEP) == 0) { splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Failed to " "dispatch function '%s' to taskq\n", sym2str(splat_mutex_owned)); rc = -EINVAL; goto out_exit; } taskq_wait(tq); /* Mutex should not be owned which checked from a different thread */ if (mp.mp_rc || mp.mp_rc2) { splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Mutex owned by " "pid %d not by taskq\n", current->pid); rc = -EINVAL; goto out_exit; } mutex_exit(&mp.mp_mtx); /* Mutex should not be owned by current */ if (mutex_owned(&mp.mp_mtx)) { splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Mutex owned by " "pid %d it should be unowned\b", current->pid); rc = -EINVAL; goto out; } if (taskq_dispatch(tq, splat_mutex_owned, &mp, TQ_SLEEP) == 0) { splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Failed to " "dispatch function '%s' to taskq\n", sym2str(splat_mutex_owned)); rc = -EINVAL; goto out; } taskq_wait(tq); /* Mutex should be owned by no one */ if (mp.mp_rc || mp.mp_rc2) { splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "Mutex owned by " "no one, %d/%d disagrees\n", mp.mp_rc, mp.mp_rc2); rc = -EINVAL; goto out; } splat_vprint(file, SPLAT_MUTEX_TEST3_NAME, "%s", "Correct mutex_owned() behavior\n"); goto out; out_exit: mutex_exit(&mp.mp_mtx); out: mutex_destroy(&mp.mp_mtx); taskq_destroy(tq); return rc; }
static int chksym(int x) { if(sym!=x) {error(ARX_ER_EXP,sym2str(x),sym2str(sym)); return 0;} return 1; }
static int splat_taskq_test8_common(struct file *file, void *arg, int minalloc, int maxalloc) { taskq_t *tq; taskqid_t id; splat_taskq_arg_t tq_arg; taskq_ent_t **tqes; int i, j, rc = 0; tqes = vmalloc(sizeof(*tqes) * TEST8_NUM_TASKS); if (tqes == NULL) return -ENOMEM; memset(tqes, 0, sizeof(*tqes) * TEST8_NUM_TASKS); splat_vprint(file, SPLAT_TASKQ_TEST8_NAME, "Taskq '%s' creating (%d/%d/%d)\n", SPLAT_TASKQ_TEST8_NAME, minalloc, maxalloc, TEST8_NUM_TASKS); if ((tq = taskq_create(SPLAT_TASKQ_TEST8_NAME, TEST8_THREADS_PER_TASKQ, maxclsyspri, minalloc, maxalloc, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_TASKQ_TEST8_NAME, "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST8_NAME); rc = -EINVAL; goto out_free; } tq_arg.file = file; tq_arg.name = SPLAT_TASKQ_TEST8_NAME; atomic_set(&tq_arg.count, 0); for (i = 0; i < TEST8_NUM_TASKS; i++) { tqes[i] = kmalloc(sizeof(taskq_ent_t), GFP_KERNEL); if (tqes[i] == NULL) { rc = -ENOMEM; goto out; } taskq_init_ent(tqes[i]); taskq_dispatch_ent(tq, splat_taskq_test8_func, &tq_arg, TQ_SLEEP, tqes[i]); id = tqes[i]->tqent_id; if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST8_NAME, "Taskq '%s' function '%s' dispatch " "%d failed\n", tq_arg.name, sym2str(splat_taskq_test8_func), i); rc = -EINVAL; goto out; } } splat_vprint(file, SPLAT_TASKQ_TEST8_NAME, "Taskq '%s' " "waiting for %d dispatches\n", tq_arg.name, TEST8_NUM_TASKS); taskq_wait(tq); splat_vprint(file, SPLAT_TASKQ_TEST8_NAME, "Taskq '%s' " "%d/%d dispatches finished\n", tq_arg.name, atomic_read(&tq_arg.count), TEST8_NUM_TASKS); if (atomic_read(&tq_arg.count) != TEST8_NUM_TASKS) rc = -ERANGE; out: splat_vprint(file, SPLAT_TASKQ_TEST8_NAME, "Taskq '%s' destroying\n", tq_arg.name); taskq_destroy(tq); out_free: for (j = 0; j < TEST8_NUM_TASKS && tqes[j] != NULL; j++) kfree(tqes[j]); vfree(tqes); return rc; }
static int splat_taskq_test6_impl(struct file *file, void *arg, boolean_t prealloc) { taskq_t *tq; taskqid_t id; splat_taskq_id_t tq_id[SPLAT_TASKQ_ORDER_MAX]; splat_taskq_arg_t tq_arg; int order[SPLAT_TASKQ_ORDER_MAX] = { 1,2,3,6,7,8,4,5 }; taskq_ent_t tqes[SPLAT_TASKQ_ORDER_MAX]; int i, rc = 0; uint_t tflags; splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' creating (%s dispatch)\n", SPLAT_TASKQ_TEST6_NAME, prealloc ? "prealloc" : "dynamic"); if ((tq = taskq_create(SPLAT_TASKQ_TEST6_NAME, 3, maxclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST6_NAME); return -EINVAL; } tq_arg.flag = 0; memset(&tq_arg.order, 0, sizeof(int) * SPLAT_TASKQ_ORDER_MAX); spin_lock_init(&tq_arg.lock); tq_arg.file = file; tq_arg.name = SPLAT_TASKQ_TEST6_NAME; for (i = 0; i < SPLAT_TASKQ_ORDER_MAX; i++) { taskq_init_ent(&tqes[i]); tq_id[i].id = i + 1; tq_id[i].arg = &tq_arg; tflags = TQ_SLEEP; if (i > 4) tflags |= TQ_FRONT; if (prealloc) { taskq_dispatch_ent(tq, splat_taskq_test6_func, &tq_id[i], tflags, &tqes[i]); id = tqes[i].tqent_id; } else { id = taskq_dispatch(tq, splat_taskq_test6_func, &tq_id[i], tflags); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' function '%s' dispatch failed\n", tq_arg.name, sym2str(splat_taskq_test6_func)); rc = -EINVAL; goto out; } if (tq_id[i].id != id) { splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' expected taskqid %d got %d\n", tq_arg.name, (int)tq_id[i].id, (int)id); rc = -EINVAL; goto out; } /* Sleep to let tasks 1-3 start executing. */ if ( i == 2 ) msleep(100); } splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' " "waiting for taskqid %d completion\n", tq_arg.name, SPLAT_TASKQ_ORDER_MAX); taskq_wait_id(tq, SPLAT_TASKQ_ORDER_MAX); rc = splat_taskq_test_order(&tq_arg, order); out: splat_vprint(file, SPLAT_TASKQ_TEST6_NAME, "Taskq '%s' destroying\n", tq_arg.name); taskq_destroy(tq); return rc; }
static int splat_taskq_test5_impl(struct file *file, void *arg, boolean_t prealloc) { taskq_t *tq; taskqid_t id; splat_taskq_id_t tq_id[SPLAT_TASKQ_ORDER_MAX]; splat_taskq_arg_t tq_arg; int order1[SPLAT_TASKQ_ORDER_MAX] = { 1,2,4,5,3,0,0,0 }; int order2[SPLAT_TASKQ_ORDER_MAX] = { 1,2,4,5,3,8,6,7 }; taskq_ent_t tqes[SPLAT_TASKQ_ORDER_MAX]; int i, rc = 0; splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' creating (%s dispatch)\n", SPLAT_TASKQ_TEST5_NAME, prealloc ? "prealloc" : "dynamic"); if ((tq = taskq_create(SPLAT_TASKQ_TEST5_NAME, 3, maxclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST5_NAME); return -EINVAL; } tq_arg.flag = 0; memset(&tq_arg.order, 0, sizeof(int) * SPLAT_TASKQ_ORDER_MAX); spin_lock_init(&tq_arg.lock); tq_arg.file = file; tq_arg.name = SPLAT_TASKQ_TEST5_NAME; for (i = 0; i < SPLAT_TASKQ_ORDER_MAX; i++) { taskq_init_ent(&tqes[i]); tq_id[i].id = i + 1; tq_id[i].arg = &tq_arg; if (prealloc) { taskq_dispatch_ent(tq, splat_taskq_test5_func, &tq_id[i], TQ_SLEEP, &tqes[i]); id = tqes[i].tqent_id; } else { id = taskq_dispatch(tq, splat_taskq_test5_func, &tq_id[i], TQ_SLEEP); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' function '%s' dispatch failed\n", tq_arg.name, sym2str(splat_taskq_test5_func)); rc = -EINVAL; goto out; } if (tq_id[i].id != id) { splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' expected taskqid %d got %d\n", tq_arg.name, (int)tq_id[i].id, (int)id); rc = -EINVAL; goto out; } } splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' " "waiting for taskqid %d completion\n", tq_arg.name, 3); taskq_wait_id(tq, 3); if ((rc = splat_taskq_test_order(&tq_arg, order1))) goto out; splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' " "waiting for taskqid %d completion\n", tq_arg.name, 8); taskq_wait_id(tq, 8); rc = splat_taskq_test_order(&tq_arg, order2); out: splat_vprint(file, SPLAT_TASKQ_TEST5_NAME, "Taskq '%s' destroying\n", tq_arg.name); taskq_destroy(tq); return rc; }
static int splat_taskq_test4_common(struct file *file, void *arg, int minalloc, int maxalloc, int nr_tasks, boolean_t prealloc) { taskq_t *tq; taskqid_t id; splat_taskq_arg_t tq_arg; taskq_ent_t *tqes; int i, j, rc = 0; tqes = kmalloc(sizeof(*tqes) * nr_tasks, GFP_KERNEL); if (tqes == NULL) return -ENOMEM; splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' creating (%s dispatch) (%d/%d/%d)\n", SPLAT_TASKQ_TEST4_NAME, prealloc ? "prealloc" : "dynamic", minalloc, maxalloc, nr_tasks); if ((tq = taskq_create(SPLAT_TASKQ_TEST4_NAME, 1, maxclsyspri, minalloc, maxalloc, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' create failed\n", SPLAT_TASKQ_TEST4_NAME); rc = -EINVAL; goto out_free; } tq_arg.file = file; tq_arg.name = SPLAT_TASKQ_TEST4_NAME; for (i = 1; i <= nr_tasks; i *= 2) { atomic_set(&tq_arg.count, 0); splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' function '%s' dispatched %d times\n", tq_arg.name, sym2str(splat_taskq_test4_func), i); for (j = 0; j < i; j++) { taskq_init_ent(&tqes[j]); if (prealloc) { taskq_dispatch_ent(tq, splat_taskq_test4_func, &tq_arg, TQ_SLEEP, &tqes[j]); id = tqes[j].tqent_id; } else { id = taskq_dispatch(tq, splat_taskq_test4_func, &tq_arg, TQ_SLEEP); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' function '%s' dispatch " "%d failed\n", tq_arg.name, sym2str(splat_taskq_test4_func), j); rc = -EINVAL; goto out; } } splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' " "waiting for %d dispatches\n", tq_arg.name, i); taskq_wait(tq); splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' " "%d/%d dispatches finished\n", tq_arg.name, atomic_read(&tq_arg.count), i); if (atomic_read(&tq_arg.count) != i) { rc = -ERANGE; goto out; } } out: splat_vprint(file, SPLAT_TASKQ_TEST4_NAME, "Taskq '%s' destroying\n", tq_arg.name); taskq_destroy(tq); out_free: kfree(tqes); return rc; }
static int splat_taskq_throughput(struct file *file, void *arg, const char *name, int nthreads, int minalloc, int maxalloc, int flags, int tasks, struct timespec *delta) { taskq_t *tq; taskqid_t id; splat_taskq_arg_t tq_arg; taskq_ent_t **tqes; atomic_t count; struct timespec start, stop; int i, j, rc = 0; tqes = vmalloc(sizeof (*tqes) * tasks); if (tqes == NULL) return (-ENOMEM); memset(tqes, 0, sizeof (*tqes) * tasks); splat_vprint(file, name, "Taskq '%s' creating (%d/%d/%d/%d)\n", name, nthreads, minalloc, maxalloc, tasks); if ((tq = taskq_create(name, nthreads, maxclsyspri, minalloc, maxalloc, flags)) == NULL) { splat_vprint(file, name, "Taskq '%s' create failed\n", name); rc = -EINVAL; goto out_free; } tq_arg.file = file; tq_arg.name = name; tq_arg.count = &count; atomic_set(tq_arg.count, 0); getnstimeofday(&start); for (i = 0; i < tasks; i++) { tqes[i] = kmalloc(sizeof (taskq_ent_t), GFP_KERNEL); if (tqes[i] == NULL) { rc = -ENOMEM; goto out; } taskq_init_ent(tqes[i]); taskq_dispatch_ent(tq, splat_taskq_throughput_func, &tq_arg, TQ_SLEEP, tqes[i]); id = tqes[i]->tqent_id; if (id == 0) { splat_vprint(file, name, "Taskq '%s' function '%s' " "dispatch %d failed\n", tq_arg.name, sym2str(splat_taskq_throughput_func), i); rc = -EINVAL; goto out; } } splat_vprint(file, name, "Taskq '%s' waiting for %d dispatches\n", tq_arg.name, tasks); taskq_wait(tq); if (delta != NULL) { getnstimeofday(&stop); *delta = timespec_sub(stop, start); } splat_vprint(file, name, "Taskq '%s' %d/%d dispatches finished\n", tq_arg.name, atomic_read(tq_arg.count), tasks); if (atomic_read(tq_arg.count) != tasks) rc = -ERANGE; out: splat_vprint(file, name, "Taskq '%s' destroying\n", tq_arg.name); taskq_destroy(tq); out_free: for (j = 0; j < tasks && tqes[j] != NULL; j++) kfree(tqes[j]); vfree(tqes); return (rc); }
static int splat_taskq_test2_impl(struct file *file, void *arg, boolean_t prealloc) { taskq_t *tq[TEST2_TASKQS] = { NULL }; taskqid_t id; splat_taskq_arg_t tq_args[TEST2_TASKQS]; taskq_ent_t *func1_tqes = NULL; taskq_ent_t *func2_tqes = NULL; int i, rc = 0; func1_tqes = kmalloc(sizeof(*func1_tqes) * TEST2_TASKQS, GFP_KERNEL); if (func1_tqes == NULL) { rc = -ENOMEM; goto out; } func2_tqes = kmalloc(sizeof(*func2_tqes) * TEST2_TASKQS, GFP_KERNEL); if (func2_tqes == NULL) { rc = -ENOMEM; goto out; } for (i = 0; i < TEST2_TASKQS; i++) { taskq_init_ent(&func1_tqes[i]); taskq_init_ent(&func2_tqes[i]); splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' creating (%s dispatch)\n", SPLAT_TASKQ_TEST2_NAME, i, prealloc ? "prealloc" : "dynamic"); if ((tq[i] = taskq_create(SPLAT_TASKQ_TEST2_NAME, TEST2_THREADS_PER_TASKQ, maxclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE)) == NULL) { splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' create failed\n", SPLAT_TASKQ_TEST2_NAME, i); rc = -EINVAL; break; } tq_args[i].flag = i; tq_args[i].id = i; tq_args[i].file = file; tq_args[i].name = SPLAT_TASKQ_TEST2_NAME; splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' function '%s' dispatching\n", tq_args[i].name, tq_args[i].id, sym2str(splat_taskq_test2_func1)); if (prealloc) { taskq_dispatch_ent(tq[i], splat_taskq_test2_func1, &tq_args[i], TQ_SLEEP, &func1_tqes[i]); id = func1_tqes[i].tqent_id; } else { id = taskq_dispatch(tq[i], splat_taskq_test2_func1, &tq_args[i], TQ_SLEEP); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' function '%s' dispatch " "failed\n", tq_args[i].name, tq_args[i].id, sym2str(splat_taskq_test2_func1)); rc = -EINVAL; break; } splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' function '%s' dispatching\n", tq_args[i].name, tq_args[i].id, sym2str(splat_taskq_test2_func2)); if (prealloc) { taskq_dispatch_ent(tq[i], splat_taskq_test2_func2, &tq_args[i], TQ_SLEEP, &func2_tqes[i]); id = func2_tqes[i].tqent_id; } else { id = taskq_dispatch(tq[i], splat_taskq_test2_func2, &tq_args[i], TQ_SLEEP); } if (id == 0) { splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq " "'%s/%d' function '%s' dispatch failed\n", tq_args[i].name, tq_args[i].id, sym2str(splat_taskq_test2_func2)); rc = -EINVAL; break; } } /* When rc is set we're effectively just doing cleanup here, so * ignore new errors in that case. They just cause noise. */ for (i = 0; i < TEST2_TASKQS; i++) { if (tq[i] != NULL) { splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' waiting\n", tq_args[i].name, tq_args[i].id); taskq_wait(tq[i]); splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d; destroying\n", tq_args[i].name, tq_args[i].id); taskq_destroy(tq[i]); if (!rc && tq_args[i].flag != ((i * 2) + 1)) { splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' processed tasks " "out of order; %d != %d\n", tq_args[i].name, tq_args[i].id, tq_args[i].flag, i * 2 + 1); rc = -EINVAL; } else { splat_vprint(file, SPLAT_TASKQ_TEST2_NAME, "Taskq '%s/%d' processed tasks " "in the correct order; %d == %d\n", tq_args[i].name, tq_args[i].id, tq_args[i].flag, i * 2 + 1); } } } out: if (func1_tqes) kfree(func1_tqes); if (func2_tqes) kfree(func2_tqes); return rc; }