Text archives Help
- 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.