162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include "mutex.h"
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "debug.h"
562306a36Sopenharmony_ci#include <linux/string.h>
662306a36Sopenharmony_ci#include <errno.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_cistatic void check_err(const char *fn, int err)
962306a36Sopenharmony_ci{
1062306a36Sopenharmony_ci	char sbuf[STRERR_BUFSIZE];
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci	if (err == 0)
1362306a36Sopenharmony_ci		return;
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci	pr_err("%s error: '%s'\n", fn, str_error_r(err, sbuf, sizeof(sbuf)));
1662306a36Sopenharmony_ci}
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define CHECK_ERR(err) check_err(__func__, err)
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic void __mutex_init(struct mutex *mtx, bool pshared)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	pthread_mutexattr_t attr;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	CHECK_ERR(pthread_mutexattr_init(&attr));
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#ifndef NDEBUG
2762306a36Sopenharmony_ci	/* In normal builds enable error checking, such as recursive usage. */
2862306a36Sopenharmony_ci	CHECK_ERR(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));
2962306a36Sopenharmony_ci#endif
3062306a36Sopenharmony_ci	if (pshared)
3162306a36Sopenharmony_ci		CHECK_ERR(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED));
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	CHECK_ERR(pthread_mutex_init(&mtx->lock, &attr));
3462306a36Sopenharmony_ci	CHECK_ERR(pthread_mutexattr_destroy(&attr));
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_civoid mutex_init(struct mutex *mtx)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	__mutex_init(mtx, /*pshared=*/false);
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_civoid mutex_init_pshared(struct mutex *mtx)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	__mutex_init(mtx, /*pshared=*/true);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_civoid mutex_destroy(struct mutex *mtx)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	CHECK_ERR(pthread_mutex_destroy(&mtx->lock));
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_civoid mutex_lock(struct mutex *mtx)
5362306a36Sopenharmony_ci	NO_THREAD_SAFETY_ANALYSIS
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	CHECK_ERR(pthread_mutex_lock(&mtx->lock));
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_civoid mutex_unlock(struct mutex *mtx)
5962306a36Sopenharmony_ci	NO_THREAD_SAFETY_ANALYSIS
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	CHECK_ERR(pthread_mutex_unlock(&mtx->lock));
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cibool mutex_trylock(struct mutex *mtx)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	int ret = pthread_mutex_trylock(&mtx->lock);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	if (ret == 0)
6962306a36Sopenharmony_ci		return true; /* Lock acquired. */
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	if (ret == EBUSY)
7262306a36Sopenharmony_ci		return false; /* Lock busy. */
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	/* Print error. */
7562306a36Sopenharmony_ci	CHECK_ERR(ret);
7662306a36Sopenharmony_ci	return false;
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic void __cond_init(struct cond *cnd, bool pshared)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	pthread_condattr_t attr;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	CHECK_ERR(pthread_condattr_init(&attr));
8462306a36Sopenharmony_ci	if (pshared)
8562306a36Sopenharmony_ci		CHECK_ERR(pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED));
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	CHECK_ERR(pthread_cond_init(&cnd->cond, &attr));
8862306a36Sopenharmony_ci	CHECK_ERR(pthread_condattr_destroy(&attr));
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_civoid cond_init(struct cond *cnd)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	__cond_init(cnd, /*pshared=*/false);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_civoid cond_init_pshared(struct cond *cnd)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	__cond_init(cnd, /*pshared=*/true);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_civoid cond_destroy(struct cond *cnd)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	CHECK_ERR(pthread_cond_destroy(&cnd->cond));
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_civoid cond_wait(struct cond *cnd, struct mutex *mtx)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	CHECK_ERR(pthread_cond_wait(&cnd->cond, &mtx->lock));
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_civoid cond_signal(struct cond *cnd)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	CHECK_ERR(pthread_cond_signal(&cnd->cond));
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_civoid cond_broadcast(struct cond *cnd)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	CHECK_ERR(pthread_cond_broadcast(&cnd->cond));
11962306a36Sopenharmony_ci}
120