blob: e6933caf0c208c0db4cd4343a253395a19393d3a [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <thread.h>
#include <spinlock.h>
#include <mutex.h>
#include <cond.h>
#include <rwlock.h>
#include <misc.h>
#define MAX_THREAD 1000
#define N_THREAD 40
int checkAbort = 0;
#define checkResults(string, val) { \
if (val) { \
printf("%d: Failed with %d at %s", GetCurrentThreadId(), val, string); \
if ( checkAbort )exit(1); \
} \
}
#define checkResultsL(string, val) { \
if (val) { \
printf("Failed with %d at %s", val, string); \
} \
}
#define checkResultsAlt(string, val, alt) { \
if (val && !(val==alt)) { \
printf("Failed with %d (%d) at %s", val, alt, string); \
if ( checkAbort )exit(1); \
} \
}
typedef struct {
int id;
} parm;
struct timespec *starttimer(struct timespec *ts, DWORD ms)
{
struct timeval tp;
/* Convert from timeval to timespec */
gettimeofday(&tp, NULL);
ts->tv_sec = tp.tv_sec;
ts->tv_nsec = tp.tv_usec * 1000;
ts->tv_sec += ms / 1000;
printf("starttimer, %d s=%ld\n",ms, ts->tv_sec);
return ts;
}
void *hello(void *arg)
{
parm *p=(parm *)arg;
printf("Hello from node %d\n", p->id);
pthread_exit(NULL);
printf("Not reached from node %d\n", p->id);
pthread_exit(NULL);
return (NULL);
}
pthread_rwlock_t rwlock;
char testType[100];
/*================================================================================*/
#define SPINLOCK_NTHREADS 50
pthread_spinlock_t spinlock;
int SLsharedData=0;
int SLsharedData2=0;
void *spinlock_threadfunc(void *parm)
{
int rc, d;
int tid = pthread_self();
printf("Thread %d: Entered\n", tid);
rc = pthread_spin_lock(&spinlock);
d= SLsharedData;
checkResults("pthread_spin_lock()\n", rc);
/********** Critical Section *******************/
printf("Thread %d: Start critical section, holding lock\n",
tid);
/* Access to shared data goes here */
++SLsharedData; --SLsharedData2;
Sleep(50);
printf("Thread %d: End critical section, release lock\n",
tid);
d -= (SLsharedData-1);
/********** Critical Section *******************/
rc = pthread_spin_unlock(&spinlock);
checkResults("pthread_spinlock_unlock()\n", rc);
if (d) {
printf("FAILED Thread %d: check SLsharedData=%d instead of 0\n", tid, d);
exit(1);
}
return NULL;
}
int spinlock_main(void)
{
pthread_t thread[SPINLOCK_NTHREADS];
int rc=0;
int i;
printf("Enter Testcase - spinlock_main %s\n",testType);
rc = pthread_spin_init(&spinlock, PTHREAD_PROCESS_SHARED);
printf("Spinlock inited\n");
checkResults("pthread_spin_init()\n", rc);
printf("Hold Spinlock to prevent access to shared data\n");
rc = pthread_spin_lock(&spinlock);
printf("Unlock Spinlock to prevent access to shared data\n");
checkResults("pthread_spin_lock()\n", rc);
rc = pthread_spin_unlock(&spinlock);
checkResults("pthread_spin_unlock()\n",rc);
printf("Hold Spinlock to prevent access to shared data 2\n");
rc = pthread_spin_lock(&spinlock);
checkResults("pthread_spin_lock() 2\n", rc);
printf("Create/start threads\n");
for (i=0; i<SPINLOCK_NTHREADS; ++i) {
rc = pthread_create(&thread[i], NULL, spinlock_threadfunc, NULL);
checkResults("pthread_create()\n", rc);
}
printf("Wait a bit until we are 'done' with the shared data\n");
Sleep(3000);
printf("Unlock shared data\n");
rc = pthread_spin_unlock(&spinlock);
checkResults("pthread_spin_lock()\n",rc);
printf("Wait for the threads to complete, and release their resources\n");
for (i=0; i <SPINLOCK_NTHREADS; ++i) {
rc = pthread_join(thread[i], NULL);
checkResults("pthread_join()\n", rc);
}
printf("Clean up, data: %d %d\n",SLsharedData,SLsharedData2);
rc = pthread_spin_destroy(&spinlock);
printf("Main completed\n");
return 0;
}
/*================================================================================*/
#define MUTEX_NTHREADS 5
#define MUTEX_LOOPCNT 0
pthread_mutex_t mutex;
int sharedData=0;
int sharedData2=0;
int mwait=30000;
int init =0, destr=0;
void *mutex_threadfunc(void *parm)
{
int rc;
int d;
int tid = 0;
printf("----------------------------\n");
//Sleep(1000);
//mutex_print(&mutex,"Lock T A");
mutex_print(&mutex,"Lock T");
printf("----------------------------\n");
//Sleep(1000);
//printf("Thread %d: Entered\n", tid);
rc = pthread_mutex_lock(&mutex);
//mutex_print(&mutex,"Locked T");
d= sharedData;
checkResults("pthread_mutex_lock()\n", rc);
/********** Critical Section *******************/
printf("Thread %d: Start critical section, holding lock\n",
tid);
/* Access to shared data goes here */
++sharedData;
Sleep(500);
--sharedData2;
printf("Thread %d: End critical section, release lock\n",
tid);
d -= (sharedData-1);
/********** Critical Section *******************/
//mutex_print(&mutex,"UnLock T");
rc = pthread_mutex_unlock(&mutex);
//mutex_print(&mutex,"UnLocked T");
checkResults("pthread_mutex_unlock()\n", rc);
if (d) {
printf("FAILED Thread %d: check sharedData=%d instead of 0\n", tid, d);
exit(1);
}
return NULL;
}
void *mutex_threadfunc_raced(void *parm)
{
int rc, rc1, i,j=0,x=0;
int d;
int rn;
int tid = pthread_self();
struct timespec ts;
//printf("Thread %d: Entered\n", tid);
while(1) {
mutex_print(&mutex,"A pthread_mutex_lock");
//rc = pthread_mutex_timedlock(&mutex,starttimer(&ts, 8000 ));
rc = pthread_mutex_lock(&mutex);
mutex_print(&mutex,"B pthread_mutex_lock");
if (rc == ETIMEDOUT) {
printf("FAILED Thread %d: pthread_mutex_timedlock ETIMEDOUT\n", tid);
continue;
}
checkResults("pthread_mutex_timedlock()\n", rc);
d= sharedData;
/********** Critical Section *******************/
/* Access to shared data goes here */
++sharedData;
Sleep(100);
--sharedData2;
d -= (sharedData-1);
/********** Critical Section *******************/
mutex_print(&mutex,"A pthread_mutex_unlock 0");
rc = pthread_mutex_unlock(&mutex);
mutex_print(&mutex,"B pthread_mutex_unlock 0");
if(rc) {
mutex_print(&mutex,"cant unlock 0");
}
checkResults("pthread_mutex_unlock()\n", rc);
if (d) {
printf("FAILED Thread %d: check sharedData=%d instead of 0\n", tid, d);
exit(1);
}
i = 0;
mutex_print(&mutex, "A pthread_mutex_destroy 0");
rc=0;//rc = pthread_mutex_destroy(&mutex);
mutex_print(&mutex,"B pthread_mutex_destroy 0");
if(rc) {
mutex_print(&mutex,"cant destroy 0");
//break;
} else {
destr ++;
mutex_print(&mutex,"destroyed 0");
}
checkResultsAlt("pthread_mutex_destroy()\n", rc, EBUSY);
do {
mutex_print(&mutex,"A pthread_mutex_timedlock()");
//rc1 = pthread_mutex_lock(&mutex);
rc1 = pthread_mutex_timedlock(&mutex,starttimer(&ts, 4000 ));
mutex_print(&mutex,"B pthread_mutex_timedlock()");
//checkResults("pthread_mutex_lock() destroy\n", rc1);
if(rc1) {
mutex_print(&mutex,"cant lock");
break;
}
mutex_print(&mutex,"A pthread_mutex_unlock() 1");
rc1 = pthread_mutex_unlock(&mutex);
mutex_print(&mutex,"B pthread_mutex_unlock() 1");
if(rc1) {
mutex_print(&mutex,"cant unlock");
break;
}
//checkResults("pthread_mutex_unlock() destroy\n", rc1);
mutex_print(&mutex, "A pthread_mutex_destroy 1");
rc=0;//rc = pthread_mutex_destroy(&mutex);
mutex_print(&mutex, "B pthread_mutex_destroy 1");
if(rc) {
mutex_print(&mutex,"cant destroy");
break;
} else {
destr ++;
mutex_print(&mutex,"destroyed");
}
checkResultsAlt("pthread_mutex_destroy() 2\n", rc, EBUSY);
i ++;
} while(rc == EBUSY);
if(i)printf("Thread %d: destroy attempts: %d success: %d\n", tid,i,x);
mutex_print(&mutex, "A pthread_mutex_init");
rc =0; //rc = pthread_mutex_init(&mutex,NULL);
mutex_print(&mutex, "B pthread_mutex_init");
if(rc) {
mutex_print(&mutex,"cant init");
break;
} else {
init ++;
mutex_print(&mutex,"re-inited");
}
checkResults("pthread_mutex_init()\n", rc);
j++;
if (j>MUTEX_LOOPCNT) {
printf("Thread %d: Leaving\n", tid);
break;
}
}
return NULL;
}
static volatile LONG _tid=0;
void *mutex_threadfunc_timed(void *parm)
{
int rc;
int d,e;
int tid = pthread_self();
struct timespec ts;
printf("Thread %d: Entered\n", tid);
mutex_print(&mutex,"Lock T");
if (rand() & 1) {
rc = pthread_mutex_timedlock(&mutex,starttimer(&ts, 20000 ));
checkResults("XX pthread_mutex_timedlock()\n", rc);
} else {
rc = pthread_mutex_lock(&mutex);
checkResults("YY pthread_mutex_lock()\n", rc);
}
mutex_print(&mutex,"Locked T");
while (rc) {
printf("%d: Lock failed with %d\n", tid, rc);
rc = pthread_mutex_timedlock(&mutex,starttimer(&ts, 2000 ));
mutex_print(&mutex,"Locked TR");
}
/********** Critical Section *******************/
_tid = GetCurrentThreadId();
d= sharedData;
printf("Thread %d: Start critical section, holding lock\n",
tid);
/* Access to shared data goes here */
++sharedData;
Sleep(100);
if (_tid != tid) {
printf("FAILED Thread %d: shared TID = %d\n", tid, _tid);
mutex_print(&mutex,"Race cond");
}
e = sharedData -1;
--sharedData2;
printf("Thread %d: End critical section, release lock\n",
tid);
d -= (e);
if (d) {
printf("FAILED Thread %d: check sharedData=%d instead of 0\n", tid, d);
mutex_print(&mutex,"Race cond");
}
_tid = 0;
/********** Critical Section *******************/
rc = pthread_mutex_unlock(&mutex);
mutex_print(&mutex,"UnLocked T");
checkResults("pthread_mutex_unlock()\n", rc);
return NULL;
}
/* PTHREAD_NORMAL_MUTEX_INITIALIZER deadlock handling thread 1 */
void *mutex_threadfuncDL1(void *parm)
{
int rc;
int d;
int tid = pthread_self();
printf("Thread %d: Entered, locking n1\n", tid);
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock() 1\n", rc);
printf("Thread %d: locked nr1\n", tid);
Sleep(1000);
printf("Thread %d: locking nr2 for a deadlock\n", tid);
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock() 2\n", rc);
printf("Thread %d: locked nr2 and externally unlocked\n", tid);
/********** Critical Section *******************/
Sleep(2000);
printf("Thread %d: Doing job\n", tid);
Sleep(2000);
printf("Thread %d: End critical section, release lock\n", tid);
/********** Critical Section *******************/
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()\n", rc);
printf("Thread %d: leaving\n", tid);
return NULL;
}
/* PTHREAD_NORMAL_MUTEX_INITIALIZER deadlock handling main thread */
int mutex_main_DL(void)
{
int rc;
int d;
pthread_t thread;
int tid = pthread_self();
rc = pthread_create(&thread, NULL, mutex_threadfuncDL1, NULL);
checkResults("mutex_main_DL: pthread_create()\n", rc);
printf("mutex_main_DL: wait for thread\n");
Sleep(3000);
printf("mutex_main_DL: try ext release deadlock\n");
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock() ext\n", rc);
printf("mutex_main_DL: unlocked 1\n");
Sleep(2000);
//rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock() ext 2\n", rc);
printf("mutex_main_DL: unlocked 2\n");
Sleep(10000);
printf("mutex_main_DL: bye!\n");
return 0;
}
int mutex_main_timed(void)
{
pthread_t thread[MUTEX_NTHREADS];
int rc=0;
int i;
struct timespec ts;
printf("Enter Testcase - mutex_main_timed %s\n",testType);
mutex = PTHREAD_NORMAL_MUTEX_INITIALIZER;
printf("Mutex inited\n");
rc = pthread_mutex_init (&mutex, NULL);
checkResults("pthread_mutex_init()\n", rc);
mutex_print(&mutex,"Locked 0");
printf("Hold Mutex to prevent access to shared data\n");
rc = pthread_mutex_lock(&mutex);
//rc = pthread_mutex_timedlock(&mutex,starttimer(&ts, 30000 ));
mutex_print(&mutex,"Locked 1");
printf("Mutex inited type=%d\n", ((mutex_t *)mutex)->type);
printf("Unlock Mutex to prevent access to shared data\n");
checkResults("pthread_mutex_lock()\n", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()\n",rc);
printf("Hold Mutex to prevent access to shared data 2\n");
mutex_print(&mutex,"Locked 2");
//rc = pthread_mutex_timedlock(&mutex,starttimer(&ts, 60000 ));
rc = pthread_mutex_lock(&mutex);
mutex_print(&mutex,"Locked 3");
checkResults("pthread_mutex_lock() 2\n", rc);
printf("Create/start threads\n");
for (i=0; i<MUTEX_NTHREADS; ++i) {
rc = pthread_create(&thread[i], NULL, mutex_threadfunc_timed, NULL);
checkResults("pthread_create()\n", rc);
}
printf("Wait a bit until we are 'done' with the shared data\n");
Sleep(5000);
printf("Unlock shared data\n");
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_lock()\n",rc);
printf("Wait for the threads to complete, and release their resources\n");
for (i=0; i <MUTEX_NTHREADS; ++i) {
rc = pthread_join(thread[i], NULL);
checkResults("pthread_join()\n", rc);
}
printf("Clean up, data: %d %d\n",sharedData,sharedData2);
rc = pthread_mutex_destroy(&mutex);
printf("Main completed\n");
return 0;
}
int mutex_main_raced(void)
{
//pthread_t thread[MUTEX_NTHREADS];
pthread_t *thread;
int rc=0;
int i, f=0, F=0;
struct timespec ts;
mutex_print_set(1);
checkAbort = 0;
thread = (pthread_t *)calloc(MUTEX_NTHREADS, sizeof(pthread_t));
printf("Enter Testcase - mutex_main_raced %s\n",testType);
mutex = PTHREAD_NORMAL_MUTEX_INITIALIZER;
printf("Mutex inited\n");
printf("Hold Mutex to prevent access to shared data\n");
//rc = pthread_mutex_timedlock(&mutex,starttimer(&ts, 3000000 ));
rc = pthread_mutex_lock(&mutex);
printf("Mutex inited type=%d\n", ((mutex_t *)mutex)->type);
printf("Unlock Mutex to prevent access to shared data\n");
checkResults("pthread_mutex_timedlock()\n", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock() 1\n",rc);
printf("Hold Mutex to prevent access to shared data 2\n");
//rc = pthread_mutex_timedlock(&mutex,starttimer(&ts, 3000000 ));
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_timedlock() 2\n", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock() 2\n",rc);
printf("Create/start threads\n");
Sleep(1000);
for (i=0; i<MUTEX_NTHREADS; ++i) {
rc = pthread_create(&thread[i], NULL, mutex_threadfunc_raced, NULL);
checkResults("pthread_create()\n", rc);
}
printf("Wait a bit until we are 'done' with the shared data\n");
printf("Unlock shared data\n");
printf("Wait for the threads to complete, and release their resources\n");
Sleep(40000);
printf("Done\n");
mutex_print(&mutex,"Done");
do {
f = 0;
for (i=0; i <MUTEX_NTHREADS; ++i) {
if( thread[i] ) {
rc = pthread_join(thread[i], NULL);
if (rc) {
f++;
printf("_pthread_tryjoin failed: %d %d %d\n",i, rc,thread[i]);
} else {
thread[i] = 0;
printf("_pthread_tryjoin OK: %d\n",i);
}
}
}
printf("Joins failed: %d destr: %d init: %d\n",f,destr,init);
F += f;
Sleep(1000);
} while (0);
printf("Joins total failed: %d destr: %d init: %d\n",F,destr,init);
printf("Clean up, data: %d %d\n",sharedData,sharedData2);
mutex_print(&mutex, "A Clean up");
rc = pthread_mutex_destroy(&mutex);
mutex_print(&mutex, "B Clean up");
// Removed in r4392: printf("Main completed spincount = %d\n", _spin_lite_getsc(0));
// Removed in r4392: printf("Main completed spinlocks = %d\n", _spin_lite_getbsc(0));
// Removed in r4392: printf("Main completed Max spincount = %d\n", _spin_lite_getscMax(0));
// Removed in r4392: printf("Main completed Avg spincount/thread = %f\n", (float)((float)_spin_lite_getsc(0)/(float)MUTEX_NTHREADS));
return 0;
}
int mutex_main_static(void)
{
pthread_t thread[MUTEX_NTHREADS];
int rc=0;
int i;
struct timespec ts;
printf("mutex_main_static: Hold Mutex to prevent access to shared data o=%d\n",0);
mutex_print(&mutex,"Lock");
rc = pthread_mutex_lock(&mutex);
mutex_print(&mutex,"Locked");
printf("Mutex inited type=%d o=%d\n", ((mutex_t *)mutex)->type,GET_OWNER(((mutex_t *)mutex)));
printf("Unlock Mutex to prevent access to shared data\n");
checkResults("pthread_mutex_lock()\n", rc);
rc = pthread_mutex_unlock(&mutex);
mutex_print(&mutex,"UnLocked");
printf("Unlocked Mutex to prevent access to shared data o=%d\n",GET_OWNER(((mutex_t *)mutex)));
checkResults("pthread_mutex_unlock()\n",rc);
printf("Hold Mutex to prevent access to shared data 2\n");
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock() 2\n", rc);
mutex_print(&mutex,"Locked 2");
printf("Create/start threads\n");
for (i=0; i<MUTEX_NTHREADS; ++i) {
rc = pthread_create(&thread[i], NULL, mutex_threadfunc, NULL);
checkResults("pthread_create()\n", rc);
}
printf("Wait a bit until we are 'done' with the shared data\n");
Sleep(3000);
printf("Unlock shared data\n");
rc = pthread_mutex_unlock(&mutex);
mutex_print(&mutex,"UnLocked 2");
checkResults("pthread_mutex_unlock()\n",rc);
return 0;
}
int mutex_main(void)
{
pthread_t *thread;
int rc=0;
int i;
int tid = 0;
mutex_print_set(1);
thread = (pthread_t *)calloc(MUTEX_NTHREADS, sizeof(pthread_t));
printf("Main thread %d: Entered\n", tid);
printf("Enter Testcase - mutex_main %s\n",testType);
if (strcmp(testType,"static") == 0) {
mutex = PTHREAD_DEFAULT_MUTEX_INITIALIZER;
return mutex_main_static();
} else if (strcmp(testType,"staticN") == 0) {
mutex = PTHREAD_NORMAL_MUTEX_INITIALIZER;
} else if (strcmp(testType,"staticND") == 0) {
mutex = PTHREAD_NORMAL_MUTEX_INITIALIZER;
return mutex_main_DL();
} else if (strcmp(testType,"staticE") == 0) {
mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
} else if (strcmp(testType,"staticR") == 0) {
mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
} else if (strcmp(testType,"timed") == 0) {
mutex = PTHREAD_NORMAL_MUTEX_INITIALIZER;
return mutex_main_timed();
} else if (strcmp(testType,"raced") == 0) {
mutex = PTHREAD_NORMAL_MUTEX_INITIALIZER;
return mutex_main_raced();
} else {
rc = pthread_mutex_init(&mutex,NULL);
printf("Mutex inited\n");
checkResults("pthread_mutex_init()\n", rc);
}
printf("Hold Mutex to prevent access to shared data o=%d\n",0);
mutex_print(&mutex,"Lock");
rc = pthread_mutex_lock(&mutex);
mutex_print(&mutex,"Locked");
printf("Mutex inited type=%d o=%d\n", ((mutex_t *)mutex)->type,GET_OWNER(((mutex_t *)mutex)));
printf("Unlock Mutex to prevent access to shared data\n");
checkResults("pthread_mutex_lock()\n", rc);
rc = pthread_mutex_unlock(&mutex);
mutex_print(&mutex,"UnLocked");
printf("Unlocked Mutex to prevent access to shared data o=%d\n",GET_OWNER(((mutex_t *)mutex)));
checkResults("pthread_mutex_unlock()\n",rc);
printf("Hold Mutex to prevent access to shared data 2\n");
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock() 2\n", rc);
mutex_print(&mutex,"Locked 2");
printf("Create/start threads\n");
for (i=0; i<MUTEX_NTHREADS; ++i) {
rc = pthread_create(&thread[i], NULL, mutex_threadfunc, NULL);
checkResults("pthread_create()\n", rc);
}
printf("Wait a bit until we are 'done' with the shared data\n");
Sleep(3000);
printf("Unlock shared data\n");
rc = pthread_mutex_unlock(&mutex);
mutex_print(&mutex,"UnLocked 2");
checkResults("pthread_mutex_unlock()\n",rc);
printf("Wait for the threads to complete, and release their resources\n");
for (i=0; i <MUTEX_NTHREADS; ++i) {
rc = pthread_join(thread[i], NULL);
checkResults("pthread_join()\n", rc);
}
printf("Clean up, data: %d %d\n",sharedData,sharedData2);
rc = pthread_mutex_destroy(&mutex);
printf("Main completed\n");
Sleep(6000);
return 0;
}
#if 1
/*================================================================================*/
#define COND_NTHREADS 3
#define COND_WAIT_TIME_SECONDS 10
int workToDo = 0;
int workLeave = 0;
pthread_cond_t cond;
pthread_mutex_t mutex;
void *condTimed_threadfunc(void *parm)
{
int tid;
int rc;
struct timespec ts;
struct timeval tp;
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
tid = pthread_self();
/* Usually worker threads will loop on these operations */
while (!workLeave) {
rc = gettimeofday(&tp, NULL);
checkResults("gettimeofday()\n", rc);
/* Convert from timeval to timespec */
ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec * 1000;
ts.tv_sec += COND_WAIT_TIME_SECONDS;
do {
if (strcmp(testType,"notTimed") == 0) {
printf("Thread %d blocked, notTimed\n", tid);
rc = pthread_cond_wait(&cond, &mutex);
} else {
printf("Thread %d blocked and waiting\n", tid);
rc = pthread_cond_timedwait(&cond, &mutex, starttimer(&ts, 6000 ));
}
/* If the wait timed out, in this example, the work is complete, and */
/* the thread will end. */
/* In reality, a timeout must be accompanied by some sort of checking */
/* to see if the work is REALLY all complete. In the simple example */
/* we'll just go belly up when we time out. */
printf("Thread %d unblocked\n", tid);
if (rc == ETIMEDOUT) {
printf("Wait %d timed out!\n", tid);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock() A\n", rc);
printf("Exit %d\n", tid);
pthread_exit(NULL);
}
checkResults("pthread_cond_timedwait()\n", rc);
} while (!workLeave && !workToDo);
if (workToDo) {
printf("Thread %d consumes work here\n", tid);
Sleep(2000);
workToDo = 0;
}
}
printf("Thread %d leaves here\n", tid);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock() B\n", rc);
return NULL;
}
int condTimed_main()
{
int rc=0;
int i;
pthread_t threadid[COND_NTHREADS];
struct timespec ts;
printf("Enter Testcase - condTimed_main %s\n",testType);
rc = pthread_mutex_init (&mutex, NULL);
checkResults("pthread_mutex_init()\n", rc);
rc = pthread_cond_init (&cond, NULL);
checkResults("pthread_cond_init()\n", rc);
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
printf("Try steal a signal 1 (wait on own signal), should timeout\n");
rc = pthread_cond_broadcast(&cond);
checkResults("pthread_cond_signal()\n", rc);
rc = pthread_cond_timedwait(&cond, &mutex, starttimer(&ts, 3000 ));
printf("rc=%d\n",rc);
checkResults("pthread_cond_timedwait() Steal 1\n", rc - ETIMEDOUT);
printf("Done, rc=%d\n",rc);
rc = pthread_mutex_unlock(&mutex);
printf("Create %d threads\n", COND_NTHREADS);
for(i=0; i<COND_NTHREADS; ++i) {
rc = pthread_create(&threadid[i], NULL, condTimed_threadfunc, NULL);
checkResults("pthread_create()\n", rc);
}
Sleep(2000);
printf("One work item to give to a thread\n");
workToDo = 1;
rc = pthread_mutex_lock(&mutex);
rc = pthread_cond_signal(&cond);
checkResults("pthread_cond_signal()\n", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()\n", rc);
Sleep(3001);
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock() 2\n", rc);
printf("One another work item to give to a thread\n");
workToDo = 1;
rc = pthread_cond_signal(&cond);
checkResults("pthread_cond_signal()\n", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()\n", rc);
//Sleep(10000);
printf("Broadcast leave to all threads, waiters=%d\n",((cond_t *)cond)->waiters_count_);
workLeave = 1;
rc = pthread_cond_broadcast(&cond);
printf("Broadcast done, waiters=%d\n",((cond_t *)cond)->waiters_count_);
checkResults("pthread_cond_broadcast()\n", rc);
printf("Try steal a signal 2, should timeout\n");
rc = pthread_mutex_lock(&mutex);
printf("pthread_mutex_lock, waiters=%d\n",((cond_t *)cond)->waiters_count_);
rc = pthread_cond_timedwait(&cond, &mutex, starttimer(&ts, 3000 ));
printf("pthread_cond_timedwait, waiters=%d\n",((cond_t *)cond)->waiters_count_);
checkResults("pthread_cond_timedwait() Steal 2\n", rc - ETIMEDOUT);
printf("Done, rc=%d\n",rc);
rc = pthread_mutex_unlock(&mutex);
printf("Wait for threads and cleanup\n");
for (i=0; i<COND_NTHREADS; ++i) {
rc = pthread_join(threadid[i], NULL);
checkResults("pthread_join()\n", rc);
}
printf("Exit, waiters=%d\n",((cond_t *)cond)->waiters_count_);
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
printf("Main completed\n");
return 0;
}
#else
/*================================================================================*/
#define COND_NTHREADS 3
#define COND_WAIT_TIME_SECONDS 10
int workToDo = 0;
int workLeave = 0;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void *condTimed_threadfunc(void *parm)
{
int tid;
int rc;
struct timespec ts;
struct timeval tp;
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
tid = pthread_self();
/* Usually worker threads will loop on these operations */
printf("condTimed_threadfunc, wait %d secs\n", COND_WAIT_TIME_SECONDS);
while (!workLeave) {
rc = gettimeofday(&tp, NULL);
checkResults("gettimeofday()\n", rc);
/* Convert from timeval to timespec */
ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec * 1000;
ts.tv_sec += COND_WAIT_TIME_SECONDS;
do {
if (strcmp(testType,"notTimed") == 0) {
printf("Thread %d blocked, notTimed\n", tid);
rc = pthread_cond_wait(&cond, &mutex);
} else {
printf("Thread %d blocked\n", tid);
rc = pthread_cond_timedwait(&cond, &mutex, starttimer(&ts, 3000 ));
}
/* If the wait timed out, in this example, the work is complete, and */
/* the thread will end. */
/* In reality, a timeout must be accompanied by some sort of checking */
/* to see if the work is REALLY all complete. In the simple example */
/* we'll just go belly up when we time out. */
printf("Thread %d unblocked\n", tid);
if (rc == ETIMEDOUT) {
printf("Wait %d timed out!\n", tid);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock() A\n", rc);
printf("Exit %d\n", tid);
pthread_exit(NULL);
}
checkResults("pthread_cond_timedwait()\n", rc);
} while (!workLeave && !workToDo);
if (workToDo) {
printf("Thread %d consumes work here\n", tid);
Sleep(2000);
workToDo = 0;
}
}
printf("Thread %d leaves here\n", tid);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock() B\n", rc);
return NULL;
}
int condTimed_main()
{
int rc=0;
int i;
pthread_t threadid[COND_NTHREADS];
struct timespec ts;
printf("Enter Testcase - condTimed_main %s\n",testType);
if (strcmp(testType,"static") == 0) {
printf("cond + mutex static initialized\n");
strcpy(testType, "notTimed");
} else {
rc = pthread_mutex_init (&mutex, NULL);
checkResults("pthread_mutex_init()\n", rc);
rc = pthread_cond_init (&cond, NULL);
checkResults("pthread_cond_init()\n", rc);
printf("cond + mutex normal initialized\n");
}
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()\n", rc);
printf("Mutex locked \n");
printf("Try steal a signal 1, should timeout\n");
printf("Timed wait 1, waiters=%d\n",cond->waiters_count_);
rc = pthread_cond_timedwait(&cond, &mutex, starttimer(&ts, 3000 ));
printf("rc=%d\n",rc);
checkResults("pthread_cond_timedwait() Steal 1\n", rc - ETIMEDOUT);
printf("Done, rc=%d\n",rc);
rc = pthread_mutex_unlock(&mutex);
printf("Create %d threads\n", COND_NTHREADS);
for(i=0; i<COND_NTHREADS; ++i) {
rc = pthread_create(&threadid[i], NULL, condTimed_threadfunc, NULL);
checkResults("pthread_create()\n", rc);
}
Sleep(2000);
printf("One work item to give to a thread\n");
workToDo = 1;
rc = pthread_mutex_lock(&mutex);
printf("Mutex locked 2\n");
rc = pthread_cond_signal(&cond);
checkResults("pthread_cond_signal()\n", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()\n", rc);
//Sleep(1000);
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock() 2\n", rc);
printf("One another work item to give to a thread\n");
workToDo = 1;
rc = pthread_cond_signal(&cond);
checkResults("pthread_cond_signal()\n", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()\n", rc);
//Sleep(1000);
printf("Broadcast leave to all threads, waiters=%d\n",cond->waiters_count_);
workLeave = 1;
rc = pthread_cond_broadcast(&cond);
//Sleep(1000);
printf("Broadcast done, waiters=%d\n",cond->waiters_count_);
checkResults("pthread_cond_broadcast()\n", rc);
printf("Try steal a signal 2, should timeout\n");
rc = pthread_mutex_lock(&mutex);
printf("Timed wait 2, waiters=%d\n",cond->waiters_count_);
rc = pthread_cond_timedwait(&cond, &mutex, starttimer(&ts, 2000 ));
checkResults("pthread_cond_timedwait() Steal 2\n", rc - ETIMEDOUT);
printf("Done, rc=%d\n",rc);
rc = pthread_mutex_unlock(&mutex);
printf("Wait for threads and cleanup\n");
for (i=0; i<COND_NTHREADS; ++i) {
rc = pthread_join(threadid[i], NULL);
checkResults("pthread_join()\n", rc);
}
printf("Exit, waiters=%d\n",cond->waiters_count_);
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
printf("Main completed\n");
return 0;
}
int cond_main()
{
strcpy(testType, "notTimed");
return condTimed_main();
}
int condStatic_main()
{
strcpy(testType, "static");
return condTimed_main();
}
#endif
/*================================================================================*/
void *rwlockTimed_rdlockThread(void *arg)
{
int rc;
int count=0;
struct timespec ts;
unsigned long long ct1 = _pthread_time_in_ms();
printf("Entered thread, getting read lock with timeout\n");
Retry:
rc = pthread_rwlock_timedrdlock(&rwlock, starttimer(&ts, 5000 ));
if (rc != 0) {
if (count >= 10) {
printf("Retried too many times, failure!\n");
exit(EXIT_FAILURE);
}
++count;
printf("RETRY...rc=%d\n",rc);
goto Retry;
}
checkResults("pthread_rwlock_timedrdlock() 1\n", rc);
Sleep(2000);
printf("unlock the read lock\n");
rc = pthread_rwlock_unlock(&rwlock);
checkResults("pthread_rwlock_unlock()\n", rc);
unsigned long long ct2 = _pthread_time_in_ms();
printf("Secondary thread complete, waited total: %ld\n",ct2-ct1);
return NULL;
}
int rwlockTimed_main(void)
{
int rc=0;
pthread_t thread;
printf("Enter Testcase rwlockTimed_main\n");
printf("Main, initialize the read write lock\n");
//rc = pthread_rwlock_init(&rwlock, NULL);
rwlock = PTHREAD_RWLOCK_INITIALIZER;
printf("RWL %p\n",rwlock);
checkResults("pthread_rwlock_init()\n", rc);
printf("Main, get the write lock\n");
rc = pthread_rwlock_wrlock(&rwlock);
checkResults("pthread_rwlock_wrlock()\n", rc);
printf("Main, create the timed rd lock thread\n");
rc = pthread_create(&thread, NULL, rwlockTimed_rdlockThread, NULL);
checkResults("pthread_create\n", rc);
printf("Main, wait a bit holding the write lock\n");
Sleep(18000);
printf("Main, Now unlock the write lock\n");
rc = pthread_rwlock_unlock(&rwlock);
checkResults("pthread_rwlock_unlock()\n", rc);
printf("Main, wait for the thread to end\n");
rc = pthread_join(thread, NULL);
checkResults("pthread_join\n", rc);
rc = pthread_rwlock_destroy(&rwlock);
rwl_print(&rwlock,"destroyed?");
checkResults("pthread_rwlock_destroy()\n", rc);
printf("Main completed\n");
return 0;
}
/*================================================================================*/
volatile static int rwdata=0;
void *rwlock_rdlockThread(void *arg)
{
int rc,i;
struct timespec ts;
printf("Entered thread, getting read lock\n");
//rc = pthread_rwlock_rdlock(&rwlock);
rc = pthread_rwlock_timedrdlock(&rwlock, starttimer(&ts, 30000 ));
checkResults("pthread_rwlock_rdlock()\n", rc);
printf("got the rwlock read lock\n");
for (i=0; i<=200; i++) {
Sleep(10);
if (rwdata) {
printf("RACE cond read %d\n", rwdata);
}
}
printf("unlock the read lock\n");
rc = pthread_rwlock_unlock(&rwlock);
checkResults("pthread_rwlock_unlock()\n", rc);
printf("Secondary thread unlocked\n");
return NULL;
}
void *rwlock_wrlockThread(void *arg)
{
int rc;
printf("Entered thread, getting write lock\n");
rc = pthread_rwlock_wrlock(&rwlock);
checkResults("pthread_rwlock_wrlock()\n", rc);
rwdata ++;
Sleep(5000);
rwdata --;
printf("Got the rwlock write lock, now unlock\n");
rc = pthread_rwlock_unlock(&rwlock);
checkResults("pthread_rwlock_unlock()\n", rc);
printf("Secondary thread unlocked\n");
return NULL;
}
int rwlock_main(void)
{
int rc=0;
pthread_t thread, thread1;
printf("Enter Testcase rwlock_main\n");
printf("Main, initialize the read write lock\n");
rc = pthread_rwlock_init(&rwlock, NULL);
checkResults("pthread_rwlock_init()\n", rc);
rwl_print(&rwlock, "Main, grab a read lock");
rc = pthread_rwlock_rdlock(&rwlock);
rwl_print(&rwlock, "Main, grabbbed a read lock");
checkResults("pthread_rwlock_rdlock()\n",rc);
/*
printf("Main, grab the same read lock again\n");
rc = pthread_rwlock_rdlock(&rwlock);
checkResults("pthread_rwlock_rdlock() second\n", rc);
*/
printf("Main, create the read lock thread\n");
rc = pthread_create(&thread, NULL, rwlock_rdlockThread, NULL);
checkResults("pthread_create\n", rc);
/*
printf("Main - unlock the first read lock\n");
rc = pthread_rwlock_unlock(&rwlock);
checkResults("pthread_rwlock_unlock()\n", rc);
*/
printf("Main, create the write lock thread\n");
rc = pthread_create(&thread1, NULL, rwlock_wrlockThread, NULL);
checkResults("pthread_create\n", rc);
printf("Main - unlock the read lock\n");
rc = pthread_rwlock_unlock(&rwlock);
checkResults("pthread_rwlock_unlock()\n", rc);
printf("Main, wait for the threads\n");
rc = pthread_join(thread, NULL);
checkResults("pthread_join\n", rc);
rc = pthread_join(thread1, NULL);
checkResults("pthread_join\n", rc);
rc = pthread_rwlock_destroy(&rwlock);
checkResults("pthread_rwlock_destroy()\n", rc);
printf("Main completed\n");
rwl_print(&rwlock, "Main completed");
return 0;
}
/*================================================================================*/
#define BARRIER_NTHREADS 50
#define BARRIER_ROUNDS 50
static pthread_barrier_t barriers[BARRIER_NTHREADS];
static pthread_mutex_t lock;
static int counters[BARRIER_NTHREADS];
static int serial[BARRIER_NTHREADS];
void *barrier_Thread(void *arg)
{
void *result = NULL;
int nr = (int)(uintptr_t)arg;
int i;
for (i = 0; i < BARRIER_ROUNDS; ++i)
{
int j;
int retval;
if (nr == 0)
{
memset (counters, '\0', sizeof (counters));
memset (serial, '\0', sizeof (serial));
}
retval = pthread_barrier_wait (&barriers[BARRIER_NTHREADS - 1]);
if (retval != 0 && retval != PTHREAD_BARRIER_SERIAL_THREAD)
{
printf ("thread %d failed to wait for all the others\n", nr);
result = (void *) 1;
}
for (j = nr; j < BARRIER_NTHREADS; ++j)
{
/* Increment the counter for this round. */
//printf ("Increment the counter for this round %d\n", j);
pthread_mutex_lock (&lock);
++counters[j];
pthread_mutex_unlock (&lock);
//printf ("Incremented the counter for this round %d\n", j);
/* Wait for the rest. */
retval = pthread_barrier_wait (&barriers[j]);
/* Test the result. */
if (nr == 0 && counters[j] != j + 1)
{
printf ("barrier in round %d released but count is %d\n",
j, counters[j]);
result = (void *) 1;
}
if (retval != 0)
{
if (retval != PTHREAD_BARRIER_SERIAL_THREAD)
{
printf ("thread %d in round %d has nonzero return value != PTHREAD_BARRIER_SERIAL_THREAD\n",
nr, j);
result = (void *) 1;
}
else
{
//printf ("pthread_mutex_lock %d\n", nr);
pthread_mutex_lock (&lock);
++serial[j];
pthread_mutex_unlock (&lock);
}
}
/* Wait for the rest again. */
printf ("Wait for the rest again %d\n",j);
retval = pthread_barrier_wait (&barriers[j]);
/* the following printf can make bugs go away - timing dependend */
/* without this printf the test hangs here */
/* try USE_MUTEX_CriticalSection + USE_COND_Semaphore */
//printf ("Wait for the rest again continue %d\n",j);
/* Now we can check whether exactly one thread was serializing. */
if (nr == 0 && serial[j] != 1)
{
printf ("not exactly one serial thread in round %d\n", j);
result = (void *) 1;
exit(1);
}
}
}
return result;
}
int barrier_main(void)
{
int rc=0;
pthread_t threads[BARRIER_NTHREADS];
int i;
void *res;
int result = 0;
printf("Enter Testcase - barrier_main %s\n",testType);
rc = pthread_mutex_init (&lock, NULL);
checkResults("pthread_mutex_init()\n", rc);
/* Initialized the barrier variables. */
for (i = 0; i < BARRIER_NTHREADS; ++i) {
if (pthread_barrier_init (&barriers[i], NULL, i + 1) != 0)
{
printf ("Failed to initialize barrier %d\n", i);
exit (1);
}
printf ("initialized barrier %d\n", i);
}
/* Start the threads. */
for (i = 0; i < BARRIER_NTHREADS; ++i) {
if (pthread_create (&threads[i], NULL, barrier_Thread, (void *)(uintptr_t)i) != 0)
{
printf ("Failed to start thread %d\n", i);
exit (1);
}
printf ("started thread %d\n", i);
}
/* And wait for them. */
printf ("Wait for %d threads\n", i);
for (i = 0; i < BARRIER_NTHREADS; ++i) {
if (pthread_join (threads[i], &res) != 0 || res != NULL)
{
printf ("thread %d returned a failure\n", i);
result = 1;
}
}
printf ("Result: %d\n", result);
if (result == 0)
puts ("all OK");
return result;
}
/*================================================================================*/
void thread(void)
{
int i;
parm *p;
pthread_t *threads;
pthread_attr_t pthread_custom_attr;
int n = N_THREAD;
n = N_THREAD;
if ((n < 1) || (n > MAX_THREAD))
{
printf ("The no of thread should between 1 and %d.\n",MAX_THREAD);
exit(1);
}
threads=(pthread_t *)malloc(n*sizeof(*threads));
pthread_attr_init(&pthread_custom_attr);
p=(parm *)malloc(sizeof(parm)*n);
/* Start up thread */
for (i=0; i<n; i++)
{
p[i].id=i;
pthread_create(&threads[i], &pthread_custom_attr, hello, (void *)(p+i));
}
/* Synchronize the completion of each thread. */
for (i=0; i<n; i++)
{
pthread_join(threads[i],NULL);
}
free(p);
pthread_exit(NULL);
}
int main(int argc, char * argv[]) {
char name[100];
if (argc < 2)
{
printf ("Usage: %s <name> [type]\nwhere <name> is test name\n",argv[0]);
printf ("test names are: thread, rwlock, rwlockTimed, cond, condTimed, condStatic, spinlock, barrier, mutex [static[N|R|E|ND]].\n");
exit(1);
}
strcpy(testType, "default");
if (argc == 3)
{
strcpy(testType, argv[2]);
}
strcpy(name, argv[1]);
printf ("Threads test: %s\n",name);
printf ("P size: %d %d\n",SIZE_MAX>UINT_MAX,sizeof(struct timespec ));
if (strcmp(name, "thread") == 0) thread();
else if (strcmp(name, "rwlock") == 0) rwlock_main();
else if (strcmp(name, "rwlockTimed") == 0) rwlockTimed_main();
//else if (strcmp(name, "cond") == 0) cond_main();
else if (strcmp(name, "condTimed") == 0) condTimed_main();
//else if (strcmp(name, "condStatic") == 0) condStatic_main();
else if (strcmp(name, "barrier") == 0) barrier_main();
else if (strcmp(name, "mutex") == 0) mutex_main();
else if (strcmp(name, "spinlock") == 0) spinlock_main();
else printf ("Unknown test name '%s'\n",name);
return 0;
}