/**
@file ptMutex.c
@author Mitch Richling <http://www.mitchr.me/>
@Copyright Copyright 1998 by Mitch Richling. All rights reserved.
@brief Basic pthread programming@EOL
@Keywords UNIX pthreads POSIX mutex
@Std ISOC POSIX UNIX98 BSD4.3 SYSV3
This C program is intended to illustrate various
concepts related to POSIX threads (pthreads) including
simple mutex and condition variable use and basic thread
creation and destruction. Notable things not
demonstrated are "Reader/Writer Locking", "Semaphores",
"Cancellation", and "Scheduling".
@Build
- MacOS X.2: c++ pthreads.cc
- Linux (RH 7.3): c++ pthreads.cc -lpthread
- Solaris 2.8: CC -lpthread -lrt pthreads.cc
@Tested
- Solaris 2.8
- MacOS X.2
- Linux (RH 7.3)
*/
#include <sys/types.h> /* UNIX types POSIX */
#include <stdio.h> /* I/O lib ISOC */
#include <string.h> /* Strings ISOC */
#include <dirent.h> /* UNIX dirs POSIX */
#include <errno.h> /* error stf POSIX */
#include <utime.h> /* utime POSIX */
#include <sys/stat.h> /* UNIX stat POSIX */
#include <time.h> /* time ISOC */
#include <pthread.h> /* threads POSIX */
#include <sched.h> /* threads POSIX */
#include <stdlib.h> /* Standard Lib ISOC */
#include <unistd.h> /* UNIX std stf POSIX */
/* Handy stuff for Multi-Threaded programs (in C only). */
#include "mtUtils.h"
/* *************************************************************************** */
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
/* *************************************************************************** */
int main(int argc, char *argv[]);
void workThread1(void *reqArg);
void workThread2(void *reqArg);
/* *************************************************************************** */
/* This is where it starts. :) */
int main(int argc, char *argv[]) {
pthread_t thread;
int *anIntPtr;
int i;
int mstrThrdNumber=0;
mtPrintf("main: startup.\n");
/* Lock mutex1 -- everyone wants to lock this on startup. */
mtPrintf("main: locking mutex1.\n");
if(pthread_mutex_lock(&mutex1)) {
mtPrintf("ERROR: pthread_mutex_lock() failed.\n");
exit(1);
} /* end if */
mtPrintf("main: mutex1 locked.\n");
mallocNsetInt(&anIntPtr, ++mstrThrdNumber);
if(pthread_create(&thread, NULL, (PTHRFUNC*)workThread1, (void *)anIntPtr) != 0) {
mtPrintf("ERROR: pthread_create() failed.\n");
exit(1);
} /* end if */
mallocNsetInt(&anIntPtr, ++mstrThrdNumber);
if(pthread_create(&thread, NULL, (PTHRFUNC*)workThread2, (void *)anIntPtr) != 0) {
mtPrintf("ERROR: pthread_create() failed.\n");
exit(1);
} /* end if */
for(i=0;i<4;i++) {
mtPrintf("main: sleeping. (%d).\n", i);
sleep(3);
} /* end for */
/* Unlock mutex1 -- everyone waiting to lock this one! */
mtPrintf("main: unlocking mutex1.\n");
if(pthread_mutex_unlock(&mutex1)) {
mtPrintf("ERROR: pthread_mutex_lock() failed.\n");
exit(1);
} /* end if */
mtPrintf("main: mutex1 unlocked.\n");
for(i=0;i<10;i++) {
mtPrintf("main: sleeping. (%d).\n", i);
sleep(3);
} /* end for */
mtPrintf("main: shutdown\n");
return (0);
} /* end func main */
/* *************************************************************************** */
void workThread1(void *reqArg) {
/* Thread will never be "joined", so we detach it. */
pthread_detach(pthread_self());
mtPrintf("worker Type 1 thread %d startup.\n", *(int *)reqArg);
mtPrintf("worker Type 1 thread %d locking mutex1.\n", *(int *)reqArg);
if(pthread_mutex_lock(&mutex1)) {
mtPrintf("ERROR: pthread_mutex_lock() failed.\n");
exit(1);
} /* end if */
mtPrintf("worker Type 1 thread %d mutex1 locked.\n", *(int *)reqArg);
mtPrintf("worker Type 1 thread %d unlocking mutex1.\n", *(int *)reqArg);
if(pthread_mutex_unlock(&mutex1)) {
mtPrintf("ERROR: pthread_mutex_unlock() failed.\n");
exit(1);
} /* end if */
mtPrintf("worker Type 1 thread %d mutex1 unlocked.\n", *(int *)reqArg);
mtPrintf("worker Type 1 thread %d shutdown.\n", *(int *)reqArg);
/* The argument given to this thread was "malloced", so we free it now. */
free(reqArg);
} /* end func workerThread */
/* *************************************************************************** */
void workThread2(void *reqArg) {
int tryLockResult;
/* Thread will never be "joined", so we detach it. */
pthread_detach(pthread_self());
mtPrintf("worker Type 2 thread %d startup.\n", *(int *)reqArg);
mtPrintf("worker Type 2 thread %d locking mutex1.\n", *(int *)reqArg);
while((tryLockResult = pthread_mutex_trylock(&mutex1))) {
if(tryLockResult != EBUSY) {
mtPrintf("ERROR: pthread_mutex_lock() failed.\n");
exit(1);
} /* end if */
mtPrintf("worker Type 2 thread %d still trying to lock mutex1.\n", *(int *)reqArg);
sleep(1);
} /* end while */
mtPrintf("worker Type 2 thread %d mutex1 locked.\n", *(int *)reqArg);
mtPrintf("worker Type 2 thread %d unlocking mutex1.\n", *(int *)reqArg);
if(pthread_mutex_unlock(&mutex1)) {
mtPrintf("ERROR: pthread_mutex_unlock() failed.\n");
exit(1);
} /* end if */
mtPrintf("worker Type 2 thread %d mutex1 unlocked.\n", *(int *)reqArg);
mtPrintf("worker Type 2 thread %d shutdown.\n", *(int *)reqArg);
/* The argument given to this thread was "malloced", so we free it now. */
free(reqArg);
} /* end func workerThread */
Generated by GNU Enscript 1.6.5.2.