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 40void 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 57STATIC VOID CompletionSchedule(VOID) 58{ 59 LOS_MpSchedule(OS_MP_CPU_ALL); 60 LOS_Schedule(); 61} 62 63void 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 87STATIC 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 99void 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 134unsigned 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 185void 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 213int 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