xref: /dflybsd-src/usr.bin/dsynth/bulk.c (revision 967a4bb3ac8da6a70cdc0385de38e9c9891ffbc9)
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
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 
85*967a4bb3SMatthew Dillon 	addbuildenv("__MAKE_CONF", "/dev/null",
86*967a4bb3SMatthew Dillon 		    BENV_ENVIRONMENT | BENV_PKGLIST);
87a67bf8dbSMatthew Dillon 
888e25f19bSMatthew Dillon 	pthread_mutex_init(&BulkMutex, NULL);
898e25f19bSMatthew Dillon 	pthread_cond_init(&BulkResponseCond, NULL);
908e25f19bSMatthew Dillon 
918e25f19bSMatthew Dillon 	pthread_mutex_lock(&BulkMutex);
928e25f19bSMatthew Dillon 	for (i = 0; i < jobs; ++i) {
938e25f19bSMatthew Dillon 		pthread_cond_init(&JobsAry[i].cond, NULL);
948e25f19bSMatthew Dillon 		pthread_create(&JobsAry[i].td, NULL, bulkthread, &JobsAry[i]);
958e25f19bSMatthew Dillon 	}
968e25f19bSMatthew Dillon 	pthread_mutex_unlock(&BulkMutex);
978e25f19bSMatthew Dillon }
988e25f19bSMatthew Dillon 
998e25f19bSMatthew Dillon void
1008e25f19bSMatthew Dillon donebulk(void)
1018e25f19bSMatthew Dillon {
1028e25f19bSMatthew Dillon 	bulk_t *bulk;
1038e25f19bSMatthew Dillon 	int i;
1048e25f19bSMatthew Dillon 
1058e25f19bSMatthew Dillon 	pthread_mutex_lock(&BulkMutex);
1068e25f19bSMatthew Dillon 	while ((bulk = BulkSubmit) != NULL) {
1078e25f19bSMatthew Dillon 		BulkSubmit = bulk->next;
1088e25f19bSMatthew Dillon 		freebulk(bulk);
1098e25f19bSMatthew Dillon 	}
1108e25f19bSMatthew Dillon 	BulkSubmitTail = &BulkSubmit;
1118e25f19bSMatthew Dillon 
1128e25f19bSMatthew Dillon 	for (i = 0; i < BulkMaxJobs; ++i) {
1138e25f19bSMatthew Dillon 		JobsAry[i].terminate = 1;
1148e25f19bSMatthew Dillon 		pthread_cond_signal(&JobsAry[i].cond);
1158e25f19bSMatthew Dillon 	}
1168e25f19bSMatthew Dillon 	pthread_mutex_unlock(&BulkMutex);
1178e25f19bSMatthew Dillon 	for (i = 0; i < BulkMaxJobs; ++i) {
1188e25f19bSMatthew Dillon 		pthread_join(JobsAry[i].td, NULL);
1198e25f19bSMatthew Dillon 		pthread_cond_destroy(&JobsAry[i].cond);
1208e25f19bSMatthew Dillon 		if (JobsAry[i].active) {
1218e25f19bSMatthew Dillon 			freebulk(JobsAry[i].active);
1228e25f19bSMatthew Dillon 			JobsAry[i].active = NULL;
1233699ee09SMatthew Dillon 			pthread_mutex_lock(&BulkMutex);
1248e25f19bSMatthew Dillon 			--BulkCurJobs;
1253699ee09SMatthew Dillon 			pthread_mutex_unlock(&BulkMutex);
1268e25f19bSMatthew Dillon 		}
1278e25f19bSMatthew Dillon 		JobsAry[i].terminate = 0;
1288e25f19bSMatthew Dillon 	}
1298e25f19bSMatthew Dillon 	ddassert(BulkCurJobs == 0);
1308e25f19bSMatthew Dillon 
1318e25f19bSMatthew Dillon 	while ((bulk = BulkResponse) != NULL) {
1328e25f19bSMatthew Dillon 		BulkResponse = bulk->next;
1338e25f19bSMatthew Dillon 		freebulk(bulk);
1348e25f19bSMatthew Dillon 	}
1358e25f19bSMatthew Dillon 	BulkResponseTail = &BulkResponse;
1368e25f19bSMatthew Dillon 
1378e25f19bSMatthew Dillon 	BulkFunc = NULL;
1388e25f19bSMatthew Dillon 
1398e25f19bSMatthew Dillon 	bzero(JobsAry, sizeof(JobsAry));
140a67bf8dbSMatthew Dillon 
141a67bf8dbSMatthew Dillon 	delbuildenv("__MAKE_CONF");
1428e25f19bSMatthew Dillon }
1438e25f19bSMatthew Dillon 
1447f0eca56SMatthew Dillon void
1458e25f19bSMatthew Dillon queuebulk(const char *s1, const char *s2, const char *s3, const char *s4)
1468e25f19bSMatthew Dillon {
1478e25f19bSMatthew Dillon 	bulk_t *bulk;
1488e25f19bSMatthew Dillon 
1498e25f19bSMatthew Dillon 	bulk = calloc(1, sizeof(*bulk));
1508e25f19bSMatthew Dillon 	if (s1)
1518e25f19bSMatthew Dillon 		bulk->s1 = strdup(s1);
1528e25f19bSMatthew Dillon 	if (s2)
1538e25f19bSMatthew Dillon 		bulk->s2 = strdup(s2);
1548e25f19bSMatthew Dillon 	if (s3)
1558e25f19bSMatthew Dillon 		bulk->s3 = strdup(s3);
1568e25f19bSMatthew Dillon 	if (s4)
1578e25f19bSMatthew Dillon 		bulk->s4 = strdup(s4);
1588e25f19bSMatthew Dillon 	bulk->state = ONSUBMIT;
1598e25f19bSMatthew Dillon 
1608e25f19bSMatthew Dillon 	pthread_mutex_lock(&BulkMutex);
1618e25f19bSMatthew Dillon 	*BulkSubmitTail = bulk;
1628e25f19bSMatthew Dillon 	BulkSubmitTail = &bulk->next;
1637f0eca56SMatthew Dillon 	if (BulkCurJobs < BulkMaxJobs) {
1648e25f19bSMatthew Dillon 		pthread_mutex_unlock(&BulkMutex);
1658e25f19bSMatthew Dillon 		bulkstart();
1667f0eca56SMatthew Dillon 	} else {
1677f0eca56SMatthew Dillon 		pthread_mutex_unlock(&BulkMutex);
1687f0eca56SMatthew Dillon 	}
1698e25f19bSMatthew Dillon }
1708e25f19bSMatthew Dillon 
1718e25f19bSMatthew Dillon /*
1728e25f19bSMatthew Dillon  * Fill any idle job slots with new jobs as available.
1738e25f19bSMatthew Dillon  */
1748e25f19bSMatthew Dillon static
1758e25f19bSMatthew Dillon void
1768e25f19bSMatthew Dillon bulkstart(void)
1778e25f19bSMatthew Dillon {
1788e25f19bSMatthew Dillon 	bulk_t *bulk;
1798e25f19bSMatthew Dillon 	int i;
1808e25f19bSMatthew Dillon 
1818e25f19bSMatthew Dillon 	pthread_mutex_lock(&BulkMutex);
1828e25f19bSMatthew Dillon 	while ((bulk = BulkSubmit) != NULL && BulkCurJobs < BulkMaxJobs) {
1838e25f19bSMatthew Dillon 		i = BulkScanJob + 1;
1848e25f19bSMatthew Dillon 		for (;;) {
1858e25f19bSMatthew Dillon 			i = i % BulkMaxJobs;
1868e25f19bSMatthew Dillon 			if (JobsAry[i].active == NULL)
1878e25f19bSMatthew Dillon 				break;
1888e25f19bSMatthew Dillon 			++i;
1898e25f19bSMatthew Dillon 		}
1908e25f19bSMatthew Dillon 		BulkScanJob = i;
1918e25f19bSMatthew Dillon 		BulkSubmit = bulk->next;
1928e25f19bSMatthew Dillon 		if (BulkSubmit == NULL)
1938e25f19bSMatthew Dillon 			BulkSubmitTail = &BulkSubmit;
1948e25f19bSMatthew Dillon 
1958e25f19bSMatthew Dillon 		bulk->state = ONRUN;
1968e25f19bSMatthew Dillon 		JobsAry[i].active = bulk;
1978e25f19bSMatthew Dillon 		pthread_cond_signal(&JobsAry[i].cond);
1988e25f19bSMatthew Dillon 		++BulkCurJobs;
1998e25f19bSMatthew Dillon 	}
2008e25f19bSMatthew Dillon 	pthread_mutex_unlock(&BulkMutex);
2018e25f19bSMatthew Dillon }
2028e25f19bSMatthew Dillon 
2038e25f19bSMatthew Dillon /*
2048e25f19bSMatthew Dillon  * Retrieve completed job or job with activity
2058e25f19bSMatthew Dillon  */
2068e25f19bSMatthew Dillon bulk_t *
2078e25f19bSMatthew Dillon getbulk(void)
2088e25f19bSMatthew Dillon {
2098e25f19bSMatthew Dillon 	bulk_t *bulk;
2108e25f19bSMatthew Dillon 
2118e25f19bSMatthew Dillon 	pthread_mutex_lock(&BulkMutex);
2128e25f19bSMatthew Dillon 	while (BulkCurJobs && BulkResponse == NULL) {
2138e25f19bSMatthew Dillon 		pthread_cond_wait(&BulkResponseCond, &BulkMutex);
2148e25f19bSMatthew Dillon 	}
2158e25f19bSMatthew Dillon 	if (BulkResponse) {
2168e25f19bSMatthew Dillon 		bulk = BulkResponse;
2178e25f19bSMatthew Dillon 		ddassert(bulk->state == ONRESPONSE);
2188e25f19bSMatthew Dillon 		BulkResponse = bulk->next;
2198e25f19bSMatthew Dillon 		if (BulkResponse == NULL)
2208e25f19bSMatthew Dillon 			BulkResponseTail = &BulkResponse;
2218e25f19bSMatthew Dillon 		bulk->state = UNLISTED;
2228e25f19bSMatthew Dillon 	} else {
2238e25f19bSMatthew Dillon 		bulk = NULL;
2248e25f19bSMatthew Dillon 	}
2258e25f19bSMatthew Dillon 	pthread_mutex_unlock(&BulkMutex);
2268e25f19bSMatthew Dillon 	bulkstart();
2278e25f19bSMatthew Dillon 
2288e25f19bSMatthew Dillon 	return bulk;
2298e25f19bSMatthew Dillon }
2308e25f19bSMatthew Dillon 
2318e25f19bSMatthew Dillon void
2328e25f19bSMatthew Dillon freebulk(bulk_t *bulk)
2338e25f19bSMatthew Dillon {
2348e25f19bSMatthew Dillon 	ddassert(bulk->state == UNLISTED);
2358e25f19bSMatthew Dillon 
2368e25f19bSMatthew Dillon 	if (bulk->s1) {
2378e25f19bSMatthew Dillon 		free(bulk->s1);
2388e25f19bSMatthew Dillon 		bulk->s1 = NULL;
2398e25f19bSMatthew Dillon 	}
2408e25f19bSMatthew Dillon 	if (bulk->s2) {
2418e25f19bSMatthew Dillon 		free(bulk->s2);
2428e25f19bSMatthew Dillon 		bulk->s2 = NULL;
2438e25f19bSMatthew Dillon 	}
2448e25f19bSMatthew Dillon 	if (bulk->s3) {
2458e25f19bSMatthew Dillon 		free(bulk->s3);
2468e25f19bSMatthew Dillon 		bulk->s3 = NULL;
2478e25f19bSMatthew Dillon 	}
2488e25f19bSMatthew Dillon 	if (bulk->s4) {
2498e25f19bSMatthew Dillon 		free(bulk->s4);
2508e25f19bSMatthew Dillon 		bulk->s4 = NULL;
2518e25f19bSMatthew Dillon 	}
2528e25f19bSMatthew Dillon 	if (bulk->r1) {
2538e25f19bSMatthew Dillon 		free(bulk->r1);
2548e25f19bSMatthew Dillon 		bulk->r1 = NULL;
2558e25f19bSMatthew Dillon 	}
2568e25f19bSMatthew Dillon 	if (bulk->r2) {
2578e25f19bSMatthew Dillon 		free(bulk->r2);
2588e25f19bSMatthew Dillon 		bulk->r2 = NULL;
2598e25f19bSMatthew Dillon 	}
2608e25f19bSMatthew Dillon 	if (bulk->r3) {
2618e25f19bSMatthew Dillon 		free(bulk->r3);
2628e25f19bSMatthew Dillon 		bulk->r3 = NULL;
2638e25f19bSMatthew Dillon 	}
2648e25f19bSMatthew Dillon 	if (bulk->r4) {
2658e25f19bSMatthew Dillon 		free(bulk->r4);
2668e25f19bSMatthew Dillon 		bulk->r4 = NULL;
2678e25f19bSMatthew Dillon 	}
2688e25f19bSMatthew Dillon 	free(bulk);
2698e25f19bSMatthew Dillon }
2708e25f19bSMatthew Dillon 
2718e25f19bSMatthew Dillon #if 0
2728e25f19bSMatthew Dillon 
2738e25f19bSMatthew Dillon /*
2748e25f19bSMatthew Dillon  * Returns non-zero if unable to read specified number of bytes
2758e25f19bSMatthew Dillon  */
2768e25f19bSMatthew Dillon static
2778e25f19bSMatthew Dillon int
2788e25f19bSMatthew Dillon readall(int fd, void *buf, size_t bytes)
2798e25f19bSMatthew Dillon {
2808e25f19bSMatthew Dillon 	ssize_t r;
2818e25f19bSMatthew Dillon 
2828e25f19bSMatthew Dillon 	for (;;) {
2838e25f19bSMatthew Dillon 		r = read(fd, buf, bytes);
2848e25f19bSMatthew Dillon 		if (r == (ssize_t)bytes)
2858e25f19bSMatthew Dillon 			break;
2868e25f19bSMatthew Dillon 		if (r > 0) {
2878e25f19bSMatthew Dillon 			buf = (char *)buf + r;
2888e25f19bSMatthew Dillon 			bytes -= r;
2898e25f19bSMatthew Dillon 			continue;
2908e25f19bSMatthew Dillon 		}
2918e25f19bSMatthew Dillon 		if (r < 0 && errno == EINTR)
2928e25f19bSMatthew Dillon 			continue;
2938e25f19bSMatthew Dillon 		return 1;
2948e25f19bSMatthew Dillon 	}
2958e25f19bSMatthew Dillon 	return 0;
2968e25f19bSMatthew Dillon }
2978e25f19bSMatthew Dillon 
2988e25f19bSMatthew Dillon static
2998e25f19bSMatthew Dillon int
3008e25f19bSMatthew Dillon writeall(int fd, const void *buf, size_t bytes)
3018e25f19bSMatthew Dillon {
3028e25f19bSMatthew Dillon 	ssize_t r;
3038e25f19bSMatthew Dillon 
3048e25f19bSMatthew Dillon 	for (;;) {
3058e25f19bSMatthew Dillon 		r = write(fd, buf, bytes);
3068e25f19bSMatthew Dillon 		if (r == (ssize_t)bytes)
3078e25f19bSMatthew Dillon 			break;
3088e25f19bSMatthew Dillon 		if (r > 0) {
3098e25f19bSMatthew Dillon 			buf = (const char *)buf + r;
3108e25f19bSMatthew Dillon 			bytes -= r;
3118e25f19bSMatthew Dillon 			continue;
3128e25f19bSMatthew Dillon 		}
3138e25f19bSMatthew Dillon 		if (r < 0 && errno == EINTR)
3148e25f19bSMatthew Dillon 			continue;
3158e25f19bSMatthew Dillon 		return 1;
3168e25f19bSMatthew Dillon 	}
3178e25f19bSMatthew Dillon 	return 0;
3188e25f19bSMatthew Dillon }
3198e25f19bSMatthew Dillon 
3208e25f19bSMatthew Dillon #endif
3218e25f19bSMatthew Dillon 
3228e25f19bSMatthew Dillon static void *
3238e25f19bSMatthew Dillon bulkthread(void *arg)
3248e25f19bSMatthew Dillon {
3258e25f19bSMatthew Dillon 	job_t *job = arg;
3268e25f19bSMatthew Dillon 	bulk_t *bulk;
3278e25f19bSMatthew Dillon 
3288e25f19bSMatthew Dillon 	pthread_mutex_lock(&BulkMutex);
3298e25f19bSMatthew Dillon 	for (;;) {
3308e25f19bSMatthew Dillon 		if (job->terminate)
3318e25f19bSMatthew Dillon 			break;
3328e25f19bSMatthew Dillon 		if (job->active == NULL)
3338e25f19bSMatthew Dillon 			pthread_cond_wait(&job->cond, &BulkMutex);
3348e25f19bSMatthew Dillon 		bulk = job->active;
3358e25f19bSMatthew Dillon 		if (bulk) {
3368e25f19bSMatthew Dillon 			bulk->state = ISRUNNING;
3378e25f19bSMatthew Dillon 
3388e25f19bSMatthew Dillon 			pthread_mutex_unlock(&BulkMutex);
3398e25f19bSMatthew Dillon 			BulkFunc(bulk);
3408e25f19bSMatthew Dillon 			pthread_mutex_lock(&BulkMutex);
3418e25f19bSMatthew Dillon 
3428e25f19bSMatthew Dillon 			bulk->state = ONRESPONSE;
3438e25f19bSMatthew Dillon 			bulk->next = NULL;
3448e25f19bSMatthew Dillon 			*BulkResponseTail = bulk;
3458e25f19bSMatthew Dillon 			BulkResponseTail = &bulk->next;
3468e25f19bSMatthew Dillon 			--BulkCurJobs;
3478e25f19bSMatthew Dillon 			pthread_cond_signal(&BulkResponseCond);
3488e25f19bSMatthew Dillon 		}
3498e25f19bSMatthew Dillon 
3508e25f19bSMatthew Dillon 		/*
3518e25f19bSMatthew Dillon 		 * Optimization - automatically fetch the next job
3528e25f19bSMatthew Dillon 		 */
3538e25f19bSMatthew Dillon 		if ((bulk = BulkSubmit) != NULL && job->terminate == 0) {
3548e25f19bSMatthew Dillon 			BulkSubmit = bulk->next;
3558e25f19bSMatthew Dillon 			if (BulkSubmit == NULL)
3568e25f19bSMatthew Dillon 				BulkSubmitTail = &BulkSubmit;
3578e25f19bSMatthew Dillon 			bulk->state = ONRUN;
3588e25f19bSMatthew Dillon 			job->active = bulk;
3598e25f19bSMatthew Dillon 			++BulkCurJobs;
3607f0eca56SMatthew Dillon 		} else {
3617f0eca56SMatthew Dillon 			job->active = NULL;
3628e25f19bSMatthew Dillon 		}
3638e25f19bSMatthew Dillon 	}
3648e25f19bSMatthew Dillon 	pthread_mutex_unlock(&BulkMutex);
3658e25f19bSMatthew Dillon 
3668e25f19bSMatthew Dillon 	return NULL;
3678e25f19bSMatthew Dillon }
368