1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** POSIX wrapper for THREADX */
17 /** */
18 /** */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 /* Include necessary system files. */
24
25 #include "tx_api.h" /* Threadx API */
26 #include "pthread.h" /* Posix API */
27 #include "px_int.h" /* Posix helper functions */
28
29
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* pthread_once PORTABLE C */
35 /* 6.1.7 */
36 /* AUTHOR */
37 /* */
38 /* William E. Lamie, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* The pthread_once function shall call the init_routine with no */
43 /* arguments. Subsequent calls of pthread_once() with the same */
44 /* once_control shall not call the init_routine. On return from */
45 /* pthread_once(), init_routine shall have completed. The */
46 /* once_control parameter shall determine whether the associated */
47 /* initialization routine has been called. */
48 /* */
49 /* INPUT */
50 /* once_control */
51 /* init_routine */
52 /* */
53 /* OUTPUT */
54 /* zero If successful */
55 /* error number If fails */
56 /* */
57 /* */
58 /* CALLS */
59 /* tx_thread_preemption_change */
60 /* tx_event_flags_create */
61 /* tx_event_flags_set */
62 /* tx_event_flags_get */
63 /* */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* Application Code */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
74 /* */
75 /**************************************************************************/
pthread_once(pthread_once_t * once_control,VOID (* init_routine)(VOID))76 INT pthread_once (pthread_once_t * once_control, VOID (*init_routine) (VOID))
77 {
78
79 INT result;
80 UINT old_treshold, temp;
81
82 if (once_control == NULL || init_routine == NULL)
83 {
84 result = EINVAL;
85 }
86 else
87 {
88 if ( once_control->state==PTH_ONCE_DONE)
89 {
90 result = 0;
91 }
92
93 /* suspend preemption */
94 tx_thread_preemption_change( tx_thread_identify(), 0, &old_treshold);
95
96 if (once_control->state==PTH_ONCE_INIT)
97 {
98 once_control->state=PTH_ONCE_STARTED;
99 tx_event_flags_create(&(once_control->event),"once flags");
100
101 /* enable preemption */
102 tx_thread_preemption_change( tx_thread_identify(),old_treshold, &temp);
103 (*init_routine)();
104
105 tx_event_flags_set(&(once_control->event), PTH_ONCE_INIT, TX_AND);
106
107 once_control->state=PTH_ONCE_DONE;
108 }
109
110 /* enable preemption */
111 tx_thread_preemption_change( tx_thread_identify(),old_treshold, &temp);
112
113 if (once_control->state==PTH_ONCE_STARTED)
114 {
115 tx_event_flags_get(&(once_control->event), PTH_ONCE_INIT, TX_AND, &(once_control->flags) ,TX_WAIT_FOREVER);
116 }
117 }
118
119 /* note: this routine will not handle the case where the init routine is a cancellation point */
120 return (result);
121 }
122