1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: wait
15 *
16 * Create: 2021-12-16
17 */
18
19 #include <los_event.h>
20 #include <los_spinlock.h>
21 #include <los_memory.h>
22 #include <linux/wait.h>
23
24 #include "soc_osal.h"
25 #include "osal_errno.h"
26 #include "osal_inner.h"
27
osal_wait_init(osal_wait * wait)28 int osal_wait_init(osal_wait *wait)
29 {
30 if (wait == NULL || wait->wait != NULL) {
31 osal_log("parameter invalid!\n");
32 return OSAL_FAILURE;
33 }
34 wait_queue_head_t *wq =
35 (wait_queue_head_t *)LOS_MemAlloc((void *)m_aucSysMem0, sizeof(wait_queue_head_t));
36 if (wq == NULL) {
37 osal_log("LOS_MemAlloc failed!\n");
38 return OSAL_FAILURE;
39 }
40
41 unsigned int ret = LOS_EventInit(&wq->stEvent);
42 if (ret != LOS_OK) {
43 osal_log("LOS_EventInit failed! ret = %#x.\n", ret);
44 LOS_MemFree((void*)m_aucSysMem0, (void *)wq);
45 return OSAL_FAILURE;
46 }
47 LOS_SpinInit(&wq->lock);
48 LOS_ListInit(&wq->poll_queue);
49 wait->wait = wq;
50 return OSAL_SUCCESS;
51 }
52
osal_wait_interruptible(osal_wait * wait,osal_wait_condition_func func,const void * param)53 int osal_wait_interruptible(osal_wait *wait, osal_wait_condition_func func, const void *param)
54 {
55 // not support interruptible wait in liteos
56 return osal_wait_uninterruptible(wait, func, param);
57 }
58
osal_wait_uninterruptible(osal_wait * wait,osal_wait_condition_func func,const void * param)59 int osal_wait_uninterruptible(osal_wait *wait, osal_wait_condition_func func, const void *param)
60 {
61 if (wait == NULL || wait->wait == NULL) {
62 osal_log("parameter invalid!\n");
63 return OSAL_FAILURE;
64 }
65 wait_queue_head_t *wq = (wait_queue_head_t *)(wait->wait);
66
67 while (func != NULL && func(param) == 0) {
68 (VOID)LOS_EventRead(&wq->stEvent, 0x1U, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
69 }
70
71 return OSAL_SUCCESS;
72 }
73
74 /**
75 * @par Description: same as <wait_event_interruptible_timeout> from liteos
76 * This API is used to sleep a process until the condition evaluates to true or a timeout elapses.
77 * The condition is checked each time when the waitqueue wait is woken up.
78 * @attention
79 * The value range of parameter timeout is [0, 0xFFFFFFFF], and 0xFFFFFFFF means waiting forever.</li>
80 * @param wait [IN] the waitqueue to wait on.
81 * @param condition [IN] a condition evaluates to true or false.
82 * @param timeout [IN] the max sleep time unit is ms.
83 *
84 * @retval #0 return 0 if the condition evaluated to false after the timeout elapsed
85 * @retval #1 return 1 if the condition evaluated to true after the timeout elapsed
86 * @retval #others return the remaining ticks if the condition evaluated to true before the timeout elapsed
87 */
osal_wait_timeout_interruptible(osal_wait * wait,osal_wait_condition_func func,const void * param,unsigned long ms)88 int osal_wait_timeout_interruptible(osal_wait *wait, osal_wait_condition_func func, const void *param, unsigned long ms)
89 {
90 if (wait == NULL || wait->wait == NULL) {
91 osal_log("parameter invalid!\n");
92 return OSAL_FAILURE;
93 }
94 wait_queue_head_t *wq = (wait_queue_head_t *)(wait->wait);
95
96 unsigned long long ticksnow = LOS_TickCountGet();
97 unsigned int timetick = LOS_MS2Tick(ms);
98 if (timetick > INT32_MAX) {
99 osal_log("ms parameter invalid!\n");
100 return OSAL_FAILURE;
101 }
102 int timeout = (int)timetick;
103 int tmp_timeout = timeout;
104 int ret = timeout;
105 if (func == NULL) {
106 return ret; /* default return timeout if condition func NULL */
107 }
108 if (ms == 0 && func(param)) {
109 return 1;
110 }
111 while (!func(param)) {
112 unsigned int event_ret = LOS_EventRead(&wq->stEvent, 0x1U, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, (tmp_timeout));
113 if (ms == OSAL_WAIT_FOREVER) {
114 if (!func(param)) {
115 continue;
116 }
117 break;
118 }
119
120 tmp_timeout = (int)(timeout - (unsigned int)(LOS_TickCountGet() - ticksnow));
121 if (tmp_timeout <= 0 || event_ret == LOS_ERRNO_EVENT_READ_TIMEOUT) {
122 ret = (func(param) == FALSE) ? FALSE : TRUE;
123 break;
124 }
125 if (func(param) != 0) {
126 ret = tmp_timeout;
127 break;
128 }
129 }
130
131 return ret;
132 }
133
134
osal_wait_timeout_uninterruptible(osal_wait * wait,osal_wait_condition_func func,const void * param,unsigned long ms)135 int osal_wait_timeout_uninterruptible(osal_wait *wait, osal_wait_condition_func func, const void *param,
136 unsigned long ms)
137 {
138 return osal_wait_timeout_interruptible(wait, func, param, ms);
139 }
140
osal_wait_wakeup(osal_wait * wait)141 void osal_wait_wakeup(osal_wait *wait)
142 {
143 if (wait == NULL || wait->wait == NULL) {
144 osal_log("parameter invalid!\n");
145 return;
146 }
147
148 wait_queue_head_t *wq = (wait_queue_head_t *)(wait->wait);
149 (VOID)LOS_EventWrite(&wq->stEvent, 0x1);
150 }
151
osal_wait_wakeup_interruptible(osal_wait * wait)152 void osal_wait_wakeup_interruptible(osal_wait *wait)
153 {
154 osal_wait_wakeup(wait);
155 }
156
osal_wait_destroy(osal_wait * wait)157 void osal_wait_destroy(osal_wait *wait)
158 {
159 if (wait == NULL || wait->wait == NULL) {
160 osal_log("parameter invalid!\n");
161 return;
162 }
163
164 wait_queue_head_t *wq = (wait_queue_head_t *)(wait->wait);
165
166 LOS_EventDestroy(&wq->stEvent);
167 LOS_ListDelInit(&wq->poll_queue);
168 LOS_MemFree((void *)m_aucSysMem0, (void *)wq);
169 wait->wait = NULL;
170 }
171