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.
		
			
				
	
	
		
			171 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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);
 | 
						|
}
 |