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
'));
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'
', 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'
', 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'
', 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);
ANSI C provides functions to get and put single characters efficiently into getchar
and putchar
operate on stdin
and stdout
, respectively, and getc
and putc
can be used on any
The overhead of locking and unlocking mutexes will probably vastly exceed the time spent performing the character copy, so these functions are no longer high performance. Pthreads could have defined new functions that provided the locked variety rather than redefining the existing functions; however, the result would be that existing code would be unsafe for use in threads. The working group decided that it was preferable to make existing code slower, rather than to make it incorrect.
Pthreads adds new functions that replace the old high-performance macros with essentially the same implementation as the traditional macros. The functions getc_unlocked
, putc_unlocked
, getchar_unlocked
, and putchar_unlocked
do not perform any locking, so you must use flockfile
and funlockfile
around any sequence of these operations. If you want to read or write a single character, you should usually use the locked variety rather than locking the file stream, calling the new unlocked get or put function, and then unlocking the file stream.
If you want to perform a sequence of fast character accesses, where you would have previously used getchar and putchar, you can now use getchar_unlocked and putchar_unlocked. The following program, putchar.c, shows the difference between using putchar and using a sequence of putchar_unlocked calls within a file lock.
9-20 When the program is run with a nonzero argument or no argument at all, it creates threads running the lock_routine function. This function locks the stdout file stream, and then writes its argument (a string) to stdout one character at a time using putchar_unlocked.
28-37 When the program is run with a zero argument, it creates threads running the unlock_routine function. This function writes its argument to stdout one character at a time using putchar. Although putchar is internally synchronized to ensure that the
¦ putchar.c
1 #include <pthread.h>
2 #include 'errors.h'
3
4 /*
5 * This function writes a string (the function's arg) to stdout,
6 * by locking the file stream and using putchar_unlocked to write
7 * each character individually.
8 */
9 void *lock_routine (void *arg)