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
RevLine 
[65f6d3c]1/**
2 * @file
3 *
4 * @brief Function Starts a New Thread in The Calling Process
[5cb175bb]5 * @ingroup POSIXAPI
[65f6d3c]6 */
7
[03598b1]8/*
9 *  16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
[412dbff6]10 */
11
[68c156a]12/*
13 *  COPYRIGHT (c) 1989-2014.
[03598b1]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
[c499856]18 *  http://www.rtems.org/license/LICENSE.
[03598b1]19 */
20
[f42b726]21#if HAVE_CONFIG_H
22#include "config.h"
23#endif
24
[03598b1]25#include <pthread.h>
26#include <errno.h>
27
[97552c98]28#include <rtems/posix/priorityimpl.h>
[5618c37a]29#include <rtems/posix/pthreadimpl.h>
[185e46f]30#include <rtems/score/cpusetimpl.h>
[5618c37a]31#include <rtems/score/threadimpl.h>
[5088d97]32#include <rtems/score/apimutex.h>
[218286bc]33#include <rtems/score/stackimpl.h>
[e045fb6c]34#include <rtems/score/schedulerimpl.h>
35
[ecf0f4c]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
[03598b1]46int pthread_create(
47  pthread_t              *thread,
48  const pthread_attr_t   *attr,
49  void                 *(*start_routine)( void * ),
50  void                   *arg
51)
52{
[ccd5434]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  };
[03598b1]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;
[f8437c8]66  bool                                is_fp;
67  bool                                status;
[03598b1]68  Thread_Control                     *the_thread;
[c5831a3f]69  Thread_Control                     *executing;
[03598b1]70  POSIX_API_Control                  *api;
71  int                                 schedpolicy = SCHED_RR;
72  struct sched_param                  schedparam;
[ce19f1fa]73  Objects_Name                        name;
[2212a2ad]74  int                                 rc;
[e135271]75  ISR_lock_Context                    lock_context;
[03598b1]76
[e889a857]77  if ( !start_routine )
78    return EFAULT;
79
[03598b1]80  the_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes;
81
82  if ( !the_attr->is_initialized )
83    return EINVAL;
84
85  /*
[ecf0f4c]86   *  Core Thread Initialize ensures we get the minimum amount of
[03598b1]87   *  stack space if it is allowed to allocate it itself.
[ecf0f4c]88   *
89   *  NOTE: If the user provides the stack we will let it drop below
90   *        twice the minimum.
[03598b1]91   */
[ecf0f4c]92  if ( the_attr->stackaddr && !_Stack_Is_enough(the_attr->stacksize) )
[03598b1]93    return EINVAL;
94
[2212a2ad]95  #if 0
96    int  cputime_clock_allowed;  /* see time.h */
97    rtems_set_errno_and_return_minus_one( ENOSYS );
98  #endif
[03598b1]99
[c5831a3f]100  executing = _Thread_Get_executing();
101
[03598b1]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
[874297f3]107   *  PTHREAD_EXPLICIT_SCHED, then scheduling parameters come from the
[03598b1]108   *  attributes structure.
109   */
110  switch ( the_attr->inheritsched ) {
111    case PTHREAD_INHERIT_SCHED:
[c5831a3f]112      api = executing->API_Extensions[ THREAD_API_POSIX ];
[03598b1]113      schedpolicy = api->schedpolicy;
114      schedparam  = api->schedparam;
[874297f3]115      break;
[03598b1]116
117    case PTHREAD_EXPLICIT_SCHED:
118      schedpolicy = the_attr->schedpolicy;
119      schedparam  = the_attr->schedparam;
[874297f3]120      break;
[03598b1]121
122    default:
123      return EINVAL;
124  }
125
126  /*
[874297f3]127   *  Check the contentionscope since rtems only supports PROCESS wide
[03598b1]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;
[874297f3]138
[03598b1]139  core_priority = _POSIX_Priority_To_core( schedparam.sched_priority );
[874297f3]140
[03598b1]141  /*
142   *  Set the core scheduling policy information.
143   */
[2212a2ad]144  rc = _POSIX_Thread_Translate_sched_param(
145    schedpolicy,
146    &schedparam,
147    &budget_algorithm,
148    &budget_callout
149  );
150  if ( rc )
151    return rc;
[03598b1]152
[185e46f]153#if defined(RTEMS_SMP)
154#if __RTEMS_HAVE_SYS_CPUSET_H__
[e045fb6c]155  status = _CPU_set_Is_valid( the_attr->affinityset, the_attr->affinitysetsize );
[68c156a]156  if ( !status )
[185e46f]157    return EINVAL;
158#endif
159#endif
160
[03598b1]161  /*
[874297f3]162   *  Currently all POSIX threads are floating point if the hardware
[03598b1]163   *  supports it.
164   */
[335e5ca]165  is_fp = true;
[03598b1]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 ) {
[23fec9f0]174    _Objects_Allocator_unlock();
[03598b1]175    return EAGAIN;
176  }
177
178  /*
179   *  Initialize the core thread for this task.
180   */
[ce19f1fa]181  name.name_p = NULL;   /* posix threads don't have a name by default */
[03598b1]182  status = _Thread_Initialize(
183    &_POSIX_Threads_Information,
184    the_thread,
[c5831a3f]185    _Scheduler_Get( executing ),
[03598b1]186    the_attr->stackaddr,
[ecf0f4c]187    _POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize),
[03598b1]188    is_fp,
189    core_priority,
[b1dbfd7]190    true,                 /* preemptible */
[03598b1]191    budget_algorithm,
192    budget_callout,
193    0,                    /* isr level */
[ce19f1fa]194    name                  /* posix threads don't have a name */
[03598b1]195  );
196  if ( !status ) {
197    _POSIX_Threads_Free( the_thread );
[23fec9f0]198    _Objects_Allocator_unlock();
[03598b1]199    return EAGAIN;
200  }
201
[54550e04]202  if ( the_attr->detachstate == PTHREAD_CREATE_DETACHED ) {
203    the_thread->Life.state |= THREAD_LIFE_DETACHED;
204  }
205
[da826560]206  the_thread->Life.state |= THREAD_LIFE_CHANGE_DEFERRED;
207
[68c156a]208#if defined(RTEMS_SMP) && __RTEMS_HAVE_SYS_CPUSET_H__
[e135271]209  _ISR_lock_ISR_disable( &lock_context );
[68c156a]210   status = _Scheduler_Set_affinity(
211     the_thread,
212     the_attr->affinitysetsize,
213     the_attr->affinityset
[e045fb6c]214   );
[e135271]215  _ISR_lock_ISR_enable( &lock_context );
[68c156a]216   if ( !status ) {
217     _POSIX_Threads_Free( the_thread );
218     _RTEMS_Unlock_allocator();
219     return EINVAL;
220   }
[185e46f]221#endif
222
[03598b1]223  /*
224   *  finish initializing the per API structure
225   */
226  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
227
[185e46f]228  _POSIX_Threads_Copy_attributes( &api->Attributes, the_attr );
[03598b1]229  api->schedpolicy = schedpolicy;
230  api->schedparam  = schedparam;
231
232  /*
233   *  POSIX threads are allocated and started in one operation.
234   */
[33829ce]235  _ISR_lock_ISR_disable( &lock_context );
236  status = _Thread_Start( the_thread, &entry, &lock_context );
[03598b1]237
[2212a2ad]238  #if defined(RTEMS_DEBUG)
239    /*
240     *  _Thread_Start only fails if the thread was in the incorrect state
[1de949a8]241     *
[2212a2ad]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 );
[23fec9f0]247      _Objects_Allocator_unlock();
[2212a2ad]248      return EINVAL;
249    }
250  #endif
251
[03598b1]252  if ( schedpolicy == SCHED_SPORADIC ) {
[e135271]253    _ISR_lock_ISR_disable( &lock_context );
[5d65d0dd]254    _POSIX_Threads_Sporadic_timer_insert( api );
[e135271]255    _ISR_lock_ISR_enable( &lock_context );
[03598b1]256  }
257
258  /*
259   *  Return the id and indicate we successfully created the thread
260   */
261  *thread = the_thread->Object.id;
262
[23fec9f0]263  _Objects_Allocator_unlock();
[5088d97]264  return 0;
[03598b1]265}
Note: See TracBrowser for help on using the repository browser.