2005-01-28 00:08:35 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
|
|
|
* All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
|
|
|
|
* All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
|
|
* University of Stuttgart. All rights reserved.
|
2005-03-24 15:43:37 +03:00
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
2005-01-28 00:08:35 +03:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
2005-01-27 04:39:55 +03:00
|
|
|
|
2005-01-28 00:08:35 +03:00
|
|
|
#undef OMPI_BUILDING
|
2005-01-27 04:39:55 +03:00
|
|
|
#include "ompi_config.h"
|
2005-01-28 00:08:35 +03:00
|
|
|
|
2005-01-27 04:39:55 +03:00
|
|
|
#include <assert.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#ifdef HAVE_PTHREAD_H
|
|
|
|
#include <pthread.h>
|
|
|
|
#endif
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "include/sys/atomic.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* default options */
|
|
|
|
|
|
|
|
int nreps = 100;
|
|
|
|
int nthreads = 2;
|
|
|
|
int enable_verbose = 0;
|
|
|
|
int enable_64_bit_tests = 0;
|
|
|
|
|
|
|
|
volatile int32_t vol32;
|
|
|
|
int32_t val32;
|
|
|
|
int32_t old32;
|
|
|
|
int32_t new32;
|
|
|
|
|
2005-01-28 00:08:35 +03:00
|
|
|
#if OMPI_HAVE_ATOMIC_MATH_64
|
2005-01-27 04:39:55 +03:00
|
|
|
volatile int64_t vol64;
|
|
|
|
int64_t val64;
|
|
|
|
int64_t old64;
|
|
|
|
int64_t new64;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
volatile int volint;
|
|
|
|
int valint;
|
|
|
|
int oldint;
|
|
|
|
int newint;
|
|
|
|
|
|
|
|
volatile void *volptr;
|
|
|
|
void *oldptr;
|
|
|
|
void *newptr;
|
|
|
|
|
|
|
|
|
|
|
|
static void help(void)
|
|
|
|
{
|
|
|
|
printf("Usage: threadtest [flags]\n"
|
|
|
|
"\n"
|
|
|
|
" Flags may be any of\n"
|
2005-01-28 00:08:35 +03:00
|
|
|
#if OMPI_HAVE_ATOMIC_MATH_64
|
2005-01-27 04:39:55 +03:00
|
|
|
" -l do 64-bit tests\n"
|
|
|
|
#endif
|
|
|
|
" -r NREPS number of repetitions\n"
|
|
|
|
" -t NTRHEADS number of threads\n"
|
|
|
|
" -v verbose output\n"
|
|
|
|
" -h print this info\n" "\n"
|
|
|
|
" Numbers may be postfixed with 'k' or 'm'\n\n");
|
|
|
|
|
2005-01-28 00:08:35 +03:00
|
|
|
#ifndef OMPI_HAVE_ATOMIC_MATH_64
|
2005-01-27 04:39:55 +03:00
|
|
|
printf(" 64-bit tests are not enabled in this build of the tests\n\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void usage(void)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Usage: threadtest [flags]\n" " threadtest -h\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void verbose(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
if (enable_verbose) {
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int str2size(char *str)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
char mod[32];
|
|
|
|
|
|
|
|
switch (sscanf(str, "%d%1[mMkK]", &size, mod)) {
|
|
|
|
case 1:
|
|
|
|
return (size);
|
|
|
|
case 2:
|
|
|
|
switch (*mod) {
|
|
|
|
case 'm':
|
|
|
|
case 'M':
|
|
|
|
return (size << 20);
|
|
|
|
case 'k':
|
|
|
|
case 'K':
|
|
|
|
return (size << 10);
|
|
|
|
default:
|
|
|
|
return (size);
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void *thread_main(void *arg)
|
|
|
|
{
|
2005-01-28 01:59:31 +03:00
|
|
|
int rank = (int) (unsigned long) arg;
|
2005-01-27 04:39:55 +03:00
|
|
|
int i;
|
|
|
|
|
|
|
|
verbose("thread-%d: Hello\n", rank);
|
|
|
|
|
|
|
|
/* thread tests */
|
|
|
|
|
|
|
|
for (i = 0; i < nreps; i++) {
|
|
|
|
ompi_atomic_add_32(&val32, 5);
|
2005-01-28 00:08:35 +03:00
|
|
|
#if OMPI_HAVE_ATOMIC_MATH_64
|
2005-01-27 04:39:55 +03:00
|
|
|
if (enable_64_bit_tests) {
|
|
|
|
ompi_atomic_add_64(&val64, 5);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
ompi_atomic_add(&valint, 5);
|
|
|
|
}
|
|
|
|
|
2005-01-28 01:59:31 +03:00
|
|
|
return (void *) (unsigned long) (rank + 1000);
|
2005-01-27 04:39:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int c;
|
2005-01-28 02:11:01 +03:00
|
|
|
#if OMPI_HAVE_POSIX_THREADS
|
2005-01-27 04:39:55 +03:00
|
|
|
int tid;
|
|
|
|
pthread_t *th;
|
2005-01-28 00:08:35 +03:00
|
|
|
#endif
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
/* option processing */
|
|
|
|
|
|
|
|
while ((c = getopt(argc, argv, "hlr:t:v")) != -1) {
|
|
|
|
switch (c) {
|
|
|
|
case 'h':
|
|
|
|
help();
|
|
|
|
break;
|
|
|
|
case 'l':
|
2005-01-28 00:08:35 +03:00
|
|
|
#if OMPI_HAVE_ATOMIC_MATH_64
|
2005-01-27 04:39:55 +03:00
|
|
|
enable_64_bit_tests = 1;
|
|
|
|
#else
|
|
|
|
usage();
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
if ((nreps = str2size(optarg)) <= 0) {
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
if ((nthreads = str2size(optarg)) <= 0) {
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
enable_verbose = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (optind != argc) {
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
|
|
|
|
verbose("main: %s\n", argv[0]);
|
|
|
|
verbose("main: nthreads = %d\n", nthreads);
|
|
|
|
verbose("main: nreps = %d\n", nreps);
|
|
|
|
|
|
|
|
/* first test single-threaded functionality */
|
|
|
|
|
|
|
|
/* -- cmpset 32-bit tests -- */
|
|
|
|
|
|
|
|
vol32 = 42, old32 = 42, new32 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_32(&vol32, old32, new32) == 1);
|
|
|
|
assert(vol32 == new32);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
vol32 = 42, old32 = 420, new32 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_32(&vol32, old32, new32) == 0);
|
|
|
|
assert(vol32 == 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
vol32 = 42, old32 = 42, new32 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_acq_32(&vol32, old32, new32) == 1);
|
|
|
|
assert(vol32 == new32);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
vol32 = 42, old32 = 420, new32 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_acq_32(&vol32, old32, new32) == 0);
|
|
|
|
assert(vol32 == 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
vol32 = 42, old32 = 42, new32 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_rel_32(&vol32, old32, new32) == 1);
|
|
|
|
assert(vol32 == new32);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
vol32 = 42, old32 = 420, new32 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_rel_32(&vol32, old32, new32) == 0);
|
|
|
|
assert(vol32 == 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
/* -- cmpset 64-bit tests -- */
|
|
|
|
|
2005-01-28 00:08:35 +03:00
|
|
|
#if OMPI_HAVE_ATOMIC_MATH_64
|
2005-01-27 04:39:55 +03:00
|
|
|
if (enable_64_bit_tests) {
|
|
|
|
verbose("64 bit serial tests\n");
|
|
|
|
vol64 = 42, old64 = 42, new64 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(1 == ompi_atomic_cmpset_64(&vol64, old64, new64));
|
|
|
|
assert(new64 == vol64);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
verbose("64 bit serial test 2\n");
|
|
|
|
vol64 = 42, old64 = 420, new64 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_64(&vol64, old64, new64) == 0);
|
|
|
|
assert(vol64 == 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
vol64 = 42, old64 = 42, new64 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_acq_64(&vol64, old64, new64) == 1);
|
|
|
|
assert(vol64 == new64);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
vol64 = 42, old64 = 420, new64 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_acq_64(&vol64, old64, new64) == 0);
|
|
|
|
assert(vol64 == 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
vol64 = 42, old64 = 42, new64 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_rel_64(&vol64, old64, new64) == 1);
|
|
|
|
assert(vol64 == new64);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
vol64 = 42, old64 = 420, new64 = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_rel_64(&vol64, old64, new64) == 0);
|
|
|
|
assert(vol64 == 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* -- cmpset int tests -- */
|
|
|
|
|
|
|
|
volint = 42, oldint = 42, newint = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset(&volint, oldint, newint) == 1);
|
|
|
|
assert(volint ==newint);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volint = 42, oldint = 420, newint = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset(&volint, oldint, newint) == 0);
|
|
|
|
assert(volint == 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volint = 42, oldint = 42, newint = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_acq(&volint, oldint, newint) == 1);
|
|
|
|
assert(volint == newint);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volint = 42, oldint = 420, newint = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_acq(&volint, oldint, newint) == 0);
|
|
|
|
assert(volint == 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volint = 42, oldint = 42, newint = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_rel(&volint, oldint, newint) == 1);
|
|
|
|
assert(volint == newint);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volint = 42, oldint = 420, newint = 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_rel(&volint, oldint, newint) == 0);
|
|
|
|
assert(volint == 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
|
|
|
|
/* -- cmpset ptr tests -- */
|
|
|
|
|
|
|
|
volptr = (void *) 42, oldptr = (void *) 42, newptr = (void *) 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_ptr(&volptr, oldptr, newptr) == 1);
|
|
|
|
assert(volptr == newptr);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volptr = (void *) 42, oldptr = (void *) 420, newptr = (void *) 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_ptr(&volptr, oldptr, newptr) == 0);
|
|
|
|
assert(volptr == (void *) 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volptr = (void *) 42, oldptr = (void *) 42, newptr = (void *) 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_acq_ptr(&volptr, oldptr, newptr) == 1);
|
|
|
|
assert(volptr == newptr);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volptr = (void *) 42, oldptr = (void *) 420, newptr = (void *) 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_acq_ptr(&volptr, oldptr, newptr) == 0);
|
|
|
|
assert(volptr == (void *) 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volptr = (void *) 42, oldptr = (void *) 42, newptr = (void *) 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_rel_ptr(&volptr, oldptr, newptr) == 1);
|
|
|
|
assert(volptr == newptr);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
volptr = (void *) 42, oldptr = (void *) 420, newptr = (void *) 50;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_cmpset_rel_ptr(&volptr, oldptr, newptr) == 0);
|
|
|
|
assert(volptr == (void *) 42);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
/* -- add_32 tests -- */
|
|
|
|
|
|
|
|
val32 = 42;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_add_32(&val32, 5) == (42 + 5));
|
|
|
|
assert((42 + 5) == val32);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
/* -- add_64 tests -- */
|
2005-01-28 00:08:35 +03:00
|
|
|
#if OMPI_HAVE_ATOMIC_MATH_64
|
2005-01-27 04:39:55 +03:00
|
|
|
if (enable_64_bit_tests) {
|
|
|
|
val64 = 42;
|
2005-01-28 00:08:35 +03:00
|
|
|
assert(ompi_atomic_add_64(&val64, 5) == (42 + 5));
|
|
|
|
assert((42 + 5) == val64);
|
2005-01-27 04:39:55 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* -- add_int tests -- */
|
|
|
|
|
|
|
|
valint = 42;
|
|
|
|
ompi_atomic_add(&valint, 5);
|
2005-01-28 00:08:35 +03:00
|
|
|
assert((42 + 5) == valint);
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
|
|
|
|
/* threaded tests */
|
|
|
|
|
|
|
|
val32 = 0;
|
2005-01-28 00:08:35 +03:00
|
|
|
#if OMPI_HAVE_ATOMIC_MATH_64
|
2005-01-27 04:39:55 +03:00
|
|
|
val64 = 0ul;
|
|
|
|
#endif
|
|
|
|
valint = 0;
|
|
|
|
|
|
|
|
/* -- create the thread set -- */
|
2005-01-28 02:11:01 +03:00
|
|
|
#if OMPI_HAVE_POSIX_THREADS
|
2005-01-27 04:39:55 +03:00
|
|
|
th = (pthread_t *) malloc(nthreads * sizeof(pthread_t));
|
|
|
|
if (!th) {
|
|
|
|
perror("malloc");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
for (tid = 0; tid < nthreads; tid++) {
|
2005-01-28 01:59:31 +03:00
|
|
|
if (pthread_create(&th[tid], NULL, thread_main, (void *) (unsigned long) tid) != 0) {
|
2005-01-27 04:39:55 +03:00
|
|
|
perror("pthread_create");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -- wait for the thread set to finish -- */
|
|
|
|
|
|
|
|
for (tid = 0; tid < nthreads; tid++) {
|
|
|
|
void *thread_return;
|
|
|
|
|
|
|
|
if (pthread_join(th[tid], &thread_return) != 0) {
|
|
|
|
perror("pthread_join");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2005-01-28 01:59:31 +03:00
|
|
|
verbose("main: thread %d returned %d\n", tid, (int) (unsigned long) thread_return);
|
2005-01-27 04:39:55 +03:00
|
|
|
}
|
|
|
|
free(th);
|
|
|
|
|
2005-01-28 00:08:35 +03:00
|
|
|
assert((5 * nthreads * nreps) == val32);
|
|
|
|
#if OMPI_HAVE_ATOMIC_MATH_64
|
2005-01-27 04:39:55 +03:00
|
|
|
if (enable_64_bit_tests) {
|
2005-01-28 00:08:35 +03:00
|
|
|
assert((5 * nthreads * nreps) == val64);
|
2005-01-27 04:39:55 +03:00
|
|
|
}
|
|
|
|
#endif
|
2005-01-28 00:08:35 +03:00
|
|
|
assert((5 * nthreads * nreps) == valint);
|
|
|
|
#endif
|
2005-01-27 04:39:55 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|