• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "linux/completion.h"
33 #include "limits.h"
34 #include "los_task_pri.h"
35 #include "los_sched_pri.h"
36 #include "los_mp.h"
37 #include "los_exc.h"
38 
39 
linux_init_completion(struct completion * x)40 void linux_init_completion(struct completion *x)
41 {
42     UINT32 intSave;
43 
44     if (x == NULL) {
45         PRINT_ERR("%s failed, input param is invalid\n", __FUNCTION__);
46         return;
47     }
48 
49     SCHEDULER_LOCK(intSave);
50     LOS_ListInit(&x->comList);
51     x->comCount = 0;
52     x->state = COMPLETION_ONE;
53     SCHEDULER_UNLOCK(intSave);
54     return;
55 }
56 
CompletionSchedule(VOID)57 STATIC VOID CompletionSchedule(VOID)
58 {
59     LOS_MpSchedule(OS_MP_CPU_ALL);
60     LOS_Schedule();
61 }
62 
linux_complete(struct completion * x)63 void linux_complete(struct completion *x)
64 {
65     UINT32 intSave;
66 
67     if (x == NULL) {
68         PRINT_ERR("%s failed, input param is invalid\n", __FUNCTION__);
69         return;
70     }
71 
72     SCHEDULER_LOCK(intSave);
73     if (!LOS_ListEmpty(&x->comList)) {
74         LosTaskCB *resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(x->comList)));
75         OsTaskWakeClearPendMask(resumedTask);
76         resumedTask->ops->wake(resumedTask);
77         SCHEDULER_UNLOCK(intSave);
78         CompletionSchedule();
79         return;
80     } else if (x->comCount != UINT_MAX) {
81         x->comCount++;
82     }
83     SCHEDULER_UNLOCK(intSave);
84     return;
85 }
86 
NoNeedWait(struct completion * x)87 STATIC BOOL NoNeedWait(struct completion *x)
88 {
89     if (x->state == COMPLETION_ALL) {
90         return TRUE;
91     }
92     if (x->comCount > 0) {
93         x->comCount--;
94         return TRUE;
95     }
96     return FALSE;
97 }
98 
linux_wait_for_completion(struct completion * x)99 void linux_wait_for_completion(struct completion *x)
100 {
101     UINT32 intSave;
102     LosTaskCB *runTask = OsCurrTaskGet();
103 
104     if (x == NULL) {
105         PRINT_ERR("%s failed, input param is invalid\n", __FUNCTION__);
106         return;
107     }
108 
109     if (OS_INT_ACTIVE) {
110         PRINT_ERR("Calling %s in interrupt callback is not allowed.\n", __FUNCTION__);
111         OsBackTrace();
112         return;
113     }
114 
115     /* DO NOT Call blocking API in system tasks */
116     if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
117         PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
118         OsBackTrace();
119         return;
120     }
121 
122     SCHEDULER_LOCK(intSave);
123     if (NoNeedWait(x) == TRUE) {
124         SCHEDULER_UNLOCK(intSave);
125         return;
126     }
127 
128     OsTaskWaitSetPendMask(OS_TASK_WAIT_COMPLETE, (UINTPTR)x, LOS_WAIT_FOREVER);
129     (void)runTask->ops->wait(runTask, &x->comList, LOS_WAIT_FOREVER);
130     SCHEDULER_UNLOCK(intSave);
131     return;
132 }
133 
linux_wait_for_completion_timeout(struct completion * x,unsigned long timeout)134 unsigned long linux_wait_for_completion_timeout(struct completion *x, unsigned long timeout)
135 {
136     UINT32 ret;
137     UINT32 intSave;
138     UINT64 lastTick;
139 
140     if (x == NULL) {
141         PRINT_ERR("%s failed, input param is invalid\n", __FUNCTION__);
142         return timeout;
143     }
144 
145     if (OS_INT_ACTIVE) {
146         PRINT_ERR("Calling %s in interrupt callback is not allowed.\n", __FUNCTION__);
147         OsBackTrace();
148         return timeout;
149     }
150 
151     LosTaskCB *runTask = OsCurrTaskGet();
152     /* DO NOT Call blocking API in systems task */
153     if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
154         PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
155         OsBackTrace();
156         return timeout;
157     }
158 
159     SCHEDULER_LOCK(intSave);
160     lastTick = LOS_TickCountGet();
161 
162     if (NoNeedWait(x) == TRUE) {
163         SCHEDULER_UNLOCK(intSave);
164         return timeout ? timeout : 1;
165     }
166 
167     if (timeout == 0) {
168         SCHEDULER_UNLOCK(intSave);
169         return timeout;
170     }
171 
172     OsTaskWaitSetPendMask(OS_TASK_WAIT_COMPLETE, (UINTPTR)x, timeout);
173     ret = runTask->ops->wait(runTask, &x->comList, timeout);
174     if (ret == LOS_ERRNO_TSK_TIMEOUT) {
175         SCHEDULER_UNLOCK(intSave);
176         return 0;
177     }
178 
179     lastTick = LOS_TickCountGet() - lastTick;
180     SCHEDULER_UNLOCK(intSave);
181 
182     return (unsigned long)((timeout > lastTick) ? (timeout - lastTick) : 1);
183 }
184 
linux_complete_all(struct completion * x)185 void linux_complete_all(struct completion *x)
186 {
187     UINT32 intSave;
188 
189     if (x == NULL) {
190         PRINT_ERR("%s failed, input param is invalid\n", __FUNCTION__);
191         return;
192     }
193 
194     SCHEDULER_LOCK(intSave);
195 
196     x->state = COMPLETION_ALL;
197     if (LOS_ListEmpty(&x->comList)) {
198         SCHEDULER_UNLOCK(intSave);
199         return;
200     }
201 
202     while (!LOS_ListEmpty(&x->comList)) {
203         LosTaskCB *resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(x->comList)));
204         OsTaskWakeClearPendMask(resumedTask);
205         resumedTask->ops->wake(resumedTask);
206     }
207     SCHEDULER_UNLOCK(intSave);
208     CompletionSchedule();
209 
210     return;
211 }
212 
linux_completion_done(struct completion * x)213 int linux_completion_done(struct completion *x)
214 {
215     UINT32 intSave;
216     int isdone;
217 
218     SCHEDULER_LOCK(intSave);
219     isdone = (x->comCount != 0);
220     SCHEDULER_UNLOCK(intSave);
221     return (isdone);
222 }
223 
224