diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-11-16 14:50:09 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-11-23 12:52:06 +0100 |
commit | c42be504c92d76d2e06d0fc8ebd05fc913376d2d (patch) | |
tree | 259f8a712a6139f427888647955bc3c95480877e /testsuites/psxtests/psxspin01/test.c | |
parent | score: Add RTEMS_ALIAS() (diff) | |
download | rtems-c42be504c92d76d2e06d0fc8ebd05fc913376d2d.tar.bz2 |
posix: Add self-contained pthread spinlock
Turn pthread_spinlock_t into a self-contained object. On uni-processor
configurations, interrupts are disabled in the lock/trylock operations
and the previous interrupt status is restored in the corresponding
unlock operations. On SMP configurations, a ticket lock is a acquired
and released in addition.
The self-contained pthread_spinlock_t object is defined by Newlib in
<sys/_pthreadtypes.h>.
typedef struct {
struct _Ticket_lock_Control _lock;
__uint32_t _interrupt_state;
} pthread_spinlock_t;
This implementation is simple and efficient. However, this test case of
the Linux Test Project would fail due to call of printf() and sleep()
during spin lock ownership:
https://github.com/linux-test-project/ltp/blob/master/testcases/open_posix_testsuite/conformance/interfaces/pthread_spin_lock/1-2.c
There is only limited support for profiling on SMP configurations.
Delete CORE spinlock implementation.
Update #2674.
Diffstat (limited to 'testsuites/psxtests/psxspin01/test.c')
-rw-r--r-- | testsuites/psxtests/psxspin01/test.c | 196 |
1 files changed, 50 insertions, 146 deletions
diff --git a/testsuites/psxtests/psxspin01/test.c b/testsuites/psxtests/psxspin01/test.c index 270cdcfc86..33153addda 100644 --- a/testsuites/psxtests/psxspin01/test.c +++ b/testsuites/psxtests/psxspin01/test.c @@ -17,6 +17,7 @@ #include "config.h" #endif +#define TESTS_USE_PRINTK #include "tmacros.h" #include <stdio.h> #include <errno.h> @@ -30,38 +31,6 @@ const char rtems_test_name[] = "PSXSPIN 1"; /* forward declarations to avoid warnings */ int test_main(void); -rtems_task SpinlockThread(rtems_task_argument arg); - -pthread_spinlock_t Spinlock; - -volatile int mainThreadSpinning; - -rtems_task SpinlockThread(rtems_task_argument arg) -{ - int status; - - if ( mainThreadSpinning ) { - puts( "main thread is not supposed to be spinning yet" ); - exit(0); - } - puts( "pthread_spin_lock( &Spinlock ) from Thread -- OK" ); - status = pthread_spin_lock( &Spinlock ); - rtems_test_assert( status == 0 ); - - puts( "sleep to allow main thread to run" ); - sleep( 1 ); - - if ( !mainThreadSpinning ) { - puts( "main thread is not spinning on lock" ); - exit(0); - } - - puts( "pthread_spin_unlock( &Spinlock ) from Thread -- OK" ); - status = pthread_spin_unlock( &Spinlock ); - rtems_test_assert( status == 0 ); - - rtems_task_delete( RTEMS_SELF ); -} /* * main entry point to the test @@ -77,158 +46,93 @@ int main( #endif { pthread_spinlock_t spinlock; + pthread_spinlock_t spinlock2; int status; - rtems_status_code rstatus; - rtems_id taskid; TEST_BEGIN(); - puts( "pthread_spin_init( NULL, PTHREAD_PROCESS_PRIVATE ) -- EINVAL" ); - status = pthread_spin_init( NULL, PTHREAD_PROCESS_PRIVATE ); - rtems_test_assert( status == EINVAL ); - - puts( "pthread_spin_init( NULL, PTHREAD_PROCESS_SHARED ) -- EINVAL" ); - status = pthread_spin_init( NULL, PTHREAD_PROCESS_PRIVATE ); - rtems_test_assert( status == EINVAL ); - - puts( "pthread_spin_init( &spinlock, 0x1234 ) -- EINVAL" ); - status = pthread_spin_init( &spinlock, 0x1234 ); - rtems_test_assert( status == EINVAL ); - - puts( "pthread_spin_init( &spinlock, PTHREAD_PROCESS_SHARED ) -- EINVAL" ); - status = pthread_spin_init( &spinlock, PTHREAD_PROCESS_SHARED ); - rtems_test_assert( status == EINVAL ); - - /* This successfully creates one */ - puts( "pthread_spin_init( &Spinlock, PTHREAD_PROCESS_PRIVATE ) -- OK" ); - status = pthread_spin_init( &Spinlock, PTHREAD_PROCESS_PRIVATE ); + puts( "pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ) -- OK" ); + status = pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ); rtems_test_assert( status == 0 ); - puts( "pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ) -- EAGAIN" ); - status = pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ); - rtems_test_assert( status == EAGAIN ); + puts( "pthread_spin_destroy( &spinlock ) -- OK" ); + status = pthread_spin_destroy( &spinlock ); + rtems_test_assert( status == 0 ); - puts( "pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ) -- EAGAIN" ); + puts( "pthread_spin_init( &spinlock, PTHREAD_PROCESS_SHARED ) -- OK" ); status = pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ); - rtems_test_assert( status == EAGAIN ); - - puts( "pthread_spin_lock( NULL ) -- EINVAL" ); - status = pthread_spin_lock( NULL ); - rtems_test_assert( status == EINVAL ); + rtems_test_assert( status == 0 ); - puts( "pthread_spin_trylock( NULL ) -- EINVAL" ); - status = pthread_spin_trylock( NULL ); - rtems_test_assert( status == EINVAL ); + puts( "pthread_spin_destroy( &spinlock ) -- OK" ); + status = pthread_spin_destroy( &spinlock ); + rtems_test_assert( status == 0 ); - puts( "pthread_spin_unlock( NULL ) -- EINVAL" ); - status = pthread_spin_unlock( NULL ); - rtems_test_assert( status == EINVAL ); + puts( "pthread_spin_init( &spinlock, 0x1234 ) -- OK" ); + status = pthread_spin_init( &spinlock, 0x1234 ); + rtems_test_assert( status == 0 ); - puts( "pthread_spin_destroy( NULL ) -- EINVAL" ); - status = pthread_spin_destroy( NULL ); - rtems_test_assert( status == EINVAL ); + puts( "pthread_spin_init( &spinlock2, 0 ) -- OK" ); + status = pthread_spin_init( &spinlock2, 0 ); + rtems_test_assert( status == 0 ); - spinlock = 0; + rtems_test_assert( _ISR_Get_level() == 0 ); - puts( "pthread_spin_lock( &spinlock ) -- EINVAL" ); + puts( "pthread_spin_lock( &spinlock ) -- OK" ); status = pthread_spin_lock( &spinlock ); - rtems_test_assert( status == EINVAL ); + rtems_test_assert( status == 0 ); - puts( "pthread_spin_trylock( &spinlock ) -- EINVAL" ); - status = pthread_spin_trylock( &spinlock ); - rtems_test_assert( status == EINVAL ); + rtems_test_assert( _ISR_Get_level() != 0 ); - puts( "pthread_spin_unlock( &spinlock ) -- EINVAL" ); - status = pthread_spin_unlock( &spinlock ); - rtems_test_assert( status == EINVAL ); - - puts( "pthread_spin_destroy( &spinlock ) -- EINVAL" ); - status = pthread_spin_destroy( &spinlock ); - rtems_test_assert( status == EINVAL ); + puts( "pthread_spin_lock( &spinlock2 ) -- OK" ); + status = pthread_spin_lock( &spinlock2 ); + rtems_test_assert( status == 0 ); - puts( "pthread_spin_unlock( &Spinlock ) -- EPERM" ); - status = pthread_spin_unlock( &Spinlock ); - rtems_test_assert( status == EPERM ); + rtems_test_assert( _ISR_Get_level() != 0 ); - /* Now some basic locking and unlocking with a deadlock verification */ - puts( "pthread_spin_lock( &Spinlock ) -- OK" ); - status = pthread_spin_lock( &Spinlock ); + puts( "pthread_spin_unlock( &spinlock2 ) -- OK" ); + status = pthread_spin_unlock( &spinlock2 ); rtems_test_assert( status == 0 ); - puts( "pthread_spin_lock( &Spinlock ) -- EDEADLK" ); - status = pthread_spin_lock( &Spinlock ); - rtems_test_assert( status == EDEADLK ); - - puts( "pthread_spin_trylock( &Spinlock ) -- EDEADLK" ); - status = pthread_spin_trylock( &Spinlock ); - rtems_test_assert( status == EDEADLK ); + rtems_test_assert( _ISR_Get_level() != 0 ); - puts( "pthread_spin_unlock( &Spinlock ) -- OK" ); - status = pthread_spin_unlock( &Spinlock ); + puts( "pthread_spin_unlock( &spinlock ) -- OK" ); + status = pthread_spin_unlock( &spinlock ); rtems_test_assert( status == 0 ); - /* Try lock/unlock pair */ - puts( "pthread_spin_trylock( &Spinlock ) -- OK" ); - status = pthread_spin_trylock( &Spinlock ); - rtems_test_assert( status == 0 ); + rtems_test_assert( _ISR_Get_level() == 0 ); - puts( "pthread_spin_unlock( &Spinlock ) -- OK" ); - status = pthread_spin_unlock( &Spinlock ); + puts( "pthread_spin_trylock( &spinlock ) -- OK" ); + status = pthread_spin_trylock( &spinlock ); rtems_test_assert( status == 0 ); - /* Let another thread lock a spinlock and we contend with it */ - - mainThreadSpinning = 0; + rtems_test_assert( _ISR_Get_level() != 0 ); - /* Create a helper task */ - rstatus = rtems_task_create( - rtems_build_name( 'S', 'P', 'I', 'N' ), - 1, - RTEMS_MINIMUM_STACK_SIZE, - RTEMS_DEFAULT_MODES, - RTEMS_DEFAULT_ATTRIBUTES, - &taskid - ); - rtems_test_assert( rstatus == RTEMS_SUCCESSFUL ); + puts( "pthread_spin_trylock( &spinlock2 ) -- OK" ); + status = pthread_spin_trylock( &spinlock2 ); + rtems_test_assert( status == 0 ); - rstatus = rtems_task_start( taskid, SpinlockThread, 0 ); - rtems_test_assert( rstatus == RTEMS_SUCCESSFUL ); - /* We should be preempted immediately. The thread is expected to: - * + verify we haven't set the main thread spinning flag - * + lock the spinlock - * + delay - */ + rtems_test_assert( _ISR_Get_level() != 0 ); - mainThreadSpinning = 1; + puts( "pthread_spin_unlock( &spinlock2 ) -- OK" ); + status = pthread_spin_unlock( &spinlock2 ); + rtems_test_assert( status == 0 ); - puts( "pthread_spin_unlock( &Spinlock ) -- EPERM" ); - status = pthread_spin_unlock( &Spinlock ); - rtems_test_assert( status == EPERM ); + rtems_test_assert( _ISR_Get_level() != 0 ); - puts( "pthread_spin_lock( &Spinlock ) -- OK" ); - status = pthread_spin_lock( &Spinlock ); + puts( "pthread_spin_unlock( &spinlock ) -- OK" ); + status = pthread_spin_unlock( &spinlock ); rtems_test_assert( status == 0 ); - /* The thread wakes up, unlocks spin lock, and deletes itself. - * So when we get back here, about a second has passed and we now - * have the spinlock locked. - */ + rtems_test_assert( _ISR_Get_level() == 0 ); - /* spin lock should be locked when we return so destroying it gives busy */ - puts( "pthread_spin_destroy( &Spinlock ) -- EBUSY" ); - status = pthread_spin_destroy( &Spinlock ); - rtems_test_assert( status == EBUSY ); - - /* Unlock it for a normal destroy */ - puts( "pthread_spin_unlock( &Spinlock ) -- OK" ); - status = pthread_spin_unlock( &Spinlock ); + puts( "pthread_spin_destroy( &spinlock2 ) -- OK" ); + status = pthread_spin_destroy( &spinlock2 ); rtems_test_assert( status == 0 ); - puts( "pthread_spin_destroy( &Spinlock ) -- OK" ); - status = pthread_spin_destroy( &Spinlock ); + puts( "pthread_spin_destroy( &spinlock ) -- OK" ); + status = pthread_spin_destroy( &spinlock ); rtems_test_assert( status == 0 ); - /*************** END OF TEST *****************/ TEST_END(); exit(0); } |