source: rtems/cpukit/score/src/threadcreateidle.c @ 03e4d1e9

Last change on this file since 03e4d1e9 was 03e4d1e9, checked in by Sebastian Huber <sebastian.huber@…>, on 06/29/22 at 12:37:47

score: Add _CPU_Use_thread_local_storage()

At some point during system initialization, the idle threads are created.
Afterwards, the boot processor basically executes within the context of an idle
thread with thread dispatching disabled. On some architectures, the
thread-local storage area of the associated thread must be set in dedicated
processor registers. Add the new CPU port function to do this:

void _CPU_Use_thread_local_storage( const Context_Control *context )

Close #4672.

  • Property mode set to 100644
File size: 4.2 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSScoreThread
7 *
8 * @brief This source file contains the implementation of
9 *   _Thread_Create_idle().
10 */
11
12/*
13 *  COPYRIGHT (c) 1989-2011.
14 *  On-Line Applications Research Corporation (OAR).
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#include <rtems/score/threadidledata.h>
43#include <rtems/score/cpuimpl.h>
44#include <rtems/score/threadimpl.h>
45#include <rtems/score/assert.h>
46#include <rtems/score/schedulerimpl.h>
47#include <rtems/score/stackimpl.h>
48#include <rtems/score/sysstate.h>
49#include <rtems/score/userextimpl.h>
50
51#include <string.h>
52
53static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu )
54{
55  Thread_Configuration  config;
56  Thread_Control       *idle;
57  Status_Control        status;
58
59  memset( &config, 0, sizeof( config ) );
60  config.scheduler = _Scheduler_Get_by_CPU( cpu );
61  _Assert( config.scheduler != NULL );
62  config.priority = _Scheduler_Map_priority(
63    config.scheduler,
64    config.scheduler->maximum_priority
65  );
66  config.name = _Objects_Build_name( 'I', 'D', 'L', 'E' );
67  config.is_fp = CPU_IDLE_TASK_IS_FP;
68  config.is_preemptible = true;
69  config.stack_size = _Thread_Idle_stack_size
70    + CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE;
71
72  /*
73   * The IDLE thread stacks may be statically allocated or there may be a
74   * custom allocator provided just as with user threads.
75   */
76  config.stack_area = (*_Stack_Allocator_allocate_for_idle)(
77    _Per_CPU_Get_index( cpu ),
78    config.stack_size
79  );
80
81  /*
82   *  The entire workspace is zeroed during its initialization.  Thus, all
83   *  fields not explicitly assigned were explicitly zeroed by
84   *  _Workspace_Initialization.
85   */
86  idle = _Thread_Internal_allocate();
87  _Assert( idle != NULL );
88
89  status = _Thread_Initialize( &_Thread_Information, idle, &config );
90  _Assert_Unused_variable_equals( status, STATUS_SUCCESSFUL );
91
92  /*
93   *  WARNING!!! This is necessary to "kick" start the system and
94   *             MUST be done before _Thread_Start is invoked.
95   */
96  cpu->heir      =
97  cpu->executing = idle;
98#if defined(RTEMS_SMP)
99  cpu->ancestor = idle;
100#endif
101
102  idle->is_idle = true;
103  idle->Start.Entry.adaptor = _Thread_Entry_adaptor_idle;
104  idle->Start.Entry.Kinds.Idle.entry = _Thread_Idle_body;
105
106  _Thread_Load_environment( idle );
107
108  idle->current_state = STATES_READY;
109  _Scheduler_Start_idle( config.scheduler, idle, cpu );
110  _User_extensions_Thread_start( idle );
111}
112
113void _Thread_Create_idle( void )
114{
115  uint32_t cpu_max;
116  uint32_t cpu_index;
117
118  _System_state_Set( SYSTEM_STATE_BEFORE_MULTITASKING );
119  cpu_max = _SMP_Get_processor_maximum();
120
121  for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
122    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
123
124    if ( _Per_CPU_Is_processor_online( cpu ) ) {
125      _Thread_Create_idle_for_CPU( cpu );
126    }
127  }
128
129  _CPU_Use_thread_local_storage(
130    &_Per_CPU_Get_executing( _Per_CPU_Get() )->Registers
131  );
132}
Note: See TracBrowser for help on using the repository browser.