source: rtems/cpukit/posix/src/pthreadcreate.c @ 1de949a8

4.104.115
Last change on this file since 1de949a8 was 1de949a8, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/30/09 at 15:49:52

Whitespace removal.

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