Beispiel #1
0
void FreeLine(
  Line_Control *line
)
{
  fflush( stdout );
  _Chain_Append( &Line_Pool, &line->Node );
}
Beispiel #2
0
void pthread_cleanup_push(
    void   (*routine)( void * ),
    void    *arg
)
{
    POSIX_Cancel_Handler_control      *handler;
    Chain_Control                     *handler_stack;
    POSIX_API_Control                 *thread_support;

    /*
     *  The POSIX standard does not address what to do when the routine
     *  is NULL.  It also does not address what happens when we cannot
     *  allocate memory or anything else bad happens.
     */
    if ( !routine )
        return;

    _Thread_Disable_dispatch();
    handler = _Workspace_Allocate( sizeof( POSIX_Cancel_Handler_control ) );

    if ( handler ) {
        thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];

        handler_stack = &thread_support->Cancellation_Handlers;

        handler->routine = routine;
        handler->arg = arg;

        _Chain_Append( handler_stack, &handler->Node );
    }
    _Thread_Enable_dispatch();
}
Beispiel #3
0
void StripBlanks( void )
{
  Line_Control      *line;
  Keyword_indices_t  index;
  int                indentation;
  int                length;

  for ( line = (Line_Control *) Lines.first ;
        !_Chain_Is_last( &line->Node ) ;
        line = (Line_Control *) line->Node.next
        ) {

    /*
     *  Strip white space from the end of each line
     */

    length = strlen( line->Contents );

    while ( isspace( line->Contents[ --length ] ) )
      line->Contents[ length ] = '\0';

    if ( strstr( line->Contents, "@chapter" ) )
      line->keyword = KEYWORD_CHAPTER;
    else if ( strstr( line->Contents, "@appendix" ) )
      line->keyword = KEYWORD_APPENDIX;
    else if ( strstr( line->Contents, "@preface" ) )
      line->keyword = KEYWORD_PREFACE;
    else if ( strstr( line->Contents, "@chapheading" ) )
      line->keyword = KEYWORD_CHAPHEADING;
    else if ( strstr( line->Contents, "@section" ) )
      line->keyword = KEYWORD_SECTION;
    else if ( strstr( line->Contents, "@subsection" ) )
      line->keyword = KEYWORD_SUBSECTION;
    else if ( strstr( line->Contents, "@subsubsection" ) )
      line->keyword = KEYWORD_SUBSUBSECTION;
    else if ( strstr( line->Contents, "@raise" ) )
      line->keyword = KEYWORD_RAISE;
    else if ( strstr( line->Contents, "@lower" ) )
      line->keyword = KEYWORD_LOWER;
    else
      line->keyword = KEYWORD_OTHER;

  }
  line = AllocateLine();
  line->keyword = KEYWORD_END;
  _Chain_Append( &Lines, &line->Node );
}
Beispiel #4
0
static void _Timer_server_Schedule_operation_method(
  Timer_server_Control *ts,
  Timer_Control *timer
)
{
  if ( ts->insert_chain == NULL ) {
    _Timer_server_Insert_timer_and_make_snapshot( ts, timer );
  } else {
    /*
     *  We interrupted a critical section of the timer server.  The timer
     *  server is not preemptible, so we must be in interrupt context here.  No
     *  thread dispatch will happen until the timer server finishes its
     *  critical section.  We have to use the protected chain methods because
     *  we may be interrupted by a higher priority interrupt.
     */
    _Chain_Append( ts->insert_chain, &timer->Object.Node );
  }
}
Beispiel #5
0
Thread_Control *_Thread_MP_Allocate_proxy (
  States_Control  the_state
)
{
  Thread_Control       *the_thread;
  Thread_Proxy_control *the_proxy;

  the_thread = (Thread_Control *)_Chain_Get( &_Thread_MP_Inactive_proxies );

  if ( !_Thread_Is_null( the_thread ) ) {

    the_proxy = (Thread_Proxy_control *) the_thread;

    _Thread_Executing->Wait.return_code = THREAD_STATUS_PROXY_BLOCKING;

    the_proxy->receive_packet = _MPCI_Receive_server_tcb->receive_packet;

    the_proxy->Object.id = _MPCI_Receive_server_tcb->receive_packet->source_tid;

    the_proxy->current_priority =
      _MPCI_Receive_server_tcb->receive_packet->source_priority;

    the_proxy->current_state = _States_Set( STATES_DORMANT, the_state );

    the_proxy->Wait = _Thread_Executing->Wait;

    _Chain_Append( &_Thread_MP_Active_proxies, &the_proxy->Active );

    return the_thread;
  }

  _Internal_error_Occurred(
    INTERNAL_ERROR_CORE,
    true,
    INTERNAL_ERROR_OUT_OF_PROXIES
  );

  /*
   *  NOTE: The following return ensures that the compiler will
   *        think that all paths return a value.
   */

  return NULL;
}
Beispiel #6
0
void ReadFileIntoChain2(
  FILE *InFile
)
{
   int   line_count;
   int   max_length;
   char *line;
   char  Buffer[ BUFFER_SIZE ];
   Line_Control *new_line;

   if ( !InFile ) {
     fprintf( stderr, "Unable to open (%s)\n", "stdin" );
     exit( 1 );
   }
   assert( InFile );

   max_length = 0;
   line_count = 0;

   _Chain_Initialize_empty( &Lines );

   for ( ;; ) {
      line = fgets( Buffer, BUFFER_SIZE, InFile );
      if ( !line )
        break;

      Buffer[ strlen( Buffer ) - 1 ] = '\0';

      new_line = AllocateLine();

      strcpy( new_line->Contents, Buffer );

      new_line->number = ++line_count;

      _Chain_Append( &Lines, &new_line->Node );
   }

   fclose( InFile );
}
Beispiel #7
0
int killinfo(
  pid_t               pid,
  int                 sig,
  const union sigval *value
)
{
  sigset_t                     mask;
  POSIX_API_Control           *api;
  uint32_t                     the_api;
  uint32_t                     index;
  uint32_t                     maximum;
  Objects_Information         *the_info;
  Objects_Control            **object_table;
  Thread_Control              *the_thread;
  Thread_Control              *interested;
  Priority_Control             interested_priority;
  Chain_Control               *the_chain;
  Chain_Node                  *the_node;
  siginfo_t                    siginfo_struct;
  siginfo_t                   *siginfo;
  POSIX_signals_Siginfo_node  *psiginfo;

  /*
   *  Only supported for the "calling process" (i.e. this node).
   */
  if ( pid != getpid() )
    rtems_set_errno_and_return_minus_one( ESRCH );

  /*
   *  Validate the signal passed.
   */
  if ( !sig )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( !is_valid_signo(sig) )
    rtems_set_errno_and_return_minus_one( EINVAL );

  /*
   *  If the signal is being ignored, then we are out of here.
   */
  if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
    return 0;

  /*
   *  P1003.1c/Draft 10, p. 33 says that certain signals should always
   *  be directed to the executing thread such as those caused by hardware
   *  faults.
   */
  if ( (sig == SIGFPE) || (sig == SIGILL) || (sig == SIGSEGV ) )
      return pthread_kill( pthread_self(), sig );

  mask = signo_to_mask( sig );

  /*
   *  Build up a siginfo structure
   */
  siginfo = &siginfo_struct;
  siginfo->si_signo = sig;
  siginfo->si_code = SI_USER;
  if ( !value ) {
    siginfo->si_value.sival_int = 0;
  } else {
    siginfo->si_value = *value;
  }

  _Thread_Disable_dispatch();

  /*
   *  Is the currently executing thread interested?  If so then it will
   *  get it an execute it as soon as the dispatcher executes.
   */
  the_thread = _Thread_Executing;

  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
  if ( _POSIX_signals_Is_interested( api, mask ) ) {
    goto process_it;
  }

  /*
   *  Is an interested thread waiting for this signal (sigwait())?
   *
   *  There is no requirement on the order of threads pending on a sigwait().
   */

  /* XXX violation of visibility -- need to define thread queue support */

  the_chain = &_POSIX_signals_Wait_queue.Queues.Fifo;

  for ( the_node = _Chain_First( the_chain );
        !_Chain_Is_tail( the_chain, the_node ) ;
        the_node = the_node->next ) {

    the_thread = THREAD_CHAIN_NODE_TO_THREAD( the_node );
    api = the_thread->API_Extensions[ THREAD_API_POSIX ];

    #if defined(DEBUG_SIGNAL_PROCESSING)
      printk( "Waiting Thread=%p option=0x%08x mask=0x%08x blocked=0x%08x\n",
        the_thread, the_thread->Wait.option, mask, api->signals_blocked);
    #endif

    /*
     * Is this thread is actually blocked waiting for the signal?
     */
    if (the_thread->Wait.option & mask)
      goto process_it;

    /*
     * Is this thread is blocked waiting for another signal but has
     * not blocked this one?
     */
    if (~api->signals_blocked & mask)
      goto process_it;
  }

  /*
   *  Is any other thread interested?  The highest priority interested
   *  thread is selected.  In the event of a tie, then the following
   *  additional criteria is used:
   *
   *    + ready thread over blocked
   *    + blocked on call interruptible by signal (can return EINTR)
   *    + blocked on call not interruptible by signal
   *
   *  This looks at every thread in the system regardless of the creating API.
   *
   *  NOTES:
   *
   *    + rtems internal threads do not receive signals.
   */
  interested = NULL;
  interested_priority = PRIORITY_MAXIMUM + 1;

  for (the_api = OBJECTS_CLASSIC_API; the_api <= OBJECTS_APIS_LAST; the_api++) {

    /*
     *  This can occur when no one is interested and an API is not configured.
     */
    if ( !_Objects_Information_table[ the_api ] )
      continue;

    the_info = _Objects_Information_table[ the_api ][ 1 ];

    #if defined(RTEMS_DEBUG)
      /*
       *  This cannot happen in the current (as of June 2009) implementation
       *  of initialization but at some point, the object information
       *  structure for a particular manager may not be installed.
       */
      if ( !the_info )
        continue;
    #endif

    maximum = the_info->maximum;
    object_table = the_info->local_table;

    for ( index = 1 ; index <= maximum ; index++ ) {
      the_thread = (Thread_Control *) object_table[ index ];

      if ( !the_thread )
        continue;

      #if defined(DEBUG_SIGNAL_PROCESSING)
        printk("\n 0x%08x/0x%08x %d/%d 0x%08x 1",
          the_thread->Object.id,
          ((interested) ? interested->Object.id : 0),
          the_thread->current_priority, interested_priority,
          the_thread->current_state
        );
      #endif

      /*
       *  If this thread is of lower priority than the interested thread,
       *  go on to the next thread.
       */
      if ( the_thread->current_priority > interested_priority )
        continue;
      DEBUG_STEP("2");

      /*
       *  If this thread is not interested, then go on to the next thread.
       */
      api = the_thread->API_Extensions[ THREAD_API_POSIX ];

      #if defined(RTEMS_DEBUG)
        if ( !api )
          continue;
      #endif

      if ( !_POSIX_signals_Is_interested( api, mask ) )
        continue;
      DEBUG_STEP("3");

      /*
       *  Now we know the thread under consideration is interested.
       *  If the thread under consideration is of higher priority, then
       *  it becomes the interested thread.
       *
       *  NOTE: We initialized interested_priority to PRIORITY_MAXIMUM + 1
       *        so we never have to worry about deferencing a NULL
       *        interested thread.
       */
      if ( the_thread->current_priority < interested_priority ) {
        interested   = the_thread;
        interested_priority = the_thread->current_priority;
        continue;
      }
      DEBUG_STEP("4");

      /*
       *  Now the thread and the interested thread have the same priority.
       *  We have to sort through the combinations of blocked/not blocked
       *  and blocking interruptibutable by signal.
       *
       *  If the interested thread is ready, don't think about changing.
       */

      if ( interested && !_States_Is_ready( interested->current_state ) ) {
        /* preferred ready over blocked */
        DEBUG_STEP("5");
        if ( _States_Is_ready( the_thread->current_state ) ) {
          interested          = the_thread;
          interested_priority = the_thread->current_priority;
          continue;
        }

        DEBUG_STEP("6");
        /* prefer blocked/interruptible over blocked/not interruptible */
        if ( !_States_Is_interruptible_by_signal(interested->current_state) ) {
          DEBUG_STEP("7");
          if ( _States_Is_interruptible_by_signal(the_thread->current_state) ) {
            DEBUG_STEP("8");
            interested          = the_thread;
            interested_priority = the_thread->current_priority;
            continue;
          }
        }
      }
    }
  }

  if ( interested ) {
    the_thread = interested;
    goto process_it;
  }

  /*
   *  OK so no threads were interested right now.  It will be left on the
   *  global pending until a thread receives it.  The global set of threads
   *  can change interest in this signal in one of the following ways:
   *
   *    + a thread is created with the signal unblocked,
   *    + pthread_sigmask() unblocks the signal,
   *    + sigprocmask() unblocks the signal, OR
   *    + sigaction() which changes the handler to SIG_IGN.
   */
  the_thread = NULL;
  goto post_process_signal;

  /*
   *  We found a thread which was interested, so now we mark that this
   *  thread needs to do the post context switch extension so it can
   *  evaluate the signals pending.
   */
process_it:

  /*
   *  Returns true if the signal was synchronously given to a thread
   *  blocked waiting for the signal.
   */
  if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {
    _Thread_Enable_dispatch();
    return 0;
  }

post_process_signal:

  /*
   *  We may have woken up a thread but we definitely need to post the
   *  signal to the process wide information set.
   */
  _POSIX_signals_Set_process_signals( mask );

  if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {

    psiginfo = (POSIX_signals_Siginfo_node *)
               _Chain_Get( &_POSIX_signals_Inactive_siginfo );
    if ( !psiginfo ) {
      _Thread_Enable_dispatch();
      rtems_set_errno_and_return_minus_one( EAGAIN );
    }

    psiginfo->Info = *siginfo;

    _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );
  }

  DEBUG_STEP("\n");
  _Thread_Enable_dispatch();
  return 0;
}
Beispiel #8
0
void _Objects_Extend_information(
  Objects_Information *information
)
{
  Objects_Control  *the_object;
  Chain_Control     Inactive;
  uint32_t          block_count;
  uint32_t          block;
  uint32_t          index_base;
  uint32_t          minimum_index;
  uint32_t          index;
  uint32_t          maximum;
  size_t            block_size;
  void             *new_object_block;
  bool              do_extend;

  /*
   *  Search for a free block of indexes. If we do NOT need to allocate or
   *  extend the block table, then we will change do_extend.
   */
  do_extend     = true;
  minimum_index = _Objects_Get_index( information->minimum_id );
  index_base    = minimum_index;
  block         = 0;

  /* if ( information->maximum < minimum_index ) */
  if ( information->object_blocks == NULL )
    block_count = 0;
  else {
    block_count = information->maximum / information->allocation_size;

    for ( ; block < block_count; block++ ) {
      if ( information->object_blocks[ block ] == NULL ) {
        do_extend = false;
        break;
      } else
        index_base += information->allocation_size;
    }
  }

  maximum = (uint32_t) information->maximum + information->allocation_size;

  /*
   *  We need to limit the number of objects to the maximum number
   *  representable in the index portion of the object Id.  In the
   *  case of 16-bit Ids, this is only 256 object instances.
   */
  if ( maximum > OBJECTS_ID_FINAL_INDEX ) {
    return;
  }

  /*
   * Allocate the name table, and the objects and if it fails either return or
   * generate a fatal error depending on auto-extending being active.
   */
  block_size = information->allocation_size * information->size;
  if ( information->auto_extend ) {
    new_object_block = _Workspace_Allocate( block_size );
    if ( !new_object_block )
      return;
  } else {
    new_object_block = _Workspace_Allocate_or_fatal_error( block_size );
  }

  /*
   *  Do we need to grow the tables?
   */
  if ( do_extend ) {
    ISR_Level         level;
    void            **object_blocks;
    uint32_t         *inactive_per_block;
    Objects_Control **local_table;
    void             *old_tables;
    size_t            block_size;

    /*
     *  Growing the tables means allocating a new area, doing a copy and
     *  updating the information table.
     *
     *  If the maximum is minimum we do not have a table to copy. First
     *  time through.
     *
     *  The allocation has :
     *
     *      void            *objects[block_count];
     *      uint32_t         inactive_count[block_count];
     *      Objects_Control *local_table[maximum];
     *
     *  This is the order in memory. Watch changing the order. See the memcpy
     *  below.
     */

    /*
     *  Up the block count and maximum
     */
    block_count++;

    /*
     *  Allocate the tables and break it up.
     */
    block_size = block_count *
           (sizeof(void *) + sizeof(uint32_t) + sizeof(Objects_Name *)) +
          ((maximum + minimum_index) * sizeof(Objects_Control *));
    object_blocks = (void**) _Workspace_Allocate( block_size );

    if ( !object_blocks ) {
      _Workspace_Free( new_object_block );
      return;
    }

    /*
     *  Break the block into the various sections.
     */
    inactive_per_block = (uint32_t *) _Addresses_Add_offset(
        object_blocks, block_count * sizeof(void*) );
    local_table = (Objects_Control **) _Addresses_Add_offset(
        inactive_per_block, block_count * sizeof(uint32_t) );

    /*
     *  Take the block count down. Saves all the (block_count - 1)
     *  in the copies.
     */
    block_count--;

    if ( information->maximum > minimum_index ) {

      /*
       *  Copy each section of the table over. This has to be performed as
       *  separate parts as size of each block has changed.
       */

      memcpy( object_blocks,
              information->object_blocks,
              block_count * sizeof(void*) );
      memcpy( inactive_per_block,
              information->inactive_per_block,
              block_count * sizeof(uint32_t) );
      memcpy( local_table,
              information->local_table,
              (information->maximum + minimum_index) * sizeof(Objects_Control *) );
    } else {

      /*
       *  Deal with the special case of the 0 to minimum_index
       */
      for ( index = 0; index < minimum_index; index++ ) {
        local_table[ index ] = NULL;
      }
    }

    /*
     *  Initialise the new entries in the table.
     */
    object_blocks[block_count] = NULL;
    inactive_per_block[block_count] = 0;

    for ( index=index_base ;
          index < ( information->allocation_size + index_base );
          index++ ) {
      local_table[ index ] = NULL;
    }

    _ISR_Disable( level );

    old_tables = information->object_blocks;

    information->object_blocks = object_blocks;
    information->inactive_per_block = inactive_per_block;
    information->local_table = local_table;
    information->maximum = (Objects_Maximum) maximum;
    information->maximum_id = _Objects_Build_id(
        information->the_api,
        information->the_class,
        _Objects_Local_node,
        information->maximum
      );

    _ISR_Enable( level );

    _Workspace_Free( old_tables );

    block_count++;
  }

  /*
   *  Assign the new object block to the object block table.
   */
  information->object_blocks[ block ] = new_object_block;

  /*
   *  Initialize objects .. add to a local chain first.
   */
  _Chain_Initialize(
    &Inactive,
    information->object_blocks[ block ],
    information->allocation_size,
    information->size
  );

  /*
   *  Move from the local chain, initialise, then append to the inactive chain
   */
  index = index_base;

  while ((the_object = (Objects_Control *) _Chain_Get( &Inactive )) != NULL ) {

    the_object->id = _Objects_Build_id(
        information->the_api,
        information->the_class,
        _Objects_Local_node,
        index
      );

    _Chain_Append( &information->Inactive, &the_object->Node );

    index++;
  }

  information->inactive_per_block[ block ] = information->allocation_size;
  information->inactive =
    (Objects_Maximum)(information->inactive + information->allocation_size);
}
void _API_extensions_Add(
  API_extensions_Control *the_extension
)
{
  _Chain_Append( &_API_extensions_List, &the_extension->Node );
}