Exemplo n.º 1
0
/*
 *  _POSIX_Threads_Sporadic_budget_TSR
 */
void _POSIX_Threads_Sporadic_budget_TSR(
    Objects_Id      id RTEMS_UNUSED,
    void           *argument
)
{
    uint32_t            ticks;
    Thread_Control     *the_thread;
    POSIX_API_Control  *api;

    the_thread = argument;

    api = the_thread->API_Extensions[ THREAD_API_POSIX ];

    /* ticks is guaranteed to be at least one */
    ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget );

    the_thread->cpu_time_budget = ticks;

    _Thread_Change_priority(
        the_thread,
        _POSIX_Priority_To_core( api->schedparam.sched_priority ),
        NULL,
        _POSIX_Threads_Sporadic_budget_TSR_filter,
        true
    );

    /* ticks is guaranteed to be at least one */
    ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period );

    _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
}
Exemplo n.º 2
0
static void _Timer_server_Reset_interval_system_watchdog(
  Timer_server_Control *ts
)
{
  ISR_Level level;

  _Timer_server_Stop_interval_system_watchdog( ts );

  _ISR_Disable( level );
  if ( !_Chain_Is_empty( &ts->Interval_watchdogs.Chain ) ) {
    Watchdog_Interval delta_interval =
      _Watchdog_First( &ts->Interval_watchdogs.Chain )->delta_interval;
    _ISR_Enable( level );

    /*
     *  The unit is TICKS here.
     */
    _Watchdog_Insert_ticks(
      &ts->Interval_watchdogs.System_watchdog,
      delta_interval
    );
  } else {
    _ISR_Enable( level );
  }
}
Exemplo n.º 3
0
boolean _Watchdog_Insert_ticks_helper(
  Watchdog_Control               *timer,
  Watchdog_Interval               ticks,
  Objects_Id                      id,
  Watchdog_Service_routine_entry  TSR,
  void                           *arg
)
{
  ISR_Level            level;

  (void) _Watchdog_Remove( timer );
  _ISR_Disable( level );

    /*
     *  Check to see if the watchdog has just been inserted by a
     *  higher priority interrupt.  If so, abandon this insert.
     */
    if ( timer->state != WATCHDOG_INACTIVE ) {
      _ISR_Enable( level );
      return FALSE;
    }

    /*
     *  OK.  Now we now the timer was not rescheduled by an interrupt
     *  so we can atomically initialize it as in use.
     */
    _Watchdog_Initialize( timer, TSR, id, arg );
    _Watchdog_Insert_ticks( timer, ticks );
  _ISR_Enable( level );
  return TRUE;
}
Exemplo n.º 4
0
rtems_status_code rtems_task_wake_after(
  rtems_interval ticks
)
{
  /*
   * It is critical to obtain the executing thread after thread dispatching is
   * disabled on SMP configurations.
   */
  Thread_Control  *executing;
  Per_CPU_Control *cpu_self;

  cpu_self = _Thread_Dispatch_disable();
    executing = _Thread_Executing;

    if ( ticks == 0 ) {
      _Thread_Yield( executing );
    } else {
      _Thread_Set_state( executing, STATES_DELAYING );
      _Thread_Wait_flags_set( executing, THREAD_WAIT_STATE_BLOCKED );
      _Watchdog_Initialize(
        &executing->Timer,
        _Thread_Timeout,
        0,
        executing
      );
      _Watchdog_Insert_ticks( &executing->Timer, ticks );
    }
  _Thread_Dispatch_enable( cpu_self );
  return RTEMS_SUCCESSFUL;
}
Exemplo n.º 5
0
rtems_status_code rtems_timer_fire_after(
  rtems_id                           id,
  rtems_interval                     ticks,
  rtems_timer_service_routine_entry  routine,
  void                              *user_data
)
{
  Timer_Control      *the_timer;
  Objects_Locations   location;
  ISR_Level           level;

  if ( ticks == 0 )
    return RTEMS_INVALID_NUMBER;

  if ( !routine )
    return RTEMS_INVALID_ADDRESS;

  the_timer = _Timer_Get( id, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      _Timer_Cancel( the_timer );

      _ISR_Disable( level );

        /*
         *  Check to see if the watchdog has just been inserted by a
         *  higher priority interrupt.  If so, abandon this insert.
         */

        if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) {
          _ISR_Enable( level );
          _Objects_Put( &the_timer->Object );
          return RTEMS_SUCCESSFUL;
        }

        /*
         *  OK.  Now we now the timer was not rescheduled by an interrupt
         *  so we can atomically initialize it as in use.
         */

        the_timer->the_class = TIMER_INTERVAL;
        _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
      _ISR_Enable( level );


      _Watchdog_Insert_ticks( &the_timer->Ticker, ticks );
      _Objects_Put( &the_timer->Object );
      return RTEMS_SUCCESSFUL;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:            /* should never return this */
#endif
    case OBJECTS_ERROR:
      break;
  }

  return RTEMS_INVALID_ID;
}
Exemplo n.º 6
0
void _Thread_queue_Enqueue_with_handler(
  Thread_queue_Control         *the_thread_queue,
  Watchdog_Interval             timeout,
  Thread_queue_Timeout_callout  handler
)
{
  Thread_Control                   *the_thread;
  ISR_Level                         level;
  Thread_blocking_operation_States  sync_state;
  Thread_blocking_operation_States (*enqueue_p)(
    Thread_queue_Control *,
    Thread_Control *,
    ISR_Level *
  );

  the_thread = _Thread_Executing;

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet )
    the_thread = _Thread_MP_Allocate_proxy( the_thread_queue->state );
  else
#endif
  /*
   *  Set the blocking state for this thread queue in the thread.
   */
  _Thread_Set_state( the_thread, the_thread_queue->state );

  /*
   *  If the thread wants to timeout, then schedule its timer.
   */
  if ( timeout ) {
    _Watchdog_Initialize(
       &the_thread->Timer,
       handler,
       the_thread->Object.id,
       NULL
    );

    _Watchdog_Insert_ticks( &the_thread->Timer, timeout );
  }

  /*
   *  Now enqueue the thread per the discipline for this thread queue.
   */
  if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY )
    enqueue_p = _Thread_queue_Enqueue_priority;
  else /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
    enqueue_p = _Thread_queue_Enqueue_fifo;

  sync_state = (*enqueue_p)( the_thread_queue, the_thread, &level );
  if ( sync_state != THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
    _Thread_blocking_operation_Cancel( sync_state, the_thread, level );
}
Exemplo n.º 7
0
/*
 *  _POSIX_Threads_Sporadic_budget_TSR
 */
void _POSIX_Threads_Sporadic_budget_TSR(
  Objects_Id      id __attribute__((unused)),
  void           *argument
)
{
  uint32_t            ticks;
  uint32_t            new_priority;
  Thread_Control     *the_thread;
  POSIX_API_Control  *api;

  the_thread = argument;

  api = the_thread->API_Extensions[ THREAD_API_POSIX ];

  /* ticks is guaranteed to be at least one */
  ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget );

  the_thread->cpu_time_budget = ticks;

  new_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority );
  the_thread->real_priority = new_priority;

  /*
   *  If holding a resource, then do not change it.
   */
  #if 0
    printk( "TSR %d %d %d\n", the_thread->resource_count,
        the_thread->current_priority, new_priority );
  #endif
  if ( the_thread->resource_count == 0 ) {
    /*
     *  If this would make them less important, then do not change it.
     */
    if ( the_thread->current_priority > new_priority ) {
      _Thread_Change_priority( the_thread, new_priority, true );
      #if 0
        printk( "raise priority\n" );
      #endif
    }
  }

  /* ticks is guaranteed to be at least one */
  ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period );

  _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
}
rtems_status_code rtems_task_wake_after(
  rtems_interval ticks
)
{
  _Thread_Disable_dispatch();
    if ( ticks == 0 ) {
      _Thread_Yield_processor();
    } else {
      _Thread_Set_state( _Thread_Executing, STATES_DELAYING );
      _Watchdog_Initialize(
        &_Thread_Executing->Timer,
        _Thread_Delay_ended,
        _Thread_Executing->Object.id,
        NULL
      );
      _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
    }
  _Thread_Enable_dispatch();
  return RTEMS_SUCCESSFUL;
}
ER dly_tsk(
  DLYTIME dlytim
)
{
  Watchdog_Interval ticks;

  ticks = TOD_MILLISECONDS_TO_TICKS(dlytim);

  _Thread_Disable_dispatch();
    if ( ticks == 0 ) {
      _Thread_Yield_processor();
    } else {
      _Thread_Set_state( _Thread_Executing, STATES_DELAYING );
      _Watchdog_Initialize(
        &_Thread_Executing->Timer,
        _Thread_Delay_ended,
        _Thread_Executing->Object.id,
        NULL
      );
      _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
    }
  _Thread_Enable_dispatch();
  return E_OK;
}
Exemplo n.º 10
0
int pthread_create(
  pthread_t              *thread,
  const pthread_attr_t   *attr,
  void                 *(*start_routine)( void * ),
  void                   *arg
)
{
  const pthread_attr_t               *the_attr;
  Priority_Control                    core_priority;
  Thread_CPU_budget_algorithms        budget_algorithm;
  Thread_CPU_budget_algorithm_callout budget_callout;
  bool                                is_fp;
  bool                                status;
  Thread_Control                     *the_thread;
  POSIX_API_Control                  *api;
  int                                 schedpolicy = SCHED_RR;
  struct sched_param                  schedparam;
  Objects_Name                        name;
  int                                 rc;

  if ( !start_routine )
    return EFAULT;

  the_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes;

  if ( !the_attr->is_initialized )
    return EINVAL;

  /*
   *  Core Thread Initialize ensures we get the minimum amount of
   *  stack space if it is allowed to allocate it itself.
   *
   *  NOTE: If the user provides the stack we will let it drop below
   *        twice the minimum.
   */
  if ( the_attr->stackaddr && !_Stack_Is_enough(the_attr->stacksize) )
    return EINVAL;

  #if 0
    int  cputime_clock_allowed;  /* see time.h */
    rtems_set_errno_and_return_minus_one( ENOSYS );
  #endif

  /*
   *  P1003.1c/Draft 10, p. 121.
   *
   *  If inheritsched is set to PTHREAD_INHERIT_SCHED, then this thread
   *  inherits scheduling attributes from the creating thread.   If it is
   *  PTHREAD_EXPLICIT_SCHED, then scheduling parameters come from the
   *  attributes structure.
   */
  switch ( the_attr->inheritsched ) {
    case PTHREAD_INHERIT_SCHED:
      api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
      schedpolicy = api->schedpolicy;
      schedparam  = api->schedparam;
      break;

    case PTHREAD_EXPLICIT_SCHED:
      schedpolicy = the_attr->schedpolicy;
      schedparam  = the_attr->schedparam;
      break;

    default:
      return EINVAL;
  }

  /*
   *  Check the contentionscope since rtems only supports PROCESS wide
   *  contention (i.e. no system wide contention).
   */
  if ( the_attr->contentionscope != PTHREAD_SCOPE_PROCESS )
    return ENOTSUP;

  /*
   *  Interpret the scheduling parameters.
   */
  if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) )
    return EINVAL;

  core_priority = _POSIX_Priority_To_core( schedparam.sched_priority );

  /*
   *  Set the core scheduling policy information.
   */
  rc = _POSIX_Thread_Translate_sched_param(
    schedpolicy,
    &schedparam,
    &budget_algorithm,
    &budget_callout
  );
  if ( rc )
    return rc;

  /*
   *  Currently all POSIX threads are floating point if the hardware
   *  supports it.
   */
  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    is_fp = true;
  #else
    is_fp = false;
  #endif

  /*
   *  Lock the allocator mutex for protection
   */
  _RTEMS_Lock_allocator();

  /*
   *  Allocate the thread control block.
   *
   *  NOTE:  Global threads are not currently supported.
   */
  the_thread = _POSIX_Threads_Allocate();
  if ( !the_thread ) {
    _RTEMS_Unlock_allocator();
    return EAGAIN;
  }

  /*
   *  Initialize the core thread for this task.
   */
  name.name_p = NULL;   /* posix threads don't have a name by default */
  status = _Thread_Initialize(
    &_POSIX_Threads_Information,
    the_thread,
    the_attr->stackaddr,
    _POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize),
    is_fp,
    core_priority,
    true,                 /* preemptible */
    budget_algorithm,
    budget_callout,
    0,                    /* isr level */
    name                  /* posix threads don't have a name */
  );

  if ( !status ) {
    _POSIX_Threads_Free( the_thread );
    _RTEMS_Unlock_allocator();
    return EAGAIN;
  }

  /*
   *  finish initializing the per API structure
   */
  api = the_thread->API_Extensions[ THREAD_API_POSIX ];

  api->Attributes  = *the_attr;
  api->detachstate = the_attr->detachstate;
  api->schedpolicy = schedpolicy;
  api->schedparam  = schedparam;

  /*
   *  This insures we evaluate the process-wide signals pending when we
   *  first run.
   *
   *  NOTE:  Since the thread starts with all unblocked, this is necessary.
   */
  the_thread->do_post_task_switch_extension = true;

  /*
   *  POSIX threads are allocated and started in one operation.
   */
  status = _Thread_Start(
    the_thread,
    THREAD_START_POINTER,
    start_routine,
    arg,
    0                     /* unused */
  );

  #if defined(RTEMS_DEBUG)
    /*
     *  _Thread_Start only fails if the thread was in the incorrect state
     *
     *  NOTE: This can only happen if someone slips in and touches the
     *        thread while we are creating it.
     */
    if ( !status ) {
      _POSIX_Threads_Free( the_thread );
      _RTEMS_Unlock_allocator();
      return EINVAL;
    }
  #endif

  if ( schedpolicy == SCHED_SPORADIC ) {
    _Watchdog_Insert_ticks(
      &api->Sporadic_timer,
      _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period )
    );
  }

  /*
   *  Return the id and indicate we successfully created the thread
   */
  *thread = the_thread->Object.id;

  _RTEMS_Unlock_allocator();
  return 0;
}
Exemplo n.º 11
0
void _Thread_queue_Enqueue(
  Thread_queue_Control *the_thread_queue,
  Thread_Control       *the_thread,
  States_Control        state,
  Watchdog_Interval     timeout
)
{
  ISR_lock_Context                 lock_context;
  Thread_blocking_operation_States sync_state;

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet )
    the_thread = _Thread_MP_Allocate_proxy( state );
  else
#endif
  /*
   *  Set the blocking state for this thread queue in the thread.
   */
  _Thread_Set_state( the_thread, state );

  /*
   *  If the thread wants to timeout, then schedule its timer.
   */
  if ( timeout ) {
    _Watchdog_Initialize(
       &the_thread->Timer,
       _Thread_queue_Timeout,
       the_thread->Object.id,
       NULL
    );

    _Watchdog_Insert_ticks( &the_thread->Timer, timeout );
  }

  /*
   * Now initiate the enqueuing and checking if the blocking operation
   * should be completed or the thread has had its blocking condition
   * satisfied before we got here.
   */
  _Thread_queue_Acquire( &lock_context );

  sync_state = the_thread_queue->sync_state;
  the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;

  if ( sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
    /*
     * Invoke the discipline specific enqueue method.
     */
    if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_FIFO ) {
      _Chain_Append_unprotected(
        &the_thread_queue->Queues.Fifo,
        &the_thread->Object.Node
      );
    } else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */
      _Thread_Lock_set( the_thread, &_Thread_queue_Lock );
      _Thread_Priority_set_change_handler(
        the_thread,
        _Thread_queue_Requeue_priority,
        the_thread_queue
      );
      _RBTree_Insert(
        &the_thread_queue->Queues.Priority,
        &the_thread->RBNode,
        _Thread_queue_Compare_priority,
        false
      );
    }

    the_thread->Wait.queue = the_thread_queue;
    the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
    _Thread_queue_Release( &lock_context );
  } else {
    /* Cancel a blocking operation due to ISR */

    _Assert(
      sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT ||
        sync_state == THREAD_BLOCKING_OPERATION_SATISFIED
    );

    _Thread_blocking_operation_Finalize( the_thread, &lock_context );
  }
}
Exemplo n.º 12
0
/*
 *  14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
 */
int nanosleep(
  const struct timespec  *rqtp,
  struct timespec        *rmtp
)
{
  /*
   * It is critical to obtain the executing thread after thread dispatching is
   * disabled on SMP configurations.
   */
  Thread_Control *executing;

  Watchdog_Interval  ticks;
  Watchdog_Interval  elapsed;


  /*
   *  Return EINVAL if the delay interval is negative.
   *
   *  NOTE:  This behavior is beyond the POSIX specification.
   *         FSU and GNU/Linux pthreads shares this behavior.
   */
  if ( !_Timespec_Is_valid( rqtp ) )
    rtems_set_errno_and_return_minus_one( EINVAL );

  /*
   * Convert the timespec delay into the appropriate number of clock ticks.
   */
  ticks = _Timespec_To_ticks( rqtp );

  /*
   *  A nanosleep for zero time is implemented as a yield.
   *  This behavior is also beyond the POSIX specification but is
   *  consistent with the RTEMS API and yields desirable behavior.
   */
  if ( !ticks ) {
    _Thread_Disable_dispatch();
      executing = _Thread_Executing;
      _Thread_Yield( executing );
    _Thread_Enable_dispatch();
    if ( rmtp ) {
       rmtp->tv_sec = 0;
       rmtp->tv_nsec = 0;
    }
    return 0;
  }

  /*
   *  Block for the desired amount of time
   */
  _Thread_Disable_dispatch();
    executing = _Thread_Executing;
    _Thread_Set_state(
      executing,
      STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
    );
    _Watchdog_Initialize(
      &executing->Timer,
      _Thread_Delay_ended,
      0,
      executing
    );
    _Watchdog_Insert_ticks( &executing->Timer, ticks );
  _Thread_Enable_dispatch();

  /*
   * Calculate the time that passed while we were sleeping and how
   * much remains from what we requested.
   */
  elapsed = executing->Timer.stop_time - executing->Timer.start_time;
  if ( elapsed >= ticks )
    ticks = 0;
  else
    ticks -= elapsed;

  /*
   * If the user wants the time remaining, do the conversion.
   */
  if ( rmtp ) {
    _Timespec_From_ticks( ticks, rmtp );
  }

  /*
   *  Only when POSIX is enabled, can a sleep be interrupted.
   */
  #if defined(RTEMS_POSIX_API)
    /*
     *  If there is time remaining, then we were interrupted by a signal.
     */
    if ( ticks )
      rtems_set_errno_and_return_minus_one( EINTR );
  #endif

  return 0;
}
Exemplo n.º 13
0
void _Event_Seize(
  rtems_event_set  event_in,
  rtems_option     option_set,
  rtems_interval   ticks,
  rtems_event_set *event_out
)
{
  Thread_Control                   *executing;
  rtems_event_set                   seized_events;
  rtems_event_set                   pending_events;
  ISR_Level                         level;
  RTEMS_API_Control                *api;
  Thread_blocking_operation_States  sync_state;

  executing = _Thread_Executing;
  executing->Wait.return_code = RTEMS_SUCCESSFUL;

  api = executing->API_Extensions[ THREAD_API_RTEMS ];

  _ISR_Disable( level );
  pending_events = api->pending_events;
  seized_events  = _Event_sets_Get( pending_events, event_in );

  if ( !_Event_sets_Is_empty( seized_events ) &&
       (seized_events == event_in || _Options_Is_any( option_set )) ) {
    api->pending_events =
      _Event_sets_Clear( pending_events, seized_events );
    _ISR_Enable( level );
    *event_out = seized_events;
    return;
  }

  if ( _Options_Is_no_wait( option_set ) ) {
    _ISR_Enable( level );
    executing->Wait.return_code = RTEMS_UNSATISFIED;
    *event_out = seized_events;
    return;
  }

  /*
   *  Note what we are waiting for BEFORE we enter the critical section.
   *  The interrupt critical section management code needs this to be
   *  set properly when we are marked as in the event critical section.
   *
   *  NOTE: Since interrupts are disabled, this isn't that much of an
   *        issue but better safe than sorry.
   */
  executing->Wait.option            = (uint32_t) option_set;
  executing->Wait.count             = (uint32_t) event_in;
  executing->Wait.return_argument   = event_out;

  _Event_Sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;

  _ISR_Enable( level );

  if ( ticks ) {
    _Watchdog_Initialize(
      &executing->Timer,
      _Event_Timeout,
      executing->Object.id,
      NULL
    );
    _Watchdog_Insert_ticks( &executing->Timer, ticks );
  }

  _Thread_Set_state( executing, STATES_WAITING_FOR_EVENT );

  _ISR_Disable( level );

  sync_state = _Event_Sync_state;
  _Event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
  if ( sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
    _ISR_Enable( level );
    return;
  }

  /*
   *  An interrupt completed the thread's blocking request.
   *  The blocking thread was satisfied by an ISR or timed out.
   *
   *  WARNING! Returning with interrupts disabled!
   */
  _Thread_blocking_operation_Cancel( sync_state, executing, level );
}
Exemplo n.º 14
0
int nanosleep(
  const struct timespec  *rqtp,
  struct timespec        *rmtp
)
{
  Watchdog_Interval  ticks;


  /*
   *  Return EINVAL if the delay interval is negative.
   *
   *  NOTE:  This behavior is beyond the POSIX specification.
   *         FSU and GNU/Linux pthreads shares this behavior.
   */
  if ( !_Timespec_Is_valid( rqtp ) )
    rtems_set_errno_and_return_minus_one( EINVAL );

  ticks = _Timespec_To_ticks( rqtp );

  /*
   *  A nanosleep for zero time is implemented as a yield.
   *  This behavior is also beyond the POSIX specification but is
   *  consistent with the RTEMS API and yields desirable behavior.
   */

  if ( !ticks ) {
    _Thread_Disable_dispatch();
      _Scheduler_Yield();
    _Thread_Enable_dispatch();
    if ( rmtp ) {
       rmtp->tv_sec = 0;
       rmtp->tv_nsec = 0;
    }
    return 0;
  }

  /*
   *  Block for the desired amount of time
   */
  _Thread_Disable_dispatch();
    _Thread_Set_state(
      _Thread_Executing,
      STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
    );
    _Watchdog_Initialize(
      &_Thread_Executing->Timer,
      _Thread_Delay_ended,
      _Thread_Executing->Object.id,
      NULL
    );
    _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
  _Thread_Enable_dispatch();

  /* calculate time remaining */

  if ( rmtp ) {
    ticks -=
      _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time;

    _Timespec_From_ticks( ticks, rmtp );

    /*
     *  Only when POSIX is enabled, can a sleep be interrupted.
     */
    #if defined(RTEMS_POSIX_API)
        /*
         *  If there is time remaining, then we were interrupted by a signal.
         */
        if ( ticks )
          rtems_set_errno_and_return_minus_one( EINTR );
    #endif
  }

  return 0;
}
Exemplo n.º 15
0
rtems_status_code rtems_rate_monotonic_period(
  rtems_id       id,
  rtems_interval length
)
{
  Rate_monotonic_Control              *the_period;
  Objects_Locations                    location;
  rtems_status_code                    return_value;
  rtems_rate_monotonic_period_states   local_state;
  ISR_Level                            level;

  the_period = _Rate_monotonic_Get( id, &location );

  switch ( location ) {
    case OBJECTS_LOCAL:
      if ( !_Thread_Is_executing( the_period->owner ) ) {
        _Thread_Enable_dispatch();
        return RTEMS_NOT_OWNER_OF_RESOURCE;
      }

      if ( length == RTEMS_PERIOD_STATUS ) {
        switch ( the_period->state ) {
          case RATE_MONOTONIC_INACTIVE:
            return_value = RTEMS_NOT_DEFINED;
            break;
          case RATE_MONOTONIC_EXPIRED:
          case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
            return_value = RTEMS_TIMEOUT;
            break;
          case RATE_MONOTONIC_ACTIVE:
          default:              /* unreached -- only to remove warnings */
            return_value = RTEMS_SUCCESSFUL;
            break;
        }
        _Thread_Enable_dispatch();
        return( return_value );
      }

      _ISR_Disable( level );
      if ( the_period->state == RATE_MONOTONIC_INACTIVE ) {
        _ISR_Enable( level );

        the_period->next_length = length;

        /*
         *  Baseline statistics information for the beginning of a period.
         */
        _Rate_monotonic_Initiate_statistics( the_period );

        the_period->state = RATE_MONOTONIC_ACTIVE;
        _Watchdog_Initialize(
          &the_period->Timer,
          _Rate_monotonic_Timeout,
          id,
          NULL
        );

        _Watchdog_Insert_ticks( &the_period->Timer, length );
        _Thread_Enable_dispatch();
        return RTEMS_SUCCESSFUL;
      }

      if ( the_period->state == RATE_MONOTONIC_ACTIVE ) {
        /*
         *  Update statistics from the concluding period.
         */
        _Rate_monotonic_Update_statistics( the_period );

        /*
         *  This tells the _Rate_monotonic_Timeout that this task is
         *  in the process of blocking on the period and that we
         *  may be changing the length of the next period.
         */
        the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
        the_period->next_length = length;

        _ISR_Enable( level );

        _Thread_Executing->Wait.id = the_period->Object.id;
        _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );

        /*
         *  Did the watchdog timer expire while we were actually blocking
         *  on it?
         */
        _ISR_Disable( level );
          local_state = the_period->state;
          the_period->state = RATE_MONOTONIC_ACTIVE;
        _ISR_Enable( level );

        /*
         *  If it did, then we want to unblock ourself and continue as
         *  if nothing happen.  The period was reset in the timeout routine.
         */
        if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
          _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );

        _Thread_Enable_dispatch();
        return RTEMS_SUCCESSFUL;
      }

      if ( the_period->state == RATE_MONOTONIC_EXPIRED ) {
        /*
         *  Update statistics from the concluding period
         */
        _Rate_monotonic_Update_statistics( the_period );

        _ISR_Enable( level );

        the_period->state = RATE_MONOTONIC_ACTIVE;
        the_period->next_length = length;

        _Watchdog_Insert_ticks( &the_period->Timer, length );
        _Scheduler_Release_job(the_period->owner, the_period->next_length);
        _Thread_Enable_dispatch();
        return RTEMS_TIMEOUT;
      }

      /*
       *  These should never happen so just return invalid Id.
       *    - RATE_MONOTONIC_OWNER_IS_BLOCKING:
       *    - RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
       */
#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:            /* should never return this */
#endif
    case OBJECTS_ERROR:
      break;
  }

  return RTEMS_INVALID_ID;
}
Exemplo n.º 16
0
void _Event_Seize(
  rtems_event_set  event_in,
  rtems_option     option_set,
  rtems_interval   ticks,
  rtems_event_set *event_out
)
{
  Thread_Control    *executing;
  rtems_event_set    seized_events;
  rtems_event_set    pending_events;
  ISR_Level          level;
  RTEMS_API_Control  *api;
  Event_Sync_states   sync_state;

  executing = _Thread_Executing;
  executing->Wait.return_code = RTEMS_SUCCESSFUL;

  api = executing->API_Extensions[ THREAD_API_RTEMS ];

  _ISR_Disable( level );
  pending_events = api->pending_events;
  seized_events  = _Event_sets_Get( pending_events, event_in );

  if ( !_Event_sets_Is_empty( seized_events ) &&
       (seized_events == event_in || _Options_Is_any( option_set )) ) {
    api->pending_events =
      _Event_sets_Clear( pending_events, seized_events );
    _ISR_Enable( level );
    *event_out = seized_events;
    return;
  }

  if ( _Options_Is_no_wait( option_set ) ) {
    _ISR_Enable( level );
    executing->Wait.return_code = RTEMS_UNSATISFIED;
    *event_out = seized_events;
    return;
  }

  _Event_Sync_state = EVENT_SYNC_NOTHING_HAPPENED;

  executing->Wait.option            = (uint32_t  ) option_set;
  executing->Wait.count             = (uint32_t  ) event_in;
  executing->Wait.return_argument   = event_out;

  _ISR_Enable( level );

  if ( ticks ) {
    _Watchdog_Initialize(
      &executing->Timer,
      _Event_Timeout,
      executing->Object.id,
      NULL
    );
    _Watchdog_Insert_ticks( &executing->Timer, ticks );
  }

  _Thread_Set_state( executing, STATES_WAITING_FOR_EVENT );

  _ISR_Disable( level );

  sync_state = _Event_Sync_state;
  _Event_Sync_state = EVENT_SYNC_SYNCHRONIZED;

  switch ( sync_state ) {
    case EVENT_SYNC_SYNCHRONIZED:
      /*
       *  This cannot happen.  It indicates that this routine did not
       *  enter the synchronization states above.
       */
      return;

    case EVENT_SYNC_NOTHING_HAPPENED:
      _ISR_Enable( level );
      return;

    case EVENT_SYNC_TIMEOUT:
      executing->Wait.return_code = RTEMS_TIMEOUT;
      _ISR_Enable( level );
      _Thread_Unblock( executing );
      return;

    case EVENT_SYNC_SATISFIED:
      if ( _Watchdog_Is_active( &executing->Timer ) ) {
        _Watchdog_Deactivate( &executing->Timer );
        _ISR_Enable( level );
        (void) _Watchdog_Remove( &executing->Timer );
      } else
        _ISR_Enable( level );
      _Thread_Unblock( executing );
      return;
  }
}