source: rtems/cpukit/posix/src/pthreadcreate.c @ be1b8a7

4.115
Last change on this file since be1b8a7 was 4b48ece0, checked in by Sebastian Huber <sebastian.huber@…>, on 07/22/13 at 08:21:03

score: Create watchdog implementation header

Move implementation specific parts of watchdog.h and watchdog.inl into
new header file watchdogimpl.h. The watchdog.h contains now only the
application visible API.

  • Property mode set to 100644
File size: 5.9 KB
Line 
1/**
2 * @file
3 *
4 * @brief Function Starts a New Thread in The Calling Process
5 * @ingroup POSIXAPI
6 */
7
8/*
9 *  16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
10 */
11
12/*  COPYRIGHT (c) 1989-2008.
13 *  On-Line Applications Research Corporation (OAR).
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.com/license/LICENSE.
18 */
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <pthread.h>
25#include <errno.h>
26
27#include <rtems/system.h>
28#include <rtems/score/thread.h>
29#include <rtems/posix/pthreadimpl.h>
30#include <rtems/posix/priorityimpl.h>
31#include <rtems/posix/time.h>
32#include <rtems/score/apimutex.h>
33#include <rtems/score/watchdogimpl.h>
34
35static inline size_t _POSIX_Threads_Ensure_minimum_stack (
36  size_t size
37)
38{
39  if ( size >= PTHREAD_MINIMUM_STACK_SIZE )
40    return size;
41  return PTHREAD_MINIMUM_STACK_SIZE;
42}
43
44
45int pthread_create(
46  pthread_t              *thread,
47  const pthread_attr_t   *attr,
48  void                 *(*start_routine)( void * ),
49  void                   *arg
50)
51{
52  const pthread_attr_t               *the_attr;
53  Priority_Control                    core_priority;
54  Thread_CPU_budget_algorithms        budget_algorithm;
55  Thread_CPU_budget_algorithm_callout budget_callout;
56  bool                                is_fp;
57  bool                                status;
58  Thread_Control                     *the_thread;
59  POSIX_API_Control                  *api;
60  int                                 schedpolicy = SCHED_RR;
61  struct sched_param                  schedparam;
62  Objects_Name                        name;
63  int                                 rc;
64
65  if ( !start_routine )
66    return EFAULT;
67
68  the_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes;
69
70  if ( !the_attr->is_initialized )
71    return EINVAL;
72
73  /*
74   *  Core Thread Initialize ensures we get the minimum amount of
75   *  stack space if it is allowed to allocate it itself.
76   *
77   *  NOTE: If the user provides the stack we will let it drop below
78   *        twice the minimum.
79   */
80  if ( the_attr->stackaddr && !_Stack_Is_enough(the_attr->stacksize) )
81    return EINVAL;
82
83  #if 0
84    int  cputime_clock_allowed;  /* see time.h */
85    rtems_set_errno_and_return_minus_one( ENOSYS );
86  #endif
87
88  /*
89   *  P1003.1c/Draft 10, p. 121.
90   *
91   *  If inheritsched is set to PTHREAD_INHERIT_SCHED, then this thread
92   *  inherits scheduling attributes from the creating thread.   If it is
93   *  PTHREAD_EXPLICIT_SCHED, then scheduling parameters come from the
94   *  attributes structure.
95   */
96  switch ( the_attr->inheritsched ) {
97    case PTHREAD_INHERIT_SCHED:
98      api = _Thread_Get_executing()->API_Extensions[ THREAD_API_POSIX ];
99      schedpolicy = api->schedpolicy;
100      schedparam  = api->schedparam;
101      break;
102
103    case PTHREAD_EXPLICIT_SCHED:
104      schedpolicy = the_attr->schedpolicy;
105      schedparam  = the_attr->schedparam;
106      break;
107
108    default:
109      return EINVAL;
110  }
111
112  /*
113   *  Check the contentionscope since rtems only supports PROCESS wide
114   *  contention (i.e. no system wide contention).
115   */
116  if ( the_attr->contentionscope != PTHREAD_SCOPE_PROCESS )
117    return ENOTSUP;
118
119  /*
120   *  Interpret the scheduling parameters.
121   */
122  if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) )
123    return EINVAL;
124
125  core_priority = _POSIX_Priority_To_core( schedparam.sched_priority );
126
127  /*
128   *  Set the core scheduling policy information.
129   */
130  rc = _POSIX_Thread_Translate_sched_param(
131    schedpolicy,
132    &schedparam,
133    &budget_algorithm,
134    &budget_callout
135  );
136  if ( rc )
137    return rc;
138
139  /*
140   *  Currently all POSIX threads are floating point if the hardware
141   *  supports it.
142   */
143  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
144    is_fp = true;
145  #else
146    is_fp = false;
147  #endif
148
149  /*
150   *  Lock the allocator mutex for protection
151   */
152  _RTEMS_Lock_allocator();
153
154  /*
155   *  Allocate the thread control block.
156   *
157   *  NOTE:  Global threads are not currently supported.
158   */
159  the_thread = _POSIX_Threads_Allocate();
160  if ( !the_thread ) {
161    _RTEMS_Unlock_allocator();
162    return EAGAIN;
163  }
164
165  /*
166   *  Initialize the core thread for this task.
167   */
168  name.name_p = NULL;   /* posix threads don't have a name by default */
169  status = _Thread_Initialize(
170    &_POSIX_Threads_Information,
171    the_thread,
172    the_attr->stackaddr,
173    _POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize),
174    is_fp,
175    core_priority,
176    true,                 /* preemptible */
177    budget_algorithm,
178    budget_callout,
179    0,                    /* isr level */
180    name                  /* posix threads don't have a name */
181  );
182
183  if ( !status ) {
184    _POSIX_Threads_Free( the_thread );
185    _RTEMS_Unlock_allocator();
186    return EAGAIN;
187  }
188
189  /*
190   *  finish initializing the per API structure
191   */
192  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
193
194  api->Attributes  = *the_attr;
195  api->detachstate = the_attr->detachstate;
196  api->schedpolicy = schedpolicy;
197  api->schedparam  = schedparam;
198
199  /*
200   *  POSIX threads are allocated and started in one operation.
201   */
202  status = _Thread_Start(
203    the_thread,
204    THREAD_START_POINTER,
205    start_routine,
206    arg,
207    0,                    /* unused */
208    NULL
209  );
210
211  #if defined(RTEMS_DEBUG)
212    /*
213     *  _Thread_Start only fails if the thread was in the incorrect state
214     *
215     *  NOTE: This can only happen if someone slips in and touches the
216     *        thread while we are creating it.
217     */
218    if ( !status ) {
219      _POSIX_Threads_Free( the_thread );
220      _RTEMS_Unlock_allocator();
221      return EINVAL;
222    }
223  #endif
224
225  if ( schedpolicy == SCHED_SPORADIC ) {
226    _Watchdog_Insert_ticks(
227      &api->Sporadic_timer,
228      _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period )
229    );
230  }
231
232  /*
233   *  Return the id and indicate we successfully created the thread
234   */
235  *thread = the_thread->Object.id;
236
237  _RTEMS_Unlock_allocator();
238  return 0;
239}
Note: See TracBrowser for help on using the repository browser.