|
Packit |
fe9d6e |
/*
|
|
Packit |
fe9d6e |
* Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P.
|
|
Packit |
fe9d6e |
*
|
|
Packit |
fe9d6e |
* This file is covered by the GNU general public license, version 2.
|
|
Packit |
fe9d6e |
* see COPYING for details.
|
|
Packit |
fe9d6e |
*/
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#if defined(_MSC_VER) || \
|
|
Packit |
fe9d6e |
defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) || \
|
|
Packit |
fe9d6e |
defined(_WIN32_WINCE)
|
|
Packit |
fe9d6e |
# define USE_WINTHREADS
|
|
Packit |
fe9d6e |
#elif defined(__vxworks)
|
|
Packit |
fe9d6e |
# define USE_VXTHREADS
|
|
Packit |
fe9d6e |
#else
|
|
Packit |
fe9d6e |
# define USE_PTHREADS
|
|
Packit |
fe9d6e |
#endif
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#include <stdlib.h>
|
|
Packit |
fe9d6e |
#include <stdio.h>
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#ifdef USE_PTHREADS
|
|
Packit |
fe9d6e |
# include <pthread.h>
|
|
Packit |
fe9d6e |
#endif
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#ifdef USE_VXTHREADS
|
|
Packit |
fe9d6e |
# include <vxworks.h>
|
|
Packit |
fe9d6e |
# include <taskLib.h>
|
|
Packit |
fe9d6e |
#endif
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#ifdef USE_WINTHREADS
|
|
Packit |
fe9d6e |
# include <windows.h>
|
|
Packit |
fe9d6e |
#endif
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#include "atomic_ops.h"
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#if !defined(AO_ATOMIC_OPS_H) && !defined(CPPCHECK)
|
|
Packit |
fe9d6e |
# error Wrong atomic_ops.h included.
|
|
Packit |
fe9d6e |
#endif
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(AO_HAVE_abort)
|
|
Packit |
fe9d6e |
# define abort() _exit(-1) /* there is no abort() in WinCE */
|
|
Packit |
fe9d6e |
#endif
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#ifndef AO_PTRDIFF_T
|
|
Packit |
fe9d6e |
# define AO_PTRDIFF_T ptrdiff_t
|
|
Packit |
fe9d6e |
#endif
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#ifndef MAX_NTHREADS
|
|
Packit |
fe9d6e |
# define MAX_NTHREADS 100
|
|
Packit |
fe9d6e |
#endif
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
typedef void * (* thr_func)(void *);
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
typedef int (* test_func)(void); /* Returns != 0 on success */
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name);
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#ifdef USE_PTHREADS
|
|
Packit |
fe9d6e |
void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
pthread_attr_t attr;
|
|
Packit |
fe9d6e |
pthread_t thr[MAX_NTHREADS];
|
|
Packit |
fe9d6e |
int i;
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
printf("Testing %s\n", name);
|
|
Packit |
fe9d6e |
if (nthreads > MAX_NTHREADS)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "run_parallel: requested too many threads\n");
|
|
Packit |
fe9d6e |
abort();
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
# ifdef _HPUX_SOURCE
|
|
Packit |
fe9d6e |
/* Default stack size is too small, especially with the 64 bit ABI */
|
|
Packit |
fe9d6e |
/* Increase it. */
|
|
Packit |
fe9d6e |
if (pthread_default_stacksize_np(1024*1024, 0) != 0)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "pthread_default_stacksize_np failed. "
|
|
Packit |
fe9d6e |
"OK after first call.\n");
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
# endif
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
pthread_attr_init(&attr);
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
for (i = 0; i < nthreads; ++i)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
int code = pthread_create(thr + i, &attr, f1, (void *)(long)i);
|
|
Packit |
fe9d6e |
if (code != 0)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "pthread_create returned %d, thread %d\n", code, i);
|
|
Packit |
fe9d6e |
abort();
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
for (i = 0; i < nthreads; ++i)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
int code = pthread_join(thr[i], NULL);
|
|
Packit |
fe9d6e |
if (code != 0)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "pthread_join returned %d, thread %d\n", code, i);
|
|
Packit |
fe9d6e |
abort();
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
if (t())
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
printf("Succeeded\n");
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
else
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "Failed\n");
|
|
Packit |
fe9d6e |
abort();
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
return 0;
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
#endif /* USE_PTHREADS */
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#ifdef USE_VXTHREADS
|
|
Packit |
fe9d6e |
void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
int thr[MAX_NTHREADS];
|
|
Packit |
fe9d6e |
int i;
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
printf("Testing %s\n", name);
|
|
Packit |
fe9d6e |
if (nthreads > MAX_NTHREADS)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "run_parallel: requested too many threads\n");
|
|
Packit |
fe9d6e |
taskSuspend(0);
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
for (i = 0; i < nthreads; ++i)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
thr[i] = taskSpawn((char*) name, 180, 0, 32768, (FUNCPTR) f1, i,
|
|
Packit |
fe9d6e |
1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
Packit |
fe9d6e |
if (thr[i] == ERROR)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "taskSpawn failed with %d, thread %d\n",
|
|
Packit |
fe9d6e |
errno, i);
|
|
Packit |
fe9d6e |
taskSuspend(0);
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
for (i = 0; i < nthreads; ++i)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
while (taskIdVerify(thr[i]) == OK)
|
|
Packit |
fe9d6e |
taskDelay(60);
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
if (t())
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
printf("Succeeded\n");
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
else
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "Failed\n");
|
|
Packit |
fe9d6e |
taskSuspend(0);
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
return 0;
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
#endif /* USE_VXTHREADS */
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
#ifdef USE_WINTHREADS
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
struct tramp_args {
|
|
Packit |
fe9d6e |
thr_func fn;
|
|
Packit |
fe9d6e |
long arg;
|
|
Packit |
fe9d6e |
};
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
DWORD WINAPI tramp(LPVOID param)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
struct tramp_args *args = (struct tramp_args *)param;
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
return (DWORD)(AO_PTRDIFF_T)(*args->fn)((LPVOID)(AO_PTRDIFF_T)args->arg);
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
HANDLE thr[MAX_NTHREADS];
|
|
Packit |
fe9d6e |
struct tramp_args args[MAX_NTHREADS];
|
|
Packit |
fe9d6e |
int i;
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
printf("Testing %s\n", name);
|
|
Packit |
fe9d6e |
if (nthreads > MAX_NTHREADS)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "run_parallel: requested too many threads\n");
|
|
Packit |
fe9d6e |
abort();
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
|
|
Packit |
fe9d6e |
for (i = 0; i < nthreads; ++i)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
args[i].fn = f1;
|
|
Packit |
fe9d6e |
args[i].arg = i;
|
|
Packit |
fe9d6e |
if ((thr[i] = CreateThread(NULL, 0, tramp, (LPVOID)(args+i), 0, NULL))
|
|
Packit |
fe9d6e |
== NULL)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "CreateThread failed with %lu, thread %d\n",
|
|
Packit |
fe9d6e |
(unsigned long)GetLastError(), i);
|
|
Packit |
fe9d6e |
abort();
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
for (i = 0; i < nthreads; ++i)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
DWORD code = WaitForSingleObject(thr[i], INFINITE);
|
|
Packit |
fe9d6e |
if (code != WAIT_OBJECT_0)
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "WaitForSingleObject returned %lu, thread %d\n",
|
|
Packit |
fe9d6e |
(unsigned long)code, i);
|
|
Packit |
fe9d6e |
abort();
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
if (t())
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
printf("Succeeded\n");
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
else
|
|
Packit |
fe9d6e |
{
|
|
Packit |
fe9d6e |
fprintf(stderr, "Failed\n");
|
|
Packit |
fe9d6e |
abort();
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
return 0;
|
|
Packit |
fe9d6e |
}
|
|
Packit |
fe9d6e |
#endif /* USE_WINTHREADS */
|