From: Narcisa Vasile <navas...@microsoft.com> Add functions for mutex init, destroy, lock, unlock, trylock.
Windows does not have a static initializer. Initialization is only done through InitializeCriticalSection(). To overcome this, RTE_INIT_MUTEX macro is added to replace static initialization of mutexes. The macro calls rte_thread_mutex_init(). Signed-off-by: Narcisa Vasile <navas...@microsoft.com> --- lib/eal/common/rte_thread.c | 69 +++++++++++++++++++++++++++++ lib/eal/include/rte_thread.h | 85 ++++++++++++++++++++++++++++++++++++ lib/eal/version.map | 5 +++ lib/eal/windows/rte_thread.c | 64 +++++++++++++++++++++++++++ 4 files changed, 223 insertions(+) diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c index 30e2ca79d1..580448d8bf 100644 --- a/lib/eal/common/rte_thread.c +++ b/lib/eal/common/rte_thread.c @@ -295,6 +295,75 @@ rte_thread_detach(rte_thread_t thread_id) return pthread_detach((pthread_t)thread_id.opaque_id); } +int +rte_thread_mutex_init(rte_thread_mutex *mutex) +{ + int ret = 0; + pthread_mutex_t *m = NULL; + + RTE_VERIFY(mutex != NULL); + + m = calloc(1, sizeof(*m)); + if (m == NULL) { + RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n"); + ret = ENOMEM; + goto cleanup; + } + + ret = pthread_mutex_init(m, NULL); + if (ret != 0) { + RTE_LOG(DEBUG, EAL, "Failed to init mutex. ret = %d\n", ret); + goto cleanup; + } + + mutex->mutex_id = m; + m = NULL; + +cleanup: + free(m); + return ret; +} + +int +rte_thread_mutex_lock(rte_thread_mutex *mutex) +{ + RTE_VERIFY(mutex != NULL); + + return pthread_mutex_lock((pthread_mutex_t *)mutex->mutex_id); +} + +int +rte_thread_mutex_unlock(rte_thread_mutex *mutex) +{ + RTE_VERIFY(mutex != NULL); + + return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex_id); +} + +int +rte_thread_mutex_try_lock(rte_thread_mutex *mutex) +{ + RTE_VERIFY(mutex != NULL); + + return pthread_mutex_trylock((pthread_mutex_t *)mutex->mutex_id); +} + +int +rte_thread_mutex_destroy(rte_thread_mutex *mutex) +{ + int ret = 0; + RTE_VERIFY(mutex != NULL); + + ret = pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex_id); + if (ret != 0) + RTE_LOG(DEBUG, EAL, "Unable to destroy mutex, ret = %d\n", ret); + + free(mutex->mutex_id); + mutex->mutex_id = NULL; + + return ret; +} + int rte_thread_barrier_init(rte_thread_barrier *barrier, int count) { diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h index 7c84e32988..09a5fd8add 100644 --- a/lib/eal/include/rte_thread.h +++ b/lib/eal/include/rte_thread.h @@ -54,6 +54,25 @@ typedef struct { #endif /* RTE_HAS_CPUSET */ +#define RTE_DECLARE_MUTEX(private_lock) rte_thread_mutex private_lock + +#define RTE_DEFINE_MUTEX(private_lock)\ +RTE_INIT(__rte_ ## private_lock ## _init)\ +{\ + RTE_VERIFY(rte_thread_mutex_init(&private_lock) == 0);\ +} + +#define RTE_INIT_MUTEX(private_lock)\ +static RTE_DECLARE_MUTEX(private_lock);\ +RTE_DEFINE_MUTEX(private_lock) + +/** + * Thread mutex representation. + */ +typedef struct rte_thread_mutex_tag { + void *mutex_id; /**< mutex identifier */ +} rte_thread_mutex; + /** * Returned by rte_thread_barrier_wait() when call is successful. */ @@ -314,6 +333,72 @@ __rte_experimental int rte_thread_set_priority(rte_thread_t thread_id, enum rte_thread_priority priority); +/** + * Initializes a mutex. + * + * @param mutex + * The mutex to be initialized. + * + * @return + * On success, return 0. + * On failure, return a positive errno-style error number. + */ +__rte_experimental +int rte_thread_mutex_init(rte_thread_mutex *mutex); + +/** + * Locks a mutex. + * + * @param mutex + * The mutex to be locked. + * + * @return + * On success, return 0. + * On failure, return a positive errno-style error number. + */ +__rte_experimental +int rte_thread_mutex_lock(rte_thread_mutex *mutex); + +/** + * Unlocks a mutex. + * + * @param mutex + * The mutex to be unlocked. + * + * @return + * On success, return 0. + * On failure, return a positive errno-style error number. + */ +__rte_experimental +int rte_thread_mutex_unlock(rte_thread_mutex *mutex); + +/** + * Tries to lock a mutex.If the mutex is already held by a different thread, + * the function returns without blocking. + * + * @param mutex + * The mutex that will be acquired, if not already locked. + * + * @return + * On success, if the mutex is acquired, return 0. + * On failure, return a positive errno-style error number. + */ +__rte_experimental +int rte_thread_mutex_try_lock(rte_thread_mutex *mutex); + +/** + * Releases all resources associated with a mutex. + * + * @param mutex + * The mutex to be uninitialized. + * + * @return + * On success, return 0. + * On failure, return a positive errno-style error number. + */ +__rte_experimental +int rte_thread_mutex_destroy(rte_thread_mutex *mutex); + /** * Initializes a synchronization barrier. * diff --git a/lib/eal/version.map b/lib/eal/version.map index 06e5f82da2..e80eea4316 100644 --- a/lib/eal/version.map +++ b/lib/eal/version.map @@ -431,6 +431,11 @@ EXPERIMENTAL { rte_thread_barrier_wait; rte_thread_barrier_destroy; rte_thread_get_affinity_by_id; + rte_thread_mutex_init; + rte_thread_mutex_lock; + rte_thread_mutex_unlock; + rte_thread_mutex_try_lock; + rte_thread_mutex_destroy; rte_thread_set_affinity_by_id; rte_thread_get_priority; rte_thread_set_priority; diff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c index 3f72bbf716..11b4863fe8 100644 --- a/lib/eal/windows/rte_thread.c +++ b/lib/eal/windows/rte_thread.c @@ -504,6 +504,70 @@ rte_thread_detach(rte_thread_t thread_id) return 0; } +int +rte_thread_mutex_init(rte_thread_mutex *mutex) +{ + int ret = 0; + CRITICAL_SECTION *m = NULL; + + RTE_VERIFY(mutex != NULL); + + m = calloc(1, sizeof(*m)); + if (m == NULL) { + RTE_LOG(DEBUG, EAL, "Unable to initialize mutex. Insufficient memory!\n"); + ret = ENOMEM; + goto cleanup; + } + + InitializeCriticalSection(m); + mutex->mutex_id = m; + m = NULL; + +cleanup: + return ret; +} + +int +rte_thread_mutex_lock(rte_thread_mutex *mutex) +{ + RTE_VERIFY(mutex != NULL); + + EnterCriticalSection(mutex->mutex_id); + return 0; +} + +int +rte_thread_mutex_unlock(rte_thread_mutex *mutex) +{ + RTE_VERIFY(mutex != NULL); + + LeaveCriticalSection(mutex->mutex_id); + return 0; +} + +int +rte_thread_mutex_try_lock(rte_thread_mutex *mutex) +{ + RTE_VERIFY(mutex != NULL); + + if (TryEnterCriticalSection(mutex->mutex_id) != 0) + return 0; + + return EBUSY; +} + +int +rte_thread_mutex_destroy(rte_thread_mutex *mutex) +{ + RTE_VERIFY(mutex != NULL); + + DeleteCriticalSection(mutex->mutex_id); + free(mutex->mutex_id); + mutex->mutex_id = NULL; + + return 0; +} + int rte_thread_barrier_init(rte_thread_barrier *barrier, int count) { -- 2.31.0.vfs.0.1