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