[complement-svn] SF.net SVN: complement: [1510] trunk/complement/explore
Status: Pre-Alpha
Brought to you by:
complement
From: <com...@us...> - 2007-02-06 10:14:03
|
Revision: 1510 http://svn.sourceforge.net/complement/?rev=1510&view=rev Author: complement Date: 2007-02-06 02:13:58 -0800 (Tue, 06 Feb 2007) Log Message: ----------- add Barrier; add yield; libxmt 1.10.1 Modified Paths: -------------- trunk/complement/explore/COPYRIGHTS trunk/complement/explore/include/mt/xmt.h trunk/complement/explore/lib/mt/ChangeLog trunk/complement/explore/lib/mt/Makefile.inc trunk/complement/explore/test/mt/Makefile.inc trunk/complement/explore/test/mt/mt_test.cc trunk/complement/explore/test/mt/mt_test.h trunk/complement/explore/test/mt/mt_test_suite.cc trunk/complement/explore/test/mt/unit_test.cc Removed Paths: ------------- trunk/complement/explore/test/mt/join.cc trunk/complement/explore/test/mt/mutex_test.cc trunk/complement/explore/test/mt/recursive_mutex.cc trunk/complement/explore/test/mt/spinlock_test.cc Modified: trunk/complement/explore/COPYRIGHTS =================================================================== --- trunk/complement/explore/COPYRIGHTS 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/COPYRIGHTS 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,4 +1,4 @@ -Copyright (c) 1997-1999, 2001-2006 Petr Ovtchenkov +Copyright (c) 1997-1999, 2001-2007 Petr Ovtchenkov Portion Copyright (c) 1999-2001 Parallel Graphics Ltd. Modified: trunk/complement/explore/include/mt/xmt.h =================================================================== --- trunk/complement/explore/include/mt/xmt.h 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/include/mt/xmt.h 2007-02-06 10:13:58 UTC (rev 1510) @@ -39,6 +39,7 @@ # ifdef _PTHREADS # include <pthread.h> # include <semaphore.h> +# include <sched.h> # else # include <thread.h> # include <synch.h> @@ -1466,7 +1467,43 @@ #endif } +template <bool SCOPE> +class __Barrier +{ + public: + __Barrier( unsigned cnt = 2 ) + { +#ifdef _PTHREADS + pthread_barrierattr_t attr; + pthread_barrierattr_init( &attr ); + pthread_barrierattr_setpshared( &attr, SCOPE ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE ); + pthread_barrier_init( &_barr, &attr, cnt ); + pthread_barrierattr_destroy( &attr ); +#endif + } + ~__Barrier() + { +#ifdef _PTHREADS + pthread_barrier_destroy( &_barr ); +#endif + } + + int wait() + { +#ifdef _PTHREADS + return pthread_barrier_wait( &_barr ); +#endif + } + + private: +#ifdef _PTHREADS + pthread_barrier_t _barr; +#endif +}; + +typedef __Barrier<false> Barrier; + __FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); __FIT_DECLSPEC void become_daemon() throw( fork_in_parent, std::runtime_error ); __FIT_DECLSPEC void block_signal( int sig ); @@ -1563,6 +1600,10 @@ static __FIT_DECLSPEC int join_all(); #endif static __FIT_DECLSPEC void signal_exit( int sig ); // signal handler +#if defined(_PTHREADS) + static int yield() + { return sched_yield(); } +#endif bool good() const { /* Locker lk( _llock ); */ return (_id != bad_thread_id); } Modified: trunk/complement/explore/lib/mt/ChangeLog =================================================================== --- trunk/complement/explore/lib/mt/ChangeLog 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/lib/mt/ChangeLog 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,3 +1,9 @@ +2007-02-06 Petr Ovtchenkov <pt...@is...> + + * xmt.h: add Barrier; add yield; + + * libxmt: version 1.10.1 + 2007-02-02 Petr Ovtchenkov <pt...@is...> * xmt.h, xmt.cc: remove _state field, unuseful; add thread Modified: trunk/complement/explore/lib/mt/Makefile.inc =================================================================== --- trunk/complement/explore/lib/mt/Makefile.inc 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/lib/mt/Makefile.inc 2007-02-06 10:13:58 UTC (rev 1510) @@ -3,6 +3,6 @@ LIBNAME = xmt MAJOR = 1 MINOR = 10 -PATCH = 0 +PATCH = 1 SRC_CC = xmt.cc thr_mgr.cc time.cc uid.cc shm.cc SRC_C = fl.c Modified: trunk/complement/explore/test/mt/Makefile.inc =================================================================== --- trunk/complement/explore/test/mt/Makefile.inc 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/test/mt/Makefile.inc 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,6 +1,6 @@ -# -*- makefile -*- Time-stamp: <06/12/16 00:37:10 ptr> +# -*- makefile -*- Time-stamp: <07/02/06 10:04:25 ptr> PRGNAME = mt_ut -SRC_CC = unit_test.cc timespec.cc mutex_test.cc spinlock_test.cc \ - recursive_mutex.cc join.cc signal-1.cc signal-2.cc signal-3.cc flck.cc lfs.cc \ +SRC_CC = unit_test.cc timespec.cc \ + signal-1.cc signal-2.cc signal-3.cc flck.cc lfs.cc \ mt_test.cc mt_test_suite.cc Deleted: trunk/complement/explore/test/mt/join.cc =================================================================== --- trunk/complement/explore/test/mt/join.cc 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/test/mt/join.cc 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,48 +0,0 @@ -// -*- C++ -*- Time-stamp: <06/08/04 11:09:21 ptr> - -/* - * Copyright (c) 2003, 2006 - * Petr Ovtchenkov - * - * Licensed under the Academic Free License Version 2.1 - * - * This material is provided "as is", with absolutely no warranty expressed - * or implied. Any use is at your own risk. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. - */ - -#include <boost/test/unit_test.hpp> - -using namespace boost::unit_test_framework; - -#include <mt/xmt.h> - -using namespace xmt; - -static int x = 0; - -Thread::ret_code thread_entry_call( void * ) -{ - x = 1; - - Thread::ret_code rt; - rt.iword = 0; - - return rt; -} - -void join_test() -{ - BOOST_CHECK( x == 0 ); - - Thread t( thread_entry_call ); - - t.join(); - - BOOST_CHECK( x == 1 ); -} Modified: trunk/complement/explore/test/mt/mt_test.cc =================================================================== --- trunk/complement/explore/test/mt/mt_test.cc 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/test/mt/mt_test.cc 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/02/02 20:53:03 ptr> +// -*- C++ -*- Time-stamp: <07/02/06 10:36:47 ptr> /* - * Copyright (c) 2006 + * Copyright (c) 2006, 2007 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -31,6 +31,334 @@ using namespace boost::unit_test_framework; namespace fs = boost::filesystem; +/* ****************************************************** + * Degenerative case: check that one thread pass throw + * own barrier. + */ +void mt_test::barrier() +{ + xmt::Barrier b( 1 ); + + b.wait(); +} + +/* ****************************************************** + * Start thread, join it. + */ + +static int x = 0; + +xmt::Thread::ret_code thread_entry_call( void * ) +{ + x = 1; + + xmt::Thread::ret_code rt; + rt.iword = 0; + + return rt; +} + +void mt_test::join_test() +{ + BOOST_CHECK( x == 0 ); + + xmt::Thread t( thread_entry_call ); + + t.join(); + + BOOST_CHECK( x == 1 ); +} + +/* ****************************************************** + * Start two threads, align ones on barrier, join. + */ + +xmt::Thread::ret_code thread2_entry_call( void *p ) +{ + xmt::Thread::ret_code rt; + rt.iword = 0; + + xmt::Barrier& b = *reinterpret_cast<xmt::Barrier *>(p); + b.wait(); + + return rt; +} + +void mt_test::barrier2() +{ + xmt::Barrier b; + + xmt::Thread t1( thread2_entry_call, &b ); + xmt::Thread t2( thread2_entry_call, &b ); + + t2.join(); + t1.join(); +} + +/* ****************************************************** + * Start two threads, align ones on barrier; one thread + * relinquish control to other; join (within Thread dtors) + */ + +xmt::Thread::ret_code thread3_entry_call( void *p ) +{ + xmt::Thread::ret_code rt; + rt.iword = 0; + + xmt::Barrier& b = *reinterpret_cast<xmt::Barrier *>(p); + b.wait(); + BOOST_CHECK( xmt::Thread::yield() == 0 ); + + return rt; +} + +void mt_test::yield() +{ + xmt::Barrier b; + + xmt::Thread t1( thread2_entry_call, &b ); + xmt::Thread t2( thread3_entry_call, &b ); + // .join()'s are in Thread's destructors +} + +/* ****************************************************** + * Test for plain mutex. + * + * Start two threads, align ones on barrier, thr2 relinquish + * control to thr1; + * thr1 acquire lock, try to yield control to thr2 (that + * should be blocked on m1); + * Correct order checked by values of x. + */ + +static xmt::Mutex m1; + +xmt::Thread::ret_code thr1( void *p ) +{ + xmt::Barrier& b = *reinterpret_cast<xmt::Barrier *>(p); + b.wait(); + + m1.lock(); + BOOST_CHECK( x == 0 ); + + xmt::Thread::yield(); + + BOOST_CHECK( x == 0 ); + x = 1; + + m1.unlock(); + + xmt::Thread::ret_code rt; + rt.iword = 0; + + return rt; +} + +xmt::Thread::ret_code thr2( void *p ) +{ + xmt::Barrier& b = *reinterpret_cast<xmt::Barrier *>(p); + b.wait(); + xmt::Thread::yield(); + + m1.lock(); + BOOST_CHECK( x == 1 ); + x = 2; + m1.unlock(); + + xmt::Thread::ret_code rt; + rt.iword = 0; + + return rt; +} + +void mt_test::mutex_test() +{ + x = 0; + xmt::Barrier b; + + xmt::Thread t1( thr1, &b ); + xmt::Thread t2( thr2, &b ); + + t1.join(); + t2.join(); + + BOOST_CHECK( x == 2 ); +} + +/* ****************************************************** + * Test for spinlocks. + * + * Start two threads, align ones on barrier, thr2 relinquish + * control to thr1; + * thr1 acquire lock, try to yield control to thr2 (that + * should be blocked on sl1); + * Correct order checked by values of x. + */ + +#ifdef __FIT_PTHREAD_SPINLOCK +static xmt::Spinlock sl1; + +xmt::Thread::ret_code thr1s( void *p ) +{ + xmt::Barrier& b = *reinterpret_cast<xmt::Barrier *>(p); + b.wait(); + + sl1.lock(); + BOOST_CHECK( x == 0 ); + + xmt::Thread::yield(); + + BOOST_CHECK( x == 0 ); + x = 1; + + sl1.unlock(); + + xmt::Thread::ret_code rt; + rt.iword = 0; + + return rt; +} + +xmt::Thread::ret_code thr2s( void *p ) +{ + xmt::Barrier& b = *reinterpret_cast<xmt::Barrier *>(p); + b.wait(); + xmt::Thread::yield(); + + sl1.lock(); + BOOST_CHECK( x == 1 ); + x = 2; + sl1.unlock(); + + xmt::Thread::ret_code rt; + rt.iword = 0; + + return rt; +} + +#endif + +void mt_test::spinlock_test() +{ +#ifdef __FIT_PTHREAD_SPINLOCK + x = 0; + xmt::Barrier b; + + xmt::Thread t1( thr1s, &b ); + xmt::Thread t2( thr2s, &b ); + + t1.join(); + t2.join(); + + BOOST_CHECK( x == 2 ); +#endif +} + +/* ****************************************************** */ + +/* + * Test for recursive-safe mutexes (detect deadlock) + * + * 1. Start thread 1. Acquire lock on m2. + * + * 2. Start thread 2. Yield control to thread 1, to be sure that thread 1 + * acquire lock on m2 first. Acquire lock on m2. + * Due to m2 locked in thread 1, waiting on m2.lock. + * + * 3. Thread 1 relinquish control to thread 2, to give it chance. + * + * 4. From thread 1 call function 'recursive', where acquire lock on m2, + * relinquish control to thread2, and then release m2. + * If mutex recursive-safe, function 'recursive' will finished correctly. + * Otherwise, deedlock will happen on m2.lock in 'recursive'. + * + * 5. Release m2 in thread 1. + * + * 6. Pass through m2 lock in thread 2. Call function 'recursive', + * where acquire lock on m2, relinquish control, and then release m2. See item 4 before. + * + * 7. Release m2 in thread 2. + * + * 8. Test finished. + * + */ + +xmt::__Mutex<true,false> m2; + +void recursive() +{ + m2.lock(); + + x = 2; + xmt::Thread::yield(); + BOOST_CHECK( x == 2 ); + + m2.unlock(); +} + +xmt::Thread::ret_code thr1r( void *p ) +{ + xmt::Barrier& b = *reinterpret_cast<xmt::Barrier *>(p); + b.wait(); + + m2.lock(); + + BOOST_CHECK( x == 0 ); + x = 1; + xmt::Thread::yield(); + BOOST_CHECK( x == 1 ); + recursive(); + BOOST_CHECK( x == 2 ); + x = 3; + + m2.unlock(); + + xmt::Thread::ret_code rt; + + rt.iword = 0; + + return rt; +} + +xmt::Thread::ret_code thr2r( void *p ) +{ + xmt::Barrier& b = *reinterpret_cast<xmt::Barrier *>(p); + b.wait(); + + xmt::Thread::yield(); + + m2.lock(); + + BOOST_CHECK( x == 3 ); + xmt::Thread::yield(); + recursive(); + BOOST_CHECK( x == 2 ); + + m2.unlock(); + + xmt::Thread::ret_code rt; + + rt.iword = 0; + + return rt; +} + +void mt_test::recursive_mutex_test() +{ + x = 0; + xmt::Barrier b; + + xmt::Thread t1( thr1r, &b ); + xmt::Thread t2( thr2r, &b ); + + t1.join(); + t2.join(); + + BOOST_CHECK( x == 2 ); +} + +/* ****************************************************** */ + void mt_test::fork() { shmid_ds ds; @@ -86,6 +414,8 @@ shmctl( id, IPC_RMID, &ds ); } +/* ****************************************************** */ + void mt_test::pid() { shmid_ds ds; @@ -148,6 +478,8 @@ shmctl( id, IPC_RMID, &ds ); } +/* ****************************************************** */ + void mt_test::shm_segment() { const char fname[] = "/tmp/mt_test.shm"; @@ -216,6 +548,8 @@ } } +/* ****************************************************** */ + void mt_test::shm_alloc() { const char fname[] = "/tmp/mt_test.shm"; @@ -290,7 +624,7 @@ } -/* +/* ****************************************************** * This test is similar mt_test::fork() above, but instead plain shm_* * functions it use allocator based on shared memory segment */ @@ -344,8 +678,8 @@ } } -/* - * Test: how to take named object +/* ****************************************************** + * Test: how to take named object in shared memory segment */ void mt_test::shm_named_obj() { @@ -425,13 +759,23 @@ } +/* ****************************************************** + * Thread pool (aka ThreadMgr) test. + * + * Start 200 threads under ThreadMgr; check that all threads + * started, check that all theads finished, no garbage in + * ThreadMgr remains. + */ + static int my_thr_cnt = 0; +static int my_thr_scnt = 0; static xmt::Mutex lock; xmt::Thread::ret_code thread_mgr_entry_call( void * ) { lock.lock(); ++my_thr_cnt; + ++my_thr_scnt; lock.unlock(); xmt::Thread::ret_code rt; @@ -455,6 +799,7 @@ // cerr << "Join!\n"; mgr.join(); + BOOST_CHECK( my_thr_scnt == 200 ); BOOST_CHECK( my_thr_cnt == 0 ); BOOST_CHECK( mgr.size() == 0 ); } Modified: trunk/complement/explore/test/mt/mt_test.h =================================================================== --- trunk/complement/explore/test/mt/mt_test.h 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/test/mt/mt_test.h 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/02/02 16:45:13 ptr> +// -*- C++ -*- Time-stamp: <07/02/06 09:48:27 ptr> /* - * Copyright (c) 2006 + * Copyright (c) 2006, 2007 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -11,8 +11,17 @@ #ifndef __MT_TEST_H #define __MT_TEST_H -struct mt_test +class mt_test { + public: + void barrier(); + void join_test(); + void barrier2(); + void yield(); + void mutex_test(); + void spinlock_test(); + void recursive_mutex_test(); + void fork(); void pid(); void shm_segment(); @@ -20,6 +29,10 @@ void fork_shm(); void shm_named_obj(); void thr_mgr(); + + private: + // static xmt::Thread::ret_code thread_entry_call( void * ); + // static int x; }; #endif // __MT_TEST_H Modified: trunk/complement/explore/test/mt/mt_test_suite.cc =================================================================== --- trunk/complement/explore/test/mt/mt_test_suite.cc 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/test/mt/mt_test_suite.cc 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/02/02 17:15:47 ptr> +// -*- C++ -*- Time-stamp: <07/02/06 10:06:37 ptr> /* * Copyright (c) 2006, 2007 @@ -11,6 +11,8 @@ #include "mt_test_suite.h" #include "mt_test.h" +#include <config/feature.h> + using namespace boost::unit_test_framework; mt_test_suite::mt_test_suite() : @@ -18,6 +20,15 @@ { boost::shared_ptr<mt_test> instance( new mt_test() ); + test_case *barrier_tc = BOOST_CLASS_TEST_CASE( &mt_test::barrier, instance ); + test_case *join_tc = BOOST_CLASS_TEST_CASE( &mt_test::join_test, instance ); + test_case *barrier2_tc = BOOST_CLASS_TEST_CASE( &mt_test::barrier2, instance ); + test_case *yield_tc = BOOST_CLASS_TEST_CASE( &mt_test::yield, instance ); + test_case *mutex_test_tc = BOOST_CLASS_TEST_CASE( &mt_test::mutex_test, instance ); +#ifdef __FIT_PTHREAD_SPINLOCK + test_case *spinlock_test_tc = BOOST_CLASS_TEST_CASE( &mt_test::spinlock_test, instance ); +#endif + test_case *recursive_mutex_test_tc = BOOST_CLASS_TEST_CASE( &mt_test::recursive_mutex_test, instance ); test_case *fork_tc = BOOST_CLASS_TEST_CASE( &mt_test::fork, instance ); test_case *pid_tc = BOOST_CLASS_TEST_CASE( &mt_test::pid, instance ); test_case *shm_segment_tc = BOOST_CLASS_TEST_CASE( &mt_test::shm_segment, instance ); @@ -27,11 +38,30 @@ test_case *thr_mgr_tc = BOOST_CLASS_TEST_CASE( &mt_test::thr_mgr, instance ); + barrier2_tc->depends_on( barrier_tc ); + barrier2_tc->depends_on( join_tc ); + yield_tc->depends_on( barrier2_tc ); + mutex_test_tc->depends_on( yield_tc ); +#ifdef __FIT_PTHREAD_SPINLOCK + spinlock_test_tc->depends_on( yield_tc ); +#endif + recursive_mutex_test_tc->depends_on( mutex_test_tc ); + pid_tc->depends_on( fork_tc ); shm_alloc_tc->depends_on( shm_segment_tc ); fork_shm_tc->depends_on( shm_alloc_tc ); shm_nm_obj_tc->depends_on( fork_shm_tc ); + add( barrier_tc, 0, 2 ); + add( join_tc ); + add( barrier2_tc, 0, 3 ); + add( yield_tc, 0, 3 ); + add( mutex_test_tc, 0, 3 ); +#ifdef __FIT_PTHREAD_SPINLOCK + add( spinlock_test_tc, 0, 3 ); +#endif + add( recursive_mutex_test_tc, 0, 3 ); + add( fork_tc ); add( pid_tc ); add( shm_segment_tc ); Deleted: trunk/complement/explore/test/mt/mutex_test.cc =================================================================== --- trunk/complement/explore/test/mt/mutex_test.cc 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/test/mt/mutex_test.cc 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,121 +0,0 @@ -// -*- C++ -*- Time-stamp: <06/12/15 10:37:09 ptr> - -/* - * Copyright (c) 2002, 2003, 2006 - * Petr Ovtchenkov - * - * Licensed under the Academic Free License Version 3.0 - * - */ - -#include <boost/test/unit_test.hpp> - -using namespace boost::unit_test_framework; - -#include <mt/xmt.h> - -using namespace std; -using namespace xmt; - -static Mutex m1; - -static int v = 0; -static volatile int msync = 0; - -xmt::Thread::ret_code thr1( void * ) -{ - m1.lock(); - msync = 1; - BOOST_CHECK( v == 0 ); - - delay( xmt::timespec( 1, 0 ) ); - - BOOST_CHECK( v == 0 ); - v = 1; - - m1.unlock(); - - xmt::Thread::ret_code rt; - rt.iword = 0; - - return rt; -} - -xmt::Thread::ret_code thr2( void * ) -{ - int j = 0; - while ( !msync ) { - ++j; - } - m1.lock(); - BOOST_CHECK( v == 1); - v = 2; - m1.unlock(); - - xmt::Thread::ret_code rt; - rt.iword = 0; - - return rt; -} - -xmt::Thread::ret_code thr3( void * ) -{ - m1.lock(); - msync = 1; - - BOOST_CHECK( v == 0 ); - - delay( xmt::timespec( 1, 0 ) ); - - v = 1; - - m1.unlock(); - xmt::Thread::ret_code rt; - rt.iword = 0; - - return rt; -} - -xmt::Thread::ret_code thr4( void * ) -{ -#ifndef _WIN32 // no trylock - int j = 0; - while ( !msync ) { - ++j; - } - if ( m1.trylock() == 0 ) { - BOOST_CHECK( v == 1 ); - m1.unlock(); - BOOST_ERROR( "m1.trylock() return zero!" ); - } -#endif // _WIN32 - - xmt::Thread::ret_code rt; - rt.iword = 0; - - return rt; -} - - -void mutex_test() -{ - v = 0; - Thread t1( thr1 ); - Thread t2( thr2 ); - - t1.join(); - t2.join(); - - msync = 0; - - BOOST_CHECK( v == 2 ); - -#ifndef _WIN32 - v = 0; - Thread t3( thr3 ); - Thread t4( thr4 ); - - t3.join(); - t4.join(); -#endif // _WIN32 -} Deleted: trunk/complement/explore/test/mt/recursive_mutex.cc =================================================================== --- trunk/complement/explore/test/mt/recursive_mutex.cc 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/test/mt/recursive_mutex.cc 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,170 +0,0 @@ -// -*- C++ -*- Time-stamp: <06/12/15 10:39:45 ptr> - -/* - * Copyright (c) 2003, 2006 - * Petr Ovtchenkov - * - * Licensed under the Academic Free License Version 3.0 - * - */ - - -/* - * Test for recursive-safe mutexes (detect deadlock) - * - * 1. Start thread 1. Acquire lock on m. Sleep hread 1 sec. - * - * 2. Start thread 2. Acquire lock on m. Due to m locked - * in thread 1, waiting on m.lock. - * - * 3. From thread 1 call function 'recursive', where acquire lock on m, - * sleep 1 sec, and release m. - * If mutex recursive-safe, function 'recursive' will finished correctly. - * Otherwise, deedlock will happen on m.lock in 'recursive'. - * - * 4. Release m in thread 1. - * - * 5. Pass through m lock in thread 2. Call function 'recursive', - * where acquire lock on m, sleep 1 sec, and release m. See item 3 before. - * - * 6. Release m in thread 2. - * - * 7. Program finished. - * - */ - -#include <boost/test/unit_test.hpp> - -using namespace boost::unit_test_framework; - -#include <mt/xmt.h> -#include <iostream> - -using namespace xmt; -using namespace std; - -// Mutex pm; - -__Mutex<true,false> m; -static int v = 0; - -void recursive() -{ - // pm.lock(); - // cerr << "before lock recursive" << endl; - // pm.unlock(); - - m.lock(); - v = 2; - - xmt::sleep( xmt::timespec(1,0) ); - BOOST_CHECK( v == 2 ); - m.unlock(); - - // pm.lock(); - // cerr << "after lock recursive" << endl; - // pm.unlock(); -} - -Thread::ret_code thread_one( void * ) -{ - // pm.lock(); - // cerr << "before lock in thread one" << endl; - // pm.unlock(); - - m.lock(); - - BOOST_CHECK( v == 0 ); - - v = 1; - - // pm.lock(); - // cerr << "after lock in thread one" << endl; - // pm.unlock(); - - xmt::sleep( xmt::timespec(1,0) ); - - BOOST_CHECK( v == 1 ); - - recursive(); - - // pm.lock(); - // cerr << "before unlock in thread one" << endl; - // pm.unlock(); - - BOOST_CHECK( v == 2 ); - - v = 3; - - m.unlock(); - - // pm.lock(); - // cerr << "after unlock in thread one" << endl; - // pm.unlock(); - - Thread::ret_code rt; - - rt.iword = 0; - - return rt; -} - -Thread::ret_code thread_two( void * ) -{ - // pm.lock(); - // cerr << "before lock in thread two" << endl; - // pm.unlock(); - - m.lock(); - - // pm.lock(); - // cerr << "after lock in thread two" << endl; - // pm.unlock(); - BOOST_CHECK( v == 3 ); - - xmt::sleep( xmt::timespec(1,0) ); - recursive(); - - // pm.lock(); - // cerr << "before unlock in thread two" << endl; - // pm.unlock(); - - BOOST_CHECK( v == 2 ); - - m.unlock(); - - // pm.lock(); - // cerr << "after unlock in thread two" << endl; - // pm.unlock(); - - Thread::ret_code rt; - - rt.iword = 0; - - return rt; -} - - -void recursive_mutex_test() -{ - // pm.lock(); - // cerr << "main: create thread one" << endl; - // pm.unlock(); - - Thread t1( thread_one ); - - // pm.lock(); - // cerr << "main: create thread two" << endl; - // pm.unlock(); - - Thread t2( thread_two ); - - t1.join(); - t2.join(); - - // pm.lock(); - // cerr << "main: End" << endl; - // pm.unlock(); - - // return 0; -} Deleted: trunk/complement/explore/test/mt/spinlock_test.cc =================================================================== --- trunk/complement/explore/test/mt/spinlock_test.cc 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/test/mt/spinlock_test.cc 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,106 +0,0 @@ -// -*- C++ -*- Time-stamp: <06/12/15 10:38:16 ptr> - -/* - * Copyright (c) 2002, 2003, 2006 - * Petr Ovtchenkov - * - * Licensed under the Academic Free License Version 3.0 - * - */ - -#include <boost/test/unit_test.hpp> - -using namespace boost::unit_test_framework; - -#include <mt/xmt.h> - -using namespace std; -using namespace xmt; - -static int v = 0; - -#ifdef __FIT_PTHREAD_SPINLOCK -static Spinlock sl1; - -xmt::Thread::ret_code thr1_sl( void * ) -{ - sl1.lock(); - BOOST_CHECK( v == 0 ); - - delay( xmt::timespec( 1, 0 ) ); - - BOOST_CHECK( v == 0 ); - v = 1; - - sl1.unlock(); - - xmt::Thread::ret_code rt; - rt.iword = 0; - - return rt; -} - -xmt::Thread::ret_code thr2_sl( void * ) -{ - sl1.lock(); - BOOST_CHECK( v == 1); - v = 2; - sl1.unlock(); - - xmt::Thread::ret_code rt; - rt.iword = 0; - - return rt; -} - -xmt::Thread::ret_code thr3_sl( void * ) -{ - sl1.lock(); - - BOOST_CHECK( v == 0 ); - - delay( xmt::timespec( 1, 0 ) ); - - v = 1; - - sl1.unlock(); - - xmt::Thread::ret_code rt; - rt.iword = 0; - - return rt; -} - -xmt::Thread::ret_code thr4_sl( void * ) -{ - if ( sl1.trylock() == 0 ) { - BOOST_CHECK( v == 1 ); - sl1.unlock(); - BOOST_ERROR( "m1.trylock() return zero!" ); - } - - xmt::Thread::ret_code rt; - rt.iword = 0; - - return rt; -} - -void spinlock_test() -{ - v = 0; - Thread t1( thr1_sl ); - Thread t2( thr2_sl ); - - t1.join(); - t2.join(); - - BOOST_CHECK( v == 2 ); - - v = 0; - Thread t3( thr3_sl ); - Thread t4( thr4_sl ); - - t3.join(); - t4.join(); -} -#endif // __FIT_PTHREAD_SPINLOCK Modified: trunk/complement/explore/test/mt/unit_test.cc =================================================================== --- trunk/complement/explore/test/mt/unit_test.cc 2007-02-05 13:09:03 UTC (rev 1509) +++ trunk/complement/explore/test/mt/unit_test.cc 2007-02-06 10:13:58 UTC (rev 1510) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <06/12/16 00:36:47 ptr> +// -*- C++ -*- Time-stamp: <07/02/06 10:08:47 ptr> /* * Copyright (c) 2002, 2003, 2004, 2006 @@ -16,12 +16,6 @@ using namespace boost::unit_test_framework; void timespec_diff(); -void join_test(); -void mutex_test(); -#ifdef __FIT_PTHREAD_SPINLOCK -void spinlock_test(); -#endif // __FIT_PTHREAD_SPINLOCK -void recursive_mutex_test(); void signal_1_test(); void signal_2_test(); void signal_3_test(); @@ -38,12 +32,6 @@ test_suite *ts = BOOST_TEST_SUITE( "libxmt test" ); ts->add( BOOST_TEST_CASE( ×pec_diff ) ); - ts->add( BOOST_TEST_CASE( &join_test ) ); - ts->add( BOOST_TEST_CASE( &mutex_test ) ); -#ifdef __FIT_PTHREAD_SPINLOCK - ts->add( BOOST_TEST_CASE( &spinlock_test ) ); -#endif - ts->add( BOOST_TEST_CASE( &recursive_mutex_test ) ); ts->add( BOOST_TEST_CASE( &signal_1_test ) ); // You can't throw exception from signal handler // (stack saved/restored, that confuse stack unwind); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |