1 /*
2  * Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the
12  *       distribution.
13  *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
14  *       its contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "os_mutex.h"
31 #include "os_util.h"
32 
33 
34 /**
35  * @brief Create and initialize a mutex object
36  * @note A mutex can only be locked by a single thread at any given time.
37  * @param[in] mutex Pointer to the mutex object
38  * @retval OS_Status, OS_OK on success
39  */
OS_MutexCreate(OS_Mutex_t * mutex)40 OS_Status OS_MutexCreate(OS_Mutex_t *mutex)
41 {
42     OS_HANDLE_ASSERT(!OS_MutexIsValid(mutex), mutex->handle);
43 
44     mutex->handle = rt_mutex_create("os_mtx", RT_IPC_FLAG_PRIO);
45     OS_DBG("%s(), handle %p\n", __func__, mutex->handle);
46 
47     if (mutex->handle == NULL) {
48         OS_ERR("err %"OS_HANDLE_F"\n", mutex->handle);
49         return OS_FAIL;
50     }
51 
52     return OS_OK;
53 }
54 
55 /**
56  * @brief Delete the mutex object
57  * @param[in] mutex Pointer to the mutex object
58  * @retval OS_Status, OS_OK on success
59  */
OS_MutexDelete(OS_Mutex_t * mutex)60 OS_Status OS_MutexDelete(OS_Mutex_t *mutex)
61 {
62     rt_err_t ret;
63 
64     OS_HANDLE_ASSERT(OS_MutexIsValid(mutex), mutex->handle);
65 
66     ret = rt_mutex_delete(mutex->handle);
67     if (ret != RT_EOK) {
68         OS_ERR("err %"OS_BASETYPE_F"\n", ret);
69         return OS_FAIL;
70     }
71     OS_MutexSetInvalid(mutex);
72     return OS_OK;
73 }
74 
75 /**
76  * @brief Lock the mutex object
77  * @note A mutex can only be locked by a single thread at any given time. If
78  *       the mutex is already locked, the caller will be blocked for the
79  *       specified time duration.
80  * @param[in] mutex Pointer to the mutex object
81  * @param[in] waitMS The maximum amount of time (in millisecond) the thread
82  *                   should remain in the blocked state to wait for the mutex
83  *                   to become unlocked.
84  *                   OS_WAIT_FOREVER for waiting forever, zero for no waiting.
85  * @retval OS_Status, OS_OK on success
86  */
OS_MutexLock(OS_Mutex_t * mutex,OS_Time_t waitMS)87 OS_Status OS_MutexLock(OS_Mutex_t *mutex, OS_Time_t waitMS)
88 {
89     rt_err_t ret;
90 
91     OS_HANDLE_ASSERT(OS_MutexIsValid(mutex), mutex->handle);
92 
93     ret = rt_mutex_take(mutex->handle, OS_CalcWaitTicks(waitMS));
94     if (ret != RT_EOK) {
95         OS_DBG("%s() fail @ %d, %"OS_TIME_F" ms\n", __func__, __LINE__, (unsigned int)waitMS);
96         return OS_FAIL;
97     }
98 
99     return OS_OK;
100 }
101 
102 /**
103  * @brief Unlock the mutex object previously locked using OS_MutexLock()
104  * @note The mutex should be unlocked from the same thread context from which
105  *       it was locked.
106  * @param[in] mutex Pointer to the mutex object
107  * @retval OS_Status, OS_OK on success
108  */
OS_MutexUnlock(OS_Mutex_t * mutex)109 OS_Status OS_MutexUnlock(OS_Mutex_t *mutex)
110 {
111     rt_err_t ret;
112 
113     OS_HANDLE_ASSERT(OS_MutexIsValid(mutex), mutex->handle);
114 
115     ret = rt_mutex_release(mutex->handle);
116     if (ret != RT_EOK) {
117         OS_DBG("%s() fail @ %d\n", __func__, __LINE__);
118         return OS_FAIL;
119     }
120 
121     return OS_OK;
122 }
123