2 * Copyright (c) 2019 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * This code uses concepts and configuration based on 'synth', by
8 * John R. Marino <draco@marino.st>, which was written in ada.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
20 * 3. Neither the name of The DragonFly Project nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific, prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * Most of these globals are locked with BulkMutex
49 static int BulkScanJob
;
50 static int BulkCurJobs
;
51 static int BulkMaxJobs
;
52 static job_t JobsAry
[MAXBULK
];
53 static void (*BulkFunc
)(bulk_t
*bulk
);
54 static bulk_t
*BulkSubmit
;
55 static bulk_t
**BulkSubmitTail
= &BulkSubmit
;
56 static bulk_t
*BulkResponse
;
57 static bulk_t
**BulkResponseTail
= &BulkResponse
;
58 static pthread_cond_t BulkResponseCond
;
59 static pthread_mutex_t BulkMutex
;
61 static void bulkstart(void);
63 static int readall(int fd
, void *buf
, size_t bytes
);
64 static int writeall(int fd
, const void *buf
, size_t bytes
);
66 static void *bulkthread(void *arg
);
69 * Initialize for bulk scan operations. Always paired with donebulk()
72 initbulk(void (*func
)(bulk_t
*bulk
), int jobs
)
79 ddassert(BulkSubmit
== NULL
);
85 addbuildenv("__MAKE_CONF", "/dev/null",
86 BENV_ENVIRONMENT
| BENV_PKGLIST
);
89 * CCache is a horrible unreliable hack but... leave the
90 * mechanism in-place in case someone has a death wish.
93 addbuildenv("WITH_CCACHE_BUILD", "yes", BENV_MAKECONF
);
94 addbuildenv("CCACHE_DIR", CCachePath
, BENV_MAKECONF
);
97 pthread_mutex_init(&BulkMutex
, NULL
);
98 pthread_cond_init(&BulkResponseCond
, NULL
);
100 pthread_mutex_lock(&BulkMutex
);
101 for (i
= 0; i
< jobs
; ++i
) {
102 pthread_cond_init(&JobsAry
[i
].cond
, NULL
);
103 pthread_create(&JobsAry
[i
].td
, NULL
, bulkthread
, &JobsAry
[i
]);
105 pthread_mutex_unlock(&BulkMutex
);
114 pthread_mutex_lock(&BulkMutex
);
115 while ((bulk
= BulkSubmit
) != NULL
) {
116 BulkSubmit
= bulk
->next
;
119 BulkSubmitTail
= &BulkSubmit
;
121 for (i
= 0; i
< BulkMaxJobs
; ++i
) {
122 JobsAry
[i
].terminate
= 1;
123 pthread_cond_signal(&JobsAry
[i
].cond
);
125 pthread_mutex_unlock(&BulkMutex
);
126 for (i
= 0; i
< BulkMaxJobs
; ++i
) {
127 pthread_join(JobsAry
[i
].td
, NULL
);
128 pthread_cond_destroy(&JobsAry
[i
].cond
);
129 if (JobsAry
[i
].active
) {
130 freebulk(JobsAry
[i
].active
);
131 JobsAry
[i
].active
= NULL
;
132 pthread_mutex_lock(&BulkMutex
);
134 pthread_mutex_unlock(&BulkMutex
);
136 JobsAry
[i
].terminate
= 0;
138 ddassert(BulkCurJobs
== 0);
140 while ((bulk
= BulkResponse
) != NULL
) {
141 BulkResponse
= bulk
->next
;
144 BulkResponseTail
= &BulkResponse
;
148 bzero(JobsAry
, sizeof(JobsAry
));
151 delbuildenv("WITH_CCACHE_BUILD");
152 delbuildenv("CCACHE_DIR");
154 delbuildenv("__MAKE_CONF");
158 queuebulk(const char *s1
, const char *s2
, const char *s3
, const char *s4
)
162 bulk
= calloc(1, sizeof(*bulk
));
164 bulk
->s1
= strdup(s1
);
166 bulk
->s2
= strdup(s2
);
168 bulk
->s3
= strdup(s3
);
170 bulk
->s4
= strdup(s4
);
171 bulk
->state
= ONSUBMIT
;
173 pthread_mutex_lock(&BulkMutex
);
174 *BulkSubmitTail
= bulk
;
175 BulkSubmitTail
= &bulk
->next
;
176 if (BulkCurJobs
< BulkMaxJobs
) {
177 pthread_mutex_unlock(&BulkMutex
);
180 pthread_mutex_unlock(&BulkMutex
);
185 * Fill any idle job slots with new jobs as available.
194 pthread_mutex_lock(&BulkMutex
);
195 while ((bulk
= BulkSubmit
) != NULL
&& BulkCurJobs
< BulkMaxJobs
) {
199 if (JobsAry
[i
].active
== NULL
)
204 BulkSubmit
= bulk
->next
;
205 if (BulkSubmit
== NULL
)
206 BulkSubmitTail
= &BulkSubmit
;
209 JobsAry
[i
].active
= bulk
;
210 pthread_cond_signal(&JobsAry
[i
].cond
);
213 pthread_mutex_unlock(&BulkMutex
);
217 * Retrieve completed job or job with activity
224 pthread_mutex_lock(&BulkMutex
);
225 while (BulkCurJobs
&& BulkResponse
== NULL
) {
226 pthread_cond_wait(&BulkResponseCond
, &BulkMutex
);
230 ddassert(bulk
->state
== ONRESPONSE
);
231 BulkResponse
= bulk
->next
;
232 if (BulkResponse
== NULL
)
233 BulkResponseTail
= &BulkResponse
;
234 bulk
->state
= UNLISTED
;
238 pthread_mutex_unlock(&BulkMutex
);
245 freebulk(bulk_t
*bulk
)
247 ddassert(bulk
->state
== UNLISTED
);
287 * Returns non-zero if unable to read specified number of bytes
291 readall(int fd
, void *buf
, size_t bytes
)
296 r
= read(fd
, buf
, bytes
);
297 if (r
== (ssize_t
)bytes
)
300 buf
= (char *)buf
+ r
;
304 if (r
< 0 && errno
== EINTR
)
313 writeall(int fd
, const void *buf
, size_t bytes
)
318 r
= write(fd
, buf
, bytes
);
319 if (r
== (ssize_t
)bytes
)
322 buf
= (const char *)buf
+ r
;
326 if (r
< 0 && errno
== EINTR
)
336 bulkthread(void *arg
)
341 pthread_mutex_lock(&BulkMutex
);
345 if (job
->active
== NULL
)
346 pthread_cond_wait(&job
->cond
, &BulkMutex
);
349 bulk
->state
= ISRUNNING
;
351 pthread_mutex_unlock(&BulkMutex
);
353 pthread_mutex_lock(&BulkMutex
);
355 bulk
->state
= ONRESPONSE
;
357 *BulkResponseTail
= bulk
;
358 BulkResponseTail
= &bulk
->next
;
360 pthread_cond_signal(&BulkResponseCond
);
364 * Optimization - automatically fetch the next job
366 if ((bulk
= BulkSubmit
) != NULL
&& job
->terminate
== 0) {
367 BulkSubmit
= bulk
->next
;
368 if (BulkSubmit
== NULL
)
369 BulkSubmitTail
= &BulkSubmit
;
377 pthread_mutex_unlock(&BulkMutex
);