13d8536b4Sopenharmony_ci/* 23d8536b4Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 33d8536b4Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. 43d8536b4Sopenharmony_ci * 53d8536b4Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 63d8536b4Sopenharmony_ci * are permitted provided that the following conditions are met: 73d8536b4Sopenharmony_ci * 83d8536b4Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 93d8536b4Sopenharmony_ci * conditions and the following disclaimer. 103d8536b4Sopenharmony_ci * 113d8536b4Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 123d8536b4Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 133d8536b4Sopenharmony_ci * provided with the distribution. 143d8536b4Sopenharmony_ci * 153d8536b4Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 163d8536b4Sopenharmony_ci * to endorse or promote products derived from this software without specific prior written 173d8536b4Sopenharmony_ci * permission. 183d8536b4Sopenharmony_ci * 193d8536b4Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 203d8536b4Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 213d8536b4Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 223d8536b4Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 233d8536b4Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 243d8536b4Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 253d8536b4Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 263d8536b4Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 273d8536b4Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 283d8536b4Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 293d8536b4Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 303d8536b4Sopenharmony_ci */ 313d8536b4Sopenharmony_ci 323d8536b4Sopenharmony_ci#include <errno.h> 333d8536b4Sopenharmony_ci#include <pthread.h> 343d8536b4Sopenharmony_ci#include <stdlib.h> 353d8536b4Sopenharmony_ci#include <unistd.h> 363d8536b4Sopenharmony_ci#include <securec.h> 373d8536b4Sopenharmony_ci#include "los_config.h" 383d8536b4Sopenharmony_ci#include "los_task.h" 393d8536b4Sopenharmony_ci#include "los_swtmr.h" 403d8536b4Sopenharmony_ci#include "time_internal.h" 413d8536b4Sopenharmony_ci#include "los_atomic.h" 423d8536b4Sopenharmony_ci#include "los_event.h" 433d8536b4Sopenharmony_ci#include "los_mux.h" 443d8536b4Sopenharmony_ci 453d8536b4Sopenharmony_ci#define INLINE inline 463d8536b4Sopenharmony_ci 473d8536b4Sopenharmony_ci#define BROADCAST_EVENT 1 483d8536b4Sopenharmony_ci#define COND_COUNTER_STEP 0x0004U 493d8536b4Sopenharmony_ci#define COND_FLAGS_MASK 0x0003U 503d8536b4Sopenharmony_ci#define COND_COUNTER_MASK (~COND_FLAGS_MASK) 513d8536b4Sopenharmony_ci 523d8536b4Sopenharmony_ciint pthread_condattr_getpshared(const pthread_condattr_t *attr, int *shared) 533d8536b4Sopenharmony_ci{ 543d8536b4Sopenharmony_ci if ((attr == NULL) || (shared == NULL)) { 553d8536b4Sopenharmony_ci return EINVAL; 563d8536b4Sopenharmony_ci } 573d8536b4Sopenharmony_ci 583d8536b4Sopenharmony_ci *shared = PTHREAD_PROCESS_PRIVATE; 593d8536b4Sopenharmony_ci 603d8536b4Sopenharmony_ci return 0; 613d8536b4Sopenharmony_ci} 623d8536b4Sopenharmony_ci 633d8536b4Sopenharmony_ciint pthread_condattr_setpshared(pthread_condattr_t *attr, int shared) 643d8536b4Sopenharmony_ci{ 653d8536b4Sopenharmony_ci (VOID)attr; 663d8536b4Sopenharmony_ci if ((shared != PTHREAD_PROCESS_PRIVATE) && (shared != PTHREAD_PROCESS_SHARED)) { 673d8536b4Sopenharmony_ci return EINVAL; 683d8536b4Sopenharmony_ci } 693d8536b4Sopenharmony_ci 703d8536b4Sopenharmony_ci if (shared != PTHREAD_PROCESS_PRIVATE) { 713d8536b4Sopenharmony_ci return ENOSYS; 723d8536b4Sopenharmony_ci } 733d8536b4Sopenharmony_ci 743d8536b4Sopenharmony_ci return 0; 753d8536b4Sopenharmony_ci} 763d8536b4Sopenharmony_ci 773d8536b4Sopenharmony_ciint pthread_condattr_destroy(pthread_condattr_t *attr) 783d8536b4Sopenharmony_ci{ 793d8536b4Sopenharmony_ci if (attr == NULL) { 803d8536b4Sopenharmony_ci return EINVAL; 813d8536b4Sopenharmony_ci } 823d8536b4Sopenharmony_ci 833d8536b4Sopenharmony_ci (VOID)memset_s(attr, sizeof(pthread_condattr_t), 0, sizeof(pthread_condattr_t)); 843d8536b4Sopenharmony_ci attr->clock = INT32_MAX; 853d8536b4Sopenharmony_ci 863d8536b4Sopenharmony_ci return 0; 873d8536b4Sopenharmony_ci} 883d8536b4Sopenharmony_ci 893d8536b4Sopenharmony_ciint pthread_condattr_getclock(const pthread_condattr_t *attr, clockid_t *clock) 903d8536b4Sopenharmony_ci{ 913d8536b4Sopenharmony_ci if ((attr == NULL) || (clock == NULL)) { 923d8536b4Sopenharmony_ci return -1; 933d8536b4Sopenharmony_ci } 943d8536b4Sopenharmony_ci 953d8536b4Sopenharmony_ci *clock = attr->clock; 963d8536b4Sopenharmony_ci 973d8536b4Sopenharmony_ci return 0; 983d8536b4Sopenharmony_ci} 993d8536b4Sopenharmony_ci 1003d8536b4Sopenharmony_ciint pthread_condattr_init(pthread_condattr_t *attr) 1013d8536b4Sopenharmony_ci{ 1023d8536b4Sopenharmony_ci if (attr == NULL) { 1033d8536b4Sopenharmony_ci return EINVAL; 1043d8536b4Sopenharmony_ci } 1053d8536b4Sopenharmony_ci 1063d8536b4Sopenharmony_ci attr->clock = CLOCK_REALTIME; 1073d8536b4Sopenharmony_ci 1083d8536b4Sopenharmony_ci return 0; 1093d8536b4Sopenharmony_ci} 1103d8536b4Sopenharmony_ci 1113d8536b4Sopenharmony_ciint pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clk) 1123d8536b4Sopenharmony_ci{ 1133d8536b4Sopenharmony_ci if ((attr == NULL) || (clk < 0)) { 1143d8536b4Sopenharmony_ci return EINVAL; 1153d8536b4Sopenharmony_ci } 1163d8536b4Sopenharmony_ci 1173d8536b4Sopenharmony_ci if ((clk != CLOCK_REALTIME) && (clk != CLOCK_MONOTONIC) && 1183d8536b4Sopenharmony_ci (clk != CLOCK_PROCESS_CPUTIME_ID) && (clk != CLOCK_THREAD_CPUTIME_ID)) { 1193d8536b4Sopenharmony_ci return EINVAL; 1203d8536b4Sopenharmony_ci } 1213d8536b4Sopenharmony_ci 1223d8536b4Sopenharmony_ci attr->clock = clk; 1233d8536b4Sopenharmony_ci 1243d8536b4Sopenharmony_ci return 0; 1253d8536b4Sopenharmony_ci} 1263d8536b4Sopenharmony_ci 1273d8536b4Sopenharmony_ciSTATIC INLINE INT32 CondInitCheck(const pthread_cond_t *cond) 1283d8536b4Sopenharmony_ci{ 1293d8536b4Sopenharmony_ci if ((cond->event.stEventList.pstPrev == NULL) && 1303d8536b4Sopenharmony_ci (cond->event.stEventList.pstNext == NULL)) { 1313d8536b4Sopenharmony_ci return 1; 1323d8536b4Sopenharmony_ci } 1333d8536b4Sopenharmony_ci 1343d8536b4Sopenharmony_ci return 0; 1353d8536b4Sopenharmony_ci} 1363d8536b4Sopenharmony_ci 1373d8536b4Sopenharmony_ciint pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) 1383d8536b4Sopenharmony_ci{ 1393d8536b4Sopenharmony_ci int ret = 0; 1403d8536b4Sopenharmony_ci pthread_condattr_t condAttr; 1413d8536b4Sopenharmony_ci 1423d8536b4Sopenharmony_ci if (cond == NULL) { 1433d8536b4Sopenharmony_ci return EINVAL; 1443d8536b4Sopenharmony_ci } 1453d8536b4Sopenharmony_ci 1463d8536b4Sopenharmony_ci if (attr == NULL) { 1473d8536b4Sopenharmony_ci pthread_condattr_init(&condAttr); 1483d8536b4Sopenharmony_ci attr = &condAttr; 1493d8536b4Sopenharmony_ci } 1503d8536b4Sopenharmony_ci 1513d8536b4Sopenharmony_ci (VOID)LOS_EventInit(&(cond->event)); 1523d8536b4Sopenharmony_ci 1533d8536b4Sopenharmony_ci cond->mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); 1543d8536b4Sopenharmony_ci if (cond->mutex == NULL) { 1553d8536b4Sopenharmony_ci return ENOMEM; 1563d8536b4Sopenharmony_ci } 1573d8536b4Sopenharmony_ci 1583d8536b4Sopenharmony_ci (VOID)pthread_mutex_init(cond->mutex, NULL); 1593d8536b4Sopenharmony_ci 1603d8536b4Sopenharmony_ci cond->value = 0; 1613d8536b4Sopenharmony_ci (VOID)pthread_mutex_lock(cond->mutex); 1623d8536b4Sopenharmony_ci cond->count = 0; 1633d8536b4Sopenharmony_ci cond->clock = attr->clock; 1643d8536b4Sopenharmony_ci (VOID)pthread_mutex_unlock(cond->mutex); 1653d8536b4Sopenharmony_ci 1663d8536b4Sopenharmony_ci return ret; 1673d8536b4Sopenharmony_ci} 1683d8536b4Sopenharmony_ci 1693d8536b4Sopenharmony_ciint pthread_cond_destroy(pthread_cond_t *cond) 1703d8536b4Sopenharmony_ci{ 1713d8536b4Sopenharmony_ci if (cond == NULL) { 1723d8536b4Sopenharmony_ci return EINVAL; 1733d8536b4Sopenharmony_ci } 1743d8536b4Sopenharmony_ci 1753d8536b4Sopenharmony_ci if (CondInitCheck(cond)) { 1763d8536b4Sopenharmony_ci return 0; 1773d8536b4Sopenharmony_ci } 1783d8536b4Sopenharmony_ci 1793d8536b4Sopenharmony_ci if (LOS_EventDestroy(&cond->event) != LOS_OK) { 1803d8536b4Sopenharmony_ci return EBUSY; 1813d8536b4Sopenharmony_ci } 1823d8536b4Sopenharmony_ci if (pthread_mutex_destroy(cond->mutex) != 0) { 1833d8536b4Sopenharmony_ci PRINT_ERR("%s mutex destroy fail!\n", __FUNCTION__); 1843d8536b4Sopenharmony_ci return EINVAL; 1853d8536b4Sopenharmony_ci } 1863d8536b4Sopenharmony_ci free(cond->mutex); 1873d8536b4Sopenharmony_ci cond->mutex = NULL; 1883d8536b4Sopenharmony_ci 1893d8536b4Sopenharmony_ci return 0; 1903d8536b4Sopenharmony_ci} 1913d8536b4Sopenharmony_ci 1923d8536b4Sopenharmony_ciSTATIC VOID PthreadCountSub(pthread_cond_t *cond) 1933d8536b4Sopenharmony_ci{ 1943d8536b4Sopenharmony_ci (VOID)pthread_mutex_lock(cond->mutex); 1953d8536b4Sopenharmony_ci if (cond->count > 0) { 1963d8536b4Sopenharmony_ci cond->count--; 1973d8536b4Sopenharmony_ci } 1983d8536b4Sopenharmony_ci (VOID)pthread_mutex_unlock(cond->mutex); 1993d8536b4Sopenharmony_ci} 2003d8536b4Sopenharmony_ci 2013d8536b4Sopenharmony_ci 2023d8536b4Sopenharmony_ciint pthread_cond_broadcast(pthread_cond_t *cond) 2033d8536b4Sopenharmony_ci{ 2043d8536b4Sopenharmony_ci int ret = 0; 2053d8536b4Sopenharmony_ci 2063d8536b4Sopenharmony_ci if (cond == NULL) { 2073d8536b4Sopenharmony_ci return EINVAL; 2083d8536b4Sopenharmony_ci } 2093d8536b4Sopenharmony_ci 2103d8536b4Sopenharmony_ci (VOID)pthread_mutex_lock(cond->mutex); 2113d8536b4Sopenharmony_ci if (cond->count > 0) { 2123d8536b4Sopenharmony_ci cond->count = 0; 2133d8536b4Sopenharmony_ci (VOID)pthread_mutex_unlock(cond->mutex); 2143d8536b4Sopenharmony_ci (VOID)LOS_EventWrite(&(cond->event), BROADCAST_EVENT); 2153d8536b4Sopenharmony_ci return ret; 2163d8536b4Sopenharmony_ci } 2173d8536b4Sopenharmony_ci (VOID)pthread_mutex_unlock(cond->mutex); 2183d8536b4Sopenharmony_ci 2193d8536b4Sopenharmony_ci return ret; 2203d8536b4Sopenharmony_ci} 2213d8536b4Sopenharmony_ci 2223d8536b4Sopenharmony_ciint pthread_cond_signal(pthread_cond_t *cond) 2233d8536b4Sopenharmony_ci{ 2243d8536b4Sopenharmony_ci int ret = 0; 2253d8536b4Sopenharmony_ci 2263d8536b4Sopenharmony_ci if (cond == NULL) { 2273d8536b4Sopenharmony_ci return EINVAL; 2283d8536b4Sopenharmony_ci } 2293d8536b4Sopenharmony_ci 2303d8536b4Sopenharmony_ci (VOID)pthread_mutex_lock(cond->mutex); 2313d8536b4Sopenharmony_ci if (cond->count > 0) { 2323d8536b4Sopenharmony_ci cond->count--; 2333d8536b4Sopenharmony_ci (VOID)pthread_mutex_unlock(cond->mutex); 2343d8536b4Sopenharmony_ci // This should modify to once. 2353d8536b4Sopenharmony_ci (VOID)LOS_EventWrite(&(cond->event), BROADCAST_EVENT); 2363d8536b4Sopenharmony_ci 2373d8536b4Sopenharmony_ci return ret; 2383d8536b4Sopenharmony_ci } 2393d8536b4Sopenharmony_ci (VOID)pthread_mutex_unlock(cond->mutex); 2403d8536b4Sopenharmony_ci 2413d8536b4Sopenharmony_ci return ret; 2423d8536b4Sopenharmony_ci} 2433d8536b4Sopenharmony_ci 2443d8536b4Sopenharmony_ciSTATIC INT32 ProcessReturnVal(pthread_cond_t *cond, INT32 val) 2453d8536b4Sopenharmony_ci{ 2463d8536b4Sopenharmony_ci INT32 ret; 2473d8536b4Sopenharmony_ci switch (val) { 2483d8536b4Sopenharmony_ci /* 0: event does not occur */ 2493d8536b4Sopenharmony_ci case 0: 2503d8536b4Sopenharmony_ci case BROADCAST_EVENT: 2513d8536b4Sopenharmony_ci ret = 0; 2523d8536b4Sopenharmony_ci break; 2533d8536b4Sopenharmony_ci case LOS_ERRNO_EVENT_READ_TIMEOUT: 2543d8536b4Sopenharmony_ci PthreadCountSub(cond); 2553d8536b4Sopenharmony_ci ret = ETIMEDOUT; 2563d8536b4Sopenharmony_ci break; 2573d8536b4Sopenharmony_ci default: 2583d8536b4Sopenharmony_ci PthreadCountSub(cond); 2593d8536b4Sopenharmony_ci ret = EINVAL; 2603d8536b4Sopenharmony_ci break; 2613d8536b4Sopenharmony_ci } 2623d8536b4Sopenharmony_ci 2633d8536b4Sopenharmony_ci return ret; 2643d8536b4Sopenharmony_ci} 2653d8536b4Sopenharmony_ci 2663d8536b4Sopenharmony_ciint pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, 2673d8536b4Sopenharmony_ci const struct timespec *ts) 2683d8536b4Sopenharmony_ci{ 2693d8536b4Sopenharmony_ci INT32 ret; 2703d8536b4Sopenharmony_ci UINT64 absTicks; 2713d8536b4Sopenharmony_ci LosMuxCB *muxPosted = NULL; 2723d8536b4Sopenharmony_ci pthread_testcancel(); 2733d8536b4Sopenharmony_ci if ((cond == NULL) || (mutex == NULL) || (ts == NULL) || (mutex->magic != _MUX_MAGIC)) { 2743d8536b4Sopenharmony_ci return EINVAL; 2753d8536b4Sopenharmony_ci } 2763d8536b4Sopenharmony_ci 2773d8536b4Sopenharmony_ci muxPosted = GET_MUX(mutex->handle); 2783d8536b4Sopenharmony_ci if ((mutex->stAttr.type == PTHREAD_MUTEX_ERRORCHECK) && (g_losTask.runTask != muxPosted->owner)) { 2793d8536b4Sopenharmony_ci return EPERM; 2803d8536b4Sopenharmony_ci } 2813d8536b4Sopenharmony_ci 2823d8536b4Sopenharmony_ci if (CondInitCheck(cond)) { 2833d8536b4Sopenharmony_ci ret = pthread_cond_init(cond, NULL); 2843d8536b4Sopenharmony_ci if (ret != 0) { 2853d8536b4Sopenharmony_ci return ret; 2863d8536b4Sopenharmony_ci } 2873d8536b4Sopenharmony_ci } 2883d8536b4Sopenharmony_ci 2893d8536b4Sopenharmony_ci (VOID)pthread_mutex_lock(cond->mutex); 2903d8536b4Sopenharmony_ci cond->count++; 2913d8536b4Sopenharmony_ci (VOID)pthread_mutex_unlock(cond->mutex); 2923d8536b4Sopenharmony_ci 2933d8536b4Sopenharmony_ci ret = OsGetTickTimeFromNow(ts, cond->clock, &absTicks); 2943d8536b4Sopenharmony_ci if (ret != 0) { 2953d8536b4Sopenharmony_ci return ret; 2963d8536b4Sopenharmony_ci } 2973d8536b4Sopenharmony_ci 2983d8536b4Sopenharmony_ci if (absTicks >= UINT32_MAX) { 2993d8536b4Sopenharmony_ci return EINVAL; 3003d8536b4Sopenharmony_ci } 3013d8536b4Sopenharmony_ci 3023d8536b4Sopenharmony_ci if (pthread_mutex_unlock(mutex) != 0) { 3033d8536b4Sopenharmony_ci PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 3043d8536b4Sopenharmony_ci } 3053d8536b4Sopenharmony_ci 3063d8536b4Sopenharmony_ci ret = (INT32)LOS_EventRead(&(cond->event), 0x0f, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, (UINT32)absTicks); 3073d8536b4Sopenharmony_ci 3083d8536b4Sopenharmony_ci if (pthread_mutex_lock(mutex) != 0) { 3093d8536b4Sopenharmony_ci PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 3103d8536b4Sopenharmony_ci } 3113d8536b4Sopenharmony_ci 3123d8536b4Sopenharmony_ci ret = ProcessReturnVal(cond, ret); 3133d8536b4Sopenharmony_ci pthread_testcancel(); 3143d8536b4Sopenharmony_ci 3153d8536b4Sopenharmony_ci return ret; 3163d8536b4Sopenharmony_ci} 3173d8536b4Sopenharmony_ci 3183d8536b4Sopenharmony_ciint pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) 3193d8536b4Sopenharmony_ci{ 3203d8536b4Sopenharmony_ci int ret; 3213d8536b4Sopenharmony_ci 3223d8536b4Sopenharmony_ci if ((cond == NULL) || (mutex == NULL)) { 3233d8536b4Sopenharmony_ci return EINVAL; 3243d8536b4Sopenharmony_ci } 3253d8536b4Sopenharmony_ci 3263d8536b4Sopenharmony_ci if (CondInitCheck(cond)) { 3273d8536b4Sopenharmony_ci ret = pthread_cond_init(cond, NULL); 3283d8536b4Sopenharmony_ci if (ret != 0) { 3293d8536b4Sopenharmony_ci return ret; 3303d8536b4Sopenharmony_ci } 3313d8536b4Sopenharmony_ci } 3323d8536b4Sopenharmony_ci 3333d8536b4Sopenharmony_ci (VOID)pthread_mutex_lock(cond->mutex); 3343d8536b4Sopenharmony_ci cond->count++; 3353d8536b4Sopenharmony_ci (VOID)pthread_mutex_unlock(cond->mutex); 3363d8536b4Sopenharmony_ci 3373d8536b4Sopenharmony_ci if (pthread_mutex_unlock(mutex) != 0) { 3383d8536b4Sopenharmony_ci PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 3393d8536b4Sopenharmony_ci } 3403d8536b4Sopenharmony_ci ret = (INT32)LOS_EventRead(&(cond->event), 0x0f, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); 3413d8536b4Sopenharmony_ci if (pthread_mutex_lock(mutex) != 0) { 3423d8536b4Sopenharmony_ci PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 3433d8536b4Sopenharmony_ci } 3443d8536b4Sopenharmony_ci 3453d8536b4Sopenharmony_ci switch (ret) { 3463d8536b4Sopenharmony_ci /* 0: event does not occur */ 3473d8536b4Sopenharmony_ci case 0: 3483d8536b4Sopenharmony_ci case BROADCAST_EVENT: 3493d8536b4Sopenharmony_ci ret = 0; 3503d8536b4Sopenharmony_ci break; 3513d8536b4Sopenharmony_ci default: 3523d8536b4Sopenharmony_ci PthreadCountSub(cond); 3533d8536b4Sopenharmony_ci ret = EINVAL; 3543d8536b4Sopenharmony_ci break; 3553d8536b4Sopenharmony_ci } 3563d8536b4Sopenharmony_ci 3573d8536b4Sopenharmony_ci return ret; 3583d8536b4Sopenharmony_ci} 359