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