/* * 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 #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; }