source: rtems/cpukit/posix/src/pthreadcreate.c @ 335e5ca

4.115
Last change on this file since 335e5ca was 335e5ca, checked in by Sebastian Huber <sebastian.huber@…>, on 06/02/15 at 19:43:54

score: Add Thread_Control::is_fp

Store the floating-point unit property in the thread control block
regardless of the CPU_HARDWARE_FP and CPU_SOFTWARE_FP settings. Make
sure the floating-point unit is only enabled for the corresponding
multilibs. This helps targets which have a volatile only floating point
context like SPARC for example.

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