1 /*
2  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 /** @file
8  * Defines the API in the
9  * <a href="group___pthread.html">Pthread library</a>
10  *
11  * @addtogroup Pthread
12  * @{
13  */
14 
15 #ifndef _PTHREAD_H
16 #define _PTHREAD_H 1
17 
18 #include <stdint.h>
19 #include <sched.h>
20 #include <time.h>
21 #include <sys/nacl_nice.h>
22 #include <sys/types.h>
23 
24 /*
25  * Signed 32-bit integer supporting CompareAndSwap and AtomicIncrement
26  * (see implementations), as well as atomic loads and stores.
27  * Instances must be naturally aligned.
28  */
29 typedef int AtomicInt32;
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 struct timespec;
36 struct __nc_basic_thread_data;
37 
38 /** Mutex type attributes */
39 enum {
40   /** Fast mutex type; for use with pthread_mutexattr_settype() */
41   PTHREAD_MUTEX_FAST_NP,
42   /** Recursive mutex type; for use with pthread_mutexattr_settype() */
43   PTHREAD_MUTEX_RECURSIVE_NP,
44   /** Error-checking mutex type; for use with pthread_mutexattr_settype() */
45   PTHREAD_MUTEX_ERRORCHECK_NP,
46   PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
47   PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
48   PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
49 
50   PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
51 };
52 
53 /*
54  * The layout of pthread_mutex_t and the static initializers are redefined
55  * in newlib's sys/lock.h file (including this file from sys/lock.h will
56  * cause include conflicts). When changing one of the definitions, make sure to
57  * change the second one.
58  */
59 /**
60  * A structure representing a thread mutex. It should be considered an
61  * opaque record; the names of the fields can change anytime.
62  */
63 typedef struct {
64   /*
65    * mutex_state is either UNLOCKED (0), LOCKED_WITHOUT_WAITERS (1) or
66    * LOCKED_WITH_WAITERS (2).  See "enum MutexState".
67    */
68   volatile int mutex_state;
69 
70   /**
71    * The kind of mutex:
72    * PTHREAD_MUTEX_FAST_NP, PTHREAD_MUTEX_RECURSIVE_NP,
73    * or PTHREAD_MUTEX_ERRORCHECK_NP
74    */
75   int mutex_type;
76 
77   /**
78    * ID of the thread that owns the mutex.  This is volatile because
79    * it is accessed concurrently, and "volatile" is a way to make
80    * loads and stores atomic in PNaCl.
81    */
82   struct __nc_basic_thread_data *volatile owner_thread_id;
83 
84   /** Recursion depth counter for recursive mutexes */
85   uint32_t recursion_counter;
86 
87   /*
88    * Padding is for compatibility with libraries (newlib etc.) that
89    * were built before libpthread switched to using futexes, and to
90    * match _LOCK_T in newlib's newlib/libc/include/sys/lock.h.
91    */
92   int unused_padding;
93 } pthread_mutex_t;
94 
95 /**
96  * A structure representing mutex attributes. It should be considered an
97  * opaque record and accessed only using pthread_mutexattr_settype().
98  */
99 typedef struct {
100   /**
101    * The kind of mutex:
102    * PTHREAD_MUTEX_FAST_NP, PTHREAD_MUTEX_RECURSIVE_NP,
103    * or PTHREAD_MUTEX_ERRORCHECK_NP
104    */
105   int kind;
106 } pthread_mutexattr_t;
107 
108 /**
109  * A structure representing a condition variable. It should be considered an
110  * opaque record; the names of the fields can change anytime.
111  */
112 typedef struct {
113   /* This is incremented on each pthread_cond_signal/broadcast() call. */
114   int sequence_number;
115 
116   /*
117    * Padding is for compatibility with libraries (newlib etc.) that
118    * were built before libpthread switched to using futexes.
119    */
120   int unused_padding;
121 } pthread_cond_t;
122 
123 /**
124  * A structure representing condition variable attributes. Currently
125  * Native Client condition variables have no attributes.
126  */
127 typedef struct {
128   int dummy; /**< Reserved; condition variables don't have attributes */
129 } pthread_condattr_t;
130 
131 /**
132  * A structure representing a rwlock. It should be considered an
133  * opaque record; the names of the fields can change anytime.
134  */
135 typedef struct {
136   pthread_mutex_t mutex;  /* mutex for all values in the structure */
137   int reader_count;
138   int writers_waiting;
139   struct __nc_basic_thread_data *writer_thread_id;
140   pthread_cond_t read_possible;
141   pthread_cond_t write_possible;
142 } pthread_rwlock_t;
143 
144 /**
145  * A structure representing rwlock attributes. It should be considered an
146  * opaque record.
147  */
148 typedef struct {
149   int dummy; /**< Reserved; rwlocks don't have attributes */
150 } pthread_rwlockattr_t;
151 
152 /** Illegal thread ID value. */
153 #define NACL_PTHREAD_ILLEGAL_THREAD_ID ((pthread_t) 0)
154 
155 /** Statically initializes a pthread_mutex_t representing a recursive mutex. */
156 #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
157     {0, PTHREAD_MUTEX_RECURSIVE, NACL_PTHREAD_ILLEGAL_THREAD_ID, 0, 0}
158 /** Statically initializes a pthread_mutex_t representing a fast mutex. */
159 #define PTHREAD_MUTEX_INITIALIZER \
160     {0, PTHREAD_MUTEX_NORMAL, NACL_PTHREAD_ILLEGAL_THREAD_ID, 0, 0}
161 /**
162  * Statically initializes a pthread_mutex_t representing an
163  * error-checking mutex.
164  */
165 #define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
166     {0, PTHREAD_MUTEX_ERRORCHECK, NACL_PTHREAD_ILLEGAL_THREAD_ID, 0, 0}
167 /** Statically initializes a condition variable (pthread_cond_t). */
168 #define PTHREAD_COND_INITIALIZER {0, 0}
169 /** Statically initializes a rwlock (pthread_rwlock_t). */
170 #define PTHREAD_RWLOCK_INITIALIZER \
171     {PTHREAD_MUTEX_INITIALIZER, 0, 0, NACL_PTHREAD_ILLEGAL_THREAD_ID, \
172      PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER}
173 
174 #define PTHREAD_PROCESS_PRIVATE  0
175 #define PTHREAD_PROCESS_SHARED   1
176 
177 
178 /* Functions for mutex handling.  */
179 
180 /**
181  * @nqPosix
182  * Initializes a mutex using attributes in mutex_attr, or using the
183  * default values if the latter is NULL.
184  *
185  * @linkPthread
186  *
187  * @param mutex The address of the mutex structure to be initialized.
188  * @param mutex_attr The address of the attributes structure.
189  *
190  * @return 0 upon success, 1 otherwise
191  */
192 int pthread_mutex_init(pthread_mutex_t *mutex,
193                        const pthread_mutexattr_t *mutex_attr);
194 
195 /**
196  * @nqPosix
197  * Destroys a mutex.
198  *
199  * @linkPthread
200  *
201  * @param mutex The address of the mutex structure to be destroyed.
202  *
203  * @return 0 upon success, non-zero error code otherwise
204  */
205 int pthread_mutex_destroy(pthread_mutex_t *mutex);
206 
207 /**
208  * @nqPosix
209  * Tries to lock a mutex.
210  *
211  * @linkPthread
212  *
213  * @param mutex The address of the mutex structure to be locked.
214  *
215  * @return 0 upon success, EBUSY if the mutex is locked by another thread,
216  * non-zero error code otherwise.
217  */
218 int pthread_mutex_trylock(pthread_mutex_t *mutex);
219 
220 /**
221  * @nqPosix
222  * Locks a mutex.
223  *
224  * @linkPthread
225  *
226  * @param mutex The address of the mutex structure to be locked.
227  *
228  * @return 0 upon success, non-zero error code otherwise.
229  */
230 int pthread_mutex_lock(pthread_mutex_t *mutex);
231 
232 /* Wait until lock becomes available, or specified time passes. */
233 int pthread_mutex_timedlock(pthread_mutex_t *mutex,
234                             const struct timespec *abstime);
235 
236 /**
237  * @nqPosix
238  * Unlocks a mutex.
239  *
240  * @linkPthread
241  *
242  * @param mutex The address of the mutex structure to be unlocked.
243  *
244  * @return 0 upon success, non-zero error code otherwise.
245  */
246 int pthread_mutex_unlock(pthread_mutex_t *mutex);
247 
248 /* Mutex attributes manipulation */
249 
250 /**
251  * @nqPosix
252  * Initializes mutex attributes.
253  *
254  * @linkPthread
255  *
256  * @param attr The address of the attributes structure to be initialized.
257  *
258  * @return 0.
259  */
260 int pthread_mutexattr_init(pthread_mutexattr_t *attr);
261 
262 /**
263  * @nqPosix
264  * Destroys mutex attributes structure.
265  *
266  * @linkPthread
267  *
268  * @param attr The address of the attributes structure to be destroyed.
269  *
270  * @return 0.
271  */
272 int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
273 
274 /**
275  * @nqPosix
276  * Sets the mutex type: fast, recursive or error-checking.
277  *
278  * @linkPthread
279  *
280  * @param attr The address of the attributes structure.
281  * @param kind PTHREAD_MUTEX_FAST_NP, PTHREAD_MUTEX_RECURSIVE_NP or
282  * PTHREAD_MUTEX_ERRORCHECK_NP.
283  *
284  * @return 0 on success, -1 for illegal values of kind.
285  */
286 int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
287 
288 /**
289  * @nqPosix
290  * Gets the mutex type: fast, recursive or error-checking.
291  *
292  * @linkPthread
293  *
294  * @param attr The address of the attributes structure.
295  * @param kind Pointer to the location where the mutex kind value is copied.
296  *
297  * @return 0.
298  */
299 int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind);
300 
301 int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared);
302 
303 int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);
304 
305 /* Functions for handling conditional variables.  */
306 
307 /**
308  * @nqPosix
309  * Initializes a condition variable.
310  *
311  * @linkPthread
312  *
313  * @param cond Pointer to the condition variable structure.
314  * @param cond_attr Pointer to the attributes structure, should be NULL as
315  * Native Client does not support any attributes for a condition variable at
316  * this stage.
317  *
318  * @return 0 for success, 1 otherwise.
319  */
320 int pthread_cond_init(pthread_cond_t *cond,
321                       const pthread_condattr_t *cond_attr);
322 
323 /**
324  * @nqPosix
325  * Destroys a condition variable.
326  *
327  * @linkPthread
328  *
329  * @param cond Pointer to the condition variable structure.
330  *
331  * @return 0 for success, non-zero error code otherwise.
332  */
333 int pthread_cond_destroy(pthread_cond_t *cond);
334 
335 /**
336  * @nqPosix
337  * Signals a condition variable, waking up one of the threads waiting on it.
338  *
339  * @linkPthread
340  *
341  * @param cond Pointer to the condition variable structure.
342  *
343  * @return 0 for success, non-zero error code otherwise.
344  */
345 int pthread_cond_signal(pthread_cond_t *cond);
346 
347 /**
348  * @nqPosix
349  * Wakes up all threads waiting on a condition variable.
350  *
351  * @linkPthread
352  *
353  * @param cond Pointer to the condition variable structure.
354  *
355  * @return 0 for success, non-zero error code otherwise.
356  */
357 int pthread_cond_broadcast(pthread_cond_t *cond);
358 
359 /**
360  * @nqPosix
361  * Waits for a condition variable to be signaled or broadcast.
362  *
363  * @linkPthread
364  *
365  * @param cond Pointer to the condition variable structure.
366  * @param mutex Pointer to the mutex structure. The mutex is assumed to be
367  * locked when this function is called.
368  *
369  * @return 0 for success, non-zero error code otherwise.
370  */
371 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
372 
373 /**
374  * @nqPosix
375  * Waits for condition variable cond to be signaled or broadcast until
376  * abstime.
377  *
378  * @linkPthread
379  *
380  * @param cond Pointer to the condition variable structure.
381  * @param mutex Pointer to the mutex structure. The mutex is assumed to be
382  * locked when this function is called.
383  * @param abstime Absolute time specification; zero is the beginning of the
384  * epoch (00:00:00 GMT, January 1, 1970).
385  *
386  * @return 0 for success, non-zero error code otherwise.
387  */
388 int pthread_cond_timedwait_abs(pthread_cond_t *cond,
389                                pthread_mutex_t *mutex,
390                                const struct timespec *abstime);
391 
392 /**
393  * @nqPosix
394  * Waits for condition variable cond to be signaled or broadcast; wait time is
395  * limited by reltime.
396  *
397  * @linkPthread
398  *
399  * @param cond Pointer to the condition variable structure.
400  * @param mutex Pointer to the mutex structure. The mutex is assumed to be
401  * locked when this function is called.
402  * @param reltime Time specification, relative to the current time.
403  *
404  * @return 0 for success, non-zero error code otherwise.
405  */
406 int pthread_cond_timedwait_rel(pthread_cond_t *cond,
407                                pthread_mutex_t *mutex,
408                                const struct timespec *reltime);
409 
410 /**
411  * Defined for POSIX compatibility; pthread_cond_timedwait() is actually
412  * a macro calling pthread_cond_timedwait_abs().
413  */
414 #define pthread_cond_timedwait pthread_cond_timedwait_abs
415 
416 /* Condition variable attributes manipulation */
417 
418 int pthread_condattr_init(pthread_condattr_t *attr);
419 
420 int pthread_condattr_destroy(pthread_condattr_t *attr);
421 
422 int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared);
423 
424 int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared);
425 
426 int pthread_condattr_getclock(const pthread_condattr_t *attr,
427                               clockid_t *clock_id);
428 
429 int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id);
430 
431 /* Functions for rwlock handling.  */
432 
433 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
434 int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr,
435                                   int *pshared);
436 int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared);
437 int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);
438 
439 int pthread_rwlock_init(pthread_rwlock_t *rwlock,
440                         const pthread_rwlockattr_t *attr);
441 
442 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
443 int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
444 int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock,
445                                const struct timespec *abstime);
446 
447 
448 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
449 int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
450 int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock,
451                                const struct timespec *abstime);
452 
453 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
454 int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
455 
456 
457 /* Threads */
458 /** Thread identifier type. */
459 typedef struct __nc_basic_thread_data *pthread_t;
460 
461 /** A structure representing thread attributes. */
462 typedef struct {
463   int joinable; /**< 1 if the thread is joinable, 0 otherwise */
464   size_t stacksize; /**< The requested thread stack size in bytes. */
465 } pthread_attr_t;
466 
467 
468 /** Joinable thread type; for use with pthread_attr_setdetachstate(). */
469 #define PTHREAD_CREATE_JOINABLE 1
470 /** Detached thread type; for use with pthread_attr_setdetachstate(). */
471 #define PTHREAD_CREATE_DETACHED 0
472 
473 /** For use with pthread_attr_setscope(). */
474 #define PTHREAD_SCOPE_PROCESS 0
475 /** For use with pthread_attr_setscope(). */
476 #define PTHREAD_SCOPE_SYSTEM  1
477 
478 /** Minimum stack size; for use with pthread_attr_setstacksize(). */
479 #define PTHREAD_STACK_MIN     (1024)
480 
481 /* default stack size */
482 #define PTHREAD_STACK_DEFAULT (512 * 1024)
483 
484 /* Thread functions  */
485 
486 /**
487  * @nqPosix
488  * Creates a thread.
489  *
490  * @linkPthread
491  *
492  * @param[out] thread_id A pointer to the location where the identifier of the
493  * newly created thread is stored on success.
494  * @param attr Thread attributes structure.
495  * @param start_routine Thread function.
496  * @param arg A single argument that is passed to the thread function.
497  *
498  * @return 0 for success, non-zero error code otherwise.
499  */
500 int pthread_create(pthread_t *thread_id,
501                    const pthread_attr_t *attr,
502                    void *(*start_routine)(void *p),
503                    void *arg);
504 
505 /**
506  * @nqPosix
507  * Obtains the identifier of the current thread.
508  *
509  * @linkPthread
510  *
511  * @return Thread ID of the current thread.
512  */
513 pthread_t pthread_self(void);
514 
515 /**
516  * @nqPosix
517  * Compares two thread identifiers.
518  *
519  * @linkPthread
520  *
521  * @param thread1 Thread ID of thread A.
522  * @param thread2 Thread ID of thread B.
523  *
524  * @return 1 if both identifiers belong to the same thread, 0 otherwise.
525  */
526 int pthread_equal(pthread_t thread1, pthread_t thread2);
527 
528 /**
529  * @nqPosix
530  * Terminates the calling thread.
531  *
532  * @linkPthread
533  *
534  * @param retval Return value of the thread.
535  *
536  * @return The function never returns.
537  */
538 void pthread_exit(void *retval);
539 
540 /**
541  * @nqPosix
542  * Makes the calling thread wait for termination of another thread.
543  *
544  * @linkPthread
545  *
546  * @param th The identifier of the thread to wait for.
547  * @param thread_return If not NULL, points to the location where the return
548  * value of the terminated thread is stored upon completion.
549  *
550  * @return 0 on success, non-zero error code otherwise.
551  */
552 int pthread_join(pthread_t th, void **thread_return);
553 
554 /**
555  * @nqPosix
556  * Indicates that the specified thread is never to be joined with
557  * pthread_join(). The resources of that thread will therefore be freed
558  * immediately when it terminates, instead of waiting for another thread to
559  * perform pthread_join() on it.
560  *
561  * @linkPthread
562  *
563  * @param th Thread identifier.
564  *
565  * @return 0 on success, non-zero error code otherwise.
566  */
567 int pthread_detach(pthread_t th);
568 
569 /**
570  * @nqPosix
571  * Sends a signal to a thread.  (Currently only a stub implementation.)
572  *
573  * @linkPthread
574  *
575  * @param thread_id The identifier of the thread to receive the signal.
576  * @param sig The signal value to send.
577  *
578  * @return 0 for success, non-zero error code otherwise.
579  */
580 int pthread_kill(pthread_t thread_id, int sig);
581 
582 /* Functions for handling thread attributes.  */
583 
584 /**
585  * @nqPosix
586  * Initializes thread attributes structure attr with default attributes
587  * (detachstate is PTHREAD_CREATE_JOINABLE).
588  *
589  * @linkPthread
590  *
591  * @param attr Pointer to thread attributes structure.
592  *
593  * @return 0 on success, non-zero error code otherwise.
594  */
595 int pthread_attr_init(pthread_attr_t *attr);
596 
597 /**
598  * @nqPosix
599  * Destroys a thread attributes structure.
600  *
601  * @linkPthread
602  *
603  * @param attr Pointer to thread attributes structure.
604  *
605  * @return 0 on success, non-zero error code otherwise.
606  */
607 int pthread_attr_destroy(pthread_attr_t *attr);
608 
609 /**
610  * @nqPosix
611  * Sets the detachstate attribute in thread attributes.
612  *
613  * @linkPthread
614  *
615  * @param attr Pointer to thread attributes structure.
616  * @param detachstate Value to be set, determines whether the thread is
617  * joinable.
618  *
619  * @return 0 on success, non-zero error code otherwise.
620  */
621 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
622 
623 /**
624  * @nqPosix
625  * Gets the detachstate attribute from thread attributes.
626  *
627  * @linkPthread
628  *
629  * @param attr Pointer to thread attributes structure.
630  * @param detachstate Location where the value of `detachstate` is stored upon
631  * successful completion.
632  *
633  * @return 0 on success, non-zero error code otherwise.
634  */
635 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
636 
637 /**
638  * @nqPosix
639  * Sets the contention scope attribute in thread attributes.
640  * Native Client (like Linux) only supports PTHREAD_SCOPE_SYSTEM.
641  *
642  * @linkPthread
643  *
644  * @param attr Pointer to thread attributes structure.
645  * @param scope Value to be set, determines the contention scope of the thread.
646  *
647  * @return 0 on success, non-zero error code otherwise.
648  */
649 int pthread_attr_setscope(pthread_attr_t *attr, int scope);
650 
651 /**
652  * @nqPosix
653  * Gets the contention scope attribute from thread attributes.
654  * Native Client (like Linux) only supports PTHREAD_SCOPE_SYSTEM.
655  *
656  * @linkPthread
657  *
658  * @param attr Pointer to thread attributes structure.
659  * @param scope Location where the value of `scope` is stored upon
660  * successful completion.
661  *
662  * @return 0 on success, non-zero error code otherwise.
663  */
664 int pthread_attr_getscope(const pthread_attr_t *attr, int *scope);
665 
666 /**
667  * @nqPosix
668  * Sets the stacksize attribute in thread attributes.  Has no effect if the
669  * size is less than PTHREAD_STACK_MIN.
670  *
671  * @linkPthread
672  *
673  * @param attr Pointer to thread attributes structure.
674  * @param stacksize Value to be set, determines the minimum stack size.
675  *
676  * @return 0 on success, non-zero error code otherwise.
677  */
678 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
679 
680 /**
681  * @nqPosix
682  * Gets the stacksize attribute in thread attributes.
683  *
684  * @linkPthread
685  *
686  * @param attr Pointer to thread attributes structure.
687  * @param stacksize Value to be set, determines the minimum stack size.
688  *
689  * @return 0 on success, non-zero error code otherwise.
690  */
691 int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);
692 
693 /**
694  * @nqPosix
695  * Gets the maximum address of the stack (assuming stacks grow
696  * downwards) of the given thread.
697  *
698  * If the given thread exits concurrently with the call to this
699  * function, the behaviour is undefined.
700  *
701  * Note that in the future this may be removed and replaced with an
702  * implementation of pthread_getattr_np(), for consistency with Linux
703  * glibc.  pthread_getattr_np() + pthread_attr_getstack() return the
704  * stack base (minimum) address and stack size.  However, that is
705  * currently unimplementable under NaCl, because NaCl does not provide
706  * a way to determine the initial thread's stack size.  See:
707  * https://code.google.com/p/nativeclient/issues/detail?id=3431
708  */
709 int pthread_get_stack_end_np(pthread_t tid, void **stack_end);
710 
711 /* Functions for handling thread-specific data.  */
712 
713 /** Thread-specific key identifier type */
714 typedef int pthread_key_t;
715 
716 /** Number of available keys for thread-specific data. */
717 #define PTHREAD_KEYS_MAX 512
718 
719 /**
720  * @nqPosix
721  * Creates a key value identifying a location in the thread-specific
722  * data area.
723  *
724  * @linkPthread
725  *
726  * @param key Pointer to the location where the value of the key is stored upon
727  * successful completion.
728  * @param destr_function Pointer to a cleanup function that is called if the
729  * thread terminates while the key is still allocated.
730  *
731  * @return 0 on success, non-zero error code otherwise.
732  */
733 int pthread_key_create(pthread_key_t *key, void (*destr_function)(void *p));
734 
735 
736 /**
737  * @nqPosix
738  * Destroys a thread-specific data key.
739  *
740  * @linkPthread
741  *
742  * @param key Key value, previously obtained using pthread_key_create().
743  *
744  * @return 0 on success, non-zero error code otherwise.
745  */
746 int pthread_key_delete(pthread_key_t key);
747 
748 /**
749  * @nqPosix
750  * Stores a value in the thread-specific data slot identified by a key value.
751  *
752  * @linkPthread
753  *
754  * @param key Key value, previously obtained using pthread_key_create().
755  * @param pointer The value to be stored.
756  *
757  * @return 0 on success, non-zero error code otherwise.
758  */
759 int pthread_setspecific(pthread_key_t key, const void *pointer);
760 
761 /**
762  * @nqPosix
763  * Gets the value currently stored at the thread-specific data slot
764  * identified by the key.
765  *
766  * @linkPthread
767  *
768  * @param key Key value, previously obtained using pthread_key_create().
769  *
770  * @return The value that was previously stored using pthread_setspecific is
771  * returned on success, otherwise NULL.
772  */
773 void *pthread_getspecific(pthread_key_t key);
774 
775 /**
776  * A structure describing a control block
777  * used with the pthread_once() function.
778  * It should be considered an opaque record;
779  * the names of the fields can change anytime.
780  */
781 typedef struct {
782   /** A flag: 1 if the function was already called, 0 if it wasn't */
783   AtomicInt32      done;
784 
785   /** Synchronization lock for the flag */
786   pthread_mutex_t lock;
787 } pthread_once_t;
788 
789 /** Static initializer for pthread_once_t. */
790 #define PTHREAD_ONCE_INIT {0, PTHREAD_MUTEX_INITIALIZER}
791 
792 /**
793  * @nqPosix
794  * Ensures that a piece of initialization code is executed at most once.
795  *
796  * @linkPthread
797  *
798  * @param __once_control Points to a static or extern variable statically
799  * initialized to PTHREAD_ONCE_INIT.
800  * @param __init_routine A pointer to the initialization function.
801  *
802  * @return 0.
803  */
804 int pthread_once(pthread_once_t *__once_control, void (*__init_routine)(void));
805 
806 /**
807  * @nqPosix
808  * Sets the scheduling priority of a thread.
809  *
810  * @linkPthread
811  *
812  * @param thread_id Identifies the thread to operate on.
813  * @param prio Scheduling priority to apply to that thread.
814  *
815  * @return 0 on success, non-zero error code otherwise.
816  */
817 int pthread_setschedprio(pthread_t thread_id, int prio);
818 
819 /*
820  * NOTE: this is only declared here to shut up
821  * some warning in the c++ system header files.
822  * We do not define this function anywhere.
823  */
824 
825 int pthread_cancel(pthread_t th);
826 
827 /*
828  * NOTE: There are only stub implementations of these functions.
829  */
830 
831 void pthread_cleanup_push(void (*func)(void *cleanup_arg), void *arg);
832 void pthread_cleanup_pop(int execute);
833 
834 /**
835  * @} End of PTHREAD group
836  */
837 
838 #ifdef __cplusplus
839 }
840 #endif
841 
842 #endif  /* pthread.h */
843