source: rtems/cpukit/score/include/rtems/score/threadimpl.h @ 01794eb

4.115
Last change on this file since 01794eb was 01794eb, checked in by Sebastian Huber <sebastian.huber@…>, on 02/07/14 at 07:55:02

score: Format _Thread_Get_maximum_internal_threads

  • Property mode set to 100644
File size: 19.2 KB
Line 
1/**
2 * @file
3 *
4 * @brief Inlined Routines from the Thread Handler
5 *
6 * This file contains the macro implementation of the inlined
7 * routines from the Thread handler.
8 */
9
10/*
11 *  COPYRIGHT (c) 1989-2008.
12 *  On-Line Applications Research Corporation (OAR).
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.com/license/LICENSE.
17 */
18
19#ifndef _RTEMS_SCORE_THREADIMPL_H
20#define _RTEMS_SCORE_THREADIMPL_H
21
22#include <rtems/score/thread.h>
23#include <rtems/score/isr.h>
24#include <rtems/score/objectimpl.h>
25#include <rtems/score/statesimpl.h>
26#include <rtems/score/sysstate.h>
27#include <rtems/score/todimpl.h>
28#include <rtems/config.h>
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34/**
35 * @addtogroup ScoreThread
36 */
37/**@{**/
38
39/**
40 *  The following structure contains the information necessary to manage
41 *  a thread which it is  waiting for a resource.
42 */
43#define THREAD_STATUS_PROXY_BLOCKING 0x1111111
44
45/**
46 *  Self for the GNU Ada Run-Time
47 */
48SCORE_EXTERN void *rtems_ada_self;
49
50/**
51 *  The following defines the information control block used to
52 *  manage this class of objects.
53 */
54SCORE_EXTERN Objects_Information _Thread_Internal_information;
55
56/**
57 *  The following context area contains the context of the "thread"
58 *  which invoked the start multitasking routine.  This context is
59 *  restored as the last action of the stop multitasking routine.  Thus
60 *  control of the processor can be returned to the environment
61 *  which initiated the system.
62 */
63SCORE_EXTERN Context_Control _Thread_BSP_context;
64
65/**
66 *  The following holds how many user extensions are in the system.  This
67 *  is used to determine how many user extension data areas to allocate
68 *  per thread.
69 */
70SCORE_EXTERN uint32_t   _Thread_Maximum_extensions;
71
72/**
73 *  The following is used to manage the length of a timeslice quantum.
74 */
75SCORE_EXTERN uint32_t   _Thread_Ticks_per_timeslice;
76
77/**
78 *  The following points to the thread whose floating point
79 *  context is currently loaded.
80 */
81#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
82SCORE_EXTERN Thread_Control *_Thread_Allocated_fp;
83#endif
84
85#if !defined(__DYNAMIC_REENT__)
86/**
87 * The C library re-enter-rant global pointer. Some C library implementations
88 * such as newlib have a single global pointer that changed during a context
89 * switch. The pointer points to that global pointer. The Thread control block
90 * holds a pointer to the task specific data.
91 */
92SCORE_EXTERN struct _reent **_Thread_libc_reent;
93#endif
94
95/**
96 *  @brief Initialize thread handler.
97 *
98 *  This routine performs the initialization necessary for this handler.
99 */
100void _Thread_Handler_initialization(void);
101
102/**
103 *  @brief Create idle thread.
104 *
105 *  This routine creates the idle thread.
106 *
107 *  @warning No thread should be created before this one.
108 */
109void _Thread_Create_idle(void);
110
111/**
112 *  @brief Start thread multitasking.
113 *
114 *  This routine initiates multitasking.  It is invoked only as
115 *  part of initialization and its invocation is the last act of
116 *  the non-multitasking part of the system initialization.
117 *
118 *
119 *  - INTERRUPT LATENCY:
120 *    + ready chain
121 *    + select heir
122 */
123void _Thread_Start_multitasking( Context_Control *context );
124
125/**
126 *  @brief Allocate the requested stack space for the thread.
127 *
128 *  Allocate the requested stack space for the thread.
129 *  Set the Start.stack field to the address of the stack.
130 *
131 *  @param[in] the_thread is the thread where the stack space is requested
132 *
133 *  @retval actual size allocated after any adjustment
134 *  @retval zero if the allocation failed
135 */
136size_t _Thread_Stack_Allocate(
137  Thread_Control *the_thread,
138  size_t          stack_size
139);
140
141/**
142 *  @brief Deallocate thread stack.
143 *
144 *  Deallocate the Thread's stack.
145 */
146void _Thread_Stack_Free(
147  Thread_Control *the_thread
148);
149
150/**
151 *  @brief Initialize thread.
152 *
153 *  This routine initializes the specified the thread.  It allocates
154 *  all memory associated with this thread.  It completes by adding
155 *  the thread to the local object table so operations on this
156 *  thread id are allowed.
157 *
158 *  @note If stack_area is NULL, it is allocated from the workspace.
159 *
160 *  @note If the stack is allocated from the workspace, then it is
161 *        guaranteed to be of at least minimum size.
162 */
163bool _Thread_Initialize(
164  Objects_Information                  *information,
165  Thread_Control                       *the_thread,
166  void                                 *stack_area,
167  size_t                                stack_size,
168  bool                                  is_fp,
169  Priority_Control                      priority,
170  bool                                  is_preemptible,
171  Thread_CPU_budget_algorithms          budget_algorithm,
172  Thread_CPU_budget_algorithm_callout   budget_callout,
173  uint32_t                              isr_level,
174  Objects_Name                          name
175);
176
177/**
178 *  @brief Initializes thread and executes it.
179 *
180 *  This routine initializes the executable information for a thread
181 *  and makes it ready to execute.  After this routine executes, the
182 *  thread competes with all other threads for CPU time.
183 *
184 *  @param the_thread is the thread to be initialized
185 *  @param the_prototype
186 *  @param entry_point
187 *  @param pointer_argument
188 *  @param numeric_argument
189 *  @param[in,out] processor The processor if used to start an idle thread
190 *  during system initialization.  Must be set to @c NULL to start a normal
191 *  thread.
192 */
193bool _Thread_Start(
194  Thread_Control            *the_thread,
195  Thread_Start_types         the_prototype,
196  void                      *entry_point,
197  void                      *pointer_argument,
198  Thread_Entry_numeric_type  numeric_argument,
199  Per_CPU_Control           *processor
200);
201
202/**
203 *  @brief Restarts the specified thread.
204 *
205 *  This support routine restarts the specified task in a way that the
206 *  next time this thread executes, it will begin execution at its
207 *  original starting point.
208 *
209 *  TODO:  multiple task arg profiles
210 */
211bool _Thread_Restart(
212  Thread_Control            *the_thread,
213  void                      *pointer_argument,
214  Thread_Entry_numeric_type  numeric_argument
215);
216
217/**
218 *  @brief Resets a thread to its initial state.
219 *
220 *  This routine resets a thread to its initial state but does
221 *  not restart it. Some APIs do this in separate
222 *  operations and this division helps support this.
223 *
224 *  @param[in] the_thread is the thread to resets
225 *  @param[in] pointer_argument
226 *  @param[in] numeric_argument
227 */
228void _Thread_Reset(
229  Thread_Control            *the_thread,
230  void                      *pointer_argument,
231  Thread_Entry_numeric_type  numeric_argument
232);
233
234/**
235 *  @brief Frees all memory associated with the specified thread.
236 *
237 *  This routine frees all memory associated with the specified
238 *  thread and removes it from the local object table so no further
239 *  operations on this thread are allowed.
240 */
241void _Thread_Close(
242  Objects_Information  *information,
243  Thread_Control       *the_thread
244);
245
246/**
247 *  @brief Removes any set states for @a the_thread.
248 *
249 *  This routine removes any set states for @a the_thread.  It performs
250 *  any necessary scheduling operations including the selection of
251 *  a new heir thread.
252 *
253 *  - INTERRUPT LATENCY:
254 *    + ready chain
255 *    + select heir
256 */
257void _Thread_Ready(
258  Thread_Control *the_thread
259);
260
261/**
262 *  @brief Clears the indicated STATES for @a the_thread.
263 *
264 *  This routine clears the indicated STATES for @a the_thread.  It performs
265 *  any necessary scheduling operations including the selection of
266 *  a new heir thread.
267 *
268 *  - INTERRUPT LATENCY:
269 *    + priority map
270 *    + select heir
271 */
272void _Thread_Clear_state(
273  Thread_Control *the_thread,
274  States_Control  state
275);
276
277/**
278 *  @brief Sets the indicated @a state for @a the_thread.
279 *
280 *  This routine sets the indicated @a state for @a the_thread.  It performs
281 *  any necessary scheduling operations including the selection of
282 *  a new heir thread.
283 *
284 *  @param[in] the_thread is the thread to set the state for.
285 *  @param[in] state is the state to set the_thread to.
286 *
287 *  - INTERRUPT LATENCY:
288 *   + ready chain
289 *   + select map
290 */
291void _Thread_Set_state(
292  Thread_Control *the_thread,
293  States_Control  state
294);
295
296/**
297 *  @brief Sets the transient state for a thread.
298 *
299 *  This routine sets the Transient state for @a the_thread.  It performs
300 *  any necessary scheduling operations including the selection of
301 *  a new heir thread.
302 *
303 *  @param[in] the_thread is the thread to preform the action upon.
304 *
305 *  - INTERRUPT LATENCY:
306 *    + single case
307 */
308void _Thread_Set_transient(
309  Thread_Control *the_thread
310);
311
312/**
313 *  @brief Initializes enviroment for a thread.
314 *
315 *  This routine initializes the context of @a the_thread to its
316 *  appropriate starting state.
317 *
318 *  @param[in] the_thread is the pointer to the thread control block.
319 */
320void _Thread_Load_environment(
321  Thread_Control *the_thread
322);
323
324/**
325 *  @brief Wrapper function for all threads.
326 *
327 *  This routine is the wrapper function for all threads.  It is
328 *  the starting point for all threads.  The user provided thread
329 *  entry point is invoked by this routine.  Operations
330 *  which must be performed immediately before and after the user's
331 *  thread executes are found here.
332 *
333 *  @note On entry, it is assumed all interrupts are blocked and that this
334 *  routine needs to set the initial isr level.  This may or may not
335 *  actually be needed by the context switch routine and as a result
336 *  interrupts may already be at there proper level.  Either way,
337 *  setting the initial isr level properly here is safe.
338 */
339void _Thread_Handler( void );
340
341/**
342 *  @brief Ended the delay of a thread.
343 *
344 *  This routine is invoked when a thread must be unblocked at the
345 *  end of a time based delay (i.e. wake after or wake when).
346 *  It is called by the watchdog handler.
347 *
348 *  @param[in] id is the thread id
349 */
350void _Thread_Delay_ended(
351  Objects_Id  id,
352  void       *ignored
353);
354
355/**
356 *  @brief Change the priority of a thread.
357 *
358 *  This routine changes the current priority of @a the_thread to
359 *  @a new_priority.  It performs any necessary scheduling operations
360 *  including the selection of a new heir thread.
361 *
362 *  @param[in] the_thread is the thread to change
363 *  @param[in] new_priority is the priority to set @a the_thread to
364 *  @param[in] prepend_it is a switch to prepend the thread
365 */
366void _Thread_Change_priority (
367  Thread_Control   *the_thread,
368  Priority_Control  new_priority,
369  bool              prepend_it
370);
371
372/**
373 *  @brief Set thread priority.
374 *
375 *  This routine updates the priority related fields in the_thread
376 *  control block to indicate the current priority is now new_priority.
377 */
378void _Thread_Set_priority(
379  Thread_Control   *the_thread,
380  Priority_Control  new_priority
381);
382
383/**
384 *  This routine updates the related suspend fields in the_thread
385 *  control block to indicate the current nested level.
386 */
387#define _Thread_Suspend( _the_thread ) \
388        _Thread_Set_state( _the_thread, STATES_SUSPENDED )
389
390/**
391 *  This routine updates the related suspend fields in the_thread
392 *  control block to indicate the current nested level.  A force
393 *  parameter of true will force a resume and clear the suspend count.
394 */
395#define _Thread_Resume( _the_thread ) \
396        _Thread_Clear_state( _the_thread, STATES_SUSPENDED )
397
398/**
399 *  @brief Maps thread Id to a TCB pointer.
400 *
401 *  This function maps thread IDs to thread control
402 *  blocks.  If ID corresponds to a local thread, then it
403 *  returns the_thread control pointer which maps to ID
404 *  and @a location is set to OBJECTS_LOCAL.  If the thread ID is
405 *  global and resides on a remote node, then location is set
406 *  to OBJECTS_REMOTE, and the_thread is undefined.
407 *  Otherwise, location is set to OBJECTS_ERROR and
408 *  the_thread is undefined.
409 *
410 *  @param[in] id is the id of the thread.
411 *  @param[in] location is the location of the block.
412 *
413 *  @note  The performance of many RTEMS services depends upon
414 *         the quick execution of the "good object" path in this
415 *         routine.  If there is a possibility of saving a few
416 *         cycles off the execution time, this routine is worth
417 *         further optimization attention.
418 */
419Thread_Control *_Thread_Get (
420  Objects_Id         id,
421  Objects_Locations *location
422);
423
424/**
425 *  @brief Cancel a blocking operation due to ISR.
426 *
427 *  This method is used to cancel a blocking operation that was
428 *  satisfied from an ISR while the thread executing was in the
429 *  process of blocking.
430 *
431 *  This method will restore the previous ISR disable level during the cancel
432 *  operation.  Thus it is an implicit _ISR_Enable().
433 *
434 *  @param[in] sync_state is the synchronization state
435 *  @param[in] the_thread is the thread whose blocking is canceled
436 *  @param[in] level is the previous ISR disable level
437 *
438 *  @note This is a rare routine in RTEMS.  It is called with
439 *        interrupts disabled and only when an ISR completed
440 *        a blocking condition in process.
441 */
442void _Thread_blocking_operation_Cancel(
443  Thread_blocking_operation_States  sync_state,
444  Thread_Control                   *the_thread,
445  ISR_Level                         level
446);
447
448/**
449 * This routine halts multitasking and returns control to
450 * the "thread" (i.e. the BSP) which initially invoked the
451 * routine which initialized the system.
452 */
453
454RTEMS_INLINE_ROUTINE void _Thread_Stop_multitasking( void )
455{
456#if defined(_CPU_Stop_multitasking)
457  _CPU_Stop_multitasking( &_Thread_BSP_context );
458#else
459  /*
460   *  This may look a bit of an odd but _Context_Restart_self is just
461   *  a very careful restore of a specific context which ensures that
462   *  if we were running within the same context, it would work.
463   *
464   *  And we will not return to this thread, so there is no point of
465   *  saving the context.
466   */
467  _Context_Restart_self( &_Thread_BSP_context );
468#endif
469
470  /***************************************************************
471   ***************************************************************
472   *   SYSTEM SHUTS DOWN!!!  WE DO NOT RETURN TO THIS POINT!!!   *
473   ***************************************************************
474   ***************************************************************
475   */
476}
477
478/**
479 * This function returns true if the_thread is the currently executing
480 * thread, and false otherwise.
481 */
482
483RTEMS_INLINE_ROUTINE bool _Thread_Is_executing (
484  const Thread_Control *the_thread
485)
486{
487  return ( the_thread == _Thread_Executing );
488}
489
490/**
491 * This function returns true if the_thread is the heir
492 * thread, and false otherwise.
493 */
494
495RTEMS_INLINE_ROUTINE bool _Thread_Is_heir (
496  const Thread_Control *the_thread
497)
498{
499  return ( the_thread == _Thread_Heir );
500}
501
502/**
503 * This routine clears any blocking state for the_thread.  It performs
504 * any necessary scheduling operations including the selection of
505 * a new heir thread.
506 */
507
508RTEMS_INLINE_ROUTINE void _Thread_Unblock (
509  Thread_Control *the_thread
510)
511{
512  _Thread_Clear_state( the_thread, STATES_BLOCKED );
513}
514
515/**
516 * This routine resets the current context of the calling thread
517 * to that of its initial state.
518 */
519
520RTEMS_INLINE_ROUTINE void _Thread_Restart_self( void )
521{
522#if defined(RTEMS_SMP)
523  ISR_Level level;
524
525  _Per_CPU_ISR_disable_and_acquire( _Per_CPU_Get(), level );
526  ( void ) level;
527#endif
528
529#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
530  if ( _Thread_Executing->fp_context != NULL )
531    _Context_Restore_fp( &_Thread_Executing->fp_context );
532#endif
533
534  _CPU_Context_Restart_self( &_Thread_Executing->Registers );
535}
536
537/**
538 * This function returns true if the floating point context of
539 * the_thread is currently loaded in the floating point unit, and
540 * false otherwise.
541 */
542
543#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
544RTEMS_INLINE_ROUTINE bool _Thread_Is_allocated_fp (
545  const Thread_Control *the_thread
546)
547{
548  return ( the_thread == _Thread_Allocated_fp );
549}
550#endif
551
552/**
553 * This routine is invoked when the currently loaded floating
554 * point context is now longer associated with an active thread.
555 */
556
557#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
558RTEMS_INLINE_ROUTINE void _Thread_Deallocate_fp( void )
559{
560  _Thread_Allocated_fp = NULL;
561}
562#endif
563
564/**
565 * This function returns true if dispatching is disabled, and false
566 * otherwise.
567 */
568
569RTEMS_INLINE_ROUTINE bool _Thread_Is_context_switch_necessary( void )
570{
571  return ( _Thread_Dispatch_necessary );
572}
573
574/**
575 * This function returns true if the_thread is NULL and false otherwise.
576 */
577
578RTEMS_INLINE_ROUTINE bool _Thread_Is_null (
579  const Thread_Control *the_thread
580)
581{
582  return ( the_thread == NULL );
583}
584
585/**
586 * @brief Is proxy blocking.
587 *
588 * status which indicates that a proxy is blocking, and false otherwise.
589 */
590RTEMS_INLINE_ROUTINE bool _Thread_Is_proxy_blocking (
591  uint32_t   code
592)
593{
594  return (code == THREAD_STATUS_PROXY_BLOCKING);
595}
596
597RTEMS_INLINE_ROUTINE uint32_t _Thread_Get_maximum_internal_threads(void)
598{
599  /* Idle threads */
600  uint32_t maximum_internal_threads =
601    rtems_configuration_get_maximum_processors();
602
603  /* MPCI thread */
604#if defined(RTEMS_MULTIPROCESSING)
605  if ( _System_state_Is_multiprocessing ) {
606    ++maximum_internal_threads;
607  }
608#endif
609
610  return maximum_internal_threads;
611}
612
613/**
614 * This routine allocates an internal thread.
615 */
616
617RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Internal_allocate( void )
618{
619  return (Thread_Control *) _Objects_Allocate( &_Thread_Internal_information );
620}
621
622/**
623 * This routine frees an internal thread.
624 */
625
626RTEMS_INLINE_ROUTINE void _Thread_Internal_free (
627  Thread_Control *the_task
628)
629{
630  _Objects_Free( &_Thread_Internal_information, &the_task->Object );
631}
632
633RTEMS_INLINE_ROUTINE void _Thread_Set_global_exit_status(
634  uint32_t exit_status
635)
636{
637  Thread_Control *idle = (Thread_Control *)
638    _Thread_Internal_information.local_table[ 1 ];
639
640  idle->Wait.return_code = exit_status;
641}
642
643RTEMS_INLINE_ROUTINE uint32_t _Thread_Get_global_exit_status( void )
644{
645  const Thread_Control *idle = (const Thread_Control *)
646    _Thread_Internal_information.local_table[ 1 ];
647
648  return idle->Wait.return_code;
649}
650
651RTEMS_INLINE_ROUTINE void _Thread_Signal_notification( Thread_Control *thread )
652{
653  if ( _ISR_Is_in_progress() && _Thread_Is_executing( thread ) ) {
654    _Thread_Dispatch_necessary = true;
655  } else {
656#if defined(RTEMS_SMP)
657    if ( thread->is_executing ) {
658      const Per_CPU_Control *cpu_of_executing = _Per_CPU_Get();
659      Per_CPU_Control *cpu_of_thread = thread->cpu;
660
661      if ( cpu_of_executing != cpu_of_thread ) {
662        cpu_of_thread->dispatch_necessary = true;
663        _Per_CPU_Send_interrupt( cpu_of_thread );
664      }
665    }
666#endif
667  }
668}
669
670RTEMS_INLINE_ROUTINE void _Thread_Update_cpu_time_used(
671  Thread_Control *executing,
672  Timestamp_Control *time_of_last_context_switch
673)
674{
675  Timestamp_Control uptime;
676  Timestamp_Control ran;
677
678  _TOD_Get_uptime( &uptime );
679  _Timestamp_Subtract(
680    time_of_last_context_switch,
681    &uptime,
682    &ran
683  );
684  *time_of_last_context_switch = uptime;
685  _Timestamp_Add_to( &executing->cpu_time_used, &ran );
686}
687
688#if !defined(__DYNAMIC_REENT__)
689/**
690 * This routine returns the C library re-enterant pointer.
691 */
692
693RTEMS_INLINE_ROUTINE struct _reent **_Thread_Get_libc_reent( void )
694{
695  return _Thread_libc_reent;
696}
697
698/**
699 * This routine set the C library re-enterant pointer.
700 */
701
702RTEMS_INLINE_ROUTINE void _Thread_Set_libc_reent (
703  struct _reent **libc_reent
704)
705{
706  _Thread_libc_reent = libc_reent;
707}
708#endif
709
710/** @}*/
711
712#ifdef __cplusplus
713}
714#endif
715
716#if defined(RTEMS_MULTIPROCESSING)
717#include <rtems/score/threadmp.h>
718#endif
719
720#endif
721/* end of include file */
Note: See TracBrowser for help on using the repository browser.