summaryrefslogblamecommitdiffstats
path: root/testsuites/psxtests/psxspin01/test.c
blob: 76d3abcafcefd25bdf9a81a59f0d0b48e96aac3f (plain) (tree)
1
2
3
4
5
6
7
8

         
  




                                                   



                                                           
                                         

   



                    
                    







                                           



                                                   













                                                             
                                   










                                                               
                                   

















                                  
                               






                                                                         
                                        


                                                                        
                                        


                                                             
                                        


                                                                             
                                        



                                                                          
                                   


                                                                              
                                        


                                                                              
                                        


                                                
                                        


                                                   
                                        


                                                  
                                        


                                                   
                                        




                                                     
                                        


                                                        
                                        


                                                       
                                        


                                                        
                                        


                                                                    
                                   



                                                                         
                                   


                                                      
                                         


                                                         
                                         


                                                   
                                   



                                                    
                                   


                                                   
                                   













                                                                 
                                                   

                                                          
                                                   








                                                                    
                                   








                                                                             
                                       



                                                   
                                   


                                                    
                                   




                                                  
/**
 *  @file
 *
 *  This test exercises the POSIX Spinlock manager.
 */

/*
 *  COPYRIGHT (c) 1989-2012.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "tmacros.h"
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

#include <pthread.h>

#include <rtems.h>  /* for task creation */

/* 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
 */

#if defined(__rtems__)
int test_main(void)
#else
int main(
  int    argc,
  char **argv
)
#endif
{
  pthread_spinlock_t    spinlock;
  int                   status;
  rtems_status_code     rstatus;
  rtems_id              taskid;

  puts( "\n\n*** POSIX SPINLOCK TEST 01 ***" );

  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 );
  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_init( &spinlock, PTHREAD_PROCESS_PRIVATE ) -- EAGAIN" );
  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 );

  puts( "pthread_spin_trylock( NULL ) -- EINVAL" );
  status = pthread_spin_trylock( NULL );
  rtems_test_assert( status == EINVAL );

  puts( "pthread_spin_unlock( NULL ) -- EINVAL" );
  status = pthread_spin_unlock( NULL );
  rtems_test_assert( status == EINVAL );

  puts( "pthread_spin_destroy( NULL ) -- EINVAL" );
  status = pthread_spin_destroy( NULL );
  rtems_test_assert( status == EINVAL );

  spinlock = 0;

  puts( "pthread_spin_lock( &spinlock ) -- EINVAL" );
  status = pthread_spin_lock( &spinlock );
  rtems_test_assert( status == EINVAL );

  puts( "pthread_spin_trylock( &spinlock ) -- EINVAL" );
  status = pthread_spin_trylock( &spinlock );
  rtems_test_assert( status == EINVAL );

  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_unlock( &Spinlock ) -- already unlocked OK" );
  status = pthread_spin_unlock( &Spinlock );
  rtems_test_assert( status == 0 );

  /* Now some basic locking and unlocking with a deadlock verification */
  puts( "pthread_spin_lock( &Spinlock ) -- OK" );
  status = pthread_spin_lock( &Spinlock );
  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 );

  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 );

  puts( "pthread_spin_unlock( &Spinlock ) -- OK" );
  status = pthread_spin_unlock( &Spinlock );
  rtems_test_assert( status == 0 );

  /* Let another thread lock a spinlock and we contend with it */

  mainThreadSpinning = 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 );

  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
   */

  mainThreadSpinning = 1;
  puts( "pthread_spin_lock( &Spinlock ) -- OK" );
  status = pthread_spin_lock( &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.
   */

  /* 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 );
  rtems_test_assert( status == 0 );

  puts( "pthread_spin_destroy( &Spinlock ) -- OK" );
  status = pthread_spin_destroy( &Spinlock );
  rtems_test_assert( status == 0 );

  /*************** END OF TEST *****************/
  puts( "*** END OF POSIX SPINLOCK TEST 01 ***" );
  exit(0);
}