Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[Manta] r2029 - in trunk: Core/Thread tests


Chronological Thread 
  • From: "Solomon Boulos" <boulos@cs.utah.edu>
  • To: manta@sci.utah.edu
  • Subject: [Manta] r2029 - in trunk: Core/Thread tests
  • Date: Fri, 1 Feb 2008 18:51:52 -0700 (MST)

Author: boulos
Date: Fri Feb  1 18:51:51 2008
New Revision: 2029

Modified:
   trunk/Core/Thread/AtomicCounter.h
   trunk/Core/Thread/AtomicCounter_default.cc
   trunk/Core/Thread/AtomicCounter_x86.cc
   trunk/tests/CMakeLists.txt
   trunk/tests/atomic_counter.cc
Log:
Core/Thread/AtomicCounter.h
Core/Thread/AtomicCounter_default.cc
Core/Thread/AtomicCounter_x86.cc

 Adding operator+= to AtomicCounter.

 Also removing the extra movl from set(). It seems the important thing
 is to label the incoming value as being read in the ASM inputs list.

tests/CMakeLists.txt
tests/atomic_counter.cc

 Expanding the AtomicCounter test to do increment (++), reset, and
 variable increment (+=).

 Adding CTest tests for 4 processor levels to make sure the
 AtomicCounter continues to work.


Modified: trunk/Core/Thread/AtomicCounter.h
==============================================================================
--- trunk/Core/Thread/AtomicCounter.h   (original)
+++ trunk/Core/Thread/AtomicCounter.h   Fri Feb  1 18:51:51 2008
@@ -101,6 +101,11 @@
   //    Increment the counter and return the old value
   int operator++(int);
 
+  // Increment the counter by the given value and return the new
+  // value. Like operator++ this doesn't return AtomicCounter& to
+  // avoid atomicity issues.
+  int operator+=(int);
+
   //////////
   // Decrement the counter and return the new value
   // This does not return AtomicCounter& like a normal --

Modified: trunk/Core/Thread/AtomicCounter_default.cc
==============================================================================
--- trunk/Core/Thread/AtomicCounter_default.cc  (original)
+++ trunk/Core/Thread/AtomicCounter_default.cc  Fri Feb  1 18:51:51 2008
@@ -111,11 +111,24 @@
 }
 
 int
+AtomicCounter::operator+=(int val)
+{
+  int oldstate = Thread::couldBlock(name_);
+  priv_->lock.lock();
+  priv_->value += val;
+  int ret=priv_->value;
+  priv_->lock.unlock();
+  Thread::couldBlockDone(oldstate);
+  return ret;
+}
+
+
+int
 AtomicCounter::operator--()
 {
   int oldstate = Thread::couldBlock(name_);
   priv_->lock.lock();
-  int ret=--priv_->value;      
+  int ret=--priv_->value;
   priv_->lock.unlock();
   Thread::couldBlockDone(oldstate);
   return ret;
@@ -130,7 +143,7 @@
   priv_->lock.unlock();
   Thread::couldBlockDone(oldstate);
   return ret;
-} 
+}
 
 void
 AtomicCounter::set(int v)

Modified: trunk/Core/Thread/AtomicCounter_x86.cc
==============================================================================
--- trunk/Core/Thread/AtomicCounter_x86.cc      (original)
+++ trunk/Core/Thread/AtomicCounter_x86.cc      Fri Feb  1 18:51:51 2008
@@ -93,6 +93,20 @@
 }
 
 int
+AtomicCounter::operator+=(int val) {
+  __volatile__ register int return_val = val;
+
+  __asm__ __volatile__(
+      "lock;\n"
+      "xaddl %1, %0;\n" :
+      "=m" (value), "=r"(return_val) :
+      "m" (value) , "r" (return_val), "r" (val) :
+      /* no unknown clobbers */
+    );
+  return return_val;
+}
+
+int
 AtomicCounter::operator--() {
   register int return_val = -1;
   __asm__ __volatile__(
@@ -123,7 +137,6 @@
 AtomicCounter::set(int v) {
   __volatile__ register int copy_val = v;
   __asm__ __volatile__(
-    "movl %1, %2;\n"
     "lock;\n"
     "xchgl %1, %0\n" :
     "=m" (value), "=r" (copy_val) :

Modified: trunk/tests/CMakeLists.txt
==============================================================================
--- trunk/tests/CMakeLists.txt  (original)
+++ trunk/tests/CMakeLists.txt  Fri Feb  1 18:51:51 2008
@@ -3,3 +3,12 @@
 
 ADD_EXECUTABLE(atomic_counter atomic_counter.cc)
 TARGET_LINK_LIBRARIES(atomic_counter ${MANTA_TARGET_LINK_LIBRARIES})
+
+IF(BUILD_TESTING)
+  SET(AtomicIterations 100)
+
+  ADD_TEST(AtomicCounter_NP1 ${CMAKE_BINARY_DIR}/bin/atomic_counter 1 
${AtomicIterations})
+  ADD_TEST(AtomicCounter_NP2 ${CMAKE_BINARY_DIR}/bin/atomic_counter 2 
${AtomicIterations})
+  ADD_TEST(AtomicCounter_NP4 ${CMAKE_BINARY_DIR}/bin/atomic_counter 4 
${AtomicIterations})
+  ADD_TEST(AtomicCounter_NP8 ${CMAKE_BINARY_DIR}/bin/atomic_counter 8 
${AtomicIterations})
+ENDIF(BUILD_TESTING)
\ No newline at end of file

Modified: trunk/tests/atomic_counter.cc
==============================================================================
--- trunk/tests/atomic_counter.cc       (original)
+++ trunk/tests/atomic_counter.cc       Fri Feb  1 18:51:51 2008
@@ -46,20 +46,29 @@
 
 using namespace Manta;
 
-class AtomicCountTest : public Runnable {
+class AtomicIncrementTest : public Runnable {
     AtomicCounter* counter;
     int count;
     int proc;
     int np;
 public:
-  AtomicCountTest(AtomicCounter* barrier, int count, int proc, int np);
+  AtomicIncrementTest(AtomicCounter* barrier, int count, int proc, int np);
+  virtual void run();
+};
+
+class AtomicVariableIncrementTest : public Runnable {
+    AtomicCounter* counter;
+    int count;
+    int proc;
+    int np;
+public:
+  AtomicVariableIncrementTest(AtomicCounter* barrier, int count, int proc, 
int np);
   virtual void run();
 };
 
 void usage(char* progname)
 {
     cerr << "usage: " << progname << " nprocessors count\n";
-    exit(1);
 }
 
 int main(int argc, char* argv[])
@@ -68,45 +77,98 @@
   int count=0;
   if(argc != 3){
     usage(argv[0]);
+    return -1;
   }
   np=atoi(argv[1]);
   count=atoi(argv[2]);
-  AtomicCounter* counter=new AtomicCounter("test counter", 0);
-  ThreadGroup* group=new ThreadGroup("test group");
-  for(int i=0;i<np;i++){
-    char buf[100];
-    sprintf(buf, "worker %d", i);
-    new Thread(new AtomicCountTest(counter, count, i, np), strdup(buf), 
group);
-  }
-  group->join();
-  AtomicCounter& counter_ref = *counter;
-  int result = counter_ref;
-  printf("adding result = %d\n", result);
-  if (result != np * count) {
+  if (count < 1) {
+    cerr << "Count must be at least 1";
     return -1;
   }
-  const int kResetValue = 0;
-  counter_ref.set(kResetValue);
-  result = counter_ref;
-  printf("Reset to %d = %d\n", kResetValue, result);
-  if (result != kResetValue) {
-    return -1;
+
+  AtomicCounter* counter=new AtomicCounter("test counter", 0);
+
+  {
+    // Test atomic increment
+    ThreadGroup* increment_group=new ThreadGroup("test group");
+    for(int i=0;i<np;i++){
+      char buf[100];
+      sprintf(buf, "worker %d", i);
+      new Thread(new AtomicIncrementTest(counter, count, i, np), 
strdup(buf), increment_group);
+    }
+    increment_group->join();
+    AtomicCounter& counter_ref = *counter;
+    int result = counter_ref;
+    int expected_increment = np * count;
+    printf("adding result = %d (expected value = %d)\n", result, 
expected_increment);
+    if (result != expected_increment) {
+      return -1;
+    }
   }
+
+  {
+    // Test reset of counter
+    const int kResetValue = 0;
+    AtomicCounter& counter_ref = *counter;
+    counter_ref.set(kResetValue);
+    int result = counter_ref;
+    printf("Reset to %d = %d\n", kResetValue, result);
+    if (result != kResetValue) {
+      return -1;
+    }
+  }
+
+  {
+    // Test atomic variable increment (+=)
+    ThreadGroup* variable_increment_group=new ThreadGroup("variable 
increment group");
+    for(int i=0;i<np;i++){
+      char buf[100];
+      sprintf(buf, "worker %d", i);
+      new Thread(new AtomicVariableIncrementTest(counter, count, i, np), 
strdup(buf), variable_increment_group);
+    }
+    variable_increment_group->join();
+
+    AtomicCounter& counter_ref = *counter;
+    int result = counter_ref;
+    // A general arithmetic series with common difference d is computed as:
+    // (n * (first + last)) / 2
+    int per_thread_result = (count * (count-1)) / 2;
+    int expected_result = np * per_thread_result;
+    printf("adding result = %d (expected value = %d)\n", result, 
expected_result);
+    if (result != expected_result) {
+      return -1;
+    }
+  }
+
   return 0;
 }
 
-AtomicCountTest::AtomicCountTest(AtomicCounter* counter,
+AtomicIncrementTest::AtomicIncrementTest(AtomicCounter* counter,
                                  int count, int proc, int np)
     : counter(counter), count(count), proc(proc), np(np)
 {
 }
 
-void AtomicCountTest::run()
+void AtomicIncrementTest::run()
 {
     for(int i=0;i<count;i++){
       AtomicCounter& ref_counter = *counter;
       ref_counter++;
     }
+}
+
+AtomicVariableIncrementTest::AtomicVariableIncrementTest(AtomicCounter* 
counter,
+                                                         int count, int 
proc, int np)
+    : counter(counter), count(count), proc(proc), np(np)
+{
+}
+
+void AtomicVariableIncrementTest::run()
+{
+  AtomicCounter& ref_counter = *counter;
+  for(int i=0;i<count;i++){
+    ref_counter += i;
+  }
 }
 
 




  • [Manta] r2029 - in trunk: Core/Thread tests, Solomon Boulos, 02/01/2008

Archive powered by MHonArc 2.6.16.

Top of page