4242 * Private Data
4343 ****************************************************************************/
4444
45+ struct timedwait_arg_s
46+ {
47+ FAR pthread_mutex_t * mutex ;
48+ unsigned int timeout_ms ;
49+ int result ;
50+ };
51+
4552static pthread_mutex_t g_mutex ;
4653static bool g_running ;
4754static int g_result ;
@@ -50,6 +57,36 @@ static int g_result;
5057 * Private Functions
5158 ****************************************************************************/
5259
60+ static void * timedwait_thread (FAR void * parameter )
61+ {
62+ FAR struct timedwait_arg_s * arg = parameter ;
63+ struct timespec abstime ;
64+
65+ clock_gettime (CLOCK_REALTIME , & abstime );
66+ abstime .tv_sec += arg -> timeout_ms / 1000 ;
67+ abstime .tv_nsec += (arg -> timeout_ms % 1000 ) * 1000000 ;
68+ if (abstime .tv_nsec >= 1000000000 )
69+ {
70+ abstime .tv_sec ++ ;
71+ abstime .tv_nsec -= 1000000000 ;
72+ }
73+
74+ arg -> result = pthread_mutex_timedlock (arg -> mutex , & abstime );
75+ if (arg -> result == 0 )
76+ {
77+ pthread_mutex_unlock (arg -> mutex );
78+ }
79+
80+ return NULL ;
81+ }
82+
83+ static void create_timedwaiter (FAR pthread_t * thread ,
84+ FAR struct timedwait_arg_s * arg )
85+ {
86+ int status = pthread_create (thread , NULL , timedwait_thread , arg );
87+ ASSERT (status == 0 );
88+ }
89+
5390static void * thread_func (FAR void * parameter )
5491{
5592 struct timespec ts ;
@@ -114,6 +151,90 @@ static void *thread_func(FAR void *parameter)
114151 return NULL ;
115152}
116153
154+ static void timedmutex_timeout_regression_test (void )
155+ {
156+ struct timedwait_arg_s short_wait ;
157+ struct timedwait_arg_s long_wait ;
158+ pthread_mutex_t mutex ;
159+ pthread_t short_thread ;
160+ pthread_t long_thread ;
161+ int status ;
162+
163+ /* A mutex must remain usable after its only waiter times out. This
164+ * verifies that the mutex blocking bit is cleared with the empty wait
165+ * queue.
166+ */
167+
168+ status = pthread_mutex_init (& mutex , NULL );
169+ ASSERT (status == 0 );
170+ status = pthread_mutex_lock (& mutex );
171+ ASSERT (status == 0 );
172+
173+ short_wait .mutex = & mutex ;
174+ short_wait .timeout_ms = 200 ;
175+ short_wait .result = -1 ;
176+ create_timedwaiter (& short_thread , & short_wait );
177+
178+ status = pthread_join (short_thread , NULL );
179+ ASSERT (status == 0 );
180+ ASSERT (short_wait .result == ETIMEDOUT );
181+
182+ status = pthread_mutex_unlock (& mutex );
183+ ASSERT (status == 0 );
184+ status = pthread_mutex_trylock (& mutex );
185+ ASSERT (status == 0 );
186+ if (status == 0 )
187+ {
188+ pthread_mutex_unlock (& mutex );
189+ }
190+
191+ status = pthread_mutex_destroy (& mutex );
192+ ASSERT (status == 0 );
193+
194+ /* If one of two waiters times out, the blocking bit must remain set for
195+ * the other waiter. Unlocking the mutex must then transfer ownership to
196+ * that remaining waiter.
197+ */
198+
199+ status = pthread_mutex_init (& mutex , NULL );
200+ ASSERT (status == 0 );
201+ status = pthread_mutex_lock (& mutex );
202+ ASSERT (status == 0 );
203+
204+ short_wait .mutex = & mutex ;
205+ short_wait .timeout_ms = 200 ;
206+ short_wait .result = -1 ;
207+ long_wait .mutex = & mutex ;
208+ long_wait .timeout_ms = 2000 ;
209+ long_wait .result = -1 ;
210+
211+ create_timedwaiter (& short_thread , & short_wait );
212+ create_timedwaiter (& long_thread , & long_wait );
213+
214+ status = pthread_join (short_thread , NULL );
215+ ASSERT (status == 0 );
216+ ASSERT (short_wait .result == ETIMEDOUT );
217+
218+ status = pthread_mutex_unlock (& mutex );
219+ ASSERT (status == 0 );
220+
221+ status = pthread_join (long_thread , NULL );
222+ ASSERT (status == 0 );
223+ ASSERT (long_wait .result == 0 );
224+
225+ status = pthread_mutex_trylock (& mutex );
226+ ASSERT (status == 0 );
227+ if (status == 0 )
228+ {
229+ pthread_mutex_unlock (& mutex );
230+ }
231+
232+ status = pthread_mutex_destroy (& mutex );
233+ ASSERT (status == 0 );
234+
235+ printf ("timedmutex regression test: PASSED\n" );
236+ }
237+
117238/****************************************************************************
118239 * Public Functions
119240 ****************************************************************************/
@@ -222,4 +343,6 @@ void timedmutex_test(void)
222343 pthread_mutex_unlock (& g_mutex );
223344errout_with_mutex :
224345 pthread_mutex_destroy (& g_mutex );
346+
347+ timedmutex_timeout_regression_test ();
225348}
0 commit comments