* 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:
parent
f38ac9b70c
commit
4800c7477b
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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, ¶m) == 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, ¶m) == 0);
|
||||
assert(pthread_create(&t, &attr, func, NULL) == 0);
|
||||
pthread_join(t, &result);
|
||||
assert((int) result == mainParam.sched_priority);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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, ¶m) == 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, ¶m) == 0);
|
||||
assert(pthread_create(&t, &attr, func, NULL) == 0);
|
||||
pthread_join(t, &result);
|
||||
assert((int) result == param.sched_priority);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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, ¶m) == 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, ¶m) == 0);
|
||||
assert(pthread_mutex_unlock(&startMx) == 0);
|
||||
pthread_join(t, &result);
|
||||
assert((int) result == param.sched_priority);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue