16 * queue.
17 */
18 DPRINTF (('A worker is starting
'));
19 status = pthread_mutex_lock (&wq->mutex);
20 if (status != 0)
21 return NULL;
22
23 while (1) {
24 timedout = 0;
25 DPRINTF (('Worker waiting for work
'));
26 clock_gettime (CLOCK_REALTIME, &timeout);
27 timeout.tv_sec += 2;
28
29 while (wq->first == NULL && !wq->quit) {
30 /*
31 * Server threads time out after spending 2 seconds
32 * waiting for new work, and exit.
33 */
34 status = pthread_cond_timedwait (
35 &wq->cv, &wq->mutex, &timeout);
36 If (status == ETIMEDOUT) {
37 DPRINTF (('Worker wait timed out
'));
38 timedout = 1;
39 break;
40 } else if (status != 0) {
41 /*
42 * This shouldn't happen, so the work queue
43 * package should fail. Because the work queue
44 * API is asynchronous, that would add
45 * complication. Because the chances of failure
46 * are slim, I choose to avoid that
47 * complication. The server thread will return,
48 * and allow another server thread to pick up
49 * the work later. Note that if this were the
50 * only server thread, the queue wouldn't be
51 * serviced until a new work item is
52 * queued. That could be fixed by creating a new
53 * server here.
54 */
55 DPRINTF ((
56 'Worker wait failed, %d (%s)
',
57 status, strerror (status)));
58 wq->counter--;
59 pthread_mutex_unlock (&wq->mutex);
60 return NULL;
61 }
62 }
63 DPRINTF (('Work queue: %#lx, quit: %d
',
64 wq->first, wq->quit));
65 we = wq->first;
66
67 if (we != NULL) {
68 wq->first = we->next;
69 If (wq->last == we)
70 wq->last = NULL;
71 status = pthread_mutex_unlock (&wq->mutex);
72 If (status != 0)
73 return NULL;
74 DPRINTF (('Worker calling engine
'));
75 wq->engine (we->data);
76 free (we);
77 status = pthread_mutex_lock (&wq->mutex);
78 if (status ! = 0)
79 return NULL;
80 }
81
82 /*
83 * If there are no more work requests, and the servers
84 * have been asked to quit, then shut down.
85 */
86 if (wq->first == NULL && wq->quit) {
87 DPRINTF (('Worker shutting down
'));
88 wq->counter--;
89
90 /*
91 * NOTE: Just to prove that every rule has an
92 * exception, I'm using the 'cv' condition for two
93 * separate predicates here. That's OK, since the
94 * case used here applies only once during the life
95 * of a work queue — during rundown. The overhead
96 * is minimal and it's not worth creating a separate
97 * condition variable that would wait and be
98 * signaled exactly once!
99 */
100 if (wq->counter == 0)
101 pthread_cond_broadcast (&wq->cv);
102 pthread_mutex_unlock (&wq->mutex);
103 return NULL;
104 }
105
106 /*
107 * If there's no more work, and we wait for as long as
108 * we're allowed, then terminate this server thread.
109 */
110 if (wq->first == NULL && timedout) {
111 DPRINTF (('engine terminating due to timeout.
'));
112 wq->counter--;
113 break;
114 }