14 void *counter_thread (void *arg)
15 {
16 int status;
17 int spin;
18
19 /*
20 * Until end_time, increment the counter each second. Instead of
21 * just incrementing the counter, it sleeps for another second
22 * with the mutex locked, to give monitor_thread a reasonable
23 * chance of running.
24 */
25 while (time (NULL) < end_time)
26 {
27 status = pthread_mutex_lock (&mutex);
28 if (status != 0)
29 err_abort (status, "Lock mutex");
30 for (spin = 0; spin < SPIN; spin++)
31 counter++;
32 status = pthread_mutex_unlock (&mutex);
33 if (status != 0)
34 err_abort (status, "Unlock mutex");
35 sleep (1);
36 }
37 printf ("Counter is %#lx\n", counter);
38 return NULL;
39 }
40
41 /*
42 * Thread start routine to "monitor" the counter. Every 3
43 * seconds, try to lock the mutex and read the counter. If the
44 * trylock fails, skip this cycle.
45 */
46 void *monitor_thread (void *arg)
47 {
48 int status;
49 int misses = 0;
50
51
52 /*
53 * Loop until end_time, checking the counter every 3 seconds.
54 */
55 while (time (NULL) < end_time)
56 {
57 sleep (3);
58 status = pthread_mutex_trylock (&mutex);
59 if (status != EBUSY)
60 {
61 if (status != 0)
62 err_abort (status, "Trylock mutex");
63 printf ("Counter is %ld\n", counter/SPIN);
64 status = pthread_mutex_unlock (&mutex);
65 if (status != 0)
66 err_abort (status, "Unlock mutex");
67 } else
68 misses++; /* Count "misses" on the lock */
69 }
70 printf ("Monitor thread missed update %d times.\n", misses);
71 return NULL;
72 }
73
74 int main (int argc, char *argv[])
75 {
76 int status;
77 pthread_t counter_thread_id;
78 pthread_t monitor_thread_id; 79
80 #ifdef sun
81 /*
82 * On Solaris 2.5, threads are not timesliced. To ensure
83 * that our threads can run concurrently, we need to
84 * increase the concurrency level to 2.
85 */
86 DPRINTF (("Setting concurrency level to 2\n"));
87 thr_setconcurrency (2);
88 #endif 89
90 end_time = time (NULL) + 60; /* Run for 1 minute */
91 status = pthread_create (
92 &counter_thread_id, NULL, counter_thread, NULL);
93 if (status != 0)
94 err_abort (status, "Create counter thread");
95 status = pthread_create (
96 &monitor_thread_id, NULL, monitor_thread, NULL);
97 if (status != 0)
98 err_abort (status, "Create monitor thread");
99 status = pthread_join (counter_thread_id, NULL);
100 if (status != 0)
101 err_abort (status, "Join counter thread");
102 status = pthread_join (monitor_thread_id, NULL);
103 if (status != 0)
104 err_abort (status, "Join monitor thread");
105 return 0;
106 }
3.2.3 Using mutexes for atomicity