source: rtems/cpukit/posix/src/pthreadcreate.c @ 5d65d0dd

5
Last change on this file since 5d65d0dd was 5d65d0dd, checked in by Sebastian Huber <sebastian.huber@…>, on 06/15/16 at 06:50:29

posix: Use _POSIX_Threads_Sporadic_timer_insert()

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