You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2005/12/17 00:03:28 UTC

svn commit: r357247 - in /incubator/stdcxx/trunk/tests/support: atomic_add.cpp atomic_xchg.cpp

Author: sebor
Date: Fri Dec 16 15:03:10 2005
New Revision: 357247

URL: http://svn.apache.org/viewcvs?rev=357247&view=rev
Log:
2005-12-16  Martin Sebor  <se...@roguewave.com>

	STDCXX-4
	* atomic_add.cpp: New test exercising the __rw_atomic_preincrement
	and __rw_atomic_predecrement overloaded functions.
	* atomic_xchg.cpp: New test exercising the __rw_atomic_exchange
	overloaded functions.

Added:
    incubator/stdcxx/trunk/tests/support/atomic_add.cpp   (with props)
    incubator/stdcxx/trunk/tests/support/atomic_xchg.cpp   (with props)

Added: incubator/stdcxx/trunk/tests/support/atomic_add.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/support/atomic_add.cpp?rev=357247&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/support/atomic_add.cpp (added)
+++ incubator/stdcxx/trunk/tests/support/atomic_add.cpp Fri Dec 16 15:03:10 2005
@@ -0,0 +1,383 @@
+/***************************************************************************
+ *
+ * atomic_add.cpp - test exercising atomic_preincrement() template
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rw/_mutex.h>
+
+#include <any.h>
+#include <cmdopt.h>
+#include <driver.h>
+#include <rwthread.h>
+
+/**************************************************************************/
+
+struct thr_args_base
+{
+    static enum tag_t {
+        Char, SChar, UChar,
+        Short, UShort, Int, UInt, Long, ULong,
+        LLong, ULLong
+    } type_tag_;
+};
+
+thr_args_base::tag_t thr_args_base::type_tag_;
+
+template <class intT>
+struct thr_args: thr_args_base
+{
+    unsigned         threadno_;     // thread ordinal number
+    static int       inc_;          // increment, decrement, or both
+    static unsigned  nincr_;        // number of increments
+    static intT     *shared_;       // shared variables
+    static unsigned  nthreads_;     // number of threads
+
+    static intT* get_array ();
+};
+
+template <class intT>
+int thr_args<intT>::inc_;
+
+template <class intT>
+unsigned thr_args<intT>::nincr_;
+
+template <class intT>
+intT* thr_args<intT>::shared_ = thr_args<intT>::get_array ();
+
+template <class intT>
+unsigned thr_args<intT>::nthreads_;
+
+// working around compiler bugs that prevent us from defining
+// a static array data member of a class template (PR #30009)
+template <class intT>
+intT* thr_args<intT>::get_array ()
+{
+    static intT array [2];
+    return array;
+}
+
+/**************************************************************************/
+
+
+template <class T>
+T preincrement (T &x)
+{
+#ifndef _RWSTD_REENTRANT
+
+    return ++x;
+
+#else   // if defined (_RWSTD_REENTRANT)
+
+    return _RW::__rw_atomic_preincrement (x, false);
+
+#endif   // _RWSTD_REENTRANT
+}
+
+
+template <class T>
+T predecrement (T &x)
+{
+#ifndef _RWSTD_REENTRANT
+
+    return --x;
+
+#else   // if defined (_RWSTD_REENTRANT)
+
+    return _RW::__rw_atomic_predecrement (x, false);
+
+#endif   // _RWSTD_REENTRANT
+}
+
+/**************************************************************************/
+
+
+template <class intT>
+void* thread_routine (thr_args<intT> *args)
+{
+    printf ("thread %u starting to %screment\n",
+            args->threadno_,
+              args->inc_ < 0 ? "de"
+            : args->inc_ > 0 ? "in"
+            : "decrement and in");
+
+    if (args->inc_ > 0) {
+
+        // exercise atomic_preincrement() in a tight loop
+
+        for (unsigned i = 0; i != args->nincr_; ++i) {
+            preincrement (args->shared_ [0]);
+            preincrement (args->shared_ [1]);
+        }
+    }
+    else if (args->inc_ < 0) {
+
+        // exercise atomic_predecrement() in a tight loop
+
+        for (unsigned i = 0; i != args->nincr_; ++i) {
+            predecrement (args->shared_ [0]);
+            predecrement (args->shared_ [1]);
+        }
+    }
+    else {
+
+        // exercise both atomic_preincrement() and atomic_predecrement()
+
+        for (unsigned i = 0; i != args->nincr_; ++i) {
+            preincrement (args->shared_ [0]);
+            predecrement (args->shared_ [0]);
+            preincrement (args->shared_ [1]);
+            predecrement (args->shared_ [1]);
+        }
+    }
+
+    return 0;
+}
+
+/**************************************************************************/
+
+extern "C" void* thread_routine (void *arg)
+{
+    thr_args_base* const args = (thr_args_base*)arg;
+
+    switch (args->type_tag_) {
+
+    case thr_args_base::Char:
+        return thread_routine ((thr_args<char>*)(arg));
+    case thr_args_base::SChar:
+        return thread_routine ((thr_args<signed char>*)(arg));
+    case thr_args_base::UChar:
+        return thread_routine ((thr_args<unsigned char>*)(arg));
+
+    case thr_args_base::Short:
+        return thread_routine ((thr_args<short>*)(arg));
+    case thr_args_base::UShort:
+        return thread_routine ((thr_args<unsigned short>*)(arg));
+
+    case thr_args_base::Int:
+        return thread_routine ((thr_args<int>*)(arg));
+    case thr_args_base::UInt:
+        return thread_routine ((thr_args<unsigned int>*)(arg));
+
+    case thr_args_base::Long:
+        return thread_routine ((thr_args<long>*)(arg));
+    case thr_args_base::ULong:
+        return thread_routine ((thr_args<unsigned long>*)(arg));
+
+#ifdef _RWSTD_LONG_LONG
+
+    case thr_args_base::LLong:
+        return thread_routine ((thr_args<_RWSTD_LONG_LONG>*)(arg));
+    case thr_args_base::ULLong:
+        return thread_routine ((thr_args<unsigned _RWSTD_LONG_LONG>*)(arg));
+
+#endif   // _RWSTD_LONG_LONG
+
+    };
+
+    return 0;
+}
+
+/**************************************************************************/
+
+/* extern */ int rw_opt_nloops   = 1024 * 1024;
+/* extern */ int rw_opt_nthreads = 4;
+
+#define MAX_THREADS   32
+
+
+template <class intT>
+void run_test (intT, thr_args_base::tag_t tag, int inc)
+{
+    static const char* const tname = rw_any_t (intT ()).type_name ();
+
+    static const char* const fun =
+          inc < 0 ? "__rw_atomic_predecrement"
+        : inc > 0 ? ":__rw_atomic_preincrement"
+        : "__rw_atomic_pre{in,de}crement";
+
+    if (!rw_enabled (tname)) {
+        rw_note (0, 0, 0, "%s test disabled", tname);
+        return;
+    }
+
+#if defined (_RWSTD_REENTRANT)
+
+    rw_info (0, 0, 0, "__rw::%s (%s&): %d iterations in %d threads",
+             fun, tname, rw_opt_nloops, rw_opt_nthreads);
+
+    rw_thread_t tid [MAX_THREADS];
+
+    typedef thr_args<intT> Args;
+
+    Args::nthreads_   = rw_opt_nthreads;
+    Args::type_tag_   = tag;
+    Args::inc_        = inc;
+    Args::nincr_      = unsigned (rw_opt_nloops);
+    Args::shared_ [0] = intT ();
+    Args::shared_ [1] = intT ();
+
+    _RWSTD_ASSERT (Args::nthreads_ < sizeof tid / sizeof *tid);
+
+    Args args [sizeof tid / sizeof *tid];
+
+    memset (args, 0, sizeof args);
+
+    for (unsigned i = 0; i != Args::nthreads_; ++i) {
+
+        args [i].threadno_ = i;
+
+        rw_fatal (0 == rw_thread_create (tid + i, 0, thread_routine, args + i),
+                  0, __LINE__, "thread_create() failed");
+    }
+            
+    for (unsigned i = 0; i != Args::nthreads_; ++i) {
+
+        rw_error (0 == rw_thread_join (tid [i], 0), 0, __LINE__,
+                  "thread_join() failed");
+    }
+
+    // compute the expected result
+    intT expect = intT ();
+
+    if (inc < 0) {
+        for (unsigned i = 0; i != Args::nthreads_ * Args::nincr_; ++i)
+            --expect;
+    }
+    else if (inc > 0) {
+        for (unsigned i = 0; i != Args::nthreads_ * Args::nincr_; ++i)
+            ++expect;
+    }
+
+    // verify that the final value of the variable shared among all
+    // threads equals the number of increments or decrements performed
+    // by all threads
+    rw_assert (Args::shared_ [0] == expect, 0, __LINE__,
+               "1. %s (%s&); %s == %s failed",
+               fun, tname, TOSTR (Args::shared_ [0]), TOSTR (expect));
+
+    rw_assert (Args::shared_ [1] == expect, 0, __LINE__,
+               "2. %s (%s&); %s == %s failed",
+               fun, tname, TOSTR (Args::shared_ [1]), TOSTR (expect));
+
+#else   // if !defined (_RWSTD_REENTRANT)
+
+    _RWSTD_UNUSED (t);
+    _RWSTD_UNUSED (tag);
+    _RWSTD_UNUSED (inc);
+
+#endif   // _RWSTD_REENTRANT
+}
+
+/**************************************************************************/
+
+static int
+run_test (int, char**)
+{
+    // check that the number of threads is valid
+    rw_fatal (-1 < rw_opt_nthreads && rw_opt_nthreads < MAX_THREADS, 0, 0,
+              "number of threads must be in the range [0, %d), got %d",
+              MAX_THREADS, rw_opt_nthreads);
+
+    // check that the number of loops is non-negative
+    rw_fatal (-1 < rw_opt_nloops, 0, 0,
+              "number of loops must be non-negative, got %d",
+              rw_opt_nloops);
+
+    // exercise atomic subtract
+    run_test ((char)0, thr_args_base::Char, -1);
+    run_test ((signed char)0, thr_args_base::SChar, -1);
+    run_test ((unsigned char)0, thr_args_base::UChar, -1);
+
+    run_test ((short)0, thr_args_base::Short, -1);
+    run_test ((unsigned short)0, thr_args_base::UShort, -1);
+
+    run_test ((int)0, thr_args_base::Int, -1);
+    run_test ((unsigned int)0, thr_args_base::UInt, -1);
+
+    run_test ((long)0, thr_args_base::Long, -1);
+    run_test ((unsigned long)0, thr_args_base::ULong, -1);
+
+#ifdef _RWSTD_LONG_LONG
+
+    run_test ((_RWSTD_LONG_LONG)0, thr_args_base::LLong, -1);
+    run_test ((unsigned _RWSTD_LONG_LONG)0, thr_args_base::ULLong, -1);
+
+#endif    // _RWSTD_LONG_LONG
+
+    // exercise atomic add
+    run_test ((char)0, thr_args_base::Char, +1);
+    run_test ((signed char)0, thr_args_base::SChar, +1);
+    run_test ((unsigned char)0, thr_args_base::UChar, +1);
+
+    run_test ((short)0, thr_args_base::Short, +1);
+    run_test ((unsigned short)0, thr_args_base::UShort, +1);
+
+    run_test ((int)0, thr_args_base::Int, +1);
+    run_test ((unsigned int)0, thr_args_base::UInt, +1);
+
+    run_test ((long)0, thr_args_base::Long, +1);
+    run_test ((unsigned long)0, thr_args_base::ULong, +1);
+
+#ifdef _RWSTD_LONG_LONG
+
+    run_test ((_RWSTD_LONG_LONG)0, thr_args_base::LLong, +1);
+    run_test ((unsigned _RWSTD_LONG_LONG)0, thr_args_base::ULLong, +1);
+
+#endif    // _RWSTD_LONG_LONG
+
+
+    // exercise both atomic add and subtract
+    run_test ((char)0, thr_args_base::Char, 0);
+    run_test ((signed char)0, thr_args_base::SChar, 0);
+    run_test ((unsigned char)0, thr_args_base::UChar, 0);
+
+    run_test ((short)0, thr_args_base::Short, 0);
+    run_test ((unsigned short)0, thr_args_base::UShort, 0);
+
+    run_test ((int)0, thr_args_base::Int, 0);
+    run_test ((unsigned int)0, thr_args_base::UInt, 0);
+
+    run_test ((long)0, thr_args_base::Long, 0);
+    run_test ((unsigned long)0, thr_args_base::ULong, 0);
+
+#ifdef _RWSTD_LONG_LONG
+
+    run_test ((_RWSTD_LONG_LONG)0, thr_args_base::LLong, 0);
+    run_test ((unsigned _RWSTD_LONG_LONG)0, thr_args_base::ULLong, 0);
+
+#endif    // _RWSTD_LONG_LONG
+
+    return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char *argv[])
+{
+    return rw_test (argc, argv, __FILE__,
+                    0 /* no clause */,
+                    0 /* no comment */, run_test,
+                    "|-nloops# "
+                    "|-nthreads#",
+                    &rw_opt_nloops,
+                    &rw_opt_nthreads);
+}

Propchange: incubator/stdcxx/trunk/tests/support/atomic_add.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/support/atomic_add.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/tests/support/atomic_xchg.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/support/atomic_xchg.cpp?rev=357247&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/support/atomic_xchg.cpp (added)
+++ incubator/stdcxx/trunk/tests/support/atomic_xchg.cpp Fri Dec 16 15:03:10 2005
@@ -0,0 +1,365 @@
+/***************************************************************************
+ *
+ * atomic_xchg.cpp - test exercising atomic_exchange() template
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rw/_mutex.h>
+
+#include <any.h>
+#include <cmdopt.h>
+#include <driver.h>
+#include <rwthread.h>
+
+/**************************************************************************/
+
+struct thr_args_base
+{
+    static enum tag_t {
+        Char, SChar, UChar,
+        Short, UShort, Int, UInt, Long, ULong,
+        LLong, ULLong
+    } type_tag_;
+
+    unsigned long threadno_;     // thread ordinal number
+    unsigned long niter_;        // number of iterations
+    unsigned long nxchg_;        // number of exchanges
+};
+
+thr_args_base::tag_t thr_args_base::type_tag_;
+
+template <class intT>
+struct thr_args: thr_args_base
+{
+    static unsigned long  nincr_;        // number of increments
+    static intT          *shared_;       // shared variables
+    static unsigned long  nthreads_;     // number of threads
+
+    static intT* get_array ();
+};
+
+template <class intT>
+unsigned long thr_args<intT>::nincr_;
+
+template <class intT>
+intT* thr_args<intT>::shared_ = thr_args<intT>::get_array ();
+
+template <class intT>
+unsigned long thr_args<intT>::nthreads_;
+
+// working around compiler bugs that prevent us from defining
+// a static array data member of a class template (PR #30009)
+template <class intT>
+/* static */ intT* thr_args<intT>::get_array ()
+{
+    static intT array [2];
+    return array;
+}
+
+/**************************************************************************/
+
+template <class intT>
+intT exchange (intT &x, intT y)
+{
+#ifndef _RWSTD_REENTRANT
+
+    intT save (x);
+
+    x = y;
+
+    return save;
+
+#else   // if defined (_RWSTD_REENTRANT)
+
+    return _RW::__rw_atomic_exchange (x, y, false);
+
+#endif   // _RWSTD_REENTRANT
+}
+
+/**************************************************************************/
+
+template <class intT>
+void* thread_routine (thr_args<intT> *args)
+{
+    // each thread operates on one of two shared values to exercise
+    // problems due to operating on adjacent bytes or half-words
+    const unsigned long inx = args->threadno_ % 2;
+
+    static volatile int failed;
+
+    // exercise atomic_exchange() in a tight loop
+
+    // perform the requested number increments, or until the
+    // shared `failed' variable is set to a non-zero value
+
+    for (unsigned long i = 0; i != args->nincr_ && !failed; ++i) {
+
+        for (unsigned long j = 0; !failed; ++j) {
+
+            // increment the number of iterations of this thread
+            ++args->niter_;
+
+            // use intT() as a special "lock" value
+            const intT old = exchange (args->shared_ [inx], intT ());
+
+            // increment the number of exchanges performed by this thread
+            ++args->nxchg_;
+
+            if (intT () != old) {
+
+                // shared variable was not locked by any other thread
+
+                // increment the value of the shared variable, taking
+                // care to avoid the special "lock" value of intT()
+                intT newval = intT (old + 1);
+
+                if (intT () == newval)
+                    ++newval;
+
+                const intT lock = exchange (args->shared_ [inx], newval);
+
+                // increment the number of exchanges
+                ++args->nxchg_;
+
+                // the returned value must be the special "lock" value
+                if (intT () == lock)
+                    break;
+
+                // fail by setting the shared failed variable (to
+                // prevent deadlock) if the returned value is not
+                // the special "lock" value
+
+                printf ("*** line %d: error: thread %lu failed "
+                        "at increment %lu after %lu iterations\n",
+                        __LINE__, args->threadno_, i, args->niter_);
+                failed = 1;
+                return 0;
+            }
+
+            if (100UL * args->nincr_ == j) {
+
+                // fail by setting the shared failed variable (to
+                // prevent deadlock) if the number of failed attempts
+                // to lock the shared variable reaches the requested
+                // number of increments * 100 (an arbitrary number)
+
+                printf ("*** line %d: error thread %lu \"timed out\" after "
+                        "%lu increments and %lu iterations\n",
+                        __LINE__, args->threadno_, i, args->niter_);
+                failed = 1;
+                return 0;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/**************************************************************************/
+
+extern "C" void* thread_routine (void *arg)
+{
+    thr_args_base* const args = (thr_args_base*)arg;
+
+    printf ("thread %lu starting\n", args->threadno_);
+
+    switch (args->type_tag_) {
+
+    case thr_args_base::Char:
+        return thread_routine ((thr_args<char>*)(arg));
+    case thr_args_base::SChar:
+        return thread_routine ((thr_args<signed char>*)(arg));
+    case thr_args_base::UChar:
+        return thread_routine ((thr_args<unsigned char>*)(arg));
+
+    case thr_args_base::Short:
+        return thread_routine ((thr_args<short>*)(arg));
+    case thr_args_base::UShort:
+        return thread_routine ((thr_args<unsigned short>*)(arg));
+
+    case thr_args_base::Int:
+        return thread_routine ((thr_args<int>*)(arg));
+    case thr_args_base::UInt:
+        return thread_routine ((thr_args<unsigned int>*)(arg));
+
+    case thr_args_base::Long:
+        return thread_routine ((thr_args<long>*)(arg));
+    case thr_args_base::ULong:
+        return thread_routine ((thr_args<unsigned long>*)(arg));
+
+#ifdef _RWSTD_LONG_LONG
+
+    case thr_args_base::LLong:
+        return thread_routine ((thr_args<_RWSTD_LONG_LONG>*)(arg));
+    case thr_args_base::ULLong:
+        return thread_routine ((thr_args<unsigned _RWSTD_LONG_LONG>*)(arg));
+
+#endif   // _RWSTD_LONG_LONG
+
+    };
+
+    return 0;
+}
+
+/**************************************************************************/
+
+/* extern */ int rw_opt_nloops   = 1024 * 1024;
+/* extern */ int rw_opt_nthreads = 4;
+
+#define MAX_THREADS   32
+
+
+template <class intT>
+void run_test (intT, thr_args_base::tag_t tag)
+{
+    static const char* const tname = rw_any_t (intT ()).type_name ();
+    static const char* const fun   = "__rw_atomic_exchange";
+
+    if (!rw_enabled (tname)) {
+        rw_note (0, 0, 0, "%s test disabled", tname);
+        return;
+    }
+
+#ifdef _RWSTD_REENTRANT
+
+    rw_info (0, 0, 0, "__rw::%s (%s&, %2$s): %d iterations in %d threads",
+             fun, tname, rw_opt_nloops, rw_opt_nthreads);
+
+    rw_thread_t tid [MAX_THREADS];
+
+    typedef thr_args<intT> Args;
+
+    Args::nthreads_   = unsigned (rw_opt_nthreads);
+    Args::type_tag_   = tag;
+    Args::nincr_      = unsigned (rw_opt_nloops);
+    Args::shared_ [0] = intT (1);
+    Args::shared_ [1] = intT (1);
+
+    _RWSTD_ASSERT (Args::nthreads_ < sizeof tid / sizeof *tid);
+
+    Args args [sizeof tid / sizeof *tid];
+
+    for (unsigned long i = 0; i != Args::nthreads_; ++i) {
+
+        args [i].threadno_ = i;
+        args [i].niter_    = 0;
+        args [i].nxchg_    = 0;
+
+        rw_fatal (0 == rw_thread_create (tid + i, 0, thread_routine, args + i),
+                  0, __LINE__, "thread_create() failed");
+    }
+            
+    for (unsigned long i = 0; i != Args::nthreads_; ++i) {
+
+        rw_error (0 == rw_thread_join (tid [i], 0), 0, __LINE__,
+                  "thread_join() failed");
+
+        if (args [i].niter_) {
+            // compute the percantage of thread iterations that resulted
+            // in increments of one of the shared variables
+            const unsigned long incrpcnt =
+                (100U * Args::nincr_) / args [i].niter_;
+
+            printf ("thread %lu performed %lu exchanges in %lu iterations "
+                    "(%lu%% increments)\n",
+                    args [i].threadno_, args [i].nxchg_,
+                    args [i].niter_, incrpcnt);
+        }
+    }
+
+    // compute the expected result
+    intT expect = intT (1);
+
+    for (unsigned long i = 0; i != (Args::nthreads_ * Args::nincr_) / 2U; ++i) {
+        if (!++expect)
+            ++expect;
+    }
+
+    // verify that the final value of the variables shared among all
+    // threads equals the number of increments performed by the threads
+    rw_assert (Args::shared_ [0] == expect, 0, __LINE__,
+               "1. %s (%s&, %2$s); %s == %s failed",
+               fun, tname, TOSTR (Args::shared_ [0]), TOSTR (expect));
+
+    rw_assert (Args::shared_ [1] == expect, 0, __LINE__,
+               "2. %s (%s&, %2$s); %s == %s failed",
+               fun, tname, TOSTR (Args::shared_ [1]), TOSTR (expect));
+
+#else   // if !defined (_RWSTD_REENTRANT)
+
+    _RWSTD_UNUSED (t);
+    _RWSTD_UNUSED (tag);
+
+#endif   // _RWSTD_REENTRANT
+}
+
+/**************************************************************************/
+
+static int
+run_test (int, char**)
+{
+    // check that the number of threads is valid
+    rw_fatal (-1 < rw_opt_nthreads && rw_opt_nthreads < MAX_THREADS, 0, 0,
+              "number of threads must be in the range [0, %d), got %d",
+              MAX_THREADS, rw_opt_nthreads);
+
+    // check that the number of loops is non-negative
+    rw_fatal (-1 < rw_opt_nloops, 0, 0,
+              "number of loops must be non-negative, got %d",
+              rw_opt_nloops);
+
+    // exercise atomic exchange
+    run_test ((char)0, thr_args_base::Char);
+    run_test ((signed char)0, thr_args_base::SChar);
+    run_test ((unsigned char)0, thr_args_base::UChar);
+
+    run_test ((short)0, thr_args_base::Short);
+    run_test ((unsigned short)0, thr_args_base::UShort);
+
+    run_test ((int)0, thr_args_base::Int);
+    run_test ((unsigned int)0, thr_args_base::UInt);
+
+    run_test ((long)0, thr_args_base::Long);
+    run_test ((unsigned long)0, thr_args_base::ULong);
+
+#ifdef _RWSTD_LONG_LONG
+
+    run_test ((_RWSTD_LONG_LONG)0, thr_args_base::LLong);
+    run_test ((unsigned _RWSTD_LONG_LONG)0, thr_args_base::ULLong);
+
+#endif    // _RWSTD_LONG_LONG
+
+    return 0;
+
+}
+
+/**************************************************************************/
+
+int main (int argc, char *argv[])
+{
+    return rw_test (argc, argv, __FILE__,
+                    0 /* no clause */,
+                    0 /* no comment */, run_test,
+                    "|-nloops# "
+                    "|-nthreads#",
+                    &rw_opt_nloops,
+                    &rw_opt_nthreads);
+}

Propchange: incubator/stdcxx/trunk/tests/support/atomic_xchg.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/support/atomic_xchg.cpp
------------------------------------------------------------------------------
    svn:keywords = Id