18e25f19bSMatthew Dillon /*
28e25f19bSMatthew Dillon * Copyright (c) 2019 The DragonFly Project. All rights reserved.
38e25f19bSMatthew Dillon *
48e25f19bSMatthew Dillon * This code is derived from software contributed to The DragonFly Project
58e25f19bSMatthew Dillon * by Matthew Dillon <dillon@backplane.com>
68e25f19bSMatthew Dillon *
78e25f19bSMatthew Dillon * This code uses concepts and configuration based on 'synth', by
88e25f19bSMatthew Dillon * John R. Marino <draco@marino.st>, which was written in ada.
98e25f19bSMatthew Dillon *
108e25f19bSMatthew Dillon * Redistribution and use in source and binary forms, with or without
118e25f19bSMatthew Dillon * modification, are permitted provided that the following conditions
128e25f19bSMatthew Dillon * are met:
138e25f19bSMatthew Dillon *
148e25f19bSMatthew Dillon * 1. Redistributions of source code must retain the above copyright
158e25f19bSMatthew Dillon * notice, this list of conditions and the following disclaimer.
168e25f19bSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
178e25f19bSMatthew Dillon * notice, this list of conditions and the following disclaimer in
188e25f19bSMatthew Dillon * the documentation and/or other materials provided with the
198e25f19bSMatthew Dillon * distribution.
208e25f19bSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
218e25f19bSMatthew Dillon * contributors may be used to endorse or promote products derived
228e25f19bSMatthew Dillon * from this software without specific, prior written permission.
238e25f19bSMatthew Dillon *
248e25f19bSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
258e25f19bSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
268e25f19bSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
278e25f19bSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
288e25f19bSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
298e25f19bSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
308e25f19bSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
318e25f19bSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
328e25f19bSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
338e25f19bSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
348e25f19bSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
358e25f19bSMatthew Dillon * SUCH DAMAGE.
368e25f19bSMatthew Dillon */
378e25f19bSMatthew Dillon #include "dsynth.h"
388e25f19bSMatthew Dillon
398e25f19bSMatthew Dillon typedef struct job {
408e25f19bSMatthew Dillon pthread_t td;
418e25f19bSMatthew Dillon pthread_cond_t cond;
428e25f19bSMatthew Dillon bulk_t *active;
438e25f19bSMatthew Dillon int terminate : 1;
448e25f19bSMatthew Dillon } job_t;
458e25f19bSMatthew Dillon
468e25f19bSMatthew Dillon /*
478e25f19bSMatthew Dillon * Most of these globals are locked with BulkMutex
488e25f19bSMatthew Dillon */
498e25f19bSMatthew Dillon static int BulkScanJob;
508e25f19bSMatthew Dillon static int BulkCurJobs;
518e25f19bSMatthew Dillon static int BulkMaxJobs;
528e25f19bSMatthew Dillon static job_t JobsAry[MAXBULK];
538e25f19bSMatthew Dillon static void (*BulkFunc)(bulk_t *bulk);
548e25f19bSMatthew Dillon static bulk_t *BulkSubmit;
558e25f19bSMatthew Dillon static bulk_t **BulkSubmitTail = &BulkSubmit;
568e25f19bSMatthew Dillon static bulk_t *BulkResponse;
578e25f19bSMatthew Dillon static bulk_t **BulkResponseTail = &BulkResponse;
588e25f19bSMatthew Dillon static pthread_cond_t BulkResponseCond;
598e25f19bSMatthew Dillon static pthread_mutex_t BulkMutex;
608e25f19bSMatthew Dillon
618e25f19bSMatthew Dillon static void bulkstart(void);
628e25f19bSMatthew Dillon #if 0
638e25f19bSMatthew Dillon static int readall(int fd, void *buf, size_t bytes);
648e25f19bSMatthew Dillon static int writeall(int fd, const void *buf, size_t bytes);
658e25f19bSMatthew Dillon #endif
668e25f19bSMatthew Dillon static void *bulkthread(void *arg);
678e25f19bSMatthew Dillon
68a67bf8dbSMatthew Dillon /*
69a67bf8dbSMatthew Dillon * Initialize for bulk scan operations. Always paired with donebulk()
70a67bf8dbSMatthew Dillon */
718e25f19bSMatthew Dillon void
initbulk(void (* func)(bulk_t * bulk),int jobs)728e25f19bSMatthew Dillon initbulk(void (*func)(bulk_t *bulk), int jobs)
738e25f19bSMatthew Dillon {
748e25f19bSMatthew Dillon int i;
758e25f19bSMatthew Dillon
768e25f19bSMatthew Dillon if (jobs > MAXBULK)
778e25f19bSMatthew Dillon jobs = MAXBULK;
788e25f19bSMatthew Dillon
798e25f19bSMatthew Dillon ddassert(BulkSubmit == NULL);
808e25f19bSMatthew Dillon BulkCurJobs = 0;
818e25f19bSMatthew Dillon BulkMaxJobs = jobs;
828e25f19bSMatthew Dillon BulkFunc = func;
838e25f19bSMatthew Dillon BulkScanJob = 0;
848e25f19bSMatthew Dillon
85967a4bb3SMatthew Dillon addbuildenv("__MAKE_CONF", "/dev/null",
86967a4bb3SMatthew Dillon BENV_ENVIRONMENT | BENV_PKGLIST);
87a67bf8dbSMatthew Dillon
88*33c3dcc3SMatthew Dillon /*
89*33c3dcc3SMatthew Dillon * CCache is a horrible unreliable hack but... leave the
90*33c3dcc3SMatthew Dillon * mechanism in-place in case someone has a death wish.
91*33c3dcc3SMatthew Dillon */
92*33c3dcc3SMatthew Dillon if (UseCCache) {
93*33c3dcc3SMatthew Dillon addbuildenv("WITH_CCACHE_BUILD", "yes", BENV_MAKECONF);
94*33c3dcc3SMatthew Dillon addbuildenv("CCACHE_DIR", CCachePath, BENV_MAKECONF);
95*33c3dcc3SMatthew Dillon }
96*33c3dcc3SMatthew Dillon
978e25f19bSMatthew Dillon pthread_mutex_init(&BulkMutex, NULL);
988e25f19bSMatthew Dillon pthread_cond_init(&BulkResponseCond, NULL);
998e25f19bSMatthew Dillon
1008e25f19bSMatthew Dillon pthread_mutex_lock(&BulkMutex);
1018e25f19bSMatthew Dillon for (i = 0; i < jobs; ++i) {
1028e25f19bSMatthew Dillon pthread_cond_init(&JobsAry[i].cond, NULL);
1038e25f19bSMatthew Dillon pthread_create(&JobsAry[i].td, NULL, bulkthread, &JobsAry[i]);
1048e25f19bSMatthew Dillon }
1058e25f19bSMatthew Dillon pthread_mutex_unlock(&BulkMutex);
1068e25f19bSMatthew Dillon }
1078e25f19bSMatthew Dillon
1088e25f19bSMatthew Dillon void
donebulk(void)1098e25f19bSMatthew Dillon donebulk(void)
1108e25f19bSMatthew Dillon {
1118e25f19bSMatthew Dillon bulk_t *bulk;
1128e25f19bSMatthew Dillon int i;
1138e25f19bSMatthew Dillon
1148e25f19bSMatthew Dillon pthread_mutex_lock(&BulkMutex);
1158e25f19bSMatthew Dillon while ((bulk = BulkSubmit) != NULL) {
1168e25f19bSMatthew Dillon BulkSubmit = bulk->next;
1178e25f19bSMatthew Dillon freebulk(bulk);
1188e25f19bSMatthew Dillon }
1198e25f19bSMatthew Dillon BulkSubmitTail = &BulkSubmit;
1208e25f19bSMatthew Dillon
1218e25f19bSMatthew Dillon for (i = 0; i < BulkMaxJobs; ++i) {
1228e25f19bSMatthew Dillon JobsAry[i].terminate = 1;
1238e25f19bSMatthew Dillon pthread_cond_signal(&JobsAry[i].cond);
1248e25f19bSMatthew Dillon }
1258e25f19bSMatthew Dillon pthread_mutex_unlock(&BulkMutex);
1268e25f19bSMatthew Dillon for (i = 0; i < BulkMaxJobs; ++i) {
1278e25f19bSMatthew Dillon pthread_join(JobsAry[i].td, NULL);
1288e25f19bSMatthew Dillon pthread_cond_destroy(&JobsAry[i].cond);
1298e25f19bSMatthew Dillon if (JobsAry[i].active) {
1308e25f19bSMatthew Dillon freebulk(JobsAry[i].active);
1318e25f19bSMatthew Dillon JobsAry[i].active = NULL;
1323699ee09SMatthew Dillon pthread_mutex_lock(&BulkMutex);
1338e25f19bSMatthew Dillon --BulkCurJobs;
1343699ee09SMatthew Dillon pthread_mutex_unlock(&BulkMutex);
1358e25f19bSMatthew Dillon }
1368e25f19bSMatthew Dillon JobsAry[i].terminate = 0;
1378e25f19bSMatthew Dillon }
1388e25f19bSMatthew Dillon ddassert(BulkCurJobs == 0);
1398e25f19bSMatthew Dillon
1408e25f19bSMatthew Dillon while ((bulk = BulkResponse) != NULL) {
1418e25f19bSMatthew Dillon BulkResponse = bulk->next;
1428e25f19bSMatthew Dillon freebulk(bulk);
1438e25f19bSMatthew Dillon }
1448e25f19bSMatthew Dillon BulkResponseTail = &BulkResponse;
1458e25f19bSMatthew Dillon
1468e25f19bSMatthew Dillon BulkFunc = NULL;
1478e25f19bSMatthew Dillon
1488e25f19bSMatthew Dillon bzero(JobsAry, sizeof(JobsAry));
149a67bf8dbSMatthew Dillon
150*33c3dcc3SMatthew Dillon if (UseCCache) {
151*33c3dcc3SMatthew Dillon delbuildenv("WITH_CCACHE_BUILD");
152*33c3dcc3SMatthew Dillon delbuildenv("CCACHE_DIR");
153*33c3dcc3SMatthew Dillon }
154a67bf8dbSMatthew Dillon delbuildenv("__MAKE_CONF");
1558e25f19bSMatthew Dillon }
1568e25f19bSMatthew Dillon
1577f0eca56SMatthew Dillon void
queuebulk(const char * s1,const char * s2,const char * s3,const char * s4)1588e25f19bSMatthew Dillon queuebulk(const char *s1, const char *s2, const char *s3, const char *s4)
1598e25f19bSMatthew Dillon {
1608e25f19bSMatthew Dillon bulk_t *bulk;
1618e25f19bSMatthew Dillon
1628e25f19bSMatthew Dillon bulk = calloc(1, sizeof(*bulk));
1638e25f19bSMatthew Dillon if (s1)
1648e25f19bSMatthew Dillon bulk->s1 = strdup(s1);
1658e25f19bSMatthew Dillon if (s2)
1668e25f19bSMatthew Dillon bulk->s2 = strdup(s2);
1678e25f19bSMatthew Dillon if (s3)
1688e25f19bSMatthew Dillon bulk->s3 = strdup(s3);
1698e25f19bSMatthew Dillon if (s4)
1708e25f19bSMatthew Dillon bulk->s4 = strdup(s4);
1718e25f19bSMatthew Dillon bulk->state = ONSUBMIT;
1728e25f19bSMatthew Dillon
1738e25f19bSMatthew Dillon pthread_mutex_lock(&BulkMutex);
1748e25f19bSMatthew Dillon *BulkSubmitTail = bulk;
1758e25f19bSMatthew Dillon BulkSubmitTail = &bulk->next;
1767f0eca56SMatthew Dillon if (BulkCurJobs < BulkMaxJobs) {
1778e25f19bSMatthew Dillon pthread_mutex_unlock(&BulkMutex);
1788e25f19bSMatthew Dillon bulkstart();
1797f0eca56SMatthew Dillon } else {
1807f0eca56SMatthew Dillon pthread_mutex_unlock(&BulkMutex);
1817f0eca56SMatthew Dillon }
1828e25f19bSMatthew Dillon }
1838e25f19bSMatthew Dillon
1848e25f19bSMatthew Dillon /*
1858e25f19bSMatthew Dillon * Fill any idle job slots with new jobs as available.
1868e25f19bSMatthew Dillon */
1878e25f19bSMatthew Dillon static
1888e25f19bSMatthew Dillon void
bulkstart(void)1898e25f19bSMatthew Dillon bulkstart(void)
1908e25f19bSMatthew Dillon {
1918e25f19bSMatthew Dillon bulk_t *bulk;
1928e25f19bSMatthew Dillon int i;
1938e25f19bSMatthew Dillon
1948e25f19bSMatthew Dillon pthread_mutex_lock(&BulkMutex);
1958e25f19bSMatthew Dillon while ((bulk = BulkSubmit) != NULL && BulkCurJobs < BulkMaxJobs) {
1968e25f19bSMatthew Dillon i = BulkScanJob + 1;
1978e25f19bSMatthew Dillon for (;;) {
1988e25f19bSMatthew Dillon i = i % BulkMaxJobs;
1998e25f19bSMatthew Dillon if (JobsAry[i].active == NULL)
2008e25f19bSMatthew Dillon break;
2018e25f19bSMatthew Dillon ++i;
2028e25f19bSMatthew Dillon }
2038e25f19bSMatthew Dillon BulkScanJob = i;
2048e25f19bSMatthew Dillon BulkSubmit = bulk->next;
2058e25f19bSMatthew Dillon if (BulkSubmit == NULL)
2068e25f19bSMatthew Dillon BulkSubmitTail = &BulkSubmit;
2078e25f19bSMatthew Dillon
2088e25f19bSMatthew Dillon bulk->state = ONRUN;
2098e25f19bSMatthew Dillon JobsAry[i].active = bulk;
2108e25f19bSMatthew Dillon pthread_cond_signal(&JobsAry[i].cond);
2118e25f19bSMatthew Dillon ++BulkCurJobs;
2128e25f19bSMatthew Dillon }
2138e25f19bSMatthew Dillon pthread_mutex_unlock(&BulkMutex);
2148e25f19bSMatthew Dillon }
2158e25f19bSMatthew Dillon
2168e25f19bSMatthew Dillon /*
2178e25f19bSMatthew Dillon * Retrieve completed job or job with activity
2188e25f19bSMatthew Dillon */
2198e25f19bSMatthew Dillon bulk_t *
getbulk(void)2208e25f19bSMatthew Dillon getbulk(void)
2218e25f19bSMatthew Dillon {
2228e25f19bSMatthew Dillon bulk_t *bulk;
2238e25f19bSMatthew Dillon
2248e25f19bSMatthew Dillon pthread_mutex_lock(&BulkMutex);
2258e25f19bSMatthew Dillon while (BulkCurJobs && BulkResponse == NULL) {
2268e25f19bSMatthew Dillon pthread_cond_wait(&BulkResponseCond, &BulkMutex);
2278e25f19bSMatthew Dillon }
2288e25f19bSMatthew Dillon if (BulkResponse) {
2298e25f19bSMatthew Dillon bulk = BulkResponse;
2308e25f19bSMatthew Dillon ddassert(bulk->state == ONRESPONSE);
2318e25f19bSMatthew Dillon BulkResponse = bulk->next;
2328e25f19bSMatthew Dillon if (BulkResponse == NULL)
2338e25f19bSMatthew Dillon BulkResponseTail = &BulkResponse;
2348e25f19bSMatthew Dillon bulk->state = UNLISTED;
2358e25f19bSMatthew Dillon } else {
2368e25f19bSMatthew Dillon bulk = NULL;
2378e25f19bSMatthew Dillon }
2388e25f19bSMatthew Dillon pthread_mutex_unlock(&BulkMutex);
2398e25f19bSMatthew Dillon bulkstart();
2408e25f19bSMatthew Dillon
2418e25f19bSMatthew Dillon return bulk;
2428e25f19bSMatthew Dillon }
2438e25f19bSMatthew Dillon
2448e25f19bSMatthew Dillon void
freebulk(bulk_t * bulk)2458e25f19bSMatthew Dillon freebulk(bulk_t *bulk)
2468e25f19bSMatthew Dillon {
2478e25f19bSMatthew Dillon ddassert(bulk->state == UNLISTED);
2488e25f19bSMatthew Dillon
2498e25f19bSMatthew Dillon if (bulk->s1) {
2508e25f19bSMatthew Dillon free(bulk->s1);
2518e25f19bSMatthew Dillon bulk->s1 = NULL;
2528e25f19bSMatthew Dillon }
2538e25f19bSMatthew Dillon if (bulk->s2) {
2548e25f19bSMatthew Dillon free(bulk->s2);
2558e25f19bSMatthew Dillon bulk->s2 = NULL;
2568e25f19bSMatthew Dillon }
2578e25f19bSMatthew Dillon if (bulk->s3) {
2588e25f19bSMatthew Dillon free(bulk->s3);
2598e25f19bSMatthew Dillon bulk->s3 = NULL;
2608e25f19bSMatthew Dillon }
2618e25f19bSMatthew Dillon if (bulk->s4) {
2628e25f19bSMatthew Dillon free(bulk->s4);
2638e25f19bSMatthew Dillon bulk->s4 = NULL;
2648e25f19bSMatthew Dillon }
2658e25f19bSMatthew Dillon if (bulk->r1) {
2668e25f19bSMatthew Dillon free(bulk->r1);
2678e25f19bSMatthew Dillon bulk->r1 = NULL;
2688e25f19bSMatthew Dillon }
2698e25f19bSMatthew Dillon if (bulk->r2) {
2708e25f19bSMatthew Dillon free(bulk->r2);
2718e25f19bSMatthew Dillon bulk->r2 = NULL;
2728e25f19bSMatthew Dillon }
2738e25f19bSMatthew Dillon if (bulk->r3) {
2748e25f19bSMatthew Dillon free(bulk->r3);
2758e25f19bSMatthew Dillon bulk->r3 = NULL;
2768e25f19bSMatthew Dillon }
2778e25f19bSMatthew Dillon if (bulk->r4) {
2788e25f19bSMatthew Dillon free(bulk->r4);
2798e25f19bSMatthew Dillon bulk->r4 = NULL;
2808e25f19bSMatthew Dillon }
2818e25f19bSMatthew Dillon free(bulk);
2828e25f19bSMatthew Dillon }
2838e25f19bSMatthew Dillon
2848e25f19bSMatthew Dillon #if 0
2858e25f19bSMatthew Dillon
2868e25f19bSMatthew Dillon /*
2878e25f19bSMatthew Dillon * Returns non-zero if unable to read specified number of bytes
2888e25f19bSMatthew Dillon */
2898e25f19bSMatthew Dillon static
2908e25f19bSMatthew Dillon int
2918e25f19bSMatthew Dillon readall(int fd, void *buf, size_t bytes)
2928e25f19bSMatthew Dillon {
2938e25f19bSMatthew Dillon ssize_t r;
2948e25f19bSMatthew Dillon
2958e25f19bSMatthew Dillon for (;;) {
2968e25f19bSMatthew Dillon r = read(fd, buf, bytes);
2978e25f19bSMatthew Dillon if (r == (ssize_t)bytes)
2988e25f19bSMatthew Dillon break;
2998e25f19bSMatthew Dillon if (r > 0) {
3008e25f19bSMatthew Dillon buf = (char *)buf + r;
3018e25f19bSMatthew Dillon bytes -= r;
3028e25f19bSMatthew Dillon continue;
3038e25f19bSMatthew Dillon }
3048e25f19bSMatthew Dillon if (r < 0 && errno == EINTR)
3058e25f19bSMatthew Dillon continue;
3068e25f19bSMatthew Dillon return 1;
3078e25f19bSMatthew Dillon }
3088e25f19bSMatthew Dillon return 0;
3098e25f19bSMatthew Dillon }
3108e25f19bSMatthew Dillon
3118e25f19bSMatthew Dillon static
3128e25f19bSMatthew Dillon int
3138e25f19bSMatthew Dillon writeall(int fd, const void *buf, size_t bytes)
3148e25f19bSMatthew Dillon {
3158e25f19bSMatthew Dillon ssize_t r;
3168e25f19bSMatthew Dillon
3178e25f19bSMatthew Dillon for (;;) {
3188e25f19bSMatthew Dillon r = write(fd, buf, bytes);
3198e25f19bSMatthew Dillon if (r == (ssize_t)bytes)
3208e25f19bSMatthew Dillon break;
3218e25f19bSMatthew Dillon if (r > 0) {
3228e25f19bSMatthew Dillon buf = (const char *)buf + r;
3238e25f19bSMatthew Dillon bytes -= r;
3248e25f19bSMatthew Dillon continue;
3258e25f19bSMatthew Dillon }
3268e25f19bSMatthew Dillon if (r < 0 && errno == EINTR)
3278e25f19bSMatthew Dillon continue;
3288e25f19bSMatthew Dillon return 1;
3298e25f19bSMatthew Dillon }
3308e25f19bSMatthew Dillon return 0;
3318e25f19bSMatthew Dillon }
3328e25f19bSMatthew Dillon
3338e25f19bSMatthew Dillon #endif
3348e25f19bSMatthew Dillon
3358e25f19bSMatthew Dillon static void *
bulkthread(void * arg)3368e25f19bSMatthew Dillon bulkthread(void *arg)
3378e25f19bSMatthew Dillon {
3388e25f19bSMatthew Dillon job_t *job = arg;
3398e25f19bSMatthew Dillon bulk_t *bulk;
3408e25f19bSMatthew Dillon
3418e25f19bSMatthew Dillon pthread_mutex_lock(&BulkMutex);
3428e25f19bSMatthew Dillon for (;;) {
3438e25f19bSMatthew Dillon if (job->terminate)
3448e25f19bSMatthew Dillon break;
3458e25f19bSMatthew Dillon if (job->active == NULL)
3468e25f19bSMatthew Dillon pthread_cond_wait(&job->cond, &BulkMutex);
3478e25f19bSMatthew Dillon bulk = job->active;
3488e25f19bSMatthew Dillon if (bulk) {
3498e25f19bSMatthew Dillon bulk->state = ISRUNNING;
3508e25f19bSMatthew Dillon
3518e25f19bSMatthew Dillon pthread_mutex_unlock(&BulkMutex);
3528e25f19bSMatthew Dillon BulkFunc(bulk);
3538e25f19bSMatthew Dillon pthread_mutex_lock(&BulkMutex);
3548e25f19bSMatthew Dillon
3558e25f19bSMatthew Dillon bulk->state = ONRESPONSE;
3568e25f19bSMatthew Dillon bulk->next = NULL;
3578e25f19bSMatthew Dillon *BulkResponseTail = bulk;
3588e25f19bSMatthew Dillon BulkResponseTail = &bulk->next;
3598e25f19bSMatthew Dillon --BulkCurJobs;
3608e25f19bSMatthew Dillon pthread_cond_signal(&BulkResponseCond);
3618e25f19bSMatthew Dillon }
3628e25f19bSMatthew Dillon
3638e25f19bSMatthew Dillon /*
3648e25f19bSMatthew Dillon * Optimization - automatically fetch the next job
3658e25f19bSMatthew Dillon */
3668e25f19bSMatthew Dillon if ((bulk = BulkSubmit) != NULL && job->terminate == 0) {
3678e25f19bSMatthew Dillon BulkSubmit = bulk->next;
3688e25f19bSMatthew Dillon if (BulkSubmit == NULL)
3698e25f19bSMatthew Dillon BulkSubmitTail = &BulkSubmit;
3708e25f19bSMatthew Dillon bulk->state = ONRUN;
3718e25f19bSMatthew Dillon job->active = bulk;
3728e25f19bSMatthew Dillon ++BulkCurJobs;
3737f0eca56SMatthew Dillon } else {
3747f0eca56SMatthew Dillon job->active = NULL;
3758e25f19bSMatthew Dillon }
3768e25f19bSMatthew Dillon }
3778e25f19bSMatthew Dillon pthread_mutex_unlock(&BulkMutex);
3788e25f19bSMatthew Dillon
3798e25f19bSMatthew Dillon return NULL;
3808e25f19bSMatthew Dillon }
381