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_cond_broadcast PORTABLE C */
34 /* 6.1.7 */
35 /* AUTHOR */
36 /* */
37 /* William E. Lamie, Microsoft Corporation */
38 /* */
39 /* DESCRIPTION */
40 /* */
41 /* These functions shall unblock all threads currently blocked on a */
42 /* specified condition variable cond. */
43 /* If more than one thread is blocked on a condition variable, */
44 /* the scheduling policy shall determine the order in which threads are*/
45 /* unblocked. When each thread unblocked as a result of this function */
46 /* call returns from its call to pthread_cond_wait or */
47 /* pthread_cond_timedwait, the thread shall own the mutex with which it*/
48 /* called pthread_cond_wait or pthread_cond_timedwait. The thread(s) */
49 /* that are unblocked shall contend for the mutex according to the */
50 /* scheduling policy (if applicable), and as if each had called */
51 /* pthread_mutex_lock.The pthread_cond_broadcast function may be called*/
52 /* by a thread whether or not it currently owns the mutex that threads */
53 /* calling pthread_cond_wait or pthread_cond_timedwait have associated */
54 /* with the condition variable during their waits; however, */
55 /* if predictable scheduling behavior is required, then that mutex */
56 /* shall be locked by the thread calling pthread_cond_broadcast. */
57 /* The pthread_cond_broadcast function shall have no effect if there */
58 /* are no threads currently blocked on cond. */
59 /* */
60 /* INPUT */
61 /* */
62 /* cond condition variable */
63 /* */
64 /* OUTPUT */
65 /* */
66 /* Ok if successful */
67 /* Error in case of any errors */
68 /* */
69 /* CALLS */
70 /* */
71 /* tx_semaphore_prioritize line up pthreads waiting at semaphore*/
72 /* tx_thread_identify to check which pthread? */
73 /* tx_thread_preemption_change to disable thread preemption */
74 /* tx_semaphore_put ThreadX semaphore put service */
75 /* tx_thread_preemption_change to enable thread preemption */
76 /* */
77 /* CALLED BY */
78 /* */
79 /* Application Code */
80 /* */
81 /* RELEASE HISTORY */
82 /* */
83 /* DATE NAME DESCRIPTION */
84 /* */
85 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
86 /* */
87 /**************************************************************************/
pthread_cond_broadcast(pthread_cond_t * cond)88 INT pthread_cond_broadcast(pthread_cond_t *cond)
89 {
90
91 TX_SEMAPHORE *semaphore_ptr;
92 TX_THREAD *thread;
93 UINT status;
94 ULONG sem_count;
95 UINT old_threshold,dummy;
96
97
98 /* Get the condition variable's internal semaphore. */
99 /* Simply convert the condition variable control block into a semaphore a cast */
100 semaphore_ptr = (&( cond->cond_semaphore ));
101 sem_count = semaphore_ptr->tx_semaphore_suspended_count;
102
103 if (!sem_count)
104 return(OK);
105
106 status = tx_semaphore_prioritize(semaphore_ptr);
107
108 if ( status != TX_SUCCESS)
109 {
110 posix_errno = EINVAL;
111 posix_set_pthread_errno(EINVAL);
112 return(EINVAL);
113 }
114
115 /* get to know about current thread */
116 thread = tx_thread_identify();
117
118 /* Got the current thread , now raise its preemption threshold */
119 /* that way the current thread does not get descheduled when */
120 /* threads with higher priority are activated */
121 tx_thread_preemption_change(thread,0,&old_threshold);
122
123 while( sem_count)
124 {
125
126 status = tx_semaphore_put(semaphore_ptr);
127 if ( status != TX_SUCCESS)
128 {
129
130 /* restore changed preemption threshold */
131 tx_thread_preemption_change(thread,old_threshold,&dummy);
132
133 posix_errno = EINVAL;
134
135 posix_set_pthread_errno(EINVAL);
136
137 return(EINVAL);
138 }
139
140 sem_count--;
141 }
142
143 /* restore changed preemption threshold */
144 tx_thread_preemption_change(thread,old_threshold,&dummy);
145 return(OK);
146 }
147