blob: 19976f72684a7a6f692622262ffcea61fca14c86 [file] [log] [blame]
sewardj811d1412002-05-13 00:38:52 +00001/********************************************************
2 * An example source module to accompany...
3 *
4 * "Using POSIX Threads: Programming with Pthreads"
5 * by Brad nichols, Dick Buttlar, Jackie Farrell
6 * O'Reilly & Associates, Inc.
7 *
8 ********************************************************
9 * stat_sigwait.c
10 *
11 * Simple example of pthreads and signals.
12 */
13
14#include <stdlib.h>
15#include <stdio.h>
16#include <unistd.h>
17#include <signal.h>
18#include <time.h>
19#include <sys/types.h>
20
21#include <pthread.h>
22
23#define MAX_NUM_THREADS 10
24
25pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
26int mean, samples, total;
27
28void *report_stats(void *p)
29{
30 int caught;
31 sigset_t sigs_to_catch;
32
33 /* Identify our thread */
34 printf("\nreport_stats() started.\n");
35
36 /*
37 * We inherited a thread sigmask with all the signals
38 * blocked. So, we can wait on whatever signals we're
39 * interested in and (as long as no other thread waits
40 * for them) we'll be sure return from sigwait() to
41 * handle it.
42 */
43
44 /* JRS 13 May 2002: this has a race condition, which is obvious if
45 you fire SIGUSR1s at it fast enough -- once sigwait returns,
46 there is no hander whilst it does the rest of the loop, so if a
47 signal arrives then, the program is killed, since that's the
48 default action for SIGUSR1. */
49
50 /* set this thread's signal mask to block out SIGUSR1 */
51 sigemptyset(&sigs_to_catch);
52 sigaddset(&sigs_to_catch, SIGUSR1);
53
54 for (;;) {
55 sigwait(&sigs_to_catch, &caught);
56
57 pthread_mutex_lock(&stats_lock);
58 mean = total/samples;
59 printf("\nreport_stats(): mean = %d, samples = %d\n", mean, samples);
60 pthread_mutex_unlock(&stats_lock);
61 }
62 return NULL;
63}
64/*
65 * worker_thread --
66 *
67 * Don't read too much into what this thread does. It's
68 * a very simpleminded example. The only interesting thing
69 * it does is write to the global statistics data-- which
70 * means the thread processing the signal has to protect
71 * against simultaneous access.
72 */
73void *worker_thread(void *p)
74{
75 time_t now;
76 for (;;) {
77
78 sleep(1 + (*(int*)p) % 2 );
79
80 now = time(NULL);
81
82 pthread_mutex_lock(&stats_lock);
83 total+=((int)now)%60; /* probably not the safest thing to do but
84 it's just an example */
85 samples++;
86 pthread_mutex_unlock(&stats_lock);
87 }
88 /* Won't get here. */
89 return NULL;
90}
91
92extern int
93main(void)
94{
95 int i;
96 pthread_t threads[MAX_NUM_THREADS];
97 int num_threads = 0;
98 sigset_t sigs_to_block;
99
100
101 /* Identify our thread */
102 printf("main() (pid %d) running in thread 0x%x\n",
103 getpid(), (int)pthread_self());
104
105 /*
106 * Set this thread's signal mask to block SIGUSR1
107 * Other threads will inherit the mask
108 */
109 sigemptyset(&sigs_to_block);
110 sigaddset(&sigs_to_block, SIGUSR1);
111 pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL);
112
113 /* spawn statistics reporting thread */
114 pthread_create(&threads[num_threads++],
115 NULL,
116 report_stats,
117 NULL);
118
119 /* spawn the threads */
120 for (i=num_threads; i<MAX_NUM_THREADS; i++) {
121 pthread_create(&threads[num_threads++],
122 NULL,
123 worker_thread,
124 &i);
125 }
126
127 printf("main()\t\t\t\t%d threads created\n",num_threads);
128
129 /* wait until all threads have finished */
130 for (i = 0; i < num_threads; i++) {
131 pthread_join(threads[i], NULL);
132 printf("main()\t\tjoined to thread %d \n", i);
133 }
134
135 printf("main()\t\tall %d threads have finished. \n", num_threads);
136
137 return 0;
138}
139