* winsup.api/pthread/: New directory. Ports of pthread functionality

tests ported from pthreads-win32 project.
* winsup.api/pthread/test.h: Commmon declaraions for pthread tests.
* winsup.api/pthread/cleanup2.c: New test.
* winsup.api/pthread/cleanup3.c: Ditto.
* winsup.api/pthread/condvar1.c: Ditto.
* winsup.api/pthread/condvar2.c: Ditto.
* winsup.api/pthread/condvar2_1.c: Ditto.
* winsup.api/pthread/condvar3.c: Ditto.
* winsup.api/pthread/condvar3_1.c: Ditto.
* winsup.api/pthread/condvar3_2.c: Ditto.
* winsup.api/pthread/condvar3_3.c: Ditto.
* winsup.api/pthread/condvar4.c: Ditto.
* winsup.api/pthread/condvar5.c: Ditto.
* winsup.api/pthread/condvar6.c: Ditto.
* winsup.api/pthread/condvar8.c: Ditto.
* winsup.api/pthread/count1.c: Ditto.
* winsup.api/pthread/create1.c: Ditto.
* winsup.api/pthread/create2.c: Ditto.
* winsup.api/pthread/equal1.c: Ditto.
* winsup.api/pthread/exit1.c: Ditto.
* winsup.api/pthread/exit2.c: Ditto.
* winsup.api/pthread/exit3.c: Ditto.
* winsup.api/pthread/inherit1.c: Ditto.
* winsup.api/pthread/join0.c: Ditto.
* winsup.api/pthread/join1.c: Ditto.
* winsup.api/pthread/join2.c: Ditto.
* winsup.api/pthread/mutex1.c: Ditto.
* winsup.api/pthread/mutex1r.c: Ditto.
* winsup.api/pthread/mutex2.c: Ditto.
* winsup.api/pthread/mutex3.c: Ditto.
* winsup.api/pthread/mutex6r.c: Ditto.
* winsup.api/pthread/once1.c: Ditto.
* winsup.api/pthread/priority1.c: Ditto.
* winsup.api/pthread/priority2.c: Ditto.
* winsup.api/pthread/self1.c: Ditto.
* winsup.api/pthread/self2.c: Ditto.
* winsup.api/pthread/tsd1.c: Ditto.
This commit is contained in:
Egor Duda 2001-11-15 11:19:48 +00:00
parent f38ac9b70c
commit 4800c7477b
37 changed files with 3099 additions and 0 deletions

View File

@ -1,3 +1,44 @@
2001-11-15 Egor Duda <deo@logos-m.ru>
* winsup.api/pthread/: New directory. Ports of pthread functionality
tests ported from pthreads-win32 project.
* winsup.api/pthread/test.h: Commmon declaraions for pthread tests.
* winsup.api/pthread/cleanup2.c: New test.
* winsup.api/pthread/cleanup3.c: Ditto.
* winsup.api/pthread/condvar1.c: Ditto.
* winsup.api/pthread/condvar2.c: Ditto.
* winsup.api/pthread/condvar2_1.c: Ditto.
* winsup.api/pthread/condvar3.c: Ditto.
* winsup.api/pthread/condvar3_1.c: Ditto.
* winsup.api/pthread/condvar3_2.c: Ditto.
* winsup.api/pthread/condvar3_3.c: Ditto.
* winsup.api/pthread/condvar4.c: Ditto.
* winsup.api/pthread/condvar5.c: Ditto.
* winsup.api/pthread/condvar6.c: Ditto.
* winsup.api/pthread/condvar8.c: Ditto.
* winsup.api/pthread/count1.c: Ditto.
* winsup.api/pthread/create1.c: Ditto.
* winsup.api/pthread/create2.c: Ditto.
* winsup.api/pthread/equal1.c: Ditto.
* winsup.api/pthread/exit1.c: Ditto.
* winsup.api/pthread/exit2.c: Ditto.
* winsup.api/pthread/exit3.c: Ditto.
* winsup.api/pthread/inherit1.c: Ditto.
* winsup.api/pthread/join0.c: Ditto.
* winsup.api/pthread/join1.c: Ditto.
* winsup.api/pthread/join2.c: Ditto.
* winsup.api/pthread/mutex1.c: Ditto.
* winsup.api/pthread/mutex1r.c: Ditto.
* winsup.api/pthread/mutex2.c: Ditto.
* winsup.api/pthread/mutex3.c: Ditto.
* winsup.api/pthread/mutex6r.c: Ditto.
* winsup.api/pthread/once1.c: Ditto.
* winsup.api/pthread/priority1.c: Ditto.
* winsup.api/pthread/priority2.c: Ditto.
* winsup.api/pthread/self1.c: Ditto.
* winsup.api/pthread/self2.c: Ditto.
* winsup.api/pthread/tsd1.c: Ditto.
2001-11-08 Corinna Vinschen <corinna@vinschen.de>
* checksignal.c: New testcase.

View File

@ -0,0 +1,157 @@
/*
* File: cleanup2.c
*
* Test Synopsis: Test cleanup handler executes (when thread is not canceled).
*
* Test Method (Validation or Falsification):
* -
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* -
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
* pthread_testcancel, pthread_cancel, pthread_join
*
* Pass Criteria:
* - Process returns zero exit status.
*
* Fail Criteria:
* - Process returns non-zero exit status.
*/
#include "test.h"
/*
* Create NUMTHREADS threads in addition to the Main thread.
*/
enum {
NUMTHREADS = 10
};
typedef struct bag_t_ bag_t;
struct bag_t_ {
int threadnum;
int started;
/* Add more per-thread state variables here */
int count;
};
static bag_t threadbag[NUMTHREADS + 1];
static int pop_count = 0;
static void
increment_pop_count(void * arg)
{
int * c = (int *) arg;
(*c)++;
}
void *
mythread(void * arg)
{
int result = 0;
bag_t * bag = (bag_t *) arg;
assert(bag == &threadbag[bag->threadnum]);
assert(bag->started == 0);
bag->started = 1;
pthread_cleanup_push(increment_pop_count, (void *) &pop_count);
sched_yield();
pthread_cleanup_pop(1);
return (void *) result;
}
int
main()
{
int failed = 0;
int i;
pthread_t t[NUMTHREADS + 1];
assert((t[0] = pthread_self()) != NULL);
for (i = 1; i <= NUMTHREADS; i++)
{
threadbag[i].started = 0;
threadbag[i].threadnum = i;
assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
}
/*
* Code to control or munipulate child threads should probably go here.
*/
Sleep(1000);
/*
* Standard check that all threads started.
*/
for (i = 1; i <= NUMTHREADS; i++)
{
if (!threadbag[i].started)
{
failed |= !threadbag[i].started;
fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
}
}
assert(!failed);
/*
* Check any results here. Set "failed" and only print output on failure.
*/
failed = 0;
for (i = 1; i <= NUMTHREADS; i++)
{
int fail = 0;
int result = 0;
assert(pthread_join(t[i], (void **) &result) == 0);
fail = (result != 0);
if (fail)
{
fprintf(stderr, "Thread %d: started %d: result: %d\n",
i,
threadbag[i].started,
result);
}
failed = (failed || fail);
}
assert(!failed);
assert(pop_count == NUMTHREADS);
/*
* Success.
*/
return 0;
}

View File

@ -0,0 +1,160 @@
/*
* File: cleanup3.c
*
* Test Synopsis: Test cleanup handler does not execute (when thread is
* not canceled).
*
* Test Method (Validation or Falsification):
* -
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* -
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
* pthread_testcancel, pthread_cancel, pthread_join
*
* Pass Criteria:
* - Process returns zero exit status.
*
* Fail Criteria:
* - Process returns non-zero exit status.
*/
#include "test.h"
/*
* Create NUMTHREADS threads in addition to the Main thread.
*/
enum {
NUMTHREADS = 10
};
typedef struct bag_t_ bag_t;
struct bag_t_ {
int threadnum;
int started;
/* Add more per-thread state variables here */
int count;
};
static bag_t threadbag[NUMTHREADS + 1];
static int pop_count = 0;
static void
increment_pop_count(void * arg)
{
int * c = (int *) arg;
(*c)++;
}
void *
mythread(void * arg)
{
int result = 0;
bag_t * bag = (bag_t *) arg;
assert(bag == &threadbag[bag->threadnum]);
assert(bag->started == 0);
bag->started = 1;
pthread_cleanup_push(increment_pop_count, (void *) &pop_count);
sched_yield();
pop_count--;
pthread_cleanup_pop(0);
return (void *) result;
}
int
main()
{
int failed = 0;
int i;
pthread_t t[NUMTHREADS + 1];
assert((t[0] = pthread_self()) != NULL);
for (i = 1; i <= NUMTHREADS; i++)
{
threadbag[i].started = 0;
threadbag[i].threadnum = i;
assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
}
/*
* Code to control or munipulate child threads should probably go here.
*/
Sleep(1000);
/*
* Standard check that all threads started.
*/
for (i = 1; i <= NUMTHREADS; i++)
{
if (!threadbag[i].started)
{
failed |= !threadbag[i].started;
fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
}
}
assert(!failed);
/*
* Check any results here. Set "failed" and only print output on failure.
*/
failed = 0;
for (i = 1; i <= NUMTHREADS; i++)
{
int fail = 0;
int result = 0;
assert(pthread_join(t[i], (void **) &result) == 0);
fail = (result != 0);
if (fail)
{
fprintf(stderr, "Thread %d: started %d: result: %d\n",
i,
threadbag[i].started,
result);
}
failed = (failed || fail);
}
assert(!failed);
assert(pop_count == -(NUMTHREADS));
/*
* Success.
*/
return 0;
}

View File

@ -0,0 +1,65 @@
/*
* File: condvar1.c
*
* Test Synopsis:
* - Test initialisation and destruction of a CV.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - Creates and then imediately destroys a CV. Does not
* test the CV.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - pthread_cond_init returns 0, and
* - pthread_cond_destroy returns 0.
* - Process returns zero exit status.
*
* Fail Criteria:
* - pthread_cond_init returns non-zero, or
* - pthread_cond_destroy returns non-zero.
* - Process returns non-zero exit status.
*/
#include "test.h"
static pthread_cond_t cv = NULL;
int
main()
{
assert(cv == NULL);
assert(pthread_cond_init(&cv, NULL) == 0);
assert(cv != NULL);
assert(pthread_cond_destroy(&cv) == 0);
assert(cv == NULL);
return 0;
}

View File

@ -0,0 +1,80 @@
/*
* File: condvar2.c
*
* Test Synopsis:
* - Test timed wait on a CV.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - Because the CV is never signaled, we expect the wait to time out.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - pthread_cond_timedwait returns ETIMEDOUT.
* - Process returns zero exit status.
*
* Fail Criteria:
* - pthread_cond_timedwait does not return ETIMEDOUT.
* - Process returns non-zero exit status.
*/
#include "test.h"
#include <sys/timeb.h>
pthread_cond_t cv;
pthread_mutex_t mutex;
int
main()
{
struct timespec abstime = { 0, 0 };
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
int result;
assert(pthread_cond_init(&cv, NULL) == 0);
assert(pthread_mutex_init(&mutex, NULL) == 0);
assert(pthread_mutex_lock(&mutex) == 0);
/* get current system time */
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 5;
assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == ETIMEDOUT);
assert(pthread_mutex_unlock(&mutex) == 0);
result = pthread_cond_destroy(&cv);
assert(result == 0);
return 0;
}

View File

@ -0,0 +1,107 @@
/*
* File: condvar2_1.c
*
* Test Synopsis:
* - Test timeout of multiple waits on a CV with no signal/broadcast.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - Because the CV is never signaled, we expect the waits to time out.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - pthread_cond_timedwait returns ETIMEDOUT.
* - Process returns zero exit status.
*
* Fail Criteria:
* - pthread_cond_timedwait does not return ETIMEDOUT.
* - Process returns non-zero exit status.
*/
#include "test.h"
#include <sys/timeb.h>
static pthread_cond_t cv;
static pthread_mutex_t mutex;
static struct timespec abstime = { 0, 0 };
enum {
NUMTHREADS = 60
};
void *
mythread(void * arg)
{
assert(pthread_mutex_lock(&mutex) == 0);
assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == ETIMEDOUT);
assert(pthread_mutex_unlock(&mutex) == 0);
return arg;
}
int
main()
{
int i;
pthread_t t[NUMTHREADS + 1];
int result = 0;
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
assert(pthread_cond_init(&cv, NULL) == 0);
assert(pthread_mutex_init(&mutex, NULL) == 0);
/* get current system time */
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 5;
assert(pthread_mutex_lock(&mutex) == 0);
for (i = 1; i <= NUMTHREADS; i++)
{
assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0);
}
assert(pthread_mutex_unlock(&mutex) == 0);
for (i = 1; i <= NUMTHREADS; i++)
{
assert(pthread_join(t[i], (void **) &result) == 0);
assert(result == i);
}
result = pthread_cond_destroy(&cv);
assert(result == 0);
return 0;
}

View File

@ -0,0 +1,115 @@
/*
* File: condvar3.c
*
* Test Synopsis:
* - Test basic function of a CV
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - The primary thread takes the lock before creating any threads.
* The secondary thread blocks on the lock allowing the primary
* thread to enter the cv wait state which releases the lock.
* The secondary thread then takes the lock and signals the waiting
* primary thread.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - pthread_cond_timedwait returns 0.
* - Process returns zero exit status.
*
* Fail Criteria:
* - pthread_cond_timedwait returns ETIMEDOUT.
* - Process returns non-zero exit status.
*/
#include "test.h"
#include <sys/timeb.h>
static pthread_cond_t cv;
static pthread_mutex_t mutex;
static int shared = 0;
enum {
NUMTHREADS = 2 /* Including the primary thread. */
};
void *
mythread(void * arg)
{
int result = 0;
assert(pthread_mutex_lock(&mutex) == 0);
shared++;
assert(pthread_mutex_unlock(&mutex) == 0);
if ((result = pthread_cond_signal(&cv)) != 0)
{
printf("Error = %s\n", error_string[result]);
}
assert(result == 0);
return (void *) 0;
}
int
main()
{
pthread_t t[NUMTHREADS];
struct timespec abstime = { 0, 0 };
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
assert((t[0] = pthread_self()) != NULL);
assert(pthread_cond_init(&cv, NULL) == 0);
assert(pthread_mutex_init(&mutex, NULL) == 0);
assert(pthread_mutex_lock(&mutex) == 0);
/* get current system time */
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
abstime.tv_sec += 5;
while (! (shared > 0))
assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == 0);
assert(shared > 0);
assert(pthread_mutex_unlock(&mutex) == 0);
assert(pthread_cond_destroy(&cv) == 0);
return 0;
}

View File

@ -0,0 +1,148 @@
/*
* File: condvar3_1.c
*
* Test Synopsis:
* - Test timeout of multiple waits on a CV with some signaled.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - Because some CVs are never signaled, we expect their waits to time out.
* Some are signaled, the rest time out. Pthread_cond_destroy() will fail
* unless all are accounted for, either signaled or timedout.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - pthread_cond_timedwait returns ETIMEDOUT.
* - Process returns zero exit status.
*
* Fail Criteria:
* - pthread_cond_timedwait does not return ETIMEDOUT.
* - Process returns non-zero exit status.
*/
#include "test.h"
#include <sys/timeb.h>
static pthread_cond_t cv;
static pthread_cond_t cv1;
static pthread_mutex_t mutex;
static struct timespec abstime = { 0, 0 };
static int timedout = 0;
static int signaled = 0;
static int awoken = 0;
static int waiting = 0;
enum {
NUMTHREADS = 60
};
void *
mythread(void * arg)
{
int result;
assert(pthread_mutex_lock(&mutex) == 0);
if ( ++waiting == NUMTHREADS)
assert(pthread_cond_signal(&cv1) == 0);
result = pthread_cond_timedwait(&cv, &mutex, &abstime);
if (result == ETIMEDOUT)
{
printf ("thread N %d has timed out\n", (int)arg);
timedout++;
}
else
{
printf ("thread N %d has waken up\n", (int)arg);
awoken++;
}
assert(pthread_mutex_unlock(&mutex) == 0);
return arg;
}
int
main()
{
int i;
pthread_t t[NUMTHREADS + 1];
int result = 0;
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
assert(pthread_cond_init(&cv, NULL) == 0);
assert(pthread_cond_init(&cv1, NULL) == 0);
assert(pthread_mutex_init(&mutex, NULL) == 0);
/* get current system time */
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 5;
assert(pthread_mutex_lock(&mutex) == 0);
for (i = 1; i <= NUMTHREADS; i++)
{
assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0);
}
do {
assert(pthread_cond_wait(&cv1,&mutex) == 0);
} while ( NUMTHREADS != waiting );
assert(pthread_mutex_unlock(&mutex) == 0);
for (i = NUMTHREADS/3; i <= 2*NUMTHREADS/3; i++)
{
printf ("sending signal N %d\n", signaled + 1);
assert(pthread_cond_signal(&cv) == 0);
signaled++;
}
for (i = 1; i <= NUMTHREADS; i++)
{
assert(pthread_join(t[i], (void **) &result) == 0);
assert(result == i);
}
fprintf(stderr, "awk = %d\n", awoken);
fprintf(stderr, "sig = %d\n", signaled);
fprintf(stderr, "tot = %d\n", timedout);
assert(signaled == awoken);
assert(timedout == NUMTHREADS - signaled);
result = pthread_cond_destroy(&cv);
assert(result == 0);
return 0;
}

View File

@ -0,0 +1,139 @@
/*
* File: condvar3_2.c
*
* Test Synopsis:
* - Test timeout of multiple waits on a CV with remainder broadcast awoken.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - Because some CVs are never signaled, we expect their waits to time out.
* Some time out, the rest are broadcast signaled. Pthread_cond_destroy() will fail
* unless all are accounted for, either signaled or timedout.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - pthread_cond_timedwait returns ETIMEDOUT.
* - Process returns zero exit status.
*
* Fail Criteria:
* - pthread_cond_timedwait does not return ETIMEDOUT.
* - Process returns non-zero exit status.
*/
#include "test.h"
#include <sys/timeb.h>
static pthread_cond_t cv;
static pthread_mutex_t mutex;
static struct timespec abstime = { 0, 0 };
static struct timespec abstime2 = { 0, 0 };
static int timedout = 0;
static int awoken = 0;
enum {
NUMTHREADS = 60
};
void *
mythread(void * arg)
{
int result;
assert(pthread_mutex_lock(&mutex) == 0);
abstime2.tv_sec = abstime.tv_sec;
if ((int) arg % 3 == 0)
{
abstime2.tv_sec += 2;
}
result = pthread_cond_timedwait(&cv, &mutex, &abstime2);
if (result == ETIMEDOUT)
{
timedout++;
}
else
{
awoken++;
}
assert(pthread_mutex_unlock(&mutex) == 0);
return arg;
}
int
main()
{
int i;
pthread_t t[NUMTHREADS + 1];
int result = 0;
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
assert(pthread_cond_init(&cv, NULL) == 0);
assert(pthread_mutex_init(&mutex, NULL) == 0);
/* get current system time */
ftime(&currSysTime);
abstime.tv_sec = abstime.tv_sec = currSysTime.time + 5;
abstime.tv_nsec = abstime2.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
assert(pthread_mutex_lock(&mutex) == 0);
for (i = 1; i <= NUMTHREADS; i++)
{
assert(pthread_create(&t[i], NULL, mythread, (void *) i) == 0);
}
assert(pthread_mutex_unlock(&mutex) == 0);
for (i = 1; i <= NUMTHREADS; i++)
{
assert(pthread_join(t[i], (void **) &result) == 0);
assert(result == i);
/*
* Approximately 2/3rds of the threads are expected to time out.
* Signal the remainder after some threads have woken up and exited
* and while some are still waking up after timeout.
* Also tests that redundant broadcasts don't return errors.
*/
if (awoken > NUMTHREADS/3)
{
assert(pthread_cond_broadcast(&cv) == 0);
}
}
assert(awoken == NUMTHREADS - timedout);
result = pthread_cond_destroy(&cv);
assert(result == 0);
return 0;
}

View File

@ -0,0 +1,100 @@
/*
* File: condvar3_3.c
*
* Test Synopsis:
* - Test timeouts and lost signals on a CV.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* -
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - pthread_cond_timedwait returns ETIMEDOUT.
* - Process returns zero exit status.
*
* Fail Criteria:
* - pthread_cond_timedwait does not return ETIMEDOUT.
* - Process returns non-zero exit status.
*/
/* Timur Aydin (taydin@snet.net) */
#include "test.h"
#include <sys/timeb.h>
pthread_cond_t cnd;
pthread_mutex_t mtx;
int main()
{
int rc;
struct timespec abstime = { 0, 0 };
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
assert(pthread_cond_init(&cnd, 0) == 0);
assert(pthread_mutex_init(&mtx, 0) == 0);
/* get current system time */
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 1;
/* Here pthread_cond_timedwait should time out after one second. */
assert(pthread_mutex_lock(&mtx) == 0);
assert((rc = pthread_cond_timedwait(&cnd, &mtx, &abstime)) == ETIMEDOUT);
assert(pthread_mutex_unlock(&mtx) == 0);
/* Here, the condition variable is signaled, but there are no
threads waiting on it. The signal should be lost and
the next pthread_cond_timedwait should time out too. */
assert(pthread_mutex_lock(&mtx) == 0);
assert((rc = pthread_cond_signal(&cnd)) == 0);
assert(pthread_mutex_unlock(&mtx) == 0);
assert(pthread_mutex_lock(&mtx) == 0);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 1;
assert((rc = pthread_cond_timedwait(&cnd, &mtx, &abstime)) == ETIMEDOUT);
assert(pthread_mutex_unlock(&mtx) == 0);
return 0;
}

View File

@ -0,0 +1,137 @@
/*
* File: condvar4.c
*
* Test Synopsis:
* - Test PTHREAD_COND_INITIALIZER.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - Test basic CV function but starting with a static initialised
* CV.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - pthread_cond_timedwait returns 0.
* - Process returns zero exit status.
*
* Fail Criteria:
* - pthread_cond_timedwait returns ETIMEDOUT.
* - Process returns non-zero exit status.
*/
#include "test.h"
#include <sys/timeb.h>
typedef struct cvthing_t_ cvthing_t;
struct cvthing_t_ {
pthread_cond_t notbusy;
pthread_mutex_t lock;
int shared;
};
static cvthing_t cvthing = {
PTHREAD_COND_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
0
};
enum {
NUMTHREADS = 2
};
void *
mythread(void * arg)
{
assert(pthread_mutex_lock(&cvthing.lock) == 0);
cvthing.shared++;
assert(pthread_mutex_unlock(&cvthing.lock) == 0);
assert(pthread_cond_signal(&cvthing.notbusy) == 0);
return (void *) 0;
}
int
main()
{
pthread_t t[NUMTHREADS];
struct timespec abstime = { 0, 0 };
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
cvthing.shared = 0;
assert((t[0] = pthread_self()) != NULL);
assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
assert(pthread_mutex_lock(&cvthing.lock) == 0);
assert(cvthing.lock != PTHREAD_MUTEX_INITIALIZER);
/* get current system time */
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 5;
assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == ETIMEDOUT);
assert(cvthing.notbusy != PTHREAD_COND_INITIALIZER);
assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 5;
while (! (cvthing.shared > 0))
assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
assert(cvthing.shared > 0);
assert(pthread_mutex_unlock(&cvthing.lock) == 0);
assert(pthread_mutex_destroy(&cvthing.lock) == 0);
assert(cvthing.lock == NULL);
assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
assert(cvthing.notbusy == NULL);
return 0;
}

View File

@ -0,0 +1,136 @@
/*
* File: condvar5.c
*
* Test Synopsis:
* - Test pthread_cond_broadcast.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - Test broadcast with one waiting CV.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - pthread_cond_timedwait returns 0.
* - Process returns zero exit status.
*
* Fail Criteria:
* - pthread_cond_timedwait returns ETIMEDOUT.
* - Process returns non-zero exit status.
*/
#include "test.h"
#include <sys/timeb.h>
typedef struct cvthing_t_ cvthing_t;
struct cvthing_t_ {
pthread_cond_t notbusy;
pthread_mutex_t lock;
int shared;
};
static cvthing_t cvthing = {
PTHREAD_COND_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
0
};
enum {
NUMTHREADS = 2
};
void *
mythread(void * arg)
{
assert(pthread_mutex_lock(&cvthing.lock) == 0);
cvthing.shared++;
assert(pthread_mutex_unlock(&cvthing.lock) == 0);
assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
return (void *) 0;
}
int
main()
{
pthread_t t[NUMTHREADS];
struct timespec abstime = { 0, 0 };
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
cvthing.shared = 0;
assert((t[0] = pthread_self()) != NULL);
assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
assert(pthread_mutex_lock(&cvthing.lock) == 0);
assert(cvthing.lock != PTHREAD_MUTEX_INITIALIZER);
/* get current system time */
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 5;
assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == ETIMEDOUT);
assert(cvthing.notbusy != PTHREAD_COND_INITIALIZER);
assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 5;
while (! (cvthing.shared > 0))
assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
assert(cvthing.shared > 0);
assert(pthread_mutex_unlock(&cvthing.lock) == 0);
assert(pthread_mutex_destroy(&cvthing.lock) == 0);
assert(cvthing.lock == NULL);
assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
assert(cvthing.notbusy == NULL);
return 0;
}

View File

@ -0,0 +1,209 @@
/*
* File:
*
* Test Synopsis:
* - Test pthread_cond_broadcast.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - Test broadcast with NUMTHREADS (=5) waiting CVs.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - Process returns zero exit status.
*
* Fail Criteria:
* - Process returns non-zero exit status.
*/
#include "test.h"
#include <sys/timeb.h>
/*
* Create NUMTHREADS threads in addition to the Main thread.
*/
enum {
NUMTHREADS = 5
};
typedef struct bag_t_ bag_t;
struct bag_t_ {
int threadnum;
int started;
/* Add more per-thread state variables here */
};
static bag_t threadbag[NUMTHREADS + 1];
typedef struct cvthing_t_ cvthing_t;
struct cvthing_t_ {
pthread_cond_t notbusy;
pthread_mutex_t lock;
int shared;
};
static cvthing_t cvthing = {
PTHREAD_COND_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
0
};
static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER;
static struct timespec abstime = { 0, 0 };
static int awoken;
void *
mythread(void * arg)
{
bag_t * bag = (bag_t *) arg;
assert(bag == &threadbag[bag->threadnum]);
assert(bag->started == 0);
bag->started = 1;
/* Wait for the start gun */
assert(pthread_mutex_lock(&start_flag) == 0);
assert(pthread_mutex_unlock(&start_flag) == 0);
assert(pthread_mutex_lock(&cvthing.lock) == 0);
while (! (cvthing.shared > 0))
assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
assert(cvthing.shared > 0);
awoken++;
assert(pthread_mutex_unlock(&cvthing.lock) == 0);
return (void *) 0;
}
int
main()
{
int failed = 0;
int i;
pthread_t t[NUMTHREADS + 1];
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
cvthing.shared = 0;
assert((t[0] = pthread_self()) != NULL);
assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
assert(pthread_mutex_lock(&start_flag) == 0);
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 5;
assert((t[0] = pthread_self()) != NULL);
awoken = 0;
for (i = 1; i <= NUMTHREADS; i++)
{
threadbag[i].started = 0;
threadbag[i].threadnum = i;
assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
}
/*
* Code to control or munipulate child threads should probably go here.
*/
assert(pthread_mutex_unlock(&start_flag) == 0);
/*
* Give threads time to start.
*/
Sleep(2000);
assert(pthread_mutex_lock(&cvthing.lock) == 0);
cvthing.shared++;
assert(pthread_mutex_unlock(&cvthing.lock) == 0);
assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
/*
* Give threads time to complete.
*/
Sleep(2000);
/*
* Cleanup the CV.
*/
assert(pthread_mutex_destroy(&cvthing.lock) == 0);
assert(cvthing.lock == NULL);
assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
assert(cvthing.notbusy == NULL);
/*
* Standard check that all threads started.
*/
for (i = 1; i <= NUMTHREADS; i++)
{
failed = !threadbag[i].started;
if (failed)
{
fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
}
}
assert(!failed);
/*
* Check any results here.
*/
assert(awoken == NUMTHREADS);
/*
* Success.
*/
return 0;
}

View File

@ -0,0 +1,221 @@
/*
* File: condvar8.c
*
* Test Synopsis:
* - Test multiple pthread_cond_broadcasts.
*
* Test Method (Validation or Falsification):
* - Validation
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* - Make NUMTHREADS threads wait on CV, broadcast signal them, and then repeat.
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - Process returns zero exit status.
*
* Fail Criteria:
* - Process returns non-zero exit status.
*/
#include "test.h"
#include <sys/timeb.h>
/*
* Create NUMTHREADS threads in addition to the Main thread.
*/
enum {
NUMTHREADS = 5
};
typedef struct bag_t_ bag_t;
struct bag_t_ {
int threadnum;
int started;
/* Add more per-thread state variables here */
};
static bag_t threadbag[NUMTHREADS + 1];
typedef struct cvthing_t_ cvthing_t;
struct cvthing_t_ {
pthread_cond_t notbusy;
pthread_mutex_t lock;
int shared;
};
static cvthing_t cvthing = {
PTHREAD_COND_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
0
};
static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER;
static struct timespec abstime = { 0, 0 };
static int awoken;
static void *
mythread(void * arg)
{
bag_t * bag = (bag_t *) arg;
assert(bag == &threadbag[bag->threadnum]);
assert(bag->started == 0);
bag->started = 1;
/* Wait for the start gun */
assert(pthread_mutex_lock(&start_flag) == 0);
assert(pthread_mutex_unlock(&start_flag) == 0);
assert(pthread_mutex_lock(&cvthing.lock) == 0);
pthread_cleanup_push((__cleanup_routine_type)pthread_mutex_unlock,
(void *) &cvthing.lock);
while (! (cvthing.shared > 0))
assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
pthread_cleanup_pop(0);
assert(cvthing.shared > 0);
awoken++;
assert(pthread_mutex_unlock(&cvthing.lock) == 0);
return (void *) 0;
}
int
main()
{
int failed = 0;
int i;
int first, last;
pthread_t t[NUMTHREADS + 1];
struct timeb currSysTime;
const DWORD NANOSEC_PER_MILLISEC = 1000000;
assert((t[0] = pthread_self()) != NULL);
assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
ftime(&currSysTime);
abstime.tv_sec = currSysTime.time;
abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
abstime.tv_sec += 10;
assert((t[0] = pthread_self()) != NULL);
awoken = 0;
for (first = 1, last = NUMTHREADS / 2;
first < NUMTHREADS;
first = last + 1, last = NUMTHREADS)
{
assert(pthread_mutex_lock(&start_flag) == 0);
for (i = first; i <= last; i++)
{
threadbag[i].started = 0;
threadbag[i].threadnum = i;
assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
assert(pthread_detach(t[i]) == 0);
}
/*
* Code to control or munipulate child threads should probably go here.
*/
cvthing.shared = 0;
assert(pthread_mutex_unlock(&start_flag) == 0);
/*
* Give threads time to start.
*/
Sleep(1000);
assert(pthread_mutex_lock(&cvthing.lock) == 0);
cvthing.shared++;
assert(pthread_mutex_unlock(&cvthing.lock) == 0);
assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
/*
* Give threads time to complete.
*/
Sleep(1000);
assert(awoken == (i - 1));
}
/*
* Standard check that all threads started.
*/
for (i = 1; i <= NUMTHREADS; i++)
{
failed = !threadbag[i].started;
if (failed)
{
fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
}
}
/*
* Cleanup the CV.
*/
assert(pthread_mutex_destroy(&cvthing.lock) == 0);
assert(cvthing.lock == NULL);
assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
assert(cvthing.notbusy == NULL);
assert(!failed);
/*
* Check any results here.
*/
assert(awoken == NUMTHREADS);
/*
* Success.
*/
return 0;
}

View File

@ -0,0 +1,62 @@
/*
* count1.c
*
* Description:
* Test some basic assertions about the number of threads at runtime.
*/
#include "test.h"
#if ! defined (__MINGW32__) || defined (__MSVCRT__)
#define NUMTHREADS (60)
#else
#define NUMTHREADS (59)
#endif
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t threads[NUMTHREADS];
static unsigned numThreads = 0;
void *
myfunc(void *arg)
{
pthread_mutex_lock(&lock);
numThreads++;
pthread_mutex_unlock(&lock);
Sleep(1000);
return 0;
}
int
main()
{
int i;
int maxThreads = sizeof(threads) / sizeof(pthread_t);
/*
* Spawn NUMTHREADS threads. Each thread should increment the
* numThreads variable, sleep for one second.
*/
for (i = 0; i < maxThreads; i++)
{
assert(pthread_create(&threads[i], NULL, myfunc, 0) == 0);
}
/*
* Wait for all the threads to exit.
*/
for (i = 0; i < maxThreads; i++)
{
assert(pthread_join(threads[i], NULL) == 0);
}
/*
* Check the number of threads created.
*/
assert((int) numThreads == maxThreads);
/*
* Success.
*/
return 0;
}

View File

@ -0,0 +1,34 @@
/*
* create1.c
*
* Description:
* Create a thread and check that it ran.
*
* Depends on API functions: None.
*/
#include "test.h"
static int washere = 0;
void * func(void * arg)
{
washere = 1;
return 0;
}
int
main()
{
pthread_t t;
assert(pthread_create(&t, NULL, func, NULL) == 0);
/* A dirty hack, but we cannot rely on pthread_join in this
primitive test. */
Sleep(2000);
assert(washere == 1);
return 0;
}

View File

@ -0,0 +1,74 @@
/*
* File: create2.c
*
* Test Synopsis:
* - Test that threads have a Win32 handle when started.
*
* Test Method (Validation or Falsification):
* - Statistical, not absolute (depends on sample size).
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* -
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - Process returns zero exit status.
*
* Fail Criteria:
* - Process returns non-zero exit status.
*/
#include "test.h"
const int NUMTHREADS = 10000;
static int washere = 0;
void * func(void * arg)
{
washere = 1;
return (void *) 0;
}
int
main()
{
pthread_t t;
pthread_attr_t attr;
void * result = NULL;
int i;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for (i = 0; i < NUMTHREADS; i++)
{
washere = 0;
assert(pthread_create(&t, &attr, func, NULL) == 0);
pthread_join(t, &result);
assert(washere == 1);
}
return 0;
}

View File

@ -0,0 +1,34 @@
/*
* Test for pthread_equal.
*
* Depends on functions: pthread_create().
*/
#include "test.h"
void * func(void * arg)
{
Sleep(2000);
return 0;
}
int
main()
{
pthread_t t1, t2;
assert(pthread_create(&t1, NULL, func, (void *) 1) == 0);
assert(pthread_create(&t2, NULL, func, (void *) 2) == 0);
assert(pthread_equal(t1, t2) == 0);
assert(pthread_equal(t1,t1) != 0);
/* This is a hack. We don't want to rely on pthread_join
yet if we can help it. */
Sleep(4000);
/* Success. */
return 0;
}

View File

@ -0,0 +1,18 @@
/*
* Test for pthread_exit().
*
* Depends on API functions: None.
*/
#include "test.h"
int
main(int argc, char * argv[])
{
/* A simple test first. */
pthread_exit((void *) 0);
/* Not reached */
assert(0);
return 0;
}

View File

@ -0,0 +1,30 @@
/*
* Test for pthread_exit().
*
* Depends on API functions:
* pthread_create()
* pthread_exit()
*/
#include "test.h"
void *
func(void * arg)
{
pthread_exit(arg);
/* Never reached. */
assert(0);
}
int
main(int argc, char * argv[])
{
pthread_t t;
assert(pthread_create(&t, NULL, func, (void *) NULL) == 0);
Sleep(1000);
return 0;
}

View File

@ -0,0 +1,34 @@
/*
* Test for pthread_exit().
*
* Depends on API functions: pthread_create().
*/
#include "test.h"
void *
func(void * arg)
{
pthread_exit(arg);
/* Never reached. */
assert(0);
}
int
main(int argc, char * argv[])
{
pthread_t id[4];
int i;
/* Create a few threads and then exit. */
for (i = 0; i < 4; i++)
{
assert(pthread_create(&id[i], NULL, func, (void *) i) == 0);
}
Sleep(1000);
/* Success. */
return 0;
}

View File

@ -0,0 +1,99 @@
/*
* File: inherit1.c
*
* Test Synopsis:
* - Test thread priority inheritance.
*
* Test Method (Validation or Falsification):
* -
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* -
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - Process returns zero exit status.
*
* Fail Criteria:
* - Process returns non-zero exit status.
*/
#include "test.h"
void * func(void * arg)
{
int policy;
struct sched_param param;
assert(pthread_getschedparam(pthread_self(), &policy, &param) == 0);
return (void *) param.sched_priority;
}
int
main()
{
pthread_t t;
pthread_t mainThread = pthread_self();
pthread_attr_t attr;
void * result = NULL;
struct sched_param param;
struct sched_param mainParam;
int maxPrio;
int minPrio;
int prio;
int policy;
int inheritsched = -1;
assert((maxPrio = sched_get_priority_max(SCHED_OTHER)) != -1);
assert((minPrio = sched_get_priority_min(SCHED_OTHER)) != -1);
assert(pthread_attr_init(&attr) == 0);
assert(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED) == 0);
assert(pthread_attr_getinheritsched(&attr, &inheritsched) == 0);
assert(inheritsched == PTHREAD_INHERIT_SCHED);
for (prio = minPrio; prio < maxPrio; prio++)
{
mainParam.sched_priority = prio;
/* Change the main thread priority */
assert(pthread_setschedparam(mainThread, SCHED_OTHER, &mainParam) == 0);
assert(pthread_getschedparam(mainThread, &policy, &mainParam) == 0);
assert(policy == SCHED_OTHER);
assert(mainParam.sched_priority == prio);
for (param.sched_priority = prio;
param.sched_priority <= maxPrio;
param.sched_priority++)
{
/* The new thread create should ignore this new priority */
assert(pthread_attr_setschedparam(&attr, &param) == 0);
assert(pthread_create(&t, &attr, func, NULL) == 0);
pthread_join(t, &result);
assert((int) result == mainParam.sched_priority);
}
}
return 0;
}

View File

@ -0,0 +1,40 @@
/*
* Test for pthread_join().
*
* Depends on API functions: pthread_create(), pthread_exit().
*/
#include "test.h"
void *
func(void * arg)
{
Sleep(2000);
pthread_exit(arg);
/* Never reached. */
exit(1);
}
int
main(int argc, char * argv[])
{
pthread_t id;
int result;
/* Create a single thread and wait for it to exit. */
assert(pthread_create(&id, NULL, func, (void *) 123) == 0);
assert(pthread_join(id, (void **) &result) == 0);
#if ! defined (__MINGW32__) || defined (__MSVCRT__)
assert(result == 123);
#else
# warning pthread_join not fully supported in this configuration.
assert(result == 0);
#endif
/* Success. */
return 0;
}

View File

@ -0,0 +1,51 @@
/*
* Test for pthread_join().
*
* Depends on API functions: pthread_create(), pthread_join(), pthread_exit().
*/
#include "test.h"
void *
func(void * arg)
{
int i = (int) arg;
Sleep(i * 500);
pthread_exit(arg);
/* Never reached. */
exit(1);
}
int
main(int argc, char * argv[])
{
pthread_t id[4];
int i;
int result;
/* Create a few threads and then exit. */
for (i = 0; i < 4; i++)
{
assert(pthread_create(&id[i], NULL, func, (void *) i) == 0);
}
/* Some threads will finish before they are joined, some after. */
Sleep(1000);
for (i = 0; i < 4; i++)
{
assert(pthread_join(id[i], (void **) &result) == 0);
#if ! defined (__MINGW32__) || defined (__MSVCRT__)
assert(result == i);
#else
# warning pthread_join not fully supported in this configuration.
assert(result == 0);
#endif
}
/* Success. */
return 0;
}

View File

@ -0,0 +1,41 @@
/*
* Test for pthread_join() returning return value from threads.
*
* Depends on API functions: pthread_create().
*/
#include "test.h"
void *
func(void * arg)
{
Sleep(1000);
return arg;
}
int
main(int argc, char * argv[])
{
pthread_t id[4];
int i;
int result;
/* Create a few threads and then exit. */
for (i = 0; i < 4; i++)
{
assert(pthread_create(&id[i], NULL, func, (void *) i) == 0);
}
for (i = 0; i < 4; i++)
{
assert(pthread_join(id[i], (void **) &result) == 0);
#if ! defined (__MINGW32__) || defined (__MSVCRT__)
/* CRTDLL _beginthread doesn't support return value, so
the assertion is guaranteed to fail. */
assert(result == i);
#endif
}
/* Success. */
return 0;
}

View File

@ -0,0 +1,36 @@
/*
* mutex1.c
*
* Create a simple mutex object, lock it, and then unlock it again.
* This is the simplest test of the pthread mutex family that we can do.
*
* Depends on API functions:
* pthread_mutex_init()
* pthread_mutex_lock()
* pthread_mutex_unlock()
* pthread_mutex_destroy()
*/
#include "test.h"
pthread_mutex_t mutex = NULL;
int
main()
{
assert(mutex == NULL);
assert(pthread_mutex_init(&mutex, NULL) == 0);
assert(mutex != NULL);
assert(pthread_mutex_lock(&mutex) == 0);
assert(pthread_mutex_unlock(&mutex) == 0);
assert(pthread_mutex_destroy(&mutex) == 0);
assert(mutex == NULL);
return 0;
}

View File

@ -0,0 +1,42 @@
/*
* mutex1r.c
*
* As for mutex1.c but with type set to PTHREAD_MUTEX_RECURSIVE.
*
* Create a simple mutex object, lock it, unlock it, then destroy it.
* This is the simplest test of the pthread mutex family that we can do.
*
* Depends on API functions:
* pthread_mutexattr_settype()
* pthread_mutex_init()
* pthread_mutex_destroy()
*/
#include "test.h"
pthread_mutex_t mutex = NULL;
pthread_mutexattr_t mxAttr;
int
main()
{
assert(pthread_mutexattr_init(&mxAttr) == 0);
assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0);
assert(mutex == NULL);
assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
assert(mutex != NULL);
assert(pthread_mutex_lock(&mutex) == 0);
assert(pthread_mutex_unlock(&mutex) == 0);
assert(pthread_mutex_destroy(&mutex) == 0);
assert(mutex == NULL);
return 0;
}

View File

@ -0,0 +1,34 @@
/*
* mutex2.c
*
* Declare a static mutex object, lock it,
* and then unlock it again.
*
* Depends on API functions:
* pthread_mutex_lock()
* pthread_mutex_unlock()
*/
#include "test.h"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int
main()
{
assert(mutex == PTHREAD_MUTEX_INITIALIZER);
assert(pthread_mutex_lock(&mutex) == 0);
assert(mutex != PTHREAD_MUTEX_INITIALIZER);
assert(mutex != NULL);
assert(pthread_mutex_unlock(&mutex) == 0);
assert(pthread_mutex_destroy(&mutex) == 0);
assert(mutex == NULL);
return 0;
}

View File

@ -0,0 +1,43 @@
/*
* mutex3.c
*
* Declare a static mutex object, lock it, trylock it,
* and then unlock it again.
*
* Depends on API functions:
* pthread_mutex_lock()
* pthread_mutex_trylock()
* pthread_mutex_unlock()
*/
#include "test.h"
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
static int washere = 0;
void * func(void * arg)
{
assert(pthread_mutex_trylock(&mutex1) == EBUSY);
washere = 1;
return 0;
}
int
main()
{
pthread_t t;
assert(pthread_mutex_lock(&mutex1) == 0);
assert(pthread_create(&t, NULL, func, NULL) == 0);
assert(pthread_join(t, NULL) == 0);
assert(pthread_mutex_unlock(&mutex1) == 0);
assert(washere == 1);
return 0;
}

View File

@ -0,0 +1,68 @@
/*
* mutex6r.c
*
* Tests PTHREAD_MUTEX_RECURSIVE mutex type.
* Thread locks mutex twice (recursive lock).
* Both locks and unlocks should succeed.
*
* Depends on API functions:
* pthread_create()
* pthread_join()
* pthread_mutexattr_init()
* pthread_mutexattr_destroy()
* pthread_mutexattr_settype()
* pthread_mutexattr_gettype()
* pthread_mutex_init()
* pthread_mutex_destroy()
* pthread_mutex_lock()
* pthread_mutex_unlock()
*/
#include "test.h"
static int lockCount = 0;
static pthread_mutex_t mutex;
static pthread_mutexattr_t mxAttr;
void * locker(void * arg)
{
assert(pthread_mutex_lock(&mutex) == 0);
lockCount++;
assert(pthread_mutex_lock(&mutex) == 0);
lockCount++;
assert(pthread_mutex_unlock(&mutex) == 0);
assert(pthread_mutex_unlock(&mutex) == 0);
return (void *) 555;
}
int
main()
{
pthread_t t;
int result = 0;
int mxType = -1;
assert(pthread_mutexattr_init(&mxAttr) == 0);
assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0);
assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0);
assert(mxType == PTHREAD_MUTEX_RECURSIVE);
assert(pthread_mutex_init(&mutex, &mxAttr) == 0);
assert(pthread_create(&t, NULL, locker, NULL) == 0);
assert(pthread_join(t, (void **) &result) == 0);
assert(result == 555);
assert(lockCount == 2);
assert(pthread_mutex_destroy(&mutex) == 0);
assert(pthread_mutexattr_destroy(&mxAttr) == 0);
exit(0);
/* Never reached */
return 0;
}

View File

@ -0,0 +1,45 @@
/*
* once1.c
*
* Create a static pthread_once and test that it calls myfunc once.
*
* Depends on API functions:
* pthread_once()
* pthread_create()
*/
#include "test.h"
pthread_once_t once = PTHREAD_ONCE_INIT;
static int washere = 0;
void
myfunc(void)
{
washere++;
}
void *
mythread(void * arg)
{
assert(pthread_once(&once, myfunc) == 0);
return 0;
}
int
main()
{
pthread_t t1, t2;
assert(pthread_create(&t1, NULL, mythread, NULL) == 0);
assert(pthread_create(&t2, NULL, mythread, NULL) == 0);
Sleep(2000);
assert(washere == 1);
return 0;
}

View File

@ -0,0 +1,78 @@
/*
* File: priority1.c
*
* Test Synopsis:
* - Test thread priority explicit setting using thread attribute.
*
* Test Method (Validation or Falsification):
* -
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* -
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - Process returns zero exit status.
*
* Fail Criteria:
* - Process returns non-zero exit status.
*/
#include "test.h"
void * func(void * arg)
{
int policy;
struct sched_param param;
assert(pthread_getschedparam(pthread_self(), &policy, &param) == 0);
assert(policy == SCHED_OTHER);
return (void *) param.sched_priority;
}
int
main()
{
pthread_t t;
pthread_attr_t attr;
void * result = NULL;
struct sched_param param;
int maxPrio = sched_get_priority_max(SCHED_OTHER);
int minPrio = sched_get_priority_min(SCHED_OTHER);
assert(pthread_attr_init(&attr) == 0);
assert(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0);
for (param.sched_priority = minPrio;
param.sched_priority <= maxPrio;
param.sched_priority++)
{
assert(pthread_attr_setschedparam(&attr, &param) == 0);
assert(pthread_create(&t, &attr, func, NULL) == 0);
pthread_join(t, &result);
assert((int) result == param.sched_priority);
}
return 0;
}

View File

@ -0,0 +1,80 @@
/*
* File: priority2.c
*
* Test Synopsis:
* - Test thread priority setting after creation.
*
* Test Method (Validation or Falsification):
* -
*
* Requirements Tested:
* -
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Description:
* -
*
* Environment:
* -
*
* Input:
* - None.
*
* Output:
* - File name, Line number, and failed expression on failure.
* - No output on success.
*
* Assumptions:
* -
*
* Pass Criteria:
* - Process returns zero exit status.
*
* Fail Criteria:
* - Process returns non-zero exit status.
*/
#include "test.h"
pthread_mutex_t startMx = PTHREAD_MUTEX_INITIALIZER;
void * func(void * arg)
{
int policy;
struct sched_param param;
assert(pthread_mutex_lock(&startMx) == 0);
assert(pthread_getschedparam(pthread_self(), &policy, &param) == 0);
assert(pthread_mutex_unlock(&startMx) == 0);
assert(policy == SCHED_OTHER);
return (void *) param.sched_priority;
}
int
main()
{
pthread_t t;
void * result = NULL;
struct sched_param param;
int maxPrio = sched_get_priority_max(SCHED_OTHER);
int minPrio = sched_get_priority_min(SCHED_OTHER);
for (param.sched_priority = minPrio;
param.sched_priority <= maxPrio;
param.sched_priority++)
{
assert(pthread_mutex_lock(&startMx) == 0);
assert(pthread_create(&t, NULL, func, NULL) == 0);
assert(pthread_setschedparam(t, SCHED_OTHER, &param) == 0);
assert(pthread_mutex_unlock(&startMx) == 0);
pthread_join(t, &result);
assert((int) result == param.sched_priority);
}
return 0;
}

View File

@ -0,0 +1,26 @@
/*
* self1.c
*
* Test for pthread_self().
*
* Depends on API functions:
* pthread_self()
*
* Implicitly depends on:
* pthread_getspecific()
* pthread_setspecific()
*/
#include "test.h"
int
main(int argc, char * argv[])
{
/*
* This should always succeed unless the system has no
* resources (memory) left.
*/
assert(pthread_self() != NULL);
return 0;
}

View File

@ -0,0 +1,46 @@
/*
* self2.c
*
* Test for pthread_self().
*
* Depends on API functions:
* pthread_create()
* pthread_self()
*
* Implicitly depends on:
* pthread_getspecific()
* pthread_setspecific()
*/
#include "test.h"
#include <string.h>
static pthread_t me;
void *
entry(void * arg)
{
me = pthread_self();
return arg;
}
int
main()
{
pthread_t t;
assert(pthread_create(&t, NULL, entry, NULL) == 0);
Sleep(2000);
/*
* Not much more we can do here but bytewise compare t with
* what pthread_self returned.
*/
assert(t == me);
assert(memcmp((const void *) t, (const void *) me, sizeof t) == 0);
/* Success. */
return 0;
}

View File

@ -0,0 +1,99 @@
/*
* test.h
*
* Useful definitions and declarations for tests.
*/
#ifndef _PTHREAD_TEST_H_
#define _PTHREAD_TEST_H_
#include "pthread.h"
#include "sched.h"
#include "semaphore.h"
#include <stdio.h>
#include <windows.h>
#include <errno.h>
/* #define assert(x) do { fprint (stderr, "assertion failed\n"); exit(1) } while (0) */
char * error_string[] = {
"ZERO_or_EOK",
"EPERM",
"ENOFILE_or_ENOENT",
"ESRCH",
"EINTR",
"EIO",
"ENXIO",
"E2BIG",
"ENOEXEC",
"EBADF",
"ECHILD",
"EAGAIN",
"ENOMEM",
"EACCES",
"EFAULT",
"UNKNOWN_15",
"EBUSY",
"EEXIST",
"EXDEV",
"ENODEV",
"ENOTDIR",
"EISDIR",
"EINVAL",
"ENFILE",
"EMFILE",
"ENOTTY",
"UNKNOWN_26",
"EFBIG",
"ENOSPC",
"ESPIPE",
"EROFS",
"EMLINK",
"EPIPE",
"EDOM",
"ERANGE",
"UNKNOWN_35",
"EDEADLOCK_or_EDEADLK",
"UNKNOWN_37",
"ENAMETOOLONG",
"ENOLCK",
"ENOSYS",
"ENOTEMPTY",
"EILSEQ",
};
/*
* The Mingw32 assert macro calls the CRTDLL _assert function
* which pops up a dialog. We want to run in batch mode so
* we define our own assert macro.
*/
#ifdef assert
# undef assert
#endif
#ifdef NDEBUG
# define assert(e) ((void)0)
#else /* NDEBUG */
#ifndef ASSERT_TRACE
# define ASSERT_TRACE 0
#else
# undef ASSERT_TRACE
# define ASSERT_TRACE 1
#endif
# define assert(e) \
((e) ? ((ASSERT_TRACE) ? fprintf(stderr, \
"Assertion succeeded: (%s), file %s, line %d\n", \
#e, __FILE__, (int) __LINE__), \
fflush(stderr) : \
0) : \
(fprintf(stderr, "Assertion failed: (%s), file %s, line %d\n", \
#e, __FILE__, (int) __LINE__), exit(1), 0))
#endif /* NDEBUG */
#endif

View File

@ -0,0 +1,170 @@
/*
* tsd1.c
*
* Test Thread Specific Data (TSD) key creation and destruction.
*
* Description:
* -
*
* Test Method (validation or falsification):
* - validation
*
* Requirements Tested:
* - keys are created for each existing thread including the main thread
* - keys are created for newly created threads
* - keys are thread specific
* - destroy routine is called on each thread exit including the main thread
*
* Features Tested:
* -
*
* Cases Tested:
* -
*
* Environment:
* -
*
* Input:
* - none
*
* Output:
* - text to stdout
*
* Assumptions:
* - already validated: pthread_create()
* pthread_once()
* - main thread also has a POSIX thread identity
*
* Pass Criteria:
* - stdout matches file reference/tsd1.out
*
* Fail Criteria:
* - fails to match file reference/tsd1.out
* - output identifies failed component
*/
#include <sched.h>
#include "test.h"
static pthread_key_t key = NULL;
static int accesscount[10];
static int thread_set[10];
static int thread_destroyed[10];
static void
destroy_key(void * arg)
{
int * j = (int *) arg;
(*j)++;
assert(*j == 2);
thread_destroyed[j - accesscount] = 1;
}
static void
setkey(void * arg)
{
int * j = (int *) arg;
thread_set[j - accesscount] = 1;
assert(*j == 0);
assert(pthread_getspecific(key) == NULL);
assert(pthread_setspecific(key, arg) == 0);
assert(pthread_getspecific(key) == arg);
(*j)++;
assert(*j == 1);
}
static void *
mythread(void * arg)
{
while (key == NULL)
{
sched_yield();
}
setkey(arg);
return 0;
/* Exiting the thread will call the key destructor. */
}
int
main()
{
int i;
int fail = 0;
pthread_t thread[10];
for (i = 1; i < 5; i++)
{
accesscount[i] = thread_set[i] = thread_destroyed[i] = 0;
assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0);
}
Sleep(2000);
/*
* Here we test that existing threads will get a key created
* for them.
*/
assert(pthread_key_create(&key, destroy_key) == 0);
/*
* Test main thread key.
*/
accesscount[0] = 0;
setkey((void *) &accesscount[0]);
/*
* Here we test that new threads will get a key created
* for them.
*/
for (i = 5; i < 10; i++)
{
accesscount[i] = thread_set[i] = thread_destroyed[i] = 0;
assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0);
}
/*
* Wait for all threads to complete.
*/
for (i = 1; i < 10; i++)
{
int result = 0;
assert(pthread_join(thread[i], (void **) &result) == 0);
}
assert(pthread_key_delete(key) == 0);
for (i = 1; i < 10; i++)
{
/*
* The counter is incremented once when the key is set to
* a value, and again when the key is destroyed. If the key
* doesn't get set for some reason then it will still be
* NULL and the destroy function will not be called, and
* hence accesscount will not equal 2.
*/
if (accesscount[i] != 2)
{
fail++;
fprintf(stderr, "Thread %d key, set = %d, destroyed = %d\n",
i, thread_set[i], thread_destroyed[i]);
}
}
fflush(stderr);
return (fail);
}