Exemple #1
0
bool _Thread_Initialize(
  Thread_Information                   *information,
  Thread_Control                       *the_thread,
  const Scheduler_Control              *scheduler,
  void                                 *stack_area,
  size_t                                stack_size,
  bool                                  is_fp,
  Priority_Control                      priority,
  bool                                  is_preemptible,
  Thread_CPU_budget_algorithms          budget_algorithm,
  Thread_CPU_budget_algorithm_callout   budget_callout,
  uint32_t                              isr_level,
  Objects_Name                          name
)
{
  uintptr_t                tls_size = _TLS_Get_size();
  size_t                   actual_stack_size = 0;
  void                    *stack = NULL;
  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    void                  *fp_area = NULL;
  #endif
  bool                     extension_status;
  size_t                   i;
  Scheduler_Node          *scheduler_node;
#if defined(RTEMS_SMP)
  Scheduler_Node          *scheduler_node_for_index;
  const Scheduler_Control *scheduler_for_index;
#endif
  size_t                   scheduler_index;
  Per_CPU_Control         *cpu = _Per_CPU_Get_by_index( 0 );

#if defined( RTEMS_SMP )
  if ( rtems_configuration_is_smp_enabled() ) {
    if ( !is_preemptible ) {
      return false;
    }

    if ( isr_level != 0 ) {
      return false;
    }
  }
#endif

  memset(
    &the_thread->current_state,
    0,
    information->Objects.size - offsetof( Thread_Control, current_state )
  );

  for ( i = 0 ; i < _Thread_Control_add_on_count ; ++i ) {
    const Thread_Control_add_on *add_on = &_Thread_Control_add_ons[ i ];

    *(void **) ( (char *) the_thread + add_on->destination_offset ) =
      (char *) the_thread + add_on->source_offset;
  }

  /*
   *  Allocate and Initialize the stack for this thread.
   */
  #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
    actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
    if ( !actual_stack_size || actual_stack_size < stack_size )
      return false;                     /* stack allocation failed */

    stack = the_thread->Start.stack;
  #else
    if ( !stack_area ) {
      actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
      if ( !actual_stack_size || actual_stack_size < stack_size )
        return false;                     /* stack allocation failed */

      stack = the_thread->Start.stack;
      the_thread->Start.core_allocated_stack = true;
    } else {
      stack = stack_area;
      actual_stack_size = stack_size;
      the_thread->Start.core_allocated_stack = false;
    }
  #endif

  _Stack_Initialize(
     &the_thread->Start.Initial_stack,
     stack,
     actual_stack_size
  );

  scheduler_index = 0;

  /* Thread-local storage (TLS) area allocation */
  if ( tls_size > 0 ) {
    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );

    the_thread->Start.tls_area =
      _Workspace_Allocate_aligned( tls_alloc, tls_align );

    if ( the_thread->Start.tls_area == NULL ) {
      goto failed;
    }
  }

  /*
   *  Allocate the floating point area for this thread
   */
  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    if ( is_fp ) {
      fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
      if ( !fp_area )
        goto failed;
      fp_area = _Context_Fp_start( fp_area, 0 );
    }
    the_thread->fp_context       = fp_area;
    the_thread->Start.fp_context = fp_area;
  #endif

  /*
   *  Get thread queue heads
   */
  the_thread->Wait.spare_heads = _Freechain_Get(
    &information->Free_thread_queue_heads,
    _Workspace_Allocate,
    _Objects_Extend_size( &information->Objects ),
    THREAD_QUEUE_HEADS_SIZE( _Scheduler_Count )
  );
  if ( the_thread->Wait.spare_heads == NULL ) {
    goto failed;
  }
  _Thread_queue_Heads_initialize( the_thread->Wait.spare_heads );

  /*
   *  General initialization
   */

  the_thread->is_fp                  = is_fp;
  the_thread->Start.isr_level        = isr_level;
  the_thread->Start.is_preemptible   = is_preemptible;
  the_thread->Start.budget_algorithm = budget_algorithm;
  the_thread->Start.budget_callout   = budget_callout;

  _Thread_Timer_initialize( &the_thread->Timer, cpu );

  switch ( budget_algorithm ) {
    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
    case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
      break;
    #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
      case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
        the_thread->cpu_time_budget =
          rtems_configuration_get_ticks_per_timeslice();
        break;
    #endif
    #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
      case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
	break;
    #endif
  }

#if defined(RTEMS_SMP)
  scheduler_node_for_index = the_thread->Scheduler.nodes;
  scheduler_for_index = &_Scheduler_Table[ 0 ];

  while ( scheduler_index < _Scheduler_Count ) {
    Priority_Control priority_for_index;

    if ( scheduler_for_index == scheduler ) {
      priority_for_index = priority;
      scheduler_node = scheduler_node_for_index;
    } else {
      /*
       * Use the idle thread priority for the non-home scheduler instances by
       * default.
       */
      priority_for_index = _Scheduler_Map_priority(
        scheduler_for_index,
        scheduler_for_index->maximum_priority
      );
    }

    _Scheduler_Node_initialize(
      scheduler_for_index,
      scheduler_node_for_index,
      the_thread,
      priority_for_index
    );
    scheduler_node_for_index = (Scheduler_Node *)
      ( (uintptr_t) scheduler_node_for_index + _Scheduler_Node_size );
    ++scheduler_for_index;
    ++scheduler_index;
  }

  _Chain_Initialize_one(
    &the_thread->Scheduler.Wait_nodes,
    &scheduler_node->Thread.Wait_node
  );
  _Chain_Initialize_one(
    &the_thread->Scheduler.Scheduler_nodes,
    &scheduler_node->Thread.Scheduler_node.Chain
  );
#else
  scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
  _Scheduler_Node_initialize(
    scheduler,
    scheduler_node,
    the_thread,
    priority
  );
  scheduler_index = 1;
#endif

  _Priority_Node_initialize( &the_thread->Real_priority, priority );
  _Priority_Initialize_one(
    &scheduler_node->Wait.Priority,
    &the_thread->Real_priority
  );

#if defined(RTEMS_SMP)
  RTEMS_STATIC_ASSERT( THREAD_SCHEDULER_BLOCKED == 0, Scheduler_state );
  the_thread->Scheduler.home = scheduler;
  _ISR_lock_Initialize( &the_thread->Scheduler.Lock, "Thread Scheduler" );
  _ISR_lock_Initialize( &the_thread->Wait.Lock.Default, "Thread Wait Default" );
  _Thread_queue_Gate_open( &the_thread->Wait.Lock.Tranquilizer );
  _RBTree_Initialize_node( &the_thread->Wait.Link.Registry_node );
  _SMP_lock_Stats_initialize( &the_thread->Potpourri_stats, "Thread Potpourri" );
#endif

  /* Initialize the CPU for the non-SMP schedulers */
  _Thread_Set_CPU( the_thread, cpu );

  _Thread_queue_Initialize( &the_thread->Join_queue );

  the_thread->current_state           = STATES_DORMANT;
  the_thread->Wait.operations         = &_Thread_queue_Operations_default;
  the_thread->Start.initial_priority  = priority;

  RTEMS_STATIC_ASSERT( THREAD_WAIT_FLAGS_INITIAL == 0, Wait_flags );

  /* POSIX Keys */
  _RBTree_Initialize_empty( &the_thread->Keys.Key_value_pairs );
  _ISR_lock_Initialize( &the_thread->Keys.Lock, "POSIX Key Value Pairs" );

  _Thread_Action_control_initialize( &the_thread->Post_switch_actions );

  /*
   *  Open the object
   */
  _Objects_Open( &information->Objects, &the_thread->Object, name );

  /*
   *  We assume the Allocator Mutex is locked and dispatching is
   *  enabled when we get here.  We want to be able to run the
   *  user extensions with dispatching enabled.  The Allocator
   *  Mutex provides sufficient protection to let the user extensions
   *  run safely.
   */
  extension_status = _User_extensions_Thread_create( the_thread );
  if ( extension_status )
    return true;

failed:

#if defined(RTEMS_SMP)
  while ( scheduler_index > 0 ) {
    scheduler_node_for_index = (Scheduler_Node *)
      ( (uintptr_t) scheduler_node_for_index - _Scheduler_Node_size );
    --scheduler_for_index;
    --scheduler_index;
    _Scheduler_Node_destroy( scheduler_for_index, scheduler_node_for_index );
  }
#else
  if ( scheduler_index > 0 ) {
    _Scheduler_Node_destroy( scheduler, scheduler_node );
  }
#endif

  _Workspace_Free( the_thread->Start.tls_area );

  _Freechain_Put(
    &information->Free_thread_queue_heads,
    the_thread->Wait.spare_heads
  );

  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    _Workspace_Free( fp_area );
  #endif

   _Thread_Stack_Free( the_thread );
  return false;
}
bool _CORE_message_queue_Initialize(
  CORE_message_queue_Control    *the_message_queue,
  CORE_message_queue_Attributes *the_message_queue_attributes,
  uint32_t                       maximum_pending_messages,
  size_t                         maximum_message_size
)
{
  size_t message_buffering_required;
  size_t allocated_message_size;

  the_message_queue->maximum_pending_messages   = maximum_pending_messages;
  the_message_queue->number_of_pending_messages = 0;
  the_message_queue->maximum_message_size       = maximum_message_size;
  _CORE_message_queue_Set_notify( the_message_queue, NULL, NULL );

  /*
   *  Round size up to multiple of a pointer for chain init and
   *  check for overflow on adding overhead to each message.
   */
  allocated_message_size = maximum_message_size;
  if (allocated_message_size & (sizeof(uint32_t) - 1)) {
    allocated_message_size += sizeof(uint32_t);
    allocated_message_size &= ~(sizeof(uint32_t) - 1);
  }

  if (allocated_message_size < maximum_message_size)
    return false;

  /*
   *  Calculate how much total memory is required for message buffering and
   *  check for overflow on the multiplication.
   */
  message_buffering_required = (size_t) maximum_pending_messages *
       (allocated_message_size + sizeof(CORE_message_queue_Buffer_control));

  if (message_buffering_required < allocated_message_size)
    return false;

  /*
   *  Attempt to allocate the message memory
   */
  the_message_queue->message_buffers = (CORE_message_queue_Buffer *)
     _Workspace_Allocate( message_buffering_required );

  if (the_message_queue->message_buffers == 0)
    return false;

  /*
   *  Initialize the pool of inactive messages, pending messages,
   *  and set of waiting threads.
   */
  _Chain_Initialize (
    &the_message_queue->Inactive_messages,
    the_message_queue->message_buffers,
    (size_t) maximum_pending_messages,
    allocated_message_size + sizeof( CORE_message_queue_Buffer_control )
  );

  _Chain_Initialize_empty( &the_message_queue->Pending_messages );

  _Thread_queue_Initialize(
    &the_message_queue->Wait_queue,
    _CORE_message_queue_Is_priority( the_message_queue_attributes ) ?
       THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
    STATES_WAITING_FOR_MESSAGE,
    CORE_MESSAGE_QUEUE_STATUS_TIMEOUT
  );

  return true;
}
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);
}
Exemple #4
0
/*
 *  _POSIX_Threads_Create_extension
 *
 *  This method is invoked for each thread created.
 */

static bool _POSIX_Threads_Create_extension(
    Thread_Control *executing __attribute__((unused)),
    Thread_Control *created
)
{
    POSIX_API_Control *api;
    POSIX_API_Control *executing_api;

    api = _Workspace_Allocate( sizeof( POSIX_API_Control ) );

    if ( !api )
        return false;

    created->API_Extensions[ THREAD_API_POSIX ] = api;

    /* XXX check all fields are touched */
    api->Attributes  = _POSIX_Threads_Default_attributes;
    api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
    api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
    api->schedparam  = _POSIX_Threads_Default_attributes.schedparam;
    api->schedparam.sched_priority =
        _POSIX_Priority_From_core( created->current_priority );

    /*
Exemple #5
0
int pthread_key_create(
  pthread_key_t  *key,
  void          (*destructor)( void * )
)
{
  POSIX_Keys_Control  *the_key;
  void                *table;
  uint32_t             the_api;
  uint32_t             bytes_to_allocate;


  _Thread_Disable_dispatch();

  the_key = _POSIX_Keys_Allocate();

  if ( !the_key ) {
    _Thread_Enable_dispatch();
    return EAGAIN;
  }

  the_key->destructor = destructor;

  /*
   *  This is a bit more complex than one might initially expect because
   *  APIs are optional.
   *
   *  NOTE: Currently RTEMS Classic API tasks are always enabled.
   */
  for ( the_api = 1; the_api <= OBJECTS_APIS_LAST; the_api++ ) {
    the_key->Values[ the_api ] = NULL;

    #if defined(RTEMS_DEBUG)
      /*
       *  Since the removal of ITRON, this cannot occur.
       */
      if ( !_Objects_Information_table[ the_api ] )
	continue;

      /*
       * Currently all managers are installed if the API is installed.
       * This would be a horrible implementation error.
       */
      if (_Objects_Information_table[ the_api ][ 1 ] == NULL )
	_Internal_error_Occurred(
	  INTERNAL_ERROR_CORE,
	  true,
	  INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY
	);
    #endif

    bytes_to_allocate = sizeof( void * ) *
      (_Objects_Information_table[ the_api ][ 1 ]->maximum + 1);
    table = _Workspace_Allocate( bytes_to_allocate );
    if ( !table ) {
      _POSIX_Keys_Free_memory( the_key );

      _POSIX_Keys_Free( the_key );
      _Thread_Enable_dispatch();
      return ENOMEM;
    }

    the_key->Values[ the_api ] = table;
    memset( table, '\0', bytes_to_allocate );
  }

  _Objects_Open_u32( &_POSIX_Keys_Information, &the_key->Object, 0 );
  *key = the_key->Object.id;
  _Thread_Enable_dispatch();
  return 0;
}
bool _Thread_Initialize(
  Objects_Information                  *information,
  Thread_Control                       *the_thread,
  void                                 *stack_area,
  size_t                                stack_size,
  bool                                  is_fp,
  Priority_Control                      priority,
  bool                                  is_preemptible,
  Thread_CPU_budget_algorithms          budget_algorithm,
  Thread_CPU_budget_algorithm_callout   budget_callout,
  uint32_t                              isr_level,
  Objects_Name                          name
)
{
  size_t               actual_stack_size = 0;
  void                *stack = NULL;
  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    void              *fp_area;
  #endif
  void                *extensions_area;
  bool                 extension_status;
  int                  i;

  /*
   *  Initialize the Ada self pointer
   */
  #if __RTEMS_ADA__
    the_thread->epos_ada_self = NULL;
  #endif

  /*
   *  Zero out all the allocated memory fields
   */
  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
    the_thread->API_Extensions[i] = NULL;

  extensions_area = NULL;
  the_thread->libc_reent = NULL;

  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    fp_area = NULL;
  #endif

  /*
   *  Allocate and Initialize the stack for this thread.
   */
  #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
    actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
    if ( !actual_stack_size || actual_stack_size < stack_size )
      return false;                     /* stack allocation failed */

    stack = the_thread->Start.stack;
  #else
    if ( !stack_area ) {
      actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
      if ( !actual_stack_size || actual_stack_size < stack_size )
        return false;                     /* stack allocation failed */

      stack = the_thread->Start.stack;
      the_thread->Start.core_allocated_stack = true;
    } else {
      stack = stack_area;
      actual_stack_size = stack_size;
      the_thread->Start.core_allocated_stack = false;
    }
  #endif

  _Stack_Initialize(
     &the_thread->Start.Initial_stack,
     stack,
     actual_stack_size
  );

  /*
   *  Allocate the floating point area for this thread
   */
  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    if ( is_fp ) {
      fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
      if ( !fp_area )
        goto failed;
      fp_area = _Context_Fp_start( fp_area, 0 );
    }
    the_thread->fp_context       = fp_area;
    the_thread->Start.fp_context = fp_area;
  #endif

  /*
   *  Initialize the thread timer
   */
  _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL );

  #ifdef __RTEMS_STRICT_ORDER_MUTEX__
    /* Initialize the head of chain of held mutexes */
    _Chain_Initialize_empty(&the_thread->lock_mutex);
  #endif

  /*
   *  Allocate the extensions area for this thread
   */
  if ( _Thread_Maximum_extensions ) {
    extensions_area = _Workspace_Allocate(
      (_Thread_Maximum_extensions + 1) * sizeof( void * )
    );
    if ( !extensions_area )
      goto failed;
  }
  the_thread->extensions = (void **) extensions_area;

  /*
   * Clear the extensions area so extension users can determine
   * if they are linked to the thread. An extension user may
   * create the extension long after tasks have been created
   * so they cannot rely on the thread create user extension
   * call.
   */
  if ( the_thread->extensions ) {
    for ( i = 0; i <= _Thread_Maximum_extensions ; i++ )
      the_thread->extensions[i] = NULL;
  }

  /*
   *  General initialization
   */

  the_thread->Start.is_preemptible   = is_preemptible;
  the_thread->Start.budget_algorithm = budget_algorithm;
  the_thread->Start.budget_callout   = budget_callout;

  switch ( budget_algorithm ) {
    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
    case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
      break;
    #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
      case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
        the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
        break;
    #endif
    #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
      case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
	break;
    #endif
  }

  the_thread->Start.isr_level         = isr_level;

  the_thread->current_state           = STATES_DORMANT;
  the_thread->Wait.queue              = NULL;
  the_thread->resource_count          = 0;
  the_thread->real_priority           = priority;
  the_thread->Start.initial_priority  = priority;
  _Thread_Set_priority( the_thread, priority );

  /*
   *  Initialize the CPU usage statistics
   */
  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
    _Timestamp_Set_to_zero( &the_thread->cpu_time_used );
  #else
    the_thread->cpu_time_used = 0;
  #endif

  /*
   *  Open the object
   */
  _Objects_Open( information, &the_thread->Object, name );

  /*
   *  We assume the Allocator Mutex is locked and dispatching is
   *  enabled when we get here.  We want to be able to run the
   *  user extensions with dispatching enabled.  The Allocator
   *  Mutex provides sufficient protection to let the user extensions
   *  run safely.
   */
  extension_status = _User_extensions_Thread_create( the_thread );
  if ( extension_status )
    return true;

failed:
  if ( the_thread->libc_reent )
    _Workspace_Free( the_thread->libc_reent );

  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
    if ( the_thread->API_Extensions[i] )
      _Workspace_Free( the_thread->API_Extensions[i] );

  if ( extensions_area )
    (void) _Workspace_Free( extensions_area );

  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    if ( fp_area )
      (void) _Workspace_Free( fp_area );
  #endif

   _Thread_Stack_Free( the_thread, true );
  return false;
}