|
Packit |
0848f5 |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* (C) 2008 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#ifndef OPA_TEST_NAIVE
|
|
Packit |
0848f5 |
# include "opa_primitives.h"
|
|
Packit |
0848f5 |
#else /* OPA_TEST_NAIVE */
|
|
Packit |
0848f5 |
# define OPA_PRIMITIVES_H_INCLUDED
|
|
Packit |
0848f5 |
# include "opa_config.h"
|
|
Packit |
0848f5 |
# include "opa_util.h"
|
|
Packit |
0848f5 |
# ifndef _opa_inline
|
|
Packit |
0848f5 |
# define _opa_inline inline
|
|
Packit |
0848f5 |
# endif
|
|
Packit |
0848f5 |
#endif /* OPA_TEST_NAIVE */
|
|
Packit |
0848f5 |
#include <assert.h>
|
|
Packit |
0848f5 |
#include <stdio.h>
|
|
Packit |
0848f5 |
#include <stdlib.h>
|
|
Packit |
0848f5 |
#include <limits.h>
|
|
Packit |
0848f5 |
#include <time.h>
|
|
Packit |
0848f5 |
#if defined(OPA_HAVE_PTHREAD_H)
|
|
Packit |
0848f5 |
# include <pthread.h>
|
|
Packit |
0848f5 |
#endif /* HAVE_PTHREAD_H */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Define the macro to use for yielding the current thread (to others) */
|
|
Packit |
0848f5 |
#if defined(OPA_HAVE_PTHREAD_YIELD)
|
|
Packit |
0848f5 |
# define OPA_TEST_YIELD() pthread_yield()
|
|
Packit |
0848f5 |
#elif defined(OPA_HAVE_SCHED_YIELD)
|
|
Packit |
0848f5 |
# include <sched.h>
|
|
Packit |
0848f5 |
# define OPA_TEST_YIELD() (void) sched_yield()
|
|
Packit |
0848f5 |
#else
|
|
Packit |
0848f5 |
# define OPA_TEST_YIELD() (void) 0
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Naive redefinition of OPA functions as simple C operations. These should
|
|
Packit |
0848f5 |
* pass all the "simple" tests, but fail on the threaded tests (with >1 thread),
|
|
Packit |
0848f5 |
* unless the tested operation is natively atomic.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
#ifdef OPA_TEST_NAIVE
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define OPA_UNIVERSAL_PRIMITIVE OPA_CAS
|
|
Packit |
0848f5 |
#define OPA_LL_SC_SUPPORTED 1
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
typedef volatile int OPA_int_t;
|
|
Packit |
0848f5 |
typedef void * volatile OPA_ptr_t;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define OPA_load_int(A) (*(A))
|
|
Packit |
0848f5 |
#define OPA_store_int(A, B) ((void) (*(A) = (B)))
|
|
Packit |
0848f5 |
#define OPA_load_ptr(A) (*(A))
|
|
Packit |
0848f5 |
#define OPA_store_ptr(A, B) ((void) (*(A) = (B)))
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define OPA_add_int(A, B) ((void) (*(A) += (B)))
|
|
Packit |
0848f5 |
#define OPA_incr_int(A) ((void) (++(*(A))))
|
|
Packit |
0848f5 |
#define OPA_decr_int(A) ((void) (--(*(A))))
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define OPA_decr_and_test_int(A) (0 == --(*(A)))
|
|
Packit |
0848f5 |
static _opa_inline int OPA_fetch_and_add_int(OPA_int_t *ptr, int val)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int prev = *ptr;
|
|
Packit |
0848f5 |
*ptr += val;
|
|
Packit |
0848f5 |
return prev;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
#define OPA_fetch_and_incr_int(A) ((*(A))++)
|
|
Packit |
0848f5 |
#define OPA_fetch_and_decr_int(A) ((*(A))--)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define OPA_cas_ptr(A, B, C) (*(A) == (B) ? (*(A) = (C), (B)) : *(A))
|
|
Packit |
0848f5 |
#define OPA_cas_int(A, B, C) (*(A) == (B) ? (*(A) = (C), (B)) : *(A))
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
static _opa_inline void *OPA_swap_ptr(OPA_ptr_t *ptr, void *val)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
void *prev;
|
|
Packit |
0848f5 |
prev = *ptr;
|
|
Packit |
0848f5 |
*ptr = val;
|
|
Packit |
0848f5 |
return prev;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
static _opa_inline int OPA_swap_int(OPA_int_t *ptr, int val)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int prev;
|
|
Packit |
0848f5 |
prev = *ptr;
|
|
Packit |
0848f5 |
*ptr = val;
|
|
Packit |
0848f5 |
return prev;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define OPA_write_barrier() ((void) 0)
|
|
Packit |
0848f5 |
#define OPA_read_barrier() ((void) 0)
|
|
Packit |
0848f5 |
#define OPA_read_write_barrier() ((void) 0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* For LL/SC only use load/store. This is more naive than the above
|
|
Packit |
0848f5 |
* implementation for CAS */
|
|
Packit |
0848f5 |
#define OPA_LL_int OPA_load_int
|
|
Packit |
0848f5 |
#define OPA_SC_int(A, B) (OPA_store_int(A, B), 1)
|
|
Packit |
0848f5 |
#define OPA_LL_ptr OPA_load_ptr
|
|
Packit |
0848f5 |
#define OPA_SC_ptr(A, B) (OPA_store_ptr(A, B), 1)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#if defined(OPA_HAVE_SCHED_YIELD)
|
|
Packit |
0848f5 |
# include <sched.h>
|
|
Packit |
0848f5 |
# define OPA_busy_wait() sched_yield()
|
|
Packit |
0848f5 |
#else
|
|
Packit |
0848f5 |
# define OPA_busy_wait() do { } while (0)
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#endif /* OPA_TEST_NAIVE */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Cache line padding. See note in opa_queue.h.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
#define OPA_TEST_CACHELINE_PADDING 128
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Print the current location on the standard output stream.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
#define AT() printf (" at %s:%d in %s()...\n", \
|
|
Packit |
0848f5 |
__FILE__, __LINE__, __FUNCTION__)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* The name of the test is printed by saying TESTING("something") which will
|
|
Packit |
0848f5 |
* result in the string `Testing something' being flushed to standard output.
|
|
Packit |
0848f5 |
* If a test passes, fails, or is skipped then the PASSED(), FAILED(), or
|
|
Packit |
0848f5 |
* SKIPPED() macro should be called. After HFAILED() or SKIPPED() the caller
|
|
Packit |
0848f5 |
* should print additional information to stdout indented by at least four
|
|
Packit |
0848f5 |
* spaces.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
#define TESTING(WHAT, NTHREADS) \
|
|
Packit |
0848f5 |
do { \
|
|
Packit |
0848f5 |
if(NTHREADS) { \
|
|
Packit |
0848f5 |
int nwritten_chars; \
|
|
Packit |
0848f5 |
printf("Testing %s with %d thread%s %n", \
|
|
Packit |
0848f5 |
WHAT, \
|
|
Packit |
0848f5 |
(int) NTHREADS, \
|
|
Packit |
0848f5 |
(NTHREADS) > 1 ? "s" : "", \
|
|
Packit |
0848f5 |
&nwritten_chars); \
|
|
Packit |
0848f5 |
printf("%*s", nwritten_chars > 70 ? 0 : 70 - nwritten_chars, ""); \
|
|
Packit |
0848f5 |
} /* end if */ \
|
|
Packit |
0848f5 |
else \
|
|
Packit |
0848f5 |
printf("Testing %-62s", WHAT); \
|
|
Packit |
0848f5 |
fflush(stdout); \
|
|
Packit |
0848f5 |
} while(0)
|
|
Packit |
0848f5 |
#define PASSED() do {puts(" PASSED");fflush(stdout);} while(0)
|
|
Packit |
0848f5 |
#define FAILED() do {puts("*FAILED*");fflush(stdout);} while(0)
|
|
Packit |
0848f5 |
#define WARNING() do {puts("*WARNING*");fflush(stdout);} while(0)
|
|
Packit |
0848f5 |
#define SKIPPED() do {puts(" -SKIP-");fflush(stdout);} while(0)
|
|
Packit |
0848f5 |
#define TEST_ERROR do {FAILED(); AT(); goto error;} while(0)
|
|
Packit |
0848f5 |
#define FAIL_OP_ERROR(OP) do {FAILED(); AT(); OP; goto error;} while(0)
|
|
Packit |
0848f5 |
#define OP_SUPPRESS(OP, COUNTER, LIMIT) do { \
|
|
Packit |
0848f5 |
if((COUNTER) <= (LIMIT)) { \
|
|
Packit |
0848f5 |
OP; \
|
|
Packit |
0848f5 |
if((COUNTER) == (LIMIT)) \
|
|
Packit |
0848f5 |
puts(" Suppressing further output..."); \
|
|
Packit |
0848f5 |
fflush(stdout); \
|
|
Packit |
0848f5 |
} /* end if */ \
|
|
Packit |
0848f5 |
} while(0)
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Array of number of threads. Each threaded test is run once for each entry in
|
|
Packit |
0848f5 |
* this array. Remove the last test if OPA_LIMIT_THREADS is defined.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
static const unsigned num_threads[] = {1, 2, 4, 10, 100};
|
|
Packit |
0848f5 |
static const unsigned num_thread_tests = sizeof(num_threads) / sizeof(num_threads[0])
|
|
Packit |
0848f5 |
#if OPA_MAX_NTHREADS < 10
|
|
Packit |
0848f5 |
- 2
|
|
Packit |
0848f5 |
#elif OPA_MAX_NTHREADS < 100
|
|
Packit |
0848f5 |
- 1
|
|
Packit |
0848f5 |
#endif /* OPA_LIMIT_THREADS */
|
|
Packit |
0848f5 |
;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Factor to reduce the number of iterations by for each test. Must be the same
|
|
Packit |
0848f5 |
* size as num_threads.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
static const unsigned iter_reduction[] = {1, 1, 1, 1, 10};
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Other global variables.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
static unsigned curr_test; /* Current test number bein run */
|
|
Packit |
0848f5 |
|