/* * 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++; sleep(4); 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; }