diff options
| author | rpj <rpj> | 2005-04-15 14:34:27 +0000 | 
|---|---|---|
| committer | rpj <rpj> | 2005-04-15 14:34:27 +0000 | 
| commit | 4a9c6d6d1fec17d8ea61ef0dd99afe00eb36cfc2 (patch) | |
| tree | 45e2df5677813bbead254a7056412a63cad3db05 /tests | |
| parent | e1fba251064eecf4cdfd63723aadb5df9174ddfe (diff) | |
''
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/once4.c | 191 | 
1 files changed, 191 insertions, 0 deletions
| diff --git a/tests/once4.c b/tests/once4.c new file mode 100644 index 0000000..69e9384 --- /dev/null +++ b/tests/once4.c @@ -0,0 +1,191 @@ +/*
 + * once4.c
 + *
 + *
 + * --------------------------------------------------------------------------
 + *
 + *      Pthreads-win32 - POSIX Threads Library for Win32
 + *      Copyright(C) 1998 John E. Bossom
 + *      Copyright(C) 1999,2005 Pthreads-win32 contributors
 + * 
 + *      Contact Email: rpj@callisto.canberra.edu.au
 + * 
 + *      The current list of contributors is contained
 + *      in the file CONTRIBUTORS included with the source
 + *      code distribution. The list can also be seen at the
 + *      following World Wide Web location:
 + *      http://sources.redhat.com/pthreads-win32/contributors.html
 + * 
 + *      This library is free software; you can redistribute it and/or
 + *      modify it under the terms of the GNU Lesser General Public
 + *      License as published by the Free Software Foundation; either
 + *      version 2 of the License, or (at your option) any later version.
 + * 
 + *      This library is distributed in the hope that it will be useful,
 + *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + *      Lesser General Public License for more details.
 + * 
 + *      You should have received a copy of the GNU Lesser General Public
 + *      License along with this library in the file COPYING.LIB;
 + *      if not, write to the Free Software Foundation, Inc.,
 + *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 + *
 + * --------------------------------------------------------------------------
 + *
 + * Create several pthread_once objects and channel several threads
 + * through each. Make the init_routine cancelable and cancel them
 + * waiters waiting. Vary the priorities.
 + *
 + * Depends on API functions:
 + *	pthread_once()
 + *	pthread_create()
 + *      pthread_testcancel()
 + *      pthread_cancel()
 + *      pthread_once()
 + */
 +
 +#include "test.h"
 +
 +#define NUM_THREADS 100 /* Targeting each once control */
 +#define NUM_ONCE    10
 +
 +pthread_once_t o = PTHREAD_ONCE_INIT;
 +pthread_once_t once[NUM_ONCE];
 +
 +typedef struct {
 +  int i;
 +  CRITICAL_SECTION cs;
 +} sharedInt_t;
 +
 +static sharedInt_t numOnce = {0, {0}};
 +static sharedInt_t numThreads = {0, {0}};
 +
 +typedef struct {
 +  int threadnum;
 +  int oncenum;
 +  int myPrio;
 +  HANDLE w32Thread;
 +} bag_t;
 +
 +static bag_t threadbag[NUM_THREADS][NUM_ONCE];
 +
 +CRITICAL_SECTION print_lock;
 +
 +void
 +mycleanupfunc(void * arg)
 +{
 +  bag_t * bag = (bag_t *) arg;
 +  EnterCriticalSection(&print_lock);
 +  /*      once thrd  prio error */
 +  printf("%4d %4d %4d %4d\n",
 +	 bag->oncenum,
 +	 bag->threadnum,
 +	 bag->myPrio,
 +	 bag->myPrio - GetThreadPriority(bag->w32Thread));
 +  LeaveCriticalSection(&print_lock);
 +}
 +
 +void
 +myinitfunc(void)
 +{
 +  EnterCriticalSection(&numOnce.cs);
 +  numOnce.i++;
 +  LeaveCriticalSection(&numOnce.cs);
 +  /* Simulate slow once routine so that following threads pile up behind it */
 +  Sleep(10);
 +  /* test for cancelation late so we're sure to have waiters. */
 +  pthread_testcancel();
 +}
 +
 +void *
 +mythread(void * arg)
 +{
 +  bag_t * bag = (bag_t *) arg;
 +  struct sched_param param;
 +
 +  /*
 +   * Cancel every thread. These threads are deferred cancelable only, so
 +   * only the thread performing the init_routine will see it (there are
 +   * no other cancelation points here). The result will be that every thread
 +   * eventually cancels only when it becomes the new initter.
 +   */
 +  pthread_t self = pthread_self();
 +  bag->w32Thread = pthread_getw32threadhandle_np(self);
 +  /*
 +   * Set priority between -2 and 2 inclusive.
 +   */
 +  bag->myPrio = (bag->threadnum % 5) - 2;
 +  param.sched_priority = bag->myPrio;
 +  pthread_setschedparam(self, SCHED_OTHER, ¶m);
 +
 +  /* Trigger a cancellation at the next cancellation point in this thread */
 +  pthread_cancel(self);
 +#if 0
 +  pthread_cleanup_push(mycleanupfunc, arg);
 +  assert(pthread_once(&once[bag->oncenum], myinitfunc) == 0);
 +  pthread_cleanup_pop(1);
 +#else
 +  assert(pthread_once(&once[bag->oncenum], myinitfunc) == 0);
 +#endif
 +  EnterCriticalSection(&numThreads.cs);
 +  numThreads.i++;
 +  LeaveCriticalSection(&numThreads.cs);
 +  return 0;
 +}
 +
 +int
 +main()
 +{
 +  pthread_t t[NUM_THREADS][NUM_ONCE];
 +  int i, j;
 +  
 +  InitializeCriticalSection(&print_lock);
 +  InitializeCriticalSection(&numThreads.cs);
 +  InitializeCriticalSection(&numOnce.cs);
 +
 +#if 0
 +  /*       once thrd  prio change */
 +  printf("once thrd  prio  error\n");
 +#endif
 +
 +  /*
 +   * Set the priority class to realtime - otherwise normal
 +   * Windows random priority boosting will obscure any problems.
 +   */
 +  SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
 +  /* Set main thread to lower prio than threads */
 +  SetThreadPriority(GetCurrentThread(), -2);
 +
 +  for (j = 0; j < NUM_ONCE; j++)
 +    {
 +      once[j] = o;
 +
 +      for (i = 0; i < NUM_THREADS; i++)
 +        {
 +	  bag_t * bag = &threadbag[i][j];
 +	  bag->threadnum = i;
 +	  bag->oncenum = j;
 +          assert(pthread_create(&t[i][j], NULL, mythread, (void *) bag) == 0);
 +        }
 +    }
 +
 +  for (j = 0; j < NUM_ONCE; j++)
 +    for (i = 0; i < NUM_THREADS; i++)
 +      if (pthread_join(t[i][j], NULL) != 0)
 +        printf("Join failed for [thread,once] = [%d,%d]\n", i, j);
 +
 +  /*
 +   * All threads will cancel, none will return normally from
 +   * pthread_once and so numThreads should never be incremented. However,
 +   * numOnce should be incremented by every thread (NUM_THREADS*NUM_ONCE).
 +   */
 +  assert(numOnce.i == NUM_ONCE * NUM_THREADS);
 +  assert(numThreads.i == 0);
 +
 +  DeleteCriticalSection(&numOnce.cs);
 +  DeleteCriticalSection(&numThreads.cs);
 +  DeleteCriticalSection(&print_lock);
 +
 +  return 0;
 +}
 | 
