source: rtems/cpukit/posix/src/pthread.c @ bf2a53d2

5
Last change on this file since bf2a53d2 was bf2a53d2, checked in by Sebastian Huber <sebastian.huber@…>, on 10/14/17 at 13:14:53

score: Rename watchdog variants

Rename PER_CPU_WATCHDOG_RELATIVE in PER_CPU_WATCHDOG_MONOTONIC to
highlight the corresponding POSIX CLOCK_MONOTONIC.

Rename PER_CPU_WATCHDOG_ABSOLUTE in PER_CPU_WATCHDOG_REALTIME to
highlight the corresponding POSIX CLOCK_REALTIME.

Update #3117.
Update #3182.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/**
2 * @file
3 *
4 * @brief Private Support Information for POSIX Threads
5 * @ingroup POSIX_PTHREADS Private Threads
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2014.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20#include <stdio.h>
21
22#include <errno.h>
23#include <pthread.h>
24#include <limits.h>
25#include <assert.h>
26
27#include <rtems/system.h>
28#include <rtems/config.h>
29#include <rtems/sysinit.h>
30#include <rtems/score/stack.h>
31#include <rtems/score/threadimpl.h>
32#include <rtems/score/threadqimpl.h>
33#include <rtems/score/userextimpl.h>
34#include <rtems/score/wkspace.h>
35#include <rtems/posix/pthreadimpl.h>
36#include <rtems/posix/priorityimpl.h>
37#include <rtems/posix/psignalimpl.h>
38#include <rtems/posix/config.h>
39#include <rtems/posix/keyimpl.h>
40#include <rtems/score/assert.h>
41#include <rtems/score/schedulerimpl.h>
42
43Thread_Information _POSIX_Threads_Information;
44
45void _POSIX_Threads_Sporadic_timer( Watchdog_Control *watchdog )
46{
47  POSIX_API_Control    *api;
48  Thread_Control       *the_thread;
49  Thread_queue_Context  queue_context;
50
51  api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic.Timer );
52  the_thread = api->thread;
53
54  _Thread_queue_Context_initialize( &queue_context );
55  _Thread_queue_Context_clear_priority_updates( &queue_context );
56  _Thread_Wait_acquire( the_thread, &queue_context );
57
58  if ( _Priority_Node_is_active( &api->Sporadic.Low_priority ) ) {
59    _Thread_Priority_add(
60      the_thread,
61      &the_thread->Real_priority,
62      &queue_context
63    );
64    _Thread_Priority_remove(
65      the_thread,
66      &api->Sporadic.Low_priority,
67      &queue_context
68    );
69    _Priority_Node_set_inactive( &api->Sporadic.Low_priority );
70  }
71
72  _Watchdog_Per_CPU_remove_monotonic( &api->Sporadic.Timer );
73  _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
74
75  _Thread_Wait_release( the_thread, &queue_context );
76  _Thread_Priority_update( &queue_context );
77}
78
79void _POSIX_Threads_Sporadic_budget_callout( Thread_Control *the_thread )
80{
81  POSIX_API_Control    *api;
82  Thread_queue_Context  queue_context;
83
84  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
85
86  _Thread_queue_Context_initialize( &queue_context );
87  _Thread_queue_Context_clear_priority_updates( &queue_context );
88  _Thread_Wait_acquire( the_thread, &queue_context );
89
90  /*
91   *  This will prevent the thread from consuming its entire "budget"
92   *  while at low priority.
93   */
94  the_thread->cpu_time_budget = UINT32_MAX;
95
96  if ( !_Priority_Node_is_active( &api->Sporadic.Low_priority ) ) {
97    _Thread_Priority_add(
98      the_thread,
99      &api->Sporadic.Low_priority,
100      &queue_context
101    );
102    _Thread_Priority_remove(
103      the_thread,
104      &the_thread->Real_priority,
105      &queue_context
106    );
107  }
108
109  _Thread_Wait_release( the_thread, &queue_context );
110  _Thread_Priority_update( &queue_context );
111}
112
113/*
114 *  _POSIX_Threads_Create_extension
115 *
116 *  This method is invoked for each thread created.
117 */
118
119static bool _POSIX_Threads_Create_extension(
120  Thread_Control *executing RTEMS_UNUSED,
121  Thread_Control *created
122)
123{
124  POSIX_API_Control *api;
125  POSIX_API_Control *executing_api;
126
127  api = created->API_Extensions[ THREAD_API_POSIX ];
128
129  /* XXX check all fields are touched */
130  api->thread = created;
131  api->schedparam.sched_priority = _POSIX_Priority_From_core(
132    _Thread_Scheduler_get_home( created ),
133    _Thread_Get_priority( created )
134  );
135
136  /*
137   *  If the thread is not a posix thread, then all posix signals are blocked
138   *  by default.
139   *
140   *  The check for class == 1 is debug.  Should never really happen.
141   */
142  RTEMS_STATIC_ASSERT( SIGNAL_EMPTY_MASK == 0, signals_pending );
143  if ( _Objects_Get_API( created->Object.id ) == OBJECTS_POSIX_API
144       #if defined(RTEMS_DEBUG)
145         && _Objects_Get_class( created->Object.id ) == 1
146       #endif
147  ) {
148    executing_api = _Thread_Get_executing()->API_Extensions[ THREAD_API_POSIX ];
149    api->signals_unblocked = executing_api->signals_unblocked;
150  }
151
152  _Watchdog_Preinitialize( &api->Sporadic.Timer, _Per_CPU_Get_by_index( 0 ) );
153  _Watchdog_Initialize( &api->Sporadic.Timer, _POSIX_Threads_Sporadic_timer );
154
155  return true;
156}
157
158static void _POSIX_Threads_Terminate_extension( Thread_Control *executing )
159{
160  POSIX_API_Control *api;
161  ISR_lock_Context   lock_context;
162
163  api = executing->API_Extensions[ THREAD_API_POSIX ];
164
165  _Thread_State_acquire( executing, &lock_context );
166
167  if ( api->schedpolicy == SCHED_SPORADIC ) {
168    _Watchdog_Per_CPU_remove_monotonic( &api->Sporadic.Timer );
169  }
170
171  _Thread_State_release( executing, &lock_context );
172}
173
174/*
175 *  _POSIX_Threads_Exitted_extension
176 *
177 *  This method is invoked each time a thread exits.
178 */
179static void _POSIX_Threads_Exitted_extension(
180  Thread_Control *executing
181)
182{
183  /*
184   *  If the executing thread was not created with the POSIX API, then this
185   *  API do not get to define its exit behavior.
186   */
187  if ( _Objects_Get_API( executing->Object.id ) == OBJECTS_POSIX_API )
188    pthread_exit( executing->Wait.return_argument );
189}
190
191User_extensions_Control _POSIX_Threads_User_extensions = {
192  .Callouts = {
193    .thread_create    = _POSIX_Threads_Create_extension,
194    .thread_exitted   = _POSIX_Threads_Exitted_extension,
195    .thread_terminate = _POSIX_Threads_Terminate_extension
196  }
197};
198
199/*
200 *  _POSIX_Threads_Manager_initialization
201 *
202 *  This routine initializes all threads manager related data structures.
203 */
204static void _POSIX_Threads_Manager_initialization(void)
205{
206  _Thread_Initialize_information(
207    &_POSIX_Threads_Information, /* object information table */
208    OBJECTS_POSIX_API,           /* object API */
209    OBJECTS_POSIX_THREADS,       /* object class */
210    Configuration_POSIX_API.maximum_threads,
211                                 /* maximum objects of this class */
212    true,                        /* true if names for this object are strings */
213    _POSIX_PATH_MAX              /* maximum length of each object's name */
214  );
215
216  /*
217   *  Add all the extensions for this API
218   */
219  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
220
221  /*
222   *  If we supported MP, then here we would ...
223   *       Register the MP Process Packet routine.
224   */
225}
226
227RTEMS_SYSINIT_ITEM(
228  _POSIX_Threads_Manager_initialization,
229  RTEMS_SYSINIT_POSIX_THREADS,
230  RTEMS_SYSINIT_ORDER_MIDDLE
231);
Note: See TracBrowser for help on using the repository browser.