コード例 #1
0
ファイル: pthreadkill.c プロジェクト: AoLaD/rtems
int pthread_kill( pthread_t thread, int sig )
{
  Thread_Control    *the_thread;
  ISR_lock_Context   lock_context;
  POSIX_API_Control *api;
  Per_CPU_Control   *cpu_self;

  if ( !is_valid_signo( sig ) ) {
    return EINVAL;
  }

  the_thread = _Thread_Get( thread, &lock_context );

  if ( the_thread == NULL ) {
    return ESRCH;
  }

  api = the_thread->API_Extensions[ THREAD_API_POSIX ];

  if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
    _ISR_lock_ISR_enable( &lock_context );
    return 0;
  }

  /* XXX critical section */

  api->signals_pending |= signo_to_mask( sig );

  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
  _ISR_lock_ISR_enable( &lock_context );

  (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );
  _Thread_Dispatch_enable( cpu_self );
  return 0;
}
コード例 #2
0
int _Scheduler_CBS_Attach_thread (
  Scheduler_CBS_Server_id server_id,
  rtems_id                task_id
)
{
  Scheduler_CBS_Server *server;
  ISR_lock_Context      lock_context;
  Thread_Control       *the_thread;
  Scheduler_CBS_Node   *node;

  if ( server_id >= _Scheduler_CBS_Maximum_servers ) {
    return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
  }

  server = &_Scheduler_CBS_Server_list[ server_id ];

  if ( !server->initialized ) {
    return SCHEDULER_CBS_ERROR_NOSERVER;
  }

  if ( server->task_id != -1 ) {
    return SCHEDULER_CBS_ERROR_FULL;
  }

  the_thread = _Thread_Get( task_id, &lock_context );

  if ( the_thread == NULL ) {
    return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
  }

  node = _Scheduler_CBS_Thread_get_node( the_thread );

  if ( node->cbs_server != NULL ) {
    _ISR_lock_ISR_enable( &lock_context );
    return SCHEDULER_CBS_ERROR_FULL;
  }

  node->cbs_server = server;

  server->task_id = task_id;

  the_thread->budget_callout   = _Scheduler_CBS_Budget_callout;
  the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
  the_thread->is_preemptible   = true;

  _ISR_lock_ISR_enable( &lock_context );
  return SCHEDULER_CBS_OK;
}
コード例 #3
0
ファイル: objectgetisr.c プロジェクト: Avanznow/rtems
Objects_Control *_Objects_Get_isr_disable(
  Objects_Information *information,
  Objects_Id           id,
  Objects_Locations   *location,
  ISR_lock_Context    *lock_context
)
{
  Objects_Control *the_object;
  uint32_t         index;

  index = id - information->minimum_id + 1;

  if ( information->maximum >= index ) {
    _ISR_lock_ISR_disable( lock_context );
    if ( (the_object = information->local_table[ index ]) != NULL ) {
      *location = OBJECTS_LOCAL;
      return the_object;
    }
    _ISR_lock_ISR_enable( lock_context );
    *location = OBJECTS_ERROR;
    return NULL;
  }
  *location = OBJECTS_ERROR;

#if defined(RTEMS_MULTIPROCESSING)
  _Objects_MP_Is_remote( information, id, location, &the_object );
  return the_object;
#else
  return NULL;
#endif
}
コード例 #4
0
ファイル: pthreadgetnamenp.c プロジェクト: gedare/rtems
int pthread_getname_np( pthread_t thread, char *name, size_t len )
{
  Thread_Control   *the_thread;
  ISR_lock_Context  lock_context;
  size_t            actual_len;

  _Objects_Allocator_lock();
  the_thread = _Thread_Get( thread, &lock_context );

  if ( the_thread == NULL ) {
    _Objects_Allocator_unlock();
    strlcpy(name, "", len);
    return ESRCH;
  }

  _ISR_lock_ISR_enable( &lock_context );
  actual_len = _Thread_Get_name( the_thread, name, len );
  _Objects_Allocator_unlock();

  if ( actual_len >= len ) {
    return ERANGE;
  }

  return 0;
}
コード例 #5
0
ファイル: dpmeminternal2external.c プロジェクト: AoLaD/rtems
rtems_status_code rtems_port_internal_to_external(
  rtems_id   id,
  void      *internal,
  void     **external
)
{
  Dual_ported_memory_Control *the_port;
  ISR_lock_Context            lock_context;
  uint32_t                    ending;

  if ( external == NULL ) {
    return RTEMS_INVALID_ADDRESS;
  }

  the_port = _Dual_ported_memory_Get( id, &lock_context );

  if ( the_port == NULL ) {
    return RTEMS_INVALID_ID;
  }

  ending = _Addresses_Subtract( internal, the_port->internal_base );

  if ( ending > the_port->length ) {
    *external = internal;
  } else {
    *external = _Addresses_Add_offset( the_port->external_base, ending );
  }

  _ISR_lock_ISR_enable( &lock_context );
  return RTEMS_SUCCESSFUL;
}
コード例 #6
0
ファイル: init.c プロジェクト: krohini1593/rtems
static void test_isr_locks( void )
{
  ISR_Level normal_interrupt_level = _ISR_Get_level();
  ISR_lock_Control initialized = ISR_LOCK_INITIALIZER("test");
  ISR_lock_Control lock;
  ISR_lock_Context lock_context;

  _ISR_lock_Initialize( &lock, "test" );
  rtems_test_assert( memcmp( &lock, &initialized, lock_size ) == 0 );

  _ISR_lock_ISR_disable_and_acquire( &lock, &lock_context );
  rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
  _ISR_lock_Flash( &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_ISR_disable( &lock_context );
  rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
  _ISR_lock_ISR_enable( &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 );
}
コード例 #7
0
static int _POSIX_Threads_Join( pthread_t thread, void **value_ptr )
{
  Thread_Control       *the_thread;
  Thread_queue_Context  queue_context;
  Per_CPU_Control      *cpu_self;
  Thread_Control       *executing;
  void                 *value;

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_set_expected_level( &queue_context, 1 );
  the_thread = _Thread_Get( thread, &queue_context.Lock_context );

  if ( the_thread == NULL ) {
    return ESRCH;
  }

  cpu_self = _Per_CPU_Get();
  executing = _Per_CPU_Get_executing( cpu_self );

  if ( executing == the_thread ) {
    _ISR_lock_ISR_enable( &queue_context.Lock_context );
    return EDEADLK;
  }

  _Thread_State_acquire_critical( the_thread, &queue_context.Lock_context );

  if ( !_Thread_Is_joinable( the_thread ) ) {
    _Thread_State_release( the_thread, &queue_context.Lock_context );
    return EINVAL;
  }

  if ( _States_Is_waiting_for_join_at_exit( the_thread->current_state ) ) {
    value = the_thread->Life.exit_value;
    _Thread_Clear_state_locked( the_thread, STATES_WAITING_FOR_JOIN_AT_EXIT );
    _Thread_Dispatch_disable_with_CPU( cpu_self, &queue_context.Lock_context );
    _Thread_State_release( the_thread, &queue_context.Lock_context );
    _Thread_Dispatch_enable( cpu_self );
  } else {
    _Thread_Join(
      the_thread,
      STATES_INTERRUPTIBLE_BY_SIGNAL | STATES_WAITING_FOR_JOIN,
      executing,
      &queue_context
    );

    if ( _POSIX_Get_error_after_wait( executing ) != 0 ) {
      _Assert( _POSIX_Get_error_after_wait( executing ) == EINTR );
      return EINTR;
    }

    value = executing->Wait.return_argument;
  }

  if ( value_ptr != NULL ) {
    *value_ptr = value;
  }

  return 0;
}
コード例 #8
0
rtems_status_code rtems_task_set_priority(
  rtems_id             id,
  rtems_task_priority  new_priority,
  rtems_task_priority *old_priority_p
)
{
  Thread_Control          *the_thread;
  ISR_lock_Context         lock_context;
  const Scheduler_Control *scheduler;
  Priority_Control         old_priority;
  rtems_status_code        status;

  if ( old_priority_p == NULL ) {
    return RTEMS_INVALID_ADDRESS;
  }

  the_thread = _Thread_Get( id, &lock_context );

  if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
    return _RTEMS_tasks_MP_Set_priority( id, new_priority, old_priority_p );
#else
    return RTEMS_INVALID_ID;
#endif
  }

  if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
    RTEMS_tasks_Set_priority_context  context;
    Per_CPU_Control                  *cpu_self;

    cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    _ISR_lock_ISR_enable( &lock_context );

    context.new_priority = new_priority;
    _Thread_Change_priority(
      the_thread,
      0,
      &context,
      _RTEMS_tasks_Set_priority_filter,
      false
    );

    _Thread_Dispatch_enable( cpu_self );
    scheduler = context.scheduler;
    old_priority = context.old_priority;
    status = context.status;
  } else {
    _Thread_State_acquire_critical( the_thread, &lock_context );
    scheduler = _Scheduler_Get_own( the_thread );
    old_priority = _Thread_Get_priority( the_thread );
    _Thread_State_release( the_thread, &lock_context );
    status = RTEMS_SUCCESSFUL;
  }

  *old_priority_p = _RTEMS_Priority_From_core( scheduler, old_priority );
  return status;
}
コード例 #9
0
ファイル: init.c プロジェクト: greenmeent/rtems
static Semaphore_Control *get_semaphore_control(rtems_id id)
{
  Thread_queue_Context queue_context;
  Semaphore_Control *sem;

  sem = _Semaphore_Get(id, &queue_context);
  rtems_test_assert(sem != NULL);
  _ISR_lock_ISR_enable(&queue_context.Lock_context);

  return sem;
}
コード例 #10
0
ファイル: condition.c プロジェクト: Avanznow/rtems
int _Condition_Wait_recursive_timed(
  struct _Condition_Control       *_condition,
  struct _Mutex_recursive_Control *_mutex,
  const struct timespec           *abstime
)
{
  ISR_lock_Context   lock_context;
  Per_CPU_Control   *cpu_self;
  Thread_Control    *executing;
  int                eno;
  unsigned int       nest_level;
  Watchdog_Interval  ticks;

  _ISR_lock_ISR_disable( &lock_context );

  switch ( _TOD_Absolute_timeout_to_ticks( abstime, &ticks ) ) {
    case TOD_ABSOLUTE_TIMEOUT_INVALID:
      _ISR_lock_ISR_enable( &lock_context );
      return EINVAL;
    case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
    case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
      _ISR_lock_ISR_enable( &lock_context );
      return ETIMEDOUT;
    default:
      break;
  }

  cpu_self = _Condition_Do_wait( _condition, ticks, &lock_context );

  nest_level = _mutex->_nest_level;
  _mutex->_nest_level = 0;
  _Mutex_recursive_Release( _mutex );
  executing = cpu_self->executing;
  _Thread_Dispatch_enable( cpu_self );
  eno = (int) executing->Wait.return_code;
  _Mutex_recursive_Acquire( _mutex );
  _mutex->_nest_level = nest_level;

  return eno;
}
コード例 #11
0
ファイル: objectidtoname.c プロジェクト: Avanznow/rtems
Objects_Name_or_id_lookup_errors _Objects_Id_to_name (
  Objects_Id      id,
  Objects_Name   *name
)
{
  uint32_t             the_api;
  uint32_t             the_class;
  Objects_Id           tmpId;
  Objects_Information *information;
  Objects_Control     *the_object = (Objects_Control *) 0;
  Objects_Locations    ignored_location;
  ISR_lock_Context     lock_context;

  /*
   *  Caller is trusted for name != NULL.
   */

  tmpId = (id == OBJECTS_ID_OF_SELF) ? _Thread_Get_executing()->Object.id : id;

  the_api = _Objects_Get_API( tmpId );
  if ( !_Objects_Is_api_valid( the_api ) )
    return OBJECTS_INVALID_ID;

  if ( !_Objects_Information_table[ the_api ] )
    return OBJECTS_INVALID_ID;

  the_class = _Objects_Get_class( tmpId );

  information = _Objects_Information_table[ the_api ][ the_class ];
  if ( !information )
    return OBJECTS_INVALID_ID;

  #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES)
    if ( information->is_string )
      return OBJECTS_INVALID_ID;
  #endif

  the_object = _Objects_Get_isr_disable(
    information,
    tmpId,
    &ignored_location,
    &lock_context
  );
  if ( !the_object )
    return OBJECTS_INVALID_ID;

  *name = the_object->name;
  _ISR_lock_ISR_enable( &lock_context );
  return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
}
コード例 #12
0
ファイル: taskdelete.c プロジェクト: AoLaD/rtems
rtems_status_code rtems_task_delete(
  rtems_id id
)
{
  Thread_Control   *the_thread;
  ISR_lock_Context  lock_context;
  Thread_Control   *executing;
  Per_CPU_Control  *cpu_self;

  the_thread = _Thread_Get( id, &lock_context );

  if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
    if ( _Thread_MP_Is_remote( id ) ) {
      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    }
#endif

    return RTEMS_INVALID_ID;
  }

  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
  _ISR_lock_ISR_enable( &lock_context );

  executing = _Per_CPU_Get_executing( cpu_self );

  if ( the_thread == executing ) {
    /*
     * The Classic tasks are neither detached nor joinable.  In case of
     * self deletion, they are detached, otherwise joinable by default.
     */
    _Thread_Exit(
      executing,
      THREAD_LIFE_TERMINATING | THREAD_LIFE_DETACHED,
      NULL
    );
  } else {
    _Thread_Close( the_thread, executing );
  }

  _Thread_Dispatch_enable( cpu_self );
  return RTEMS_SUCCESSFUL;
}
コード例 #13
0
ファイル: coremsgbroadcast.c プロジェクト: greenmeent/rtems
Status_Control _CORE_message_queue_Broadcast(
  CORE_message_queue_Control *the_message_queue,
  const void                 *buffer,
  size_t                      size,
  uint32_t                   *count,
  Thread_queue_Context       *queue_context
)
{
  Thread_Control             *the_thread;
  uint32_t                    number_broadcasted;

  if ( size > the_message_queue->maximum_message_size ) {
    _ISR_lock_ISR_enable( &queue_context->Lock_context );
    return STATUS_MESSAGE_INVALID_SIZE;
  }

  number_broadcasted = 0;

  _CORE_message_queue_Acquire_critical( the_message_queue, queue_context );

  while (
    ( the_thread =
      _CORE_message_queue_Dequeue_receiver(
        the_message_queue,
        buffer,
        size,
        0,
        queue_context
      )
    )
  ) {
    number_broadcasted += 1;

    _CORE_message_queue_Acquire( the_message_queue, queue_context );
  }

  _CORE_message_queue_Release( the_message_queue, queue_context );

  *count = number_broadcasted;
  return STATUS_SUCCESSFUL;
}
コード例 #14
0
ファイル: ratemoncancel.c プロジェクト: greenmeent/rtems
rtems_status_code rtems_rate_monotonic_cancel(
  rtems_id id
)
{
  Rate_monotonic_Control *the_period;
  ISR_lock_Context        lock_context;
  Thread_Control         *executing;

  the_period = _Rate_monotonic_Get( id, &lock_context );
  if ( the_period == NULL ) {
    return RTEMS_INVALID_ID;
  }

  executing = _Thread_Executing;
  if ( executing != the_period->owner ) {
    _ISR_lock_ISR_enable( &lock_context );
    return RTEMS_NOT_OWNER_OF_RESOURCE;
  }

  _Rate_monotonic_Cancel( the_period, executing, &lock_context );
  return RTEMS_SUCCESSFUL;
}
コード例 #15
0
ファイル: task1.c プロジェクト: greenmeent/rtems
void complete_test( void )
{
  uint32_t             index;
  rtems_id             task_id;
  ISR_lock_Context     lock_context;
  Thread_queue_Context queue_context;

  benchmark_timer_initialize();
    thread_resume( Middle_tcb );
  thread_resume_time = benchmark_timer_read();

  _Thread_Set_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE );

  benchmark_timer_initialize();
    _Thread_Unblock( Middle_tcb );
  thread_unblock_time = benchmark_timer_read();

  _Thread_Set_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE );

  benchmark_timer_initialize();
    _Thread_Clear_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE );
  thread_ready_time = benchmark_timer_read();

  benchmark_timer_initialize();
    for ( index=1 ; index <= OPERATION_COUNT ; index++ )
      (void) benchmark_timer_empty_function();
  overhead = benchmark_timer_read();

  task_id = Middle_tcb->Object.id;

  benchmark_timer_initialize();
    for ( index=1 ; index <= OPERATION_COUNT ; index++ ) {
      (void) _Thread_Get( task_id, &lock_context );
      _ISR_lock_ISR_enable( &lock_context );
    }
  thread_get_time = benchmark_timer_read();

  benchmark_timer_initialize();
    for ( index=1 ; index <= OPERATION_COUNT ; index++ ) {
      (void) _Semaphore_Get( Semaphore_id, &queue_context );
      _ISR_lock_ISR_enable( &queue_context.Lock_context );
    }
  semaphore_get_time = benchmark_timer_read();

  benchmark_timer_initialize();
    for ( index=1 ; index <= OPERATION_COUNT ; index++ ) {
      (void) _Thread_Get( 0x3, &lock_context );
      _ISR_lock_ISR_enable( &lock_context );
    }
  thread_get_invalid_time = benchmark_timer_read();

  /*
   *  This is the running task and we have tricked RTEMS out enough where
   *  we need to set some internal tracking information to match this.
   */

  set_thread_heir( _Thread_Get_executing() );
  set_thread_dispatch_necessary( false );

  /*
   *  Now dump all the times
   */

  put_time(
    "rtems interrupt: _ISR_Local_disable",
    isr_disable_time,
    1,
    0,
    0
  );

  put_time(
    "rtems interrupt: _ISR_Local_flash",
    isr_flash_time,
    1,
    0,
    0
  );

  put_time(
    "rtems interrupt: _ISR_Local_enable",
    isr_enable_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: _Thread_Dispatch_disable",
    thread_disable_dispatch_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: _Thread_Dispatch_enable",
    thread_enable_dispatch_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: _Thread_Set_state",
    thread_set_state_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: _Thread_Dispatch NO FP",
    thread_dispatch_no_fp_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: context switch: no floating point contexts",
    context_switch_no_fp_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: context switch: self",
    context_switch_self_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: context switch to another task",
    context_switch_another_task_time,
    1,
    0,
    0
  );

#if (CPU_HARDWARE_FP == 1) || (CPU_SOFTWARE_FP == 1)
  put_time(
    "rtems internal: fp context switch restore 1st FP task",
    context_switch_restore_1st_fp_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: fp context switch save idle and restore initialized",
    context_switch_save_idle_restore_initted_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: fp context switch save idle, restore idle",
    context_switch_save_restore_idle_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: fp context switch save initialized, restore initialized",
    context_switch_save_restore_initted_time,
    1,
    0,
    0
  );
#else
    puts(
     "rtems internal: fp context switch restore 1st FP task - NA\n"
     "rtems internal: fp context switch save idle restore initialized - NA\n"
     "rtems internal: fp context switch save idle restore idle - NA\n"
     "rtems internal: fp context switch save initialized\n"
                      " restore initialized - NA"
   );
#endif

  put_time(
    "rtems internal: _Thread_Resume",
    thread_resume_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: _Thread_Unblock",
    thread_unblock_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: _Thread_Ready",
    thread_ready_time,
    1,
    0,
    0
  );

  put_time(
    "rtems internal: _Thread_Get",
    thread_get_time,
    OPERATION_COUNT,
    0,
    0
  );

  put_time(
    "rtems internal: _Semaphore_Get",
    semaphore_get_time,
    OPERATION_COUNT,
    0,
    0
  );

  put_time(
    "rtems internal: _Thread_Get: invalid id",
    thread_get_invalid_time,
    OPERATION_COUNT,
    0,
    0
  );

  TEST_END();
  rtems_test_exit( 0 );
}
コード例 #16
0
ファイル: mqueuesendsupp.c プロジェクト: Avanznow/rtems
int _POSIX_Message_queue_Send_support(
  mqd_t               mqdes,
  const char         *msg_ptr,
  size_t              msg_len,
  unsigned int        msg_prio,
  bool                wait,
  Watchdog_Interval   timeout
)
{
  POSIX_Message_queue_Control    *the_mq;
  POSIX_Message_queue_Control_fd *the_mq_fd;
  Objects_Locations               location;
  CORE_message_queue_Status       msg_status;
  bool                            do_wait;
  Thread_Control                 *executing;
  ISR_lock_Context                lock_context;

  /*
   * Validate the priority.
   * XXX - Do not validate msg_prio is not less than 0.
   */

  if ( msg_prio > MQ_PRIO_MAX )
    rtems_set_errno_and_return_minus_one( EINVAL );

  the_mq_fd = _POSIX_Message_queue_Get_fd_interrupt_disable(
    mqdes,
    &location,
    &lock_context
  );
  switch ( location ) {

    case OBJECTS_LOCAL:
      if ( (the_mq_fd->oflag & O_ACCMODE) == O_RDONLY ) {
        _ISR_lock_ISR_enable( &lock_context );
        rtems_set_errno_and_return_minus_one( EBADF );
      }

      the_mq = the_mq_fd->Queue;

      /*
       *  A timed receive with a bad time will do a poll regardless.
       */
      if ( wait )
        do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? false : true;
      else
        do_wait = wait;

      /*
       *  Now perform the actual message receive
       */
      executing = _Thread_Executing;
      msg_status = _CORE_message_queue_Submit(
        &the_mq->Message_queue,
        executing,
        msg_ptr,
        msg_len,
        mqdes,      /* mqd_t is an object id */
        NULL,
        _POSIX_Message_queue_Priority_to_core( msg_prio ),
        do_wait,
        timeout,   /* no timeout */
        &lock_context
      );

      /*
       *  If we had to block, then this is where the task returns
       *  after it wakes up.  The returned status is correct for
       *  non-blocking operations but if we blocked, then we need
       *  to look at the status in our TCB.
       */

      if ( msg_status == CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT )
        msg_status = executing->Wait.return_code;

      if ( !msg_status )
        return msg_status;

      rtems_set_errno_and_return_minus_one(
        _POSIX_Message_queue_Translate_core_message_queue_return_code(
          msg_status
        )
      );

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
#endif
    case OBJECTS_ERROR:
      break;
  }

  rtems_set_errno_and_return_minus_one( EBADF );
}
コード例 #17
0
ファイル: coremsgsubmit.c プロジェクト: Avanznow/rtems
CORE_message_queue_Status _CORE_message_queue_Submit(
  CORE_message_queue_Control                *the_message_queue,
  Thread_Control                            *executing,
  const void                                *buffer,
  size_t                                     size,
  Objects_Id                                 id,
  #if defined(RTEMS_MULTIPROCESSING)
    CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
  #else
    CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support  RTEMS_UNUSED,
  #endif
  CORE_message_queue_Submit_types            submit_type,
  bool                                       wait,
  Watchdog_Interval                          timeout,
  ISR_lock_Context                          *lock_context
)
{
  CORE_message_queue_Buffer_control *the_message;
  Thread_Control                    *the_thread;

  if ( size > the_message_queue->maximum_message_size ) {
    _ISR_lock_ISR_enable( lock_context );
    return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
  }

  _CORE_message_queue_Acquire_critical( the_message_queue, lock_context );

  /*
   *  Is there a thread currently waiting on this message queue?
   */

  the_thread = _CORE_message_queue_Dequeue_receiver(
    the_message_queue,
    buffer,
    size,
    submit_type,
    lock_context
  );
  if ( the_thread != NULL ) {
    #if defined(RTEMS_MULTIPROCESSING)
      if ( !_Objects_Is_local_id( the_thread->Object.id ) )
        (*api_message_queue_mp_support) ( the_thread, id );

      _Thread_Dispatch_enable( _Per_CPU_Get() );
    #endif
    return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
  }

  /*
   *  No one waiting on the message queue at this time, so attempt to
   *  queue the message up for a future receive.
   */
  the_message =
      _CORE_message_queue_Allocate_message_buffer( the_message_queue );
  if ( the_message ) {
    the_message->Contents.size = size;
    _CORE_message_queue_Set_message_priority( the_message, submit_type );
    _CORE_message_queue_Copy_buffer(
      buffer,
      the_message->Contents.buffer,
      size
    );

    _CORE_message_queue_Insert_message(
       the_message_queue,
       the_message,
       submit_type
    );
    _CORE_message_queue_Release( the_message_queue, lock_context );
    return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
  }

  #if !defined(RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND)
    _CORE_message_queue_Release( the_message_queue, lock_context );
    return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
  #else
    /*
     *  No message buffers were available so we may need to return an
     *  overflow error or block the sender until the message is placed
     *  on the queue.
     */
    if ( !wait ) {
      _CORE_message_queue_Release( the_message_queue, lock_context );
      return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
    }

    /*
     *  Do NOT block on a send if the caller is in an ISR.  It is
     *  deadly to block in an ISR.
     */
    if ( _ISR_Is_in_progress() ) {
      _CORE_message_queue_Release( the_message_queue, lock_context );
      return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
    }

    /*
     *  WARNING!! executing should NOT be used prior to this point.
     *  Thus the unusual choice to open a new scope and declare
     *  it as a variable.  Doing this emphasizes how dangerous it
     *  would be to use this variable prior to here.
     */
    executing->Wait.id = id;
    executing->Wait.return_argument_second.immutable_object = buffer;
    executing->Wait.option = (uint32_t) size;
    executing->Wait.count = submit_type;

    _Thread_queue_Enqueue_critical(
      &the_message_queue->Wait_queue.Queue,
      the_message_queue->Wait_queue.operations,
      executing,
      STATES_WAITING_FOR_MESSAGE,
      timeout,
      CORE_MESSAGE_QUEUE_STATUS_TIMEOUT,
      lock_context
    );
    #if defined(RTEMS_MULTIPROCESSING)
      _Thread_Dispatch_enable( _Per_CPU_Get() );
    #endif

    return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT;
  #endif
}
コード例 #18
0
ファイル: mqueuerecvsupp.c プロジェクト: AoLaD/rtems
ssize_t _POSIX_Message_queue_Receive_support(
  mqd_t               mqdes,
  char               *msg_ptr,
  size_t              msg_len,
  unsigned int       *msg_prio,
  bool                wait,
  Watchdog_Interval   timeout
)
{
  POSIX_Message_queue_Control *the_mq;
  Thread_queue_Context         queue_context;
  size_t                       length_out;
  bool                         do_wait;
  Thread_Control              *executing;
  Status_Control               status;

  the_mq = _POSIX_Message_queue_Get( mqdes, &queue_context );

  if ( the_mq == NULL ) {
    rtems_set_errno_and_return_minus_one( EBADF );
  }

  if ( ( the_mq->oflag & O_ACCMODE ) == O_WRONLY ) {
    _ISR_lock_ISR_enable( &queue_context.Lock_context.Lock_context );
    rtems_set_errno_and_return_minus_one( EBADF );
  }

  if ( msg_len < the_mq->Message_queue.maximum_message_size ) {
    _ISR_lock_ISR_enable( &queue_context.Lock_context.Lock_context );
    rtems_set_errno_and_return_minus_one( EMSGSIZE );
  }

  /*
   *  Now if something goes wrong, we return a "length" of -1
   *  to indicate an error.
   */

  length_out = -1;

  /*
   *  A timed receive with a bad time will do a poll regardless.
   */
  if ( wait ) {
    do_wait = ( the_mq->oflag & O_NONBLOCK ) == 0;
  } else {
    do_wait = wait;
  }

  _CORE_message_queue_Acquire_critical(
    &the_mq->Message_queue,
    &queue_context
  );

  if ( the_mq->open_count == 0 ) {
    _CORE_message_queue_Release( &the_mq->Message_queue, &queue_context );
    rtems_set_errno_and_return_minus_one( EBADF );
  }

  /*
   *  Now perform the actual message receive
   */
  executing = _Thread_Executing;
  _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
  status = _CORE_message_queue_Seize(
    &the_mq->Message_queue,
    executing,
    msg_ptr,
    &length_out,
    do_wait,
    &queue_context
  );

  if ( msg_prio != NULL ) {
    *msg_prio = _POSIX_Message_queue_Priority_from_core(
      executing->Wait.count
    );
  }

  if ( status != STATUS_SUCCESSFUL ) {
    rtems_set_errno_and_return_minus_one( _POSIX_Get_error( status ) );
  }

  return length_out;
}
コード例 #19
0
ファイル: ratemonperiod.c プロジェクト: gedare/rtems
rtems_status_code rtems_rate_monotonic_period(
  rtems_id       id,
  rtems_interval length
)
{
  Rate_monotonic_Control            *the_period;
  ISR_lock_Context                   lock_context;
  Thread_Control                    *executing;
  rtems_status_code                  status;
  rtems_rate_monotonic_period_states state;

  the_period = _Rate_monotonic_Get( id, &lock_context );
  if ( the_period == NULL ) {
    return RTEMS_INVALID_ID;
  }

  executing = _Thread_Executing;
  if ( executing != the_period->owner ) {
    _ISR_lock_ISR_enable( &lock_context );
    return RTEMS_NOT_OWNER_OF_RESOURCE;
  }

  _Rate_monotonic_Acquire_critical( the_period, &lock_context );

  state = the_period->state;

  if ( length == RTEMS_PERIOD_STATUS ) {
    status = _Rate_monotonic_Get_status_for_state( state );
    _Rate_monotonic_Release( the_period, &lock_context );
  } else {
    switch ( state ) {
      case RATE_MONOTONIC_ACTIVE:

        if( the_period->postponed_jobs > 0 ){
          /*
           * If the number of postponed jobs is not 0, it means the
           * previous postponed instance is finished without exceeding
           * the current period deadline.
           *
           * Do nothing on the watchdog deadline assignment but release the
           * next remaining postponed job.
           */
          status = _Rate_monotonic_Block_while_expired(
            the_period,
            length,
            executing,
            &lock_context
          );
        }else{
          /*
           * Normal case that no postponed jobs and no expiration, so wait for
           * the period and update the deadline of watchdog accordingly.
           */
          status = _Rate_monotonic_Block_while_active(
            the_period,
            length,
            executing,
            &lock_context
          );
        }
        break;
      case RATE_MONOTONIC_INACTIVE:
        status = _Rate_monotonic_Activate(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
      default:
        /*
         * As now this period was already TIMEOUT, there must be at least one
         * postponed job recorded by the watchdog. The one which exceeded
         * the previous deadlines was just finished.
         *
         * Maybe there is more than one job postponed due to the preemption or
         * the previous finished job.
         */
        _Assert( state == RATE_MONOTONIC_EXPIRED );
        status = _Rate_monotonic_Block_while_expired(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
    }
  }

  return status;
}
コード例 #20
0
ファイル: coremutexsurrender.c プロジェクト: fsmd/RTEMS
CORE_mutex_Status _CORE_mutex_Surrender(
  CORE_mutex_Control                *the_mutex,
#if defined(RTEMS_MULTIPROCESSING)
  Objects_Id                         id,
  CORE_mutex_API_mp_support_callout  api_mutex_mp_support,
#else
  Objects_Id                         id __attribute__((unused)),
  CORE_mutex_API_mp_support_callout  api_mutex_mp_support __attribute__((unused)),
#endif
  ISR_lock_Context                  *lock_context
)
{
  Thread_Control *the_thread;
  Thread_Control *holder;

  holder = the_mutex->holder;

  /*
   *  The following code allows a thread (or ISR) other than the thread
   *  which acquired the mutex to release that mutex.  This is only
   *  allowed when the mutex in quetion is FIFO or simple Priority
   *  discipline.  But Priority Ceiling or Priority Inheritance mutexes
   *  must be released by the thread which acquired them.
   */

  if ( the_mutex->Attributes.only_owner_release ) {
    if ( !_Thread_Is_executing( holder ) ) {
      _ISR_lock_ISR_enable( lock_context );
      return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE;
    }
  }

  _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, lock_context );

  /* XXX already unlocked -- not right status */

  if ( !the_mutex->nest_count ) {
    _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    return CORE_MUTEX_STATUS_SUCCESSFUL;
  }

  the_mutex->nest_count--;

  if ( the_mutex->nest_count != 0 ) {
    /*
     *  All error checking is on the locking side, so if the lock was
     *  allowed to acquired multiple times, then we should just deal with
     *  that.  The RTEMS_DEBUG is just a validation.
     */
    #if defined(RTEMS_DEBUG)
      switch ( the_mutex->Attributes.lock_nesting_behavior ) {
        case CORE_MUTEX_NESTING_ACQUIRES:
          _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
          return CORE_MUTEX_STATUS_SUCCESSFUL;
        #if defined(RTEMS_POSIX_API)
          case CORE_MUTEX_NESTING_IS_ERROR:
            /* should never occur */
            _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
            return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
        #endif
        case CORE_MUTEX_NESTING_BLOCKS:
          /* Currently no API exercises this behavior. */
          break;
      }
    #else
      _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
      /* must be CORE_MUTEX_NESTING_ACQUIRES or we wouldn't be here */
      return CORE_MUTEX_STATUS_SUCCESSFUL;
    #endif
  }

  /*
   *  Formally release the mutex before possibly transferring it to a
   *  blocked thread.
   */
  if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
       _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
    CORE_mutex_Status pop_status =
      _CORE_mutex_Pop_priority( the_mutex, holder );

    if ( pop_status != CORE_MUTEX_STATUS_SUCCESSFUL ) {
      _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
      return pop_status;
    }

    holder->resource_count--;
  }
  the_mutex->holder = NULL;

  /*
   *  Now we check if another thread was waiting for this mutex.  If so,
   *  transfer the mutex to that thread.
   */
  if ( ( the_thread = _Thread_queue_First_locked( &the_mutex->Wait_queue ) ) ) {
    /*
     * We must extract the thread now since this will restore its default
     * thread lock.  This is necessary to avoid a deadlock in the
     * _Thread_Change_priority() below due to a recursive thread queue lock
     * acquire.
     */
    _Thread_queue_Extract_locked( &the_mutex->Wait_queue, the_thread );

#if defined(RTEMS_MULTIPROCESSING)
    _Thread_Dispatch_disable();

    if ( _Objects_Is_local_id( the_thread->Object.id ) )
#endif
    {
      the_mutex->holder     = the_thread;
      the_mutex->nest_count = 1;

      switch ( the_mutex->Attributes.discipline ) {
        case CORE_MUTEX_DISCIPLINES_FIFO:
        case CORE_MUTEX_DISCIPLINES_PRIORITY:
          break;
        case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
          _CORE_mutex_Push_priority( the_mutex, the_thread );
          the_thread->resource_count++;
          break;
        case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
          _CORE_mutex_Push_priority( the_mutex, the_thread );
          the_thread->resource_count++;
          _Thread_Raise_priority(
            the_thread,
            the_mutex->Attributes.priority_ceiling
          );
          break;
      }
    }

    _Thread_queue_Unblock_critical(
      &the_mutex->Wait_queue,
      the_thread,
      lock_context
    );

#if defined(RTEMS_MULTIPROCESSING)
    if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {

      the_mutex->holder     = NULL;
      the_mutex->nest_count = 1;

      ( *api_mutex_mp_support)( the_thread, id );

    }

    _Thread_Dispatch_enable( _Per_CPU_Get() );
#endif
  } else {
    _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
  }

  /*
   *  Whether or not someone is waiting for the mutex, an
   *  inherited priority must be lowered if this is the last
   *  mutex (i.e. resource) this task has.
   */
  if ( !_Thread_Owns_resources( holder ) ) {
    /*
     * Ensure that the holder resource count is visible to all other processors
     * and that we read the latest priority restore hint.
     */
    _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );

    if ( holder->priority_restore_hint ) {
      Per_CPU_Control *cpu_self;

      cpu_self = _Thread_Dispatch_disable();
      _Thread_Restore_priority( holder );
      _Thread_Dispatch_enable( cpu_self );
    }
  }

  return CORE_MUTEX_STATUS_SUCCESSFUL;
}
コード例 #21
0
ファイル: ratemonperiod.c プロジェクト: AoLaD/rtems
rtems_status_code rtems_rate_monotonic_period(
  rtems_id       id,
  rtems_interval length
)
{
  Rate_monotonic_Control            *the_period;
  ISR_lock_Context                   lock_context;
  Thread_Control                    *executing;
  rtems_status_code                  status;
  rtems_rate_monotonic_period_states state;

  the_period = _Rate_monotonic_Get( id, &lock_context );
  if ( the_period == NULL ) {
    return RTEMS_INVALID_ID;
  }

  executing = _Thread_Executing;
  if ( executing != the_period->owner ) {
    _ISR_lock_ISR_enable( &lock_context );
    return RTEMS_NOT_OWNER_OF_RESOURCE;
  }

  _Rate_monotonic_Acquire_critical( the_period, &lock_context );

  state = the_period->state;

  if ( length == RTEMS_PERIOD_STATUS ) {
    status = _Rate_monotonic_Get_status_for_state( state );
    _Rate_monotonic_Release( the_period, &lock_context );
  } else {
    switch ( state ) {
      case RATE_MONOTONIC_ACTIVE:
        status = _Rate_monotonic_Block_while_active(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
      case RATE_MONOTONIC_INACTIVE:
        status = _Rate_monotonic_Activate(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
      default:
        _Assert( state == RATE_MONOTONIC_EXPIRED );
        status = _Rate_monotonic_Block_while_expired(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
    }
  }

  return status;
}