#include "osal_mutex.h"
#include <pthread.h>
#include <stdatomic.h>
#include "securec.h"
#include "hdf_core_log.h"
#include "osal_mem.h"

#define HDF_LOG_TAG osal_mutex
#define HDF_NANO_UNITS 1000000000
#define HDF_KILO_UNIT 1000
#define HDF_WAIT_FOREVER 0xFFFFFFFF

typedef struct {
    pthread_mutex_t mutex;
    atomic_int refCount;
} OsalMutexExt;

int32_t OsalMutexInit(struct OsalMutex *mutex)
{
    OsalMutexExt *ext = NULL;
    int32_t ret;

    if (mutex == NULL) {
        HDF_LOGE("%s invalid param", __func__);
        return HDF_ERR_INVALID_PARAM;
    }

    mutex->realMutex = NULL;

    ext = (OsalMutexExt *)OsalMemCalloc(sizeof(OsalMutexExt));
    if (ext == NULL) {
        HDF_LOGE("%s malloc fail", __func__);
        return HDF_ERR_MALLOC_FAIL;
    }

    ret = pthread_mutex_init(&ext->mutex, NULL);
    if (ret != 0) {
        HDF_LOGE("%s: failed to init pthread mutex %d", __func__, ret);
        OsalMemFree(ext);
        return HDF_FAILURE;
    }

    atomic_init(&ext->refCount, 0);
    mutex->realMutex = (void *)ext;

    return HDF_SUCCESS;
}

int32_t OsalMutexDestroy(struct OsalMutex *mutex)
{
    int32_t ret = 0;
    OsalMutexExt *ext = NULL;

    if (mutex == NULL || mutex->realMutex == NULL) {
        return HDF_ERR_INVALID_PARAM;
    }
    ext = (OsalMutexExt *)mutex->realMutex;

    ret = pthread_mutex_trylock(&ext->mutex);
    if (ret != 0) {
        HDF_LOGE("%s: mutex is locked by other thread", __func__);
        return HDF_ERR_IO;
    }
    
    if (atomic_load(&ext->refCount) != 0) {
        HDF_LOGE("%s: refCount is not zero (%d)", __func__, atomic_load(&ext->refCount));
        pthread_mutex_unlock(&ext->mutex); 
        return HDF_ERR_IO;
    }


    ret = pthread_mutex_destroy(&ext->mutex);
    if (ret != 0) {
        HDF_LOGE("%s: failed to destroy pthread mutex %d", __func__, ret);
    }

    OsalMemFree(ext);
    mutex->realMutex = NULL;

    return HDF_SUCCESS;
}


int32_t OsalMutexLock(struct OsalMutex *mutex)
{
    if (mutex == NULL || mutex->realMutex == NULL) {
        HDF_LOGE("%s invalid param", __func__);
        return HDF_ERR_INVALID_PARAM;
    }
    return OsalMutexTimedLock(mutex, HDF_WAIT_FOREVER);
}

int32_t OsalMutexTimedLock(struct OsalMutex *mutex, uint32_t ms)
{
    int32_t ret;
    OsalMutexExt *ext = NULL;

    if (mutex == NULL || mutex->realMutex == NULL) {
        HDF_LOGE("%s invalid param", __func__);
        return HDF_ERR_INVALID_PARAM;
    }
    ext = (OsalMutexExt *)mutex->realMutex;

    if (ms == HDF_WAIT_FOREVER) {
      
        ret = pthread_mutex_lock(&ext->mutex);
        if (ret != 0) {
            HDF_LOGE("pthread_mutex_lock fail %d", ret);
            return HDF_FAILURE;
        }
        atomic_fetch_add_explicit(&ext->refCount, 1, memory_order_release);
        return HDF_SUCCESS;
    } else {
        struct timespec time;
        (void)memset_s(&time, sizeof(time), 0, sizeof(time));
        clock_gettime(CLOCK_REALTIME, &time);
        time.tv_sec += (time_t)ms / HDF_KILO_UNIT;
        time.tv_nsec += (time_t)(ms % HDF_KILO_UNIT) * 1000 * 1000; 
        if (time.tv_nsec >= HDF_NANO_UNITS) {
            time.tv_nsec -= HDF_NANO_UNITS;
            time.tv_sec += 1;
        }

        ret = pthread_mutex_timedlock(&ext->mutex, &time);
        if (ret == 0) {
            atomic_fetch_add_explicit(&ext->refCount, 1, memory_order_release);
            return HDF_SUCCESS;
        } else if (ret == ETIMEDOUT) {
            HDF_LOGD("%s timed out, ms:%u", __func__, ms);
            return HDF_ERR_TIMEOUT;
        } else {
            HDF_LOGE("%s pthread_mutex_timedlock fail, ms:%u ret:%d", __func__, ms, ret);
            return HDF_FAILURE;
        }
    }
}

int32_t OsalMutexUnlock(struct OsalMutex *mutex)
{
    int32_t ret;
    OsalMutexExt *ext = NULL;

    if (mutex == NULL || mutex->realMutex == NULL) {
        HDF_LOGE("%s invalid param", __func__);
        return HDF_ERR_INVALID_PARAM;
    }
    ext = (OsalMutexExt *)mutex->realMutex;

    if (atomic_load_explicit(&ext->refCount, memory_order_acquire) <= 0) {
        HDF_LOGE("%s: unlock unlocked mutex (refCount=%d)", __func__, atomic_load(&ext->refCount));
        return HDF_ERR_INVALID_PARAM; 
    }
    ret = pthread_mutex_unlock(&ext->mutex);
    if (ret != 0) {
        HDF_LOGE("%s failed to pthread unlock %d", __func__, ret);
        return ret;
    }
    atomic_fetch_sub_explicit(&ext->refCount, 1, memory_order_release);
    return HDF_SUCCESS;
}
相关文件下载
osal_mutex_fixed.rar
3.32 KB
下载
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐