Пример #1
0
static void test_isr_locks( void )
{
  ISR_Level normal_interrupt_level = _ISR_Get_level();
  ISR_lock_Control initialized = ISR_LOCK_INITIALIZER;
  ISR_lock_Control lock;
  ISR_lock_Context lock_context;

  _ISR_lock_Initialize( &lock );
  rtems_test_assert( memcmp( &lock, &initialized, sizeof( lock ) ) == 0 );

  _ISR_lock_ISR_disable_and_acquire( &lock, &lock_context );
  rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
  _ISR_lock_Release_and_ISR_enable( &lock, &lock_context );

  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );

  _ISR_lock_Acquire( &lock, &lock_context );
  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
  _ISR_lock_Release( &lock, &lock_context );

  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );

  _ISR_lock_Destroy( &lock );
  _ISR_lock_Destroy( &initialized );
}
Пример #2
0
static void isr_level_check_task( rtems_task_argument arg )
{
  test_isr_level_context *ctx = (test_isr_level_context *) arg;
  rtems_status_code sc;

  ctx->actual_level = _ISR_Get_level();

  sc = rtems_event_send( ctx->master_task_id,  TEST_ISR_EVENT );
  rtems_test_assert( sc == RTEMS_SUCCESSFUL );

  ( void ) rtems_task_suspend( RTEMS_SELF );
  rtems_test_assert( 0 );
}
  void _Assert_Thread_dispatching_repressed( void )
  {
    bool dispatch_is_disabled;
    ISR_Level level;
    Per_CPU_Control *per_cpu;

    _ISR_Disable( level );
    per_cpu = _Per_CPU_Get_by_index( _SMP_Get_current_processor() );
    dispatch_is_disabled = per_cpu->thread_dispatch_disable_level != 0;
    _ISR_Enable( level );

    _Assert( dispatch_is_disabled || _ISR_Get_level() != 0 );
  }
void _Giant_Drop( Per_CPU_Control *self_cpu )
{
  Giant_Control *giant = &_Giant;
  uint32_t self_cpu_index = _Per_CPU_Get_index( self_cpu );

  _Assert( _ISR_Get_level() != 0 );

  if ( giant->owner_cpu == self_cpu_index ) {
    giant->nest_level = 0;
    giant->owner_cpu = NO_OWNER_CPU;
    _SMP_lock_Release( &giant->lock, &self_cpu->Giant_lock_context );
  }
}
Пример #5
0
static void test_isr_level( void )
{
  ISR_Level mask = CPU_MODES_INTERRUPT_MASK;
  ISR_Level normal = _ISR_Get_level();
  ISR_Level current = 0;
  ISR_Level last_proper_level;

  _ISR_Set_level( current );
  rtems_test_assert( _ISR_Get_level() == current );

  for ( current = current + 1 ; current <= mask ; ++current ) {
    ISR_Level actual;

    _ISR_Set_level( current );

    actual = _ISR_Get_level();
    rtems_test_assert( actual == current || actual == ( current - 1 ) );

    if ( _ISR_Get_level() != current ) {
      break;
    }
  }

  last_proper_level = current - 1;

  for ( current = current + 1 ; current <= mask ; ++current ) {
    _ISR_Set_level( current );
    rtems_test_assert( _ISR_Get_level() == current );
  }

  _ISR_Set_level( normal );

  /*
   * Now test that the ISR level specified for _Thread_Initialize() propagates
   * properly to the thread.
   */
  test_isr_level_for_new_threads( last_proper_level );
}
Пример #6
0
rtems_status_code rtems_task_mode(
    rtems_mode  mode_set,
    rtems_mode  mask,
    rtems_mode *previous_mode_set
)
{
    Thread_Control     *executing;
    RTEMS_API_Control  *api;
    ASR_Information    *asr;
    bool                is_asr_enabled = false;
    bool                needs_asr_dispatching = false;
    rtems_mode          old_mode;

    if ( !previous_mode_set )
        return RTEMS_INVALID_ADDRESS;

    executing     = _Thread_Executing;
    api = executing->API_Extensions[ THREAD_API_RTEMS ];
    asr = &api->Signal;

    old_mode  = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;

    if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE )
        old_mode |= RTEMS_NO_TIMESLICE;
    else
        old_mode |= RTEMS_TIMESLICE;

    old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
    old_mode |= _ISR_Get_level();

    *previous_mode_set = old_mode;

    /*
     *  These are generic thread scheduling characteristics.
     */

    if ( mask & RTEMS_PREEMPT_MASK )
        executing->is_preemptible = _Modes_Is_preempt(mode_set) ? true : false;

    if ( mask & RTEMS_TIMESLICE_MASK ) {
        if ( _Modes_Is_timeslice(mode_set) ) {
            executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
            executing->cpu_time_budget  = _Thread_Ticks_per_timeslice;
        } else
            executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    }

    /*
     *  Set the new interrupt level
     */

    if ( mask & RTEMS_INTERRUPT_MASK )
        _Modes_Set_interrupt_level( mode_set );

    /*
     *  This is specific to the RTEMS API
     */

    is_asr_enabled = false;
    needs_asr_dispatching = false;

    if ( mask & RTEMS_ASR_MASK ) {
        is_asr_enabled = _Modes_Is_asr_disabled( mode_set ) ? false : true;
        if ( is_asr_enabled != asr->is_enabled ) {
            asr->is_enabled = is_asr_enabled;
            _ASR_Swap_signals( asr );
            if ( _ASR_Are_signals_pending( asr ) ) {
                needs_asr_dispatching = true;
                executing->do_post_task_switch_extension = true;
            }
        }
    }

    if ( _System_state_Is_up( _System_state_Get() ) )
        if ( _Thread_Evaluate_mode() || needs_asr_dispatching )
            _Thread_Dispatch();

    return RTEMS_SUCCESSFUL;
}
Пример #7
0
void _Thread_Handler( void )
{
  Thread_Control *executing = _Thread_Executing;
  ISR_Level       level;


  /*
   * Some CPUs need to tinker with the call frame or registers when the
   * thread actually begins to execute for the first time.  This is a
   * hook point where the port gets a shot at doing whatever it requires.
   */
  _Context_Initialization_at_thread_begin();

  #if !defined(RTEMS_SMP)
    /*
     * have to put level into a register for those cpu's that use
     * inline asm here
     */
    level = executing->Start.isr_level;
    _ISR_Set_level( level );
  #endif

  /*
   * Initialize the floating point context because we do not come
   * through _Thread_Dispatch on our first invocation. So the normal
   * code path for performing the FP context switch is not hit.
   */
  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    #if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
      if ( (executing->fp_context != NULL) &&
            !_Thread_Is_allocated_fp( executing ) ) {
        if ( _Thread_Allocated_fp != NULL )
          _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
        _Thread_Allocated_fp = executing;
      }
    #endif
  #endif

  /*
   * Take care that 'begin' extensions get to complete before
   * 'switch' extensions can run.  This means must keep dispatch
   * disabled until all 'begin' extensions complete.
   */
  _User_extensions_Thread_begin( executing );

  /*
   *  At this point, the dispatch disable level BETTER be 1.
   */
  #if defined(RTEMS_SMP)
    {
      /*
       * On SMP we enter _Thread_Handler() with interrupts disabled and
       * _Thread_Dispatch() obtained the per-CPU lock for us.  We have to
       * release it here and set the desired interrupt level of the thread.
       */
      Per_CPU_Control *cpu_self = _Per_CPU_Get();

      _Assert( cpu_self->thread_dispatch_disable_level == 1 );
      _Assert( _ISR_Get_level() != 0 );

      _Thread_Debug_set_real_processor( executing, cpu_self );

      cpu_self->thread_dispatch_disable_level = 0;
      _Profiling_Thread_dispatch_enable( cpu_self, 0 );

      level = executing->Start.isr_level;
      _ISR_Set_level( level);

      /*
       * The thread dispatch level changed from one to zero.  Make sure we lose
       * no thread dispatch necessary update.
       */
      _Thread_Dispatch();
    }
  #else
    _Thread_Enable_dispatch();
  #endif

  /*
   *  RTEMS supports multiple APIs and each API can define a different
   *  thread/task prototype. The following code supports invoking the
   *  user thread entry point using the prototype expected.
   */
  if ( executing->Start.prototype == THREAD_START_NUMERIC ) {
    executing->Wait.return_argument =
      (*(Thread_Entry_numeric) executing->Start.entry_point)(
        executing->Start.numeric_argument
      );
  }
  #if defined(RTEMS_POSIX_API)
    else if ( executing->Start.prototype == THREAD_START_POINTER ) {
      executing->Wait.return_argument =
        (*(Thread_Entry_pointer) executing->Start.entry_point)(
          executing->Start.pointer_argument
        );
    }
  #endif
  #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
    else if ( executing->Start.prototype == THREAD_START_BOTH_POINTER_FIRST ) {
      executing->Wait.return_argument =
         (*(Thread_Entry_both_pointer_first) executing->Start.entry_point)(
           executing->Start.pointer_argument,
           executing->Start.numeric_argument
         );
    }
    else if ( executing->Start.prototype == THREAD_START_BOTH_NUMERIC_FIRST ) {
      executing->Wait.return_argument =
       (*(Thread_Entry_both_numeric_first) executing->Start.entry_point)(
         executing->Start.numeric_argument,
         executing->Start.pointer_argument
       );
    }
  #endif

  /*
   *  In the switch above, the return code from the user thread body
   *  was placed in return_argument.  This assumed that if it returned
   *  anything (which is not supporting in all APIs), then it would be
   *  able to fit in a (void *).
   */

  _User_extensions_Thread_exitted( executing );

  _Terminate(
    INTERNAL_ERROR_CORE,
    true,
    INTERNAL_ERROR_THREAD_EXITTED
  );
}
Пример #8
0
 void _Assert_Thread_dispatching_repressed( void )
 {
   _Assert( !_Thread_Dispatch_is_enabled() || _ISR_Get_level() != 0 );
 }
Пример #9
0
void _Thread_Handler( void )
{
  Thread_Control  *executing = _Thread_Executing;
  ISR_Level        level;
  Per_CPU_Control *cpu_self;

  /*
   * Some CPUs need to tinker with the call frame or registers when the
   * thread actually begins to execute for the first time.  This is a
   * hook point where the port gets a shot at doing whatever it requires.
   */
  _Context_Initialization_at_thread_begin();

  /* On SMP we enter _Thread_Handler() with interrupts disabled */
  _SMP_Assert( _ISR_Get_level() != 0 );

  /*
   * have to put level into a register for those cpu's that use
   * inline asm here
   */
  level = executing->Start.isr_level;
  _ISR_Set_level( level );

  /*
   * Initialize the floating point context because we do not come
   * through _Thread_Dispatch on our first invocation. So the normal
   * code path for performing the FP context switch is not hit.
   */
  _Thread_Restore_fp( executing );

  /*
   * Do not use the level of the thread control block, since it has a
   * different format.
   */
  _ISR_Local_disable( level );

  /*
   *  At this point, the dispatch disable level BETTER be 1.
   */
  cpu_self = _Per_CPU_Get();
  _Assert( cpu_self->thread_dispatch_disable_level == 1 );

  /*
   * Make sure we lose no thread dispatch necessary update and execute the
   * post-switch actions.  As a side-effect change the thread dispatch level
   * from one to zero.  Do not use _Thread_Enable_dispatch() since there is no
   * valid thread dispatch necessary indicator in this context.
   */
  _Thread_Do_dispatch( cpu_self, level );

  /*
   * Invoke the thread begin extensions in the context of the thread entry
   * function with thread dispatching enabled.  This enables use of dynamic
   * memory allocation, creation of POSIX keys and use of C++ thread local
   * storage.  Blocking synchronization primitives are allowed also.
   */
  _User_extensions_Thread_begin( executing );

  /*
   *  RTEMS supports multiple APIs and each API can define a different
   *  thread/task prototype. The following code supports invoking the
   *  user thread entry point using the prototype expected.
   */
  ( *executing->Start.Entry.adaptor )( executing );

  /*
   *  In the call above, the return code from the user thread body which return
   *  something was placed in return_argument.  This assumed that if it
   *  returned anything (which is not supporting in all APIs), then it would be
   *  able to fit in a (void *).
   */

  _User_extensions_Thread_exitted( executing );

  _Terminate(
    INTERNAL_ERROR_CORE,
    true,
    INTERNAL_ERROR_THREAD_EXITTED
  );
}
Пример #10
0
int main(
  int    argc,
  char **argv
)
#endif
{
  pthread_spinlock_t    spinlock;
  pthread_spinlock_t    spinlock2;
  int                   status;

  TEST_BEGIN();

  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_destroy( &spinlock ) -- OK" );
  status = pthread_spin_destroy( &spinlock );
  rtems_test_assert( status == 0 );

  puts( "pthread_spin_init( &spinlock, PTHREAD_PROCESS_SHARED ) -- OK" );
  status = pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE );
  rtems_test_assert( status == 0 );

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

  puts( "pthread_spin_init( &spinlock, 0x1234 ) -- OK" );
  status = pthread_spin_init( &spinlock, 0x1234 );
  rtems_test_assert( status == 0 );

  puts( "pthread_spin_init( &spinlock2, 0 ) -- OK" );
  status = pthread_spin_init( &spinlock2, 0 );
  rtems_test_assert( status == 0 );

  rtems_test_assert( _ISR_Get_level() == 0 );

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

  rtems_test_assert( _ISR_Get_level() != 0 );

  puts( "pthread_spin_lock( &spinlock2 ) -- OK" );
  status = pthread_spin_lock( &spinlock2 );
  rtems_test_assert( status == 0 );

  rtems_test_assert( _ISR_Get_level() != 0 );

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

  rtems_test_assert( _ISR_Get_level() != 0 );

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

  rtems_test_assert( _ISR_Get_level() == 0 );

  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_trylock( &spinlock2 ) -- OK" );
  status = pthread_spin_trylock( &spinlock2 );
  rtems_test_assert( status == 0 );

  rtems_test_assert( _ISR_Get_level() != 0 );

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

  rtems_test_assert( _ISR_Get_level() != 0 );

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

  rtems_test_assert( _ISR_Get_level() == 0 );

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

  TEST_END();
  exit(0);
}
Пример #11
0
rtems_status_code rtems_task_mode(
  rtems_mode  mode_set,
  rtems_mode  mask,
  rtems_mode *previous_mode_set
)
{
  Thread_Control     *executing;
  RTEMS_API_Control  *api;
  ASR_Information    *asr;
  bool                needs_asr_dispatching;
  rtems_mode          old_mode;

  if ( !previous_mode_set )
    return RTEMS_INVALID_ADDRESS;

  executing     = _Thread_Get_executing();
  api = executing->API_Extensions[ THREAD_API_RTEMS ];
  asr = &api->Signal;

  old_mode  = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;

  if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE )
    old_mode |= RTEMS_NO_TIMESLICE;
  else
    old_mode |= RTEMS_TIMESLICE;

  old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
  old_mode |= _ISR_Get_level();

  *previous_mode_set = old_mode;

  /*
   *  These are generic thread scheduling characteristics.
   */
  if ( mask & RTEMS_PREEMPT_MASK ) {
#if defined( RTEMS_SMP )
    if (
      rtems_configuration_is_smp_enabled()
        && !_Modes_Is_preempt( mode_set )
    ) {
      return RTEMS_NOT_IMPLEMENTED;
    }
#endif

    executing->is_preemptible = _Modes_Is_preempt( mode_set );
  }

  if ( mask & RTEMS_TIMESLICE_MASK ) {
    if ( _Modes_Is_timeslice(mode_set) ) {
      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
      executing->cpu_time_budget  = _Thread_Ticks_per_timeslice;
    } else
      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
  }

  /*
   *  Set the new interrupt level
   */
  if ( mask & RTEMS_INTERRUPT_MASK )
    _Modes_Set_interrupt_level( mode_set );

  /*
   *  This is specific to the RTEMS API
   */
  needs_asr_dispatching = false;
  if ( mask & RTEMS_ASR_MASK ) {
    bool is_asr_enabled = !_Modes_Is_asr_disabled( mode_set );

    if ( is_asr_enabled != asr->is_enabled ) {
      asr->is_enabled = is_asr_enabled;
      _ASR_Swap_signals( asr );
      if ( _ASR_Are_signals_pending( asr ) ) {
        needs_asr_dispatching = true;
      }
    }
  }

  _RTEMS_Tasks_Dispatch_if_necessary( executing, needs_asr_dispatching );

  return RTEMS_SUCCESSFUL;
}
Пример #12
0
void rtems_initialize_data_structures(void)
{
  _System_state_Handler_initialization( FALSE );

  _CPU_Initialize();

  /*
   *  Do this as early as possible to ensure no debugging output
   *  is even attempted to be printed.
   */
  _Debug_Manager_initialization();

  _API_extensions_Initialization();

  _Thread_Dispatch_initialization();

  _User_extensions_Handler_initialization();
  _ISR_Handler_initialization();

  /*
   * Initialize the internal support API and allocator Mutex
   */
  _Objects_Information_table[OBJECTS_INTERNAL_API] = _Internal_Objects;

  _API_Mutex_Initialization( 2 );
  _API_Mutex_Allocate( &_RTEMS_Allocator_Mutex );
  _API_Mutex_Allocate( &_Once_Mutex );

  _Watchdog_Handler_initialization();
  _TOD_Handler_initialization();

  _Thread_Handler_initialization();

  _Scheduler_Handler_initialization();

  _SMP_Handler_initialize();

  _CPU_set_Handler_initialization();

/* MANAGERS */
  /*
   * Install our API Object Management Table and initialize the
   * various managers.
   */
  _Objects_Information_table[OBJECTS_CLASSIC_API] = _RTEMS_Objects;

  _RTEMS_tasks_Manager_initialization();
  _Semaphore_Manager_initialization();

  /*
   * Install our API Object Management Table and initialize the
   * various managers.
   */
  _Objects_Information_table[OBJECTS_POSIX_API] = _POSIX_Objects;

  _POSIX_Key_Manager_initialization();

  /*
   * Discover and initialize the secondary cores in an SMP system.
   */
  _SMP_Handler_initialize();

  _System_state_Set( SYSTEM_STATE_BEFORE_MULTITASKING );

  /*
   *  No threads should be created before this point!!!
   *  _Thread_Executing and _Thread_Heir are not set.
   *
   *  At this point all API extensions are in place.  After the call to
   *  _Thread_Create_idle() _Thread_Executing and _Thread_Heir will be set.
   */
  _Thread_Create_idle();

  /*
   *  Scheduling can properly occur now as long as we avoid dispatching.
   */

  _System_state_Set( SYSTEM_STATE_UP );

  _SMP_Request_start_multitasking();

  _Thread_Start_multitasking();

  /* Add Initialization of the Thread_Dispatch wrapper */
  Init__wrap__Thread_Dispatch();

  /*
   *  Now we are back in a non-dispatching critical section
   */
  #if defined(RTEMS_SMP)
   {
      ISR_Level  level;

      /*
       * On SMP we enter _Thread_Handler() with interrupts disabled and
       * _Thread_Dispatch() obtained the per-CPU lock for us.  We have to
       * release it here and set the desired interrupt level of the thread.
       */
      Per_CPU_Control *cpu_self = _Per_CPU_Get();

      _Assert( cpu_self->thread_dispatch_disable_level == 1 );
      _Assert( _ISR_Get_level() != 0 );

      cpu_self->thread_dispatch_disable_level = 0;
      _Profiling_Thread_dispatch_enable( cpu_self, 0 );

      /* For whatever reason, we haven't locked our per cpu yet in the
       * Scheduler Simulator. Until this is done, this release is not needed.
       */
      /* _Per_CPU_Release( cpu_self ); */

      level =  _Thread_Executing->Start.isr_level;
      _ISR_Set_level( level);

      /*
       * The thread dispatch level changed from one to zero.  Make sure we lose
       * no thread dispatch necessary update.
       */
      _Thread_Dispatch();
    }
  #else
    _Thread_Enable_dispatch();
  #endif

  /*
   * Print an initial message
   */
  check_heir_and_executing();
}