source: rtems/c/src/exec/posix/src/pthread.c @ dd32d883

4.104.114.84.95
Last change on this file since dd32d883 was dd32d883, checked in by Joel Sherrill <joel.sherrill@…>, on 05/29/96 at 22:46:05

posix initialization threads table was misnamed "posix initialization
tasks table"

  • Property mode set to 100644
File size: 16.0 KB
RevLine 
[8165b48f]1/*
[eb5a7e07]2 *  $Id$
[5e9b32b]3 */
4
[613cff6]5#include <assert.h>
[5e9b32b]6#include <errno.h>
7#include <pthread.h>
8#include <limits.h>
9
[f4719d5a]10#include <rtems/system.h>
[5a18e04]11#include <rtems/score/apiext.h>
[5e9b32b]12#include <rtems/score/stack.h>
13#include <rtems/score/thread.h>
[5a18e04]14#include <rtems/score/userext.h>
15#include <rtems/score/wkspace.h>
[5e9b32b]16#include <rtems/posix/pthread.h>
[ece8c9a]17#include <rtems/posix/priority.h>
[5a18e04]18#include <rtems/posix/config.h>
[5e9b32b]19
20/*PAGE
21 *
22 *  The default pthreads attributes structure.
23 */
24 
25const pthread_attr_t _POSIX_Threads_Default_attributes = {
26  TRUE,                    /* is_initialized */
27  0,                       /* stackaddr */
28  STACK_MINIMUM_SIZE,      /* stacksize */
29  PTHREAD_SCOPE_PROCESS,   /* contentionscope */
30  PTHREAD_INHERIT_SCHED,   /* inheritsched */
31  SCHED_FIFO,              /* schedpolicy */
32  {                        /* schedparam */
33    128,                   /* sched_priority */
34    0,                     /* ss_low_priority */
35    { 0L, 0 },             /* ss_replenish_period */
36    { 0L, 0 }              /* ss_initial_budget */
37  },
38  PTHREAD_CREATE_DETACHED, /* detachstate */
39  1                        /* cputime_clock_allowed */
40};
41
[5a18e04]42/*PAGE
43 *
44 *  _POSIX_Threads_Create_extension
45 *
46 *  XXX
47 */
48 
49boolean _POSIX_Threads_Create_extension(
50  Thread_Control *executing,
51  Thread_Control *created
52)
53{
54  POSIX_API_Control *api;
55 
56  api = _Workspace_Allocate( sizeof( POSIX_API_Control ) );
57 
58  if ( !api )
59    return FALSE;
60 
61  created->API_Extensions[ THREAD_API_POSIX ] = api;
62 
63  /* XXX something should go here */
64
65  return TRUE;
66}
67 
68/*PAGE
69 *
70 *  _POSIX_Threads_Delete_extension
71 *
72 *  XXX
73 */
74 
75User_extensions_routine _POSIX_Threads_Delete_extension(
76  Thread_Control *executing,
77  Thread_Control *deleted
78)
79{
80  (void) _Workspace_Free( deleted->API_Extensions[ THREAD_API_POSIX ] );
81 
82  deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
83}
84
85/*PAGE
86 *
[dd32d883]87 *  _POSIX_Threads_Initialize_user_threads
[5a18e04]88 *
89 *  This routine creates and starts all configured user
90 *  initialzation threads.
91 *
92 *  Input parameters: NONE
93 *
94 *  Output parameters:  NONE
95 */
96 
[dd32d883]97void _POSIX_Threads_Initialize_user_threads( void )
[5a18e04]98{
[dd32d883]99  int                                 status;
100  unsigned32                          index;
101  unsigned32                          maximum;
102  posix_initialization_threads_table *user_threads;
103  pthread_t                           thread_id;
104 
105  user_threads = _POSIX_Threads_User_initialization_threads;
106  maximum      = _POSIX_Threads_Number_of_initialization_threads;
[613cff6]107
[dd32d883]108  if ( !user_threads || maximum == 0 )
[613cff6]109    return;
[5a18e04]110 
111  for ( index=0 ; index < maximum ; index++ ) {
[dd32d883]112    status = pthread_create(
113      &thread_id,
114      NULL,
115      user_threads[ index ].entry,
116      NULL
117    );
[613cff6]118    assert( !status );
[5a18e04]119  }
120}
121
122API_extensions_Control _POSIX_Threads_API_extensions = {
123  { NULL, NULL },
124  NULL,                                     /* predriver */
[dd32d883]125  _POSIX_Threads_Initialize_user_threads,   /* postdriver */
[5a18e04]126  NULL,                                     /* post switch */
127};
128 
129User_extensions_Control _POSIX_Threads_User_extensions = {
130  { NULL, NULL },
131  { _POSIX_Threads_Create_extension,          /* create */
132    NULL,                                     /* start */
133    NULL,                                     /* restart */
134    _POSIX_Threads_Delete_extension,          /* delete */
135    NULL,                                     /* switch */
136    NULL,                                     /* begin */
137    NULL,                                     /* exitted */
138    NULL                                      /* fatal */
139  }
140};
141 
[5e9b32b]142/*PAGE
143 *
144 *  _POSIX_Threads_Manager_initialization
145 *
146 *  This routine initializes all threads manager related data structures.
147 *
148 *  Input parameters:
149 *    maximum_pthreads - maximum configured pthreads
150 *
151 *  Output parameters:  NONE
152 */
153 
154void _POSIX_Threads_Manager_initialization(
[dd32d883]155  unsigned32                          maximum_pthreads,
156  unsigned32                          number_of_initialization_threads,
157  posix_initialization_threads_table *user_threads
[5a18e04]158 
[5e9b32b]159)
160{
[dd32d883]161  _POSIX_Threads_Number_of_initialization_threads =
162                                           number_of_initialization_threads;
163  _POSIX_Threads_User_initialization_threads = user_threads;
[5a18e04]164
[974ff40]165  /*
166   *  There may not be any POSIX initialization threads configured.
167   */
168
169#if 0
[dd32d883]170  if ( user_threads == NULL || number_of_initialization_threads == 0 )
[5a18e04]171    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
[974ff40]172#endif
[5a18e04]173
[5e9b32b]174  _Objects_Initialize_information(
175    &_POSIX_Threads_Information,
176    OBJECTS_POSIX_THREADS,
[ece8c9a]177    FALSE,                               /* does not support global */
[5e9b32b]178    maximum_pthreads,
179    sizeof( POSIX_Threads_Control ),
180    TRUE,
[ece8c9a]181    5,                                   /* length is arbitrary for now */
182    TRUE                                 /* this class is threads */
[5e9b32b]183  );
[5a18e04]184
[613cff6]185  /*
186   *  Add all the extensions for this API
187   */
188 
189  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
190 
191  _API_extensions_Add( &_POSIX_Threads_API_extensions );
192 
193  /*
194   *  If we supported MP, then here we would ...
195   *       Register the MP Process Packet routine.
196   */
197 
[5e9b32b]198}
199
200/*PAGE
201 *
202 *  3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
[568ebf3]203 *
204 *  RTEMS does not support processes, so we fall under this and do not
205 *  provide this routine:
206 *
207 *  "Either the implementation shall support the pthread_atfork() function
208 *   as described above or the pthread_atfork() funciton shall not be
209 *   provided."
[5e9b32b]210 */
211
212/*PAGE
213 *
214 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
215 */
216
217int pthread_attr_setscope(
218  pthread_attr_t  *attr,
219  int              contentionscope
220)
221{
222  if ( !attr || !attr->is_initialized )
223    return EINVAL;
224
225  attr->contentionscope = contentionscope;
226  return 0;
227}
228
229/*PAGE
230 *
231 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
232 */
233
234int pthread_attr_getscope(
235  const pthread_attr_t  *attr,
236  int                   *contentionscope
237)
238{
239  if ( !attr || !attr->is_initialized )
240    return EINVAL;
241
242  *contentionscope = attr->contentionscope;
243  return 0;
244}
245
246/*PAGE
247 *
248 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
249 */
250
251int pthread_attr_setinheritsched(
252  pthread_attr_t  *attr,
253  int              inheritsched
254)
255{
256  if ( !attr || !attr->is_initialized )
257    return EINVAL;
258
259  attr->inheritsched = inheritsched;
260  return 0;
261}
262
263/*PAGE
264 *
265 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
266 */
267
268int pthread_attr_getinheritsched(
269  const pthread_attr_t  *attr,
270  int                   *inheritsched
271)
272{
273  if ( !attr || !attr->is_initialized )
274    return EINVAL;
275
276  *inheritsched = attr->inheritsched;
277  return 0;
278}
279
280/*PAGE
281 *
282 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
283 */
284
285int pthread_attr_setschedpolicy(
286  pthread_attr_t  *attr,
287  int              policy
288)
289{
290  if ( !attr || !attr->is_initialized )
291    return EINVAL;
292
293  attr->schedpolicy = policy;
294  return 0;
295}
296
297/*PAGE
298 *
299 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
300 */
301
302int pthread_attr_getschedpolicy(
303  const pthread_attr_t  *attr,
304  int                   *policy
305)
306{
307  if ( !attr || !attr->is_initialized )
308    return EINVAL;
309
310  *policy = attr->schedpolicy;
311  return 0;
312}
313
314/*PAGE
315 *
316 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
317 */
318
319int pthread_attr_setschedparam(
320  pthread_attr_t            *attr,
[f4719d5a]321  const struct sched_param  *param
[5e9b32b]322)
323{
324  if ( !attr || !attr->is_initialized )
325    return EINVAL;
326
[f4719d5a]327  attr->schedparam = *param;
[5e9b32b]328  return 0;
329}
330
331/*PAGE
332 *
333 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
334 */
335
336int pthread_attr_getschedparam(
337  const pthread_attr_t   *attr,
338  struct sched_param     *param
339)
340{
341  if ( !attr || !attr->is_initialized )
342    return EINVAL;
343
344  *param = attr->schedparam;
345  return 0;
346}
347
348/*PAGE
349 *
350 *  13.5.2 Dynamic Thread Scheduling Parameters Access,
351 *         P1003.1c/Draft 10, p. 124
352 */
353
354int pthread_getschedparam(
355  pthread_t           thread,
356  int                *policy,
357  struct sched_param *param
358)
359{
360  pthread_attr_t *attr;   /* XXX: really need to get this from the thread */
361
362  if ( !policy || !param  )
363    return EINVAL;
364
365  *policy = attr->schedpolicy;
366  *param  = attr->schedparam;
367  return 0;
368}
369
370/*PAGE
371 *
372 *  13.5.2 Dynamic Thread Scheduling Parameters Access,
373 *         P1003.1c/Draft 10, p. 124
374 */
375
376int pthread_setschedparam(
377  pthread_t           thread,
378  int                 policy,
379  struct sched_param *param
380)
381{
382  /* XXX need to reschedule after doing this to the thread */
383  pthread_attr_t *attr;   /* XXX: really need to get this from the thread */
384
385  if ( !param )
386    return EINVAL;
387
388  attr->schedpolicy = policy;
389  attr->schedparam  = *param;
390  return 0;
391}
392
393/*PAGE
394 *
395 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
396 */
397
398int pthread_attr_init(
399  pthread_attr_t  *attr
400)
401{
402  if ( !attr )
403    return EINVAL;
404 
405  *attr = _POSIX_Threads_Default_attributes;
406  return 0;
407}
408
409/*PAGE
410 *
411 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
412 */
413
414int pthread_attr_destroy(
415  pthread_attr_t  *attr
416)
417{
418  if ( !attr || !attr->is_initialized )
419    return EINVAL;
420 
421  attr->is_initialized = FALSE;
422  return 0;
423}
424 
425/*PAGE
426 *
427 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
428 */
429
430int pthread_attr_getstacksize(
431  const pthread_attr_t  *attr,
432  size_t                *stacksize
433)
434{
435  if ( !attr || !attr->is_initialized )
436    return EINVAL;
437
438  *stacksize = attr->stacksize;
439  return 0;
440}
441 
442/*PAGE
443 *
444 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
445 */
446
447int pthread_attr_setstacksize(
448  pthread_attr_t  *attr,
449  size_t           stacksize
450)
451{
452  if ( !attr || !attr->is_initialized )
453    return EINVAL;
454
[9c877c0d]455  if ( stacksize < STACK_MINIMUM_SIZE )
456    attr->stacksize = STACK_MINIMUM_SIZE;
457  else
458    attr->stacksize = stacksize;
[5e9b32b]459  return 0;
460}
461 
462/*PAGE
463 *
464 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
465 */
466
467int pthread_attr_getstackaddr(
468  const pthread_attr_t   *attr,
469  void                  **stackaddr
470)
471{
472  if ( !attr || !attr->is_initialized )
473    return EINVAL;
474
475  *stackaddr = attr->stackaddr;
476  return 0;
477}
478 
479/*PAGE
480 *
481 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
482 */
483
484int pthread_attr_setstackaddr(
485  pthread_attr_t  *attr,
486  void            *stackaddr
487)
488{
489  if ( !attr || !attr->is_initialized )
490    return EINVAL;
491
492  attr->stackaddr = stackaddr;
493  return 0;
494}
495 
496/*PAGE
497 *
498 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
499 */
500
501int pthread_attr_getdetachstate(
502  const pthread_attr_t  *attr,
503  int                   *detachstate
504)
505{
506  if ( !attr || !attr->is_initialized )
507    return EINVAL;
508
509  *detachstate = attr->detachstate;
510  return 0;
511}
512 
513/*PAGE
514 *
515 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
516 */
517
518int pthread_attr_setdetachstate(
519  pthread_attr_t  *attr,
520  int              detachstate
521)
522{
523  if ( !attr || !attr->is_initialized )
524    return EINVAL;
525
526  attr->detachstate = detachstate;
527  return 0;
528}
529
530/*PAGE
531 *
532 *  16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
533 */
534
535int pthread_create(
[974ff40]536  pthread_t              *thread,
537  const pthread_attr_t   *attr,
538  void                 *(*start_routine)( void * ),
539  void                   *arg
[5e9b32b]540)
541{
[cfcfdf0]542  const pthread_attr_t  *attrp;
[ece8c9a]543  Priority_Control       core_priority;
544  boolean                is_fp;
545  boolean                status;
546  Thread_Control        *the_thread;
547  char                  *default_name = "psx";
[5a18e04]548
[cfcfdf0]549  attrp = (attr) ? attr : &_POSIX_Threads_Default_attributes;
[5a18e04]550
[cfcfdf0]551  if ( !attrp->is_initialized )
[5a18e04]552    return EINVAL;
553
554  /*
555   *  Core Thread Initialize insures we get the minimum amount of
556   *  stack space.
557   */
558
559#if 0
560  int contentionscope;
561  int inheritsched;
562  int schedpolicy;
563  struct sched_param schedparam;
564
565#if defined(_POSIX_THREAD_CPUTIME)
566  int  cputime_clock_allowed;  /* see time.h */
567#endif
568  int  detachstate;
569#endif
[974ff40]570
[ece8c9a]571  /*
572   *  Validate the RTEMS API priority and convert it to the core priority range.
573   */
574 
[cfcfdf0]575  if ( !_POSIX_Priority_Is_valid( attrp->schedparam.sched_priority ) )
[ece8c9a]576    return EINVAL;
577 
[cfcfdf0]578  core_priority = _POSIX_Priority_To_core( attrp->schedparam.sched_priority );
[ece8c9a]579 
580  /*
[7f72217e]581   *  Currently all POSIX threads are floating point if the hardware
582   *  supports it.
[ece8c9a]583   */
584
[7f72217e]585  is_fp = CPU_HARDWARE_FP;
[ece8c9a]586
587  /*
588   *  Disable dispatch for protection
589   */
590 
591  _Thread_Disable_dispatch();
592 
593  /*
594   *  Allocate the thread control block.
595   *
596   *  NOTE:  Global threads are not currently supported.
597   */
598
599  the_thread = _POSIX_Threads_Allocate();
600
601  if ( !the_thread ) {
602    _Thread_Enable_dispatch();
603    return EINVAL;
604  }
605
606  /*
607   *  Initialize the core thread for this task.
608   */
609 
610  status = _Thread_Initialize(
611    &_POSIX_Threads_Information,
612    the_thread,
[cfcfdf0]613    attrp->stackaddr,
614    attrp->stacksize,
[ece8c9a]615    is_fp,
616    core_priority,
617    TRUE,                 /* preemptible */
618    TRUE,                 /* timesliced */
619    0,                    /* isr level */
620    &default_name         /* posix threads don't have a name */
621  );
622 
623  if ( !status ) {
624    _POSIX_Threads_Free( the_thread );
625    _Thread_Enable_dispatch();
626    return EINVAL;
627  }
628
[cfcfdf0]629  status = _Thread_Start(
630    the_thread,
631    THREAD_START_POINTER,
632    start_routine,
633    arg,
634    0                     /* unused */
635  );
636
637  /*
638   *  _Thread_Start only fails if the thread was in the incorrect state
639   */
640
641  if ( !status ) {
642    _POSIX_Threads_Free( the_thread );
643    _Thread_Enable_dispatch();
644    return EINVAL;
645  }
646
647
648  /*
649   *  Return the id and indicate we successfully created the thread
650   */
651
[ece8c9a]652  *thread = the_thread->Object.id;
653
654 _Thread_Enable_dispatch();
655
656 return 0;
657
[5e9b32b]658}
659
660/*PAGE
661 *
662 *  16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147
663 */
664
665int pthread_join(
666  pthread_t   thread,
667  void      **value_ptr
668)
669{
670  return POSIX_NOT_IMPLEMENTED();
671}
672
673/*PAGE
674 *
675 *  16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149
676 */
677
678int pthread_detach(
679  pthread_t   thread
680)
681{
682  return POSIX_NOT_IMPLEMENTED();
683}
684
[974ff40]685/*PAGE
686 *
687 * 16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150
688 */
689 
690void pthread_exit(
691  void  *value_ptr
692)
693{
[cfcfdf0]694  register Thread_Control *the_thread;
695
696  the_thread = _Thread_Executing;
697
698  _Thread_Disable_dispatch();
699
700  /*
701   *  XXX Will need to deal with join/detach
702   */
703
704  _Thread_Close( &_POSIX_Threads_Information, the_thread );
705 
706  _POSIX_Threads_Free( the_thread );
707
708  _Thread_Enable_dispatch();
[974ff40]709}
[5e9b32b]710
711/*PAGE
712 *
713 * 16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. XXX
714 */
715
716pthread_t pthread_self( void )
717{
718  return _Thread_Executing->Object.id;
719}
720
721/*PAGE
722 *
723 *  16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153
724 */
725
726int pthread_equal(
727  pthread_t  t1,
728  pthread_t  t2
729)
730{
731#ifdef RTEMS_DEBUG
732 /* XXX may want to do a "get" to make sure both are valid. */
733 /* XXX behavior is undefined if not valid pthread_t's */
734#endif
735  return _Objects_Are_ids_equal( t1, t1 );
736}
737
738/*PAGE
739 *
740 *  16.1.8 Dynamic Package Initialization
741 */
742
743int pthread_once(
744  pthread_once_t  *once_control,
745  void           (*init_routine)(void)
746)
747{
748  /* XXX: Should we implement this routine this way or make it a full */
749  /* XXX: fledged object? */
750
751  if ( !once_control || !init_routine )
752    return EINVAL;
753
754  _Thread_Disable_dispatch();
755
756  if ( !once_control->is_initialized ) {
757
758    once_control->is_initialized = TRUE;
759    once_control->init_executed = TRUE;
760    (*init_routine)();
761
762  } if ( !once_control->init_executed ) {
763
764    once_control->init_executed = TRUE;
765    (*init_routine)();
766
767  }
768 
769  _Thread_Enable_dispatch();
770
771  return 0;
772}
773
774/*PAGE
775 *
776 *  20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/D8, p. 58
777 */
778 
779int pthread_getcpuclockid(
780  pthread_t    pid,
781  clockid_t   *clock_id
782)
783{
784  return POSIX_NOT_IMPLEMENTED();
785}
786
787/*PAGE
788 *
789 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
790 */
791
792int pthread_attr_setcputime(
793  pthread_attr_t  *attr,
794  int              clock_allowed
795)
796{
797  if ( !attr || !attr->is_initialized )
798    return EINVAL;
799
800  attr->cputime_clock_allowed = clock_allowed;
801  return 0;
802}
803
804/*PAGE
805 *
806 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
807 */
808
809int pthread_attr_getcputime(
810  pthread_attr_t  *attr,
811  int             *clock_allowed
812)
813{
814  if ( !attr || !attr->is_initialized )
815    return EINVAL;
816
817  *clock_allowed = attr->cputime_clock_allowed;
818  return 0;
819}
Note: See TracBrowser for help on using the repository browser.