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