209 stderr,
210 'Thread %d: %s is type %o (%s))
',
211 mine->index,
212 work->path,
213 filestat.st_mode & S_IFMT,
214 (S_ISFIFO (filestat.st_mode) ? 'FIFO'
215 :(S_ISCHR (filestat.st_mode) ? 'CHR'
216 :(S_ISBLK (filestat.st_mode) ? 'BLK'
217 :(S_ISSOCK (filestat.st_mode) ? 'SOCK'
218 :'unknown')))));
219
220 free (work->path); /* Free path buffer */
221 free (work); /* We're done with this */
222
223 /*
224 * Decrement count of outstanding work items, and wake
225 * waiters (trying to collect results or start a new
226 * calculation) if the crew is now idle.
227 *
228 * It's important that the count be decremented AFTER
229 * processing the current work item. That ensures the
230 * count won't go to 0 until we're really done.
231 */
232 status = pthread_mutex_lock (&crew->mutex);
233 if (status != 0)
234 err_abort (status, 'Lock crew mutex');
235
236 crew->work_count--;
237 DPRINTF (('Crew %d decremented work to %d
', mine->index,
238 crew->work_count));
239 if (crew->work_count <= 0) {
240 DPRINTF (('Crew thread %d done
', mine->index));
241 status = pthread_cond_broadcast (&crew->done);
242 if (status != 0)
243 err_abort (status, 'Wake waiters');
244 status = pthread_mutex_unlock (&crew->mutex);
245 if (status != 0)
246 err_abort (status, 'Unlock mutex');
247 break;
248 }
249
250 status = pthread_mutex_unlock (&crew->mutex);
251 if (status != 0)
252 err_abort (status, 'Unlock mutex');
253
254 }
255
256 free (entry);
257 return NULL;
258 }
Part 3 shows crew_create, the function used to create a new work crew. This simple example does not provide a way to destroy a work crew, because that is not necessary — the work crew would be destroyed only when the main program was prepared to exit, and process exit will destroy all threads and process data.
12-15 The crew_create
function begins by checking the crew_size
argument.The size of the crew is not allowed to exceed the size of the crew array in crew_t. If the requested size is acceptable, copy it into the structure.
16-31 Start with no work and an empty work queue. Initialize the crew's synchronization objects.
36-43 Then, for each crew member, initialize the member's worker_t
data. The index of the member within the crew array is recorded, and a pointer back to the crew_t
. Then the crew member thread is created, with a pointer to the member's worker_t
as its argument.
¦ crew.c part 3 crew_create
1 /*
2 * Create a work crew.
3 */
4 int crew_create (crew_t *crew, int crew_size)
5 {
6 int crew_index;
7 int status;
8
9 /*
10 * We won't create more than CREW_SIZE members.
11 */
12 if (crew_size > CREW_SIZE)
13 return EINVAL;
14
15 crew->crew_size = crew_size;
16 crew->work_count = 0;
17 crew->first = NULL;
18 crew->last = NULL;
19
20 /*
21 * Initialize synchronization objects.
22 */
23 status = pthread_mutex_init (&crew->mutex, NULL);
24 if (status != 0)
25 return status;
26 status = pthread_cond_init (&crew->done, NULL);
27 if (status != 0)
28 return status;
29 status = pthread_cond_init (&crew->go, NULL);
30 if (status != 0)
31 return status;
32
33 /*
34 * Create the worker threads.
35 */
36 for (crew_index = 0; crew_index < CREW_SIZE; crew_index++) {