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