29-30 The two calls to funlockfile must, ofcourse, be made in the opposite order. Despite the specialized call, you are effectively locking mutexes within the
■ flock.c
1 #include
2 #include "errors.h"
3
4 /*
5 * This routine writes a prompt to stdout (passed as the thread's
6 * "arg"), and reads a response. All other I/O to stdin and stdout
7 * is prevented by the file locks until both prompt and fgets are
8 * complete.
9 */
10 void *prompt_routine (void *arg)
11 {
12 char *prompt = (char*)arg;
13 char *string;
14 int len;
15
16 string = (char*)malloc (128);
17 if (string == NULL)
18 errno_abort ("Alloc string");
19 flockfile (stdin);
20 flockfile (stdout);
21 printf (prompt);
22 if (fgets (string, 128, stdin) == NULL)
23 string[0] = '\0' ;
24 else {
25 len = strlen (string);
26 if (len > 0 && string[len-l] == '\n')
27 string[len-l] = '\0';
28 }
29 funlockfile (stdout);
30 funlockfile (stdin);
31 return (void*)string;
32 }
33
34 int main (int argc, char *argv[])
35 {
36 pthread_t threadl, thread2, thread3;
37 char *string;
38 int status;
39
40 #ifdef sun
41 /*
42 * On Solaris 2.5, threads are not timesliced. To ensure
43 * that our threads can run concurrently, we need to
44 * increase the concurrency level.
45 */
46 DPRINTF (("Setting concurrency level to 4\n"));
47 thr_setconcurrency (4);
48 #endif
49 status = pthread_create (
50 &threadl, NULL, prompt_routine, "Thread 1> ");
51 if (status != 0)
52 err_abort (status, "Create thread");
53 status = pthread_create (
54 &thread2, NULL, prompt_routine, "Thread 2> ");
55 if (status != 0)
56 err_abort (status, "Create thread");
57 status = pthread_create (
58 &thread3, NULL, prompt_routine, "Thread 3> ");
59 if (status != 0)
60 err_abort (status, "Create thread");
61 status = pthread_join (threadl, (void**)&string);
62 if (status != 0)
63 err_abort (status, "Join thread");
64 printf ("Thread 1: \"%s\"\n", string);
65 free (string);
66 status = pthread_join (thread2, (void**)&string);
67 if (status != 0)
68 err_abort (status, "Join thread");
69 printf ("Thread 1: \"% s\"\n", string);
70 free (string);
71 status = pthread_join (thread3, (void**)&string);
72 if (status != 0)
73 err_abort (status, "Join thread");
74 printf ("Thread 1: \"% s\"\n", string);
75 free (string);
76 return 0;
77 }
You can also use the flockfile and funlockfile functions to ensure that a series of writes is not interrupted by a file access from some other thread. The ftrylockfile function works like pthread_mutex_trylock in that it attempts to lock the file and, if the file is already locked, returns an error status instead of blocking.
6.4.2 getchar unlocked and putchar unlocked
int getc_unlocked (FILE *stream);
int getchar_unlocked (void);
int putc_unlocked (int c, FILE *stream);
int putchar_unlocked (int c);