72 status = pthread_cond_signal (&request->done);
73 if (status != 0)
74 err_abort (status, "Signal server condition");
75 status = pthread_mutex_unlock (&tty_server.mutex);
76 if (status != 0)
77 err_abort (status, "Unlock server mutex");
78 } else
79 free (request);
80 if (operation == REQ_QUIT)
81 break;
82 }
83 return NULL;
84 }
Part 3 shows the function that is called to initiate a request to the tty server thread. The caller specifies the desired operation (REQ_QUIT, REQ_READ, or REQ_ WRITE), whether the operation is synchronous or not (sync), an optional prompt string (prompt) for REQ_READ operations, and the pointer to a string (input for REQ_WRITE, or a buffer to return the result of an REQ_READ operation).
16-40 If a tty server thread is not already running, start one. A temporary thread attributes object (detached_attr) is created, and the
45-76 Allocate and initialize a server request (request_t) packet. If the request is synchronous, initialize the condition variable (done) in the request packet — otherwise the condition variable isn't used. The new request is linked onto the request queue.
81-83 Wake the server thread to handle the queued request.
88-105 If the request is synchronous, wait for the server to set done_flag and signal the done condition variable. If the operation is REQ_READ, copy the result string into the output buffer. Finally, destroy the condition variable, and free the request packet.
■ server.c part 3 tty_server_request
1 /*
2 * Request an operation
3 */
4 void tty_server_request (
5 int operation,
6 int sync,
7 const char *prompt,
8 char *string)
9 {
10 request_t *request;
11 int status;
12
13 status = pthread_mutex_lock (&tty_server.mutex);
14 if (status != 0)
15 err_abort (status, "Lock server mutex");
16 if (!tty_server.running) {
17 pthread_t thread;
18 pthread_attr_t detached_attr;
19
20 status = pthread_attr_init (&detached_attr);
21 if (status != 0)
22 err_abort (status, "Init attributes object");
23 status = pthread_attr_setdetachstate (
24 &detached_attr, PTHREAD_CREATE_DETACHED);
25 if (status != 0)
26 err_abort (status, "Set detach state");
27 tty_server.running = 1;
28 status = pthread_create (&thread, &detached_attr,
29 tty_server_routine, NULL);
30 if (status != 0)
31 err_abort (status, "Create server");
32
33 /*
34 * Ignore an error in destroying the attributes object.
35 * It's unlikely to fail, there's nothing useful we can
36 * do about it, and it's not worth aborting the program
37 * over it.
38 */
39 pthread_attr_destroy (&detached_attr);
40 }
41
42 /*
43 * Create and initialize a request structure.
44 */
45 request = (request_t*)malloc (sizeof (request_t));
46 if (request == NULL)
47 errno_abort ("Allocate request");
48 request->next = NULL;
49 request->operation = operation;
50 request->synchronous = sync;
51 if (sync) {
52 request->done_flag = 0;
53 status = pthread_cond_init (&request->done, NULL);
54 if (status != 0)
55 err_abort (status, "Init request condition");
56 }
57 if (prompt != NULL)