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 /** POSIX wrapper for THREADX */
15 /** */
16 /** */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 /* Include necessary system files. */
22
23 #include "tx_api.h" /* Threadx API */
24 #include "pthread.h" /* Posix API */
25 #include "px_int.h" /* Posix helper functions */
26
27
28 /**************************************************************************/
29 /* */
30 /* FUNCTION RELEASE */
31 /* */
32 /* pthread_cond_wait PORTABLE C */
33 /* 6.1.7 */
34 /* AUTHOR */
35 /* */
36 /* William E. Lamie, Microsoft Corporation */
37 /* */
38 /* DESCRIPTION */
39 /* */
40 /* This function shall block on a condition variable. They shall be */
41 /* called with mutex locked by the calling thread or undefined behavior*/
42 /* results. These functions atomically release the mutex and cause the */
43 /* calling thread to block on the condition variable cond; atomically */
44 /* here means atomically with respect to access by another thread to */
45 /* the mutex and then the request for semaphore. */
46 /* */
47 /* Upon successful return, the mutex shall have been locked and shall */
48 /* be owned by the calling thread. */
49 /* */
50 /* When using condition variables there is always a Boolean predicate */
51 /* involving shared variables associated with each condition wait that */
52 /* is true if the thread should proceed. Spurious wakeups from the */
53 /* pthread_cond_timedwait or pthread_cond_wait functions may occur. */
54 /* Since the return from pthread_cond_timedwait or pthread_cond_wait */
55 /* does not imply anything about the value of this predicate, the */
56 /* predicate should be re-evaluated upon such return. The effect of */
57 /* using more than one mutex for concurrent pthread_cond_timedwait or */
58 /* pthread_cond_wait operations on the same condition variable is */
59 /* undefined; that is, a condition variable becomes bound to a unique */
60 /* mutex when a thread waits on the condition variable, and this */
61 /* (dynamic) binding shall end when the wait returns. */
62 /* */
63 /* INPUT */
64 /* */
65 /* cond condition variable */
66 /* mutex mutex to be associated with condition */
67 /* variable */
68 /* */
69 /* OUTPUT */
70 /* */
71 /* OK if succesfull */
72 /* ERROR in case of any error */
73 /* */
74 /* CALLS */
75 /* */
76 /* pthread_mutex_unlock unlocks the mutex held by the caller */
77 /* tx_semaphore_get try to get sempaphore internal to cond */
78 /* tx_semaphore_prioritize prioritize all suspended pthreads */
79 /* pthread_mutex_lock lock the mutex */
80 /* */
81 /* CALLED BY */
82 /* */
83 /* Application Code */
84 /* */
85 /* RELEASE HISTORY */
86 /* */
87 /* DATE NAME DESCRIPTION */
88 /* */
89 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
90 /* */
91 /**************************************************************************/
pthread_cond_wait(pthread_cond_t * cond,pthread_mutex_t * mutex)92 INT pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
93 {
94
95 TX_SEMAPHORE *semaphore_ptr;
96 UINT status;
97 UINT old_threshold,dummy;
98 TX_THREAD *thread;
99
100 /* Find the current thread. */
101 thread = tx_thread_identify();
102
103 /* Raise its preemption threshold so it does not get descheduled. */
104 tx_thread_preemption_change(thread,0,&old_threshold);
105
106 pthread_mutex_unlock(mutex);
107
108 semaphore_ptr = (&( cond->cond_semaphore ));
109
110 status = tx_semaphore_get(semaphore_ptr, TX_WAIT_FOREVER);
111
112 /* Restore original preemption threshold. */
113 tx_thread_preemption_change(thread, old_threshold, &dummy);
114
115
116 if ( status != TX_SUCCESS)
117 {
118 posix_errno = EINVAL;
119 posix_set_pthread_errno(EINVAL);
120 return(EINVAL);
121 }
122
123 status = tx_semaphore_prioritize(semaphore_ptr);
124
125 if ( status != TX_SUCCESS)
126 {
127 posix_errno = EINVAL;
128 posix_set_pthread_errno(EINVAL);
129 return(EINVAL);
130 }
131
132 pthread_mutex_lock(mutex);
133 return(OK);
134 }
135