37 crew->crew[crew_index].index = crew_index;
38 crew->crew[crew_index].crew = crew;
39 status = pthread_create (&crew->crew[crew_index].thread,
40 NULL, worker_routine, (void*)&crew->crew[crew_index]);
41 if (status != 0)
42 err_abort (status, 'Create worker');
43 }
44 return 0;
45 }
Part 4 shows the crew_start function, which is called to assign a new path name and search string to the work crew. The function is synchronous — that is, after assigning the task it waits for the crew members to complete the task before returning to the caller. The crew_start function assumes that the crew_t structure has been previously created by calling crew_create, shown in part 3, but does not attempt to validate the structure.
20-26 Wait for the crew members to finish any previously assigned work. Although crew_start is synchronous, the crew may be processing a task assigned by another thread. On creation, the crew's work_count is set to 0, so the first call to crew start will not need to wait.
28-43 Get the proper values of path_max and name_max for the file system specified by the file path we'll be reading. The pathconf
function may return a value of -1 without setting errno, if the requested value for the file system is 'unlimited.' To detect this, we need to clear errno before making the call. If pathconf
returns -1 without setting errno, assume reasonable values.
47-48 The values returned by pathconf don't include the terminating null character of a string — so add one character to both.
49-67 Allocate a work queue entry (work_t) and fill it in. Add it to the end of the request queue.
68-75 We've queued a single work request, so awaken one of the waiting work crew members by signaling the condition variable. If the attempt fails, free the work request, clear the work queue, and return with the error.
76-80 Wait for the crew to complete the task. The crew members handle all output, so when they're done we simply return to the caller.
¦ crew.c part 4 crew_start
1 /*
2 * Pass a file path to a work crew previously created
3 * using crew_create
4 */
5 int crew_start (
6 crew_p crew,
7 char *filepath,
8 char *search)
9 {
10 work_p request;
11 int status;
12
13 status = pthread_mutex_lock (&crew->mutex);
14 if (status != 0)
15 return status;
16
17 /*
18 * If the crew is busy, wait for them to finish.
19 */
20 while (crew->work_count > 0) {
21 status = pthread_cond_wait (&crew->done, &crew->mutex);
22 if (status != 0) {
23 pthread_mutex_unlock (&crew->mutex);
24 return status;
25 }
26 } 27
28 errno = 0;
29 path_max = pathconf (filepath, _PC_PATH_MAX);
30 if (path_max == -1) {
31 if (errno == 0)
32 path_max = 1024; /* 'No limit' */
33 else
34 errno_abort ('Unable to get PATH_MAX');
35 }
36 errno = 0;
37 name_max = pathconf (filepath, _PC_NAME_MAX);
38 if (name_max == -1) {
39 if (errno == 0)
40 name_max = 256; /* 'No limit' */
41 else
42 errno_abort ('Unable to get NAME_MAX');
43 }
44 DPRINTF ((
45 'PATH_MAX for %s is %ld, NAME_MAX is %ld
',
46 filepath, path_max, name_max));
47 path_max++; /* Add null byte */
48 name_max++; /* Add null byte */
49 request = (work_p)malloc (sizeof (work_t));
50 if (request == NULL)
51 errno_abort ('Unable to allocate request');
52 DPRINTF (('Requesting %s
', filepath));
53 request->path = (char*)malloc (path_max);
54 if (request->path == NULL)
55 errno_abort ('Unable to allocate path');
56 strcpy (request->path, filepath);
57 request->string = search;
58 request->next = NULL;
59 if (crew->first == NULL) {
60 crew->first = request;
61 crew->last = request;
62 } else {
63 crew->last->next = request;
64 crew->last = request;
65 } 66
67 crew->work_count++;
68 status = pthread_cond_signal (&crew->go);
69 if (status != 0) {
70 free (crew->first);
71 crew->first = NULL;