Blame src/openpa/test/opa_test.h

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