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_semaphore.h"
31 #include "os_util.h"
32 
33 
34 /**
35  * @brief Create and initialize a counting semaphore object
36  * @param[in] sem Pointer to the semaphore object
37  * @param[in] initCount The count value assigned to the semaphore when it is
38  *                      created.
39  * @param[in] maxCount The maximum count value that can be reached. When the
40  *                     semaphore reaches this value it can no longer be
41  *                     released.
42  * @retval OS_Status, OS_OK on success
43  */
OS_SemaphoreCreate(OS_Semaphore_t * sem,uint32_t initCount,uint32_t maxCount)44 OS_Status OS_SemaphoreCreate(OS_Semaphore_t *sem, uint32_t initCount, uint32_t maxCount)
45 {
46 //  OS_HANDLE_ASSERT(!OS_SemaphoreIsValid(sem), sem->handle);
47 
48     sem->handle = rt_sem_create("os_sem", initCount, RT_IPC_FLAG_PRIO);
49     OS_DBG("%s(), handle %p\n", __func__, sem->handle);
50 
51     if (sem->handle == NULL) {
52         OS_ERR("err %"OS_HANDLE_F"\n", sem->handle);
53         return OS_FAIL;
54     }
55 
56     return OS_OK;
57 }
58 
59 /**
60  * @brief Create and initialize a binary semaphore object
61  * @note A binary semaphore is equal to a counting semaphore created by calling
62          OS_SemaphoreCreate(sem, 0, 1).
63  * @param[in] sem Pointer to the semaphore object
64  * @retval OS_Status, OS_OK on success
65  */
OS_SemaphoreCreateBinary(OS_Semaphore_t * sem)66 OS_Status OS_SemaphoreCreateBinary(OS_Semaphore_t *sem)
67 {
68     OS_ERR("OS_SemaphoreCreateBinary() NOT SUPPORT!\n");
69 
70     return OS_SemaphoreCreate(sem, 0, 1);
71 }
72 
73 /**
74  * @brief Delete the semaphore object
75  * @param[in] sem Pointer to the semaphore object
76  * @retval OS_Status, OS_OK on success
77  */
OS_SemaphoreDelete(OS_Semaphore_t * sem)78 OS_Status OS_SemaphoreDelete(OS_Semaphore_t *sem)
79 {
80     rt_err_t ret;
81 
82     OS_HANDLE_ASSERT(OS_SemaphoreIsValid(sem), sem->handle);
83 
84     ret = rt_sem_delete(sem->handle);
85     if (ret != RT_EOK) {
86         OS_ERR("err %"OS_BASETYPE_F"\n", ret);
87         return OS_FAIL;
88     }
89     OS_SemaphoreSetInvalid(sem);
90     return OS_OK;
91 }
92 
93 /**
94  * @brief Wait until the semaphore object becomes available
95  * @param[in] sem Pointer to the semaphore object
96  * @param[in] waitMS The maximum amount of time (in millisecond) the thread
97  *                   should remain in the blocked state to wait for the
98  *                   semaphore to become available.
99  *                   OS_WAIT_FOREVER for waiting forever, zero for no waiting.
100  * @retval OS_Status, OS_OK on success
101  */
OS_SemaphoreWait(OS_Semaphore_t * sem,OS_Time_t waitMS)102 OS_Status OS_SemaphoreWait(OS_Semaphore_t *sem, OS_Time_t waitMS)
103 {
104     rt_err_t ret;
105 
106     OS_DBG("%s(), handle %p, wait %u ms\n", __func__, sem->handle, (unsigned int)waitMS);
107     OS_HANDLE_ASSERT(OS_SemaphoreIsValid(sem), sem->handle);
108 
109     ret = rt_sem_take(sem->handle, OS_CalcWaitTicks(waitMS));
110     if (ret != RT_EOK) {
111         OS_DBG("%s() fail @ %d, %"OS_TIME_F" ms\n", __func__, __LINE__, (unsigned int)waitMS);
112         return OS_E_TIMEOUT;
113     }
114 
115     return OS_OK;
116 }
117 
118 /**
119  * @brief Release the semaphore object
120  * @param[in] sem Pointer to the semaphore object
121  * @retval OS_Status, OS_OK on success
122  */
OS_SemaphoreRelease(OS_Semaphore_t * sem)123 OS_Status OS_SemaphoreRelease(OS_Semaphore_t *sem)
124 {
125     rt_err_t ret;
126 
127     OS_HANDLE_ASSERT(OS_SemaphoreIsValid(sem), sem->handle);
128 
129     ret = rt_sem_release(sem->handle);
130     if (ret != RT_EOK) {
131         OS_DBG("%s() fail @ %d\n", __func__, __LINE__);
132         return OS_FAIL;
133     }
134 
135     return OS_OK;
136 }
137 
138 /**
139  * @brief Release the semaphore object
140  * @param[in] sem Pointer to the semaphore object
141  * @retval OS_Status, OS_OK on success
142  */
OS_SemaphoreReset(OS_Semaphore_t * sem)143 OS_Status OS_SemaphoreReset(OS_Semaphore_t *sem)
144 {
145     rt_err_t ret;
146 
147     OS_HANDLE_ASSERT(OS_SemaphoreIsValid(sem), sem->handle);
148 
149     ret = rt_sem_control(sem->handle, RT_IPC_CMD_RESET, NULL);
150     if (ret != RT_EOK) {
151         OS_DBG("%s() fail @ %d\n", __func__, __LINE__);
152         return OS_FAIL;
153     }
154 
155     return OS_OK;
156 }
157