-
Notifications
You must be signed in to change notification settings - Fork 63
/
trylock.c
120 lines (110 loc) · 3.3 KB
/
trylock.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* trylock.c
*
* Demonstrate a simple use of pthread_mutex_trylock. The
* counter_thread updates a shared counter at intervals, and a
* monitor_thread occasionally reports the current value of the
* counter -- but only if the mutex is not already locked by
* counter_thread.
*
* Special notes: On a Solaris system, call thr_setconcurrency()
* to allow interleaved thread execution, since threads are not
* timesliced.
*/
#include <pthread.h>
#include "errors.h"
#define SPIN 10000000
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
long counter;
time_t end_time;
/*
* Thread start routine that repeatedly locks a mutex and
* increments a counter.
*/
void *counter_thread (void *arg)
{
int status;
int spin;
/*
* Until end_time, increment the counter each
* second. Instead of just incrementing the counter, it
* sleeps for another second with the mutex locked, to give
* monitor_thread a reasonable chance of running.
*/
while (time (NULL) < end_time)
{
status = pthread_mutex_lock (&mutex);
if (status != 0)
err_abort (status, "Lock mutex");
for (spin = 0; spin < SPIN; spin++)
counter++;
status = pthread_mutex_unlock (&mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
sleep (1);
}
printf ("Counter is %#lx\n", counter);
return NULL;
}
/*
* Thread start routine to "monitor" the counter. Every 3
* seconds, try to lock the mutex and read the counter. If the
* trylock fails, skip this cycle.
*/
void *monitor_thread (void *arg)
{
int status;
int misses = 0;
/*
* Loop until end_time, checking the counter every 3
* seconds.
*/
while (time (NULL) < end_time)
{
sleep (3);
status = pthread_mutex_trylock (&mutex);
if (status != EBUSY)
{
if (status != 0)
err_abort (status, "Trylock mutex");
printf ("Counter is %ld\n", counter/SPIN);
status = pthread_mutex_unlock (&mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
} else
misses++; /* Count "misses" on the lock */
}
printf ("Monitor thread missed update %d times.\n", misses);
return NULL;
}
int main (int argc, char *argv[])
{
int status;
pthread_t counter_thread_id;
pthread_t monitor_thread_id;
#ifdef sun
/*
* On Solaris 2.5, threads are not timesliced. To ensure
* that our threads can run concurrently, we need to
* increase the concurrency level to 2.
*/
DPRINTF (("Setting concurrency level to 2\n"));
thr_setconcurrency (2);
#endif
end_time = time (NULL) + 60; /* Run for 1 minute */
status = pthread_create (
&counter_thread_id, NULL, counter_thread, NULL);
if (status != 0)
err_abort (status, "Create counter thread");
status = pthread_create (
&monitor_thread_id, NULL, monitor_thread, NULL);
if (status != 0)
err_abort (status, "Create monitor thread");
status = pthread_join (counter_thread_id, NULL);
if (status != 0)
err_abort (status, "Join counter thread");
status = pthread_join (monitor_thread_id, NULL);
if (status != 0)
err_abort (status, "Join monitor thread");
return 0;
}