• 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 
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 
57 STATIC VOID CompletionSchedule(VOID)
58 {
59     LOS_MpSchedule(OS_MP_CPU_ALL);
60     LOS_Schedule();
61 }
62 
63 void linux_complete(struct completion *x)
64 {
65     UINT32 intSave;
66     LosTaskCB *resumedTask = NULL;
67 
68     if (x == NULL) {
69         PRINT_ERR("%s failed, input param is invalid\n", __FUNCTION__);
70         return;
71     }
72 
73     SCHEDULER_LOCK(intSave);
74     if (!LOS_ListEmpty(&x->comList)) {
75         resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(x->comList)));
76         OsTaskWakeClearPendMask(resumedTask);
77         OsSchedTaskWake(resumedTask);
78         SCHEDULER_UNLOCK(intSave);
79         CompletionSchedule();
80         return;
81     } else if (x->comCount != UINT_MAX) {
82         x->comCount++;
83     }
84     SCHEDULER_UNLOCK(intSave);
85     return;
86 }
87 
88 STATIC BOOL NoNeedWait(struct completion *x)
89 {
90     if (x->state == COMPLETION_ALL) {
91         return TRUE;
92     }
93     if (x->comCount > 0) {
94         x->comCount--;
95         return TRUE;
96     }
97     return FALSE;
98 }
99 
100 void linux_wait_for_completion(struct completion *x)
101 {
102     UINT32 intSave;
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 (OsCurrTaskGet()->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)OsSchedTaskWait(&x->comList, LOS_WAIT_FOREVER, TRUE);
130     SCHEDULER_UNLOCK(intSave);
131     return;
132 }
133 
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     LosTaskCB *runTask = NULL;
140 
141     if (x == NULL) {
142         PRINT_ERR("%s failed, input param is invalid\n", __FUNCTION__);
143         return timeout;
144     }
145 
146     if (OS_INT_ACTIVE) {
147         PRINT_ERR("Calling %s in interrupt callback is not allowed.\n", __FUNCTION__);
148         OsBackTrace();
149         return timeout;
150     }
151 
152     runTask = OsCurrTaskGet();
153     /* DO NOT Call blocking API in systems task */
154     if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
155         PRINTK("Warning: DO NOT call %s in system tasks.\n", __FUNCTION__);
156         OsBackTrace();
157         return timeout;
158     }
159 
160     SCHEDULER_LOCK(intSave);
161     lastTick = LOS_TickCountGet();
162 
163     if (NoNeedWait(x) == TRUE) {
164         SCHEDULER_UNLOCK(intSave);
165         return timeout ? timeout : 1;
166     }
167 
168     if (timeout == 0) {
169         SCHEDULER_UNLOCK(intSave);
170         return timeout;
171     }
172 
173     OsTaskWaitSetPendMask(OS_TASK_WAIT_COMPLETE, (UINTPTR)x, timeout);
174     ret = OsSchedTaskWait(&x->comList, timeout, TRUE);
175     if (ret == LOS_ERRNO_TSK_TIMEOUT) {
176         SCHEDULER_UNLOCK(intSave);
177         return 0;
178     }
179 
180     lastTick = LOS_TickCountGet() - lastTick;
181     SCHEDULER_UNLOCK(intSave);
182 
183     return (unsigned long)((timeout > lastTick) ? (timeout - lastTick) : 1);
184 }
185 
186 void linux_complete_all(struct completion *x)
187 {
188     UINT32 intSave;
189     LosTaskCB *resumedTask = NULL;
190 
191     if (x == NULL) {
192         PRINT_ERR("%s failed, input param is invalid\n", __FUNCTION__);
193         return;
194     }
195 
196     SCHEDULER_LOCK(intSave);
197 
198     x->state = COMPLETION_ALL;
199     if (LOS_ListEmpty(&x->comList)) {
200         SCHEDULER_UNLOCK(intSave);
201         return;
202     }
203 
204     while (!LOS_ListEmpty(&x->comList)) {
205         resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(x->comList)));
206         OsTaskWakeClearPendMask(resumedTask);
207         OsSchedTaskWake(resumedTask);
208     }
209     SCHEDULER_UNLOCK(intSave);
210     CompletionSchedule();
211 
212     return;
213 }
214 
215 int linux_completion_done(struct completion *x)
216 {
217     UINT32 intSave;
218     int isdone;
219 
220     SCHEDULER_LOCK(intSave);
221     isdone = (x->comCount != 0);
222     SCHEDULER_UNLOCK(intSave);
223     return (isdone);
224 }
225 
226