Skip to content

[feat](pthread): Add pthread_mutex_timedlock #10163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components/libc/posix/pthreads/pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime);
int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex, int *prioceiling);
int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling);

Expand Down
62 changes: 62 additions & 0 deletions components/libc/posix/pthreads/pthread_mutex.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,68 @@ int pthread_mutex_trylock(pthread_mutex_t *mutex)
}
RTM_EXPORT(pthread_mutex_trylock);


/**
* @brief Attempts to lock a mutex with a timeout.
*
* This function attempts to lock the mutex object pointed to by `mutex`. If the mutex
* is already locked by another thread, the function will block until the mutex becomes
* available or the specified timeout occurs.
*
* @param[in,out] mutex Pointer to the mutex to be locked.
* @param[in] abstime Pointer to a `struct timespec` structure specifying the absolute time
* when the function should return if the mutex is not available.
*
* @return
* - 0 on success.
* - Non-zero error code on failure, including:
* - `EINVAL`: The mutex is invalid or uninitialized.
* - `EDEADLK`: A deadlock condition was detected (e.g., the current thread
* already holds the mutex in a recursive locking scenario).
*
* @note
* This function is useful for implementing timed mutex acquisition. If the mutex
* was initialized with the `PTHREAD_MUTEX_RECURSIVE` attribute, the calling thread can
* lock it multiple times, but must unlock it the same number of times.
*
* @warning
* Attempting to timedlock an uninitialized or destroyed mutex results in undefined behavior.
*
* @see pthread_mutex_lock, pthread_mutex_unlock, pthread_mutex_trylock, pthread_mutex_init
*/
int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime)
{
int mtype;
rt_err_t result;

if (!mutex)
return EINVAL;

if (mutex->attr == -1)
{
/* init mutex */
pthread_mutex_init(mutex, RT_NULL);
}

mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
rt_enter_critical();
if (mutex->lock.owner == rt_thread_self() && mtype != PTHREAD_MUTEX_RECURSIVE)
{
rt_exit_critical();
return EDEADLK;
}
rt_exit_critical();

rt_int32_t timeout = rt_timespec_to_tick(abstime);

result = rt_mutex_take(&(mutex->lock), timeout);
if (result == RT_EOK)
return 0;
Copy link
Preview

Copilot AI Apr 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When rt_mutex_take fails due to a timeout, returning EINVAL may be misleading. Consider checking if the error indicates a timeout and returning ETIMEDOUT as specified by the POSIX standard.

Suggested change
return 0;
return 0;
else if (result == -RT_ETIMEOUT) /* Assuming -RT_ETIMEOUT indicates a timeout */
return ETIMEDOUT;

Copilot uses AI. Check for mistakes.


return EINVAL;
Copy link
Preview

Copilot AI Apr 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value from rt_mutex_take is always translated to EINVAL, irrespective of whether the failure was due to a timeout or another error. Consider translating the error codes from rt_mutex_take (for example, returning ETIMEDOUT when the timeout expires) to provide more accurate feedback to the caller.

Copilot uses AI. Check for mistakes.

}
RTM_EXPORT(pthread_mutex_timedlock);

int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *prioceiling)
{
return EINVAL;
Expand Down
Loading