13d8536b4Sopenharmony_ci/* 23d8536b4Sopenharmony_ci * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved. 33d8536b4Sopenharmony_ci * 43d8536b4Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 53d8536b4Sopenharmony_ci * are permitted provided that the following conditions are met: 63d8536b4Sopenharmony_ci * 73d8536b4Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 83d8536b4Sopenharmony_ci * conditions and the following disclaimer. 93d8536b4Sopenharmony_ci * 103d8536b4Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 113d8536b4Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 123d8536b4Sopenharmony_ci * provided with the distribution. 133d8536b4Sopenharmony_ci * 143d8536b4Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 153d8536b4Sopenharmony_ci * to endorse or promote products derived from this software without specific prior written 163d8536b4Sopenharmony_ci * permission. 173d8536b4Sopenharmony_ci * 183d8536b4Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 193d8536b4Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 203d8536b4Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 213d8536b4Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 223d8536b4Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 233d8536b4Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 243d8536b4Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 253d8536b4Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 263d8536b4Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 273d8536b4Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 283d8536b4Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 293d8536b4Sopenharmony_ci */ 303d8536b4Sopenharmony_ci 313d8536b4Sopenharmony_ci#include "poll.h" 323d8536b4Sopenharmony_ci#include <sys/time.h> 333d8536b4Sopenharmony_ci#include <time.h> 343d8536b4Sopenharmony_ci#include "securec.h" 353d8536b4Sopenharmony_ci#include "poll_impl.h" 363d8536b4Sopenharmony_ci#include "los_interrupt.h" 373d8536b4Sopenharmony_ci#include "los_memory.h" 383d8536b4Sopenharmony_ci 393d8536b4Sopenharmony_ciVOID PollWaitQueueInit(struct PollWaitQueue *waitQueue) 403d8536b4Sopenharmony_ci{ 413d8536b4Sopenharmony_ci if (waitQueue == NULL) { 423d8536b4Sopenharmony_ci return; 433d8536b4Sopenharmony_ci } 443d8536b4Sopenharmony_ci LOS_ListInit(&waitQueue->queue); 453d8536b4Sopenharmony_ci} 463d8536b4Sopenharmony_ci 473d8536b4Sopenharmony_ciSTATIC INLINE VOID SetAddPollWaitFlag(struct PollTable *table, BOOL addQueueFlag) 483d8536b4Sopenharmony_ci{ 493d8536b4Sopenharmony_ci table->addQueueFlag = addQueueFlag; 503d8536b4Sopenharmony_ci} 513d8536b4Sopenharmony_ci 523d8536b4Sopenharmony_ciSTATIC VOID DestroyPollWait(struct PollTable *table) 533d8536b4Sopenharmony_ci{ 543d8536b4Sopenharmony_ci UINT32 intSave; 553d8536b4Sopenharmony_ci struct PollWaitNode *waitNode = table->node; 563d8536b4Sopenharmony_ci 573d8536b4Sopenharmony_ci intSave = LOS_IntLock(); 583d8536b4Sopenharmony_ci LOS_ListDelete(&waitNode->node); 593d8536b4Sopenharmony_ci LOS_IntRestore(intSave); 603d8536b4Sopenharmony_ci 613d8536b4Sopenharmony_ci (VOID)LOS_MemFree(OS_SYS_MEM_ADDR, waitNode); 623d8536b4Sopenharmony_ci if (LOS_SemDelete(table->sem) != LOS_OK) { 633d8536b4Sopenharmony_ci PRINT_ERR("destroy poll sem failed!\n"); 643d8536b4Sopenharmony_ci } 653d8536b4Sopenharmony_ci} 663d8536b4Sopenharmony_ci 673d8536b4Sopenharmony_ciSTATIC VOID AddPollWaitQueue(struct PollWaitQueue *waitQueue, struct PollTable *table) 683d8536b4Sopenharmony_ci{ 693d8536b4Sopenharmony_ci UINT32 intSave; 703d8536b4Sopenharmony_ci struct PollWaitNode *waitNode = LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct PollWaitNode)); 713d8536b4Sopenharmony_ci if (waitNode == NULL) { 723d8536b4Sopenharmony_ci return; 733d8536b4Sopenharmony_ci } 743d8536b4Sopenharmony_ci 753d8536b4Sopenharmony_ci intSave = LOS_IntLock(); 763d8536b4Sopenharmony_ci waitNode->table = table; 773d8536b4Sopenharmony_ci LOS_ListAdd(&waitQueue->queue, &waitNode->node); 783d8536b4Sopenharmony_ci table->node = waitNode; 793d8536b4Sopenharmony_ci LOS_IntRestore(intSave); 803d8536b4Sopenharmony_ci} 813d8536b4Sopenharmony_ci 823d8536b4Sopenharmony_ciSTATIC INT32 WaitSemTime(struct PollTable *table, UINT32 timeout) 833d8536b4Sopenharmony_ci{ 843d8536b4Sopenharmony_ci if (timeout != 0) { 853d8536b4Sopenharmony_ci return LOS_SemPend(table->sem, LOS_MS2Tick(timeout)); 863d8536b4Sopenharmony_ci } else { 873d8536b4Sopenharmony_ci return LOS_SemPend(table->sem, LOS_WAIT_FOREVER); 883d8536b4Sopenharmony_ci } 893d8536b4Sopenharmony_ci} 903d8536b4Sopenharmony_ci 913d8536b4Sopenharmony_ciSTATIC INT32 QueryFds(struct pollfd *fds, nfds_t nfds, struct PollTable *table) 923d8536b4Sopenharmony_ci{ 933d8536b4Sopenharmony_ci UINT32 i; 943d8536b4Sopenharmony_ci INT32 ret; 953d8536b4Sopenharmony_ci INT32 count = 0; 963d8536b4Sopenharmony_ci 973d8536b4Sopenharmony_ci if (((nfds != 0) && (fds == NULL)) || (table == NULL)) { 983d8536b4Sopenharmony_ci errno = EINVAL; 993d8536b4Sopenharmony_ci return -1; 1003d8536b4Sopenharmony_ci } 1013d8536b4Sopenharmony_ci 1023d8536b4Sopenharmony_ci for (i = 0; i < nfds; i++) { 1033d8536b4Sopenharmony_ci struct pollfd *tmpFds = &fds[i]; 1043d8536b4Sopenharmony_ci if (tmpFds->fd < 0) { 1053d8536b4Sopenharmony_ci errno = EBADF; 1063d8536b4Sopenharmony_ci return -1; 1073d8536b4Sopenharmony_ci } 1083d8536b4Sopenharmony_ci table->event = tmpFds->events | POLLERR | POLLHUP; 1093d8536b4Sopenharmony_ci 1103d8536b4Sopenharmony_ci ret = PollQueryFd(tmpFds->fd, table); 1113d8536b4Sopenharmony_ci if (ret < 0) { 1123d8536b4Sopenharmony_ci errno = -ret; 1133d8536b4Sopenharmony_ci return -1; 1143d8536b4Sopenharmony_ci } 1153d8536b4Sopenharmony_ci 1163d8536b4Sopenharmony_ci tmpFds->revents = (tmpFds->events | POLLERR | POLLHUP) & (PollEvent)ret; 1173d8536b4Sopenharmony_ci if (tmpFds->revents != 0) { 1183d8536b4Sopenharmony_ci count++; 1193d8536b4Sopenharmony_ci SetAddPollWaitFlag(table, FALSE); 1203d8536b4Sopenharmony_ci } 1213d8536b4Sopenharmony_ci } 1223d8536b4Sopenharmony_ci 1233d8536b4Sopenharmony_ci return count; 1243d8536b4Sopenharmony_ci} 1253d8536b4Sopenharmony_ci 1263d8536b4Sopenharmony_ciVOID PollNotify(struct PollWaitQueue *waitQueue, PollEvent event) 1273d8536b4Sopenharmony_ci{ 1283d8536b4Sopenharmony_ci UINT32 intSave; 1293d8536b4Sopenharmony_ci struct PollWaitNode *waitNode = NULL; 1303d8536b4Sopenharmony_ci 1313d8536b4Sopenharmony_ci if (waitQueue == NULL) { 1323d8536b4Sopenharmony_ci return; 1333d8536b4Sopenharmony_ci } 1343d8536b4Sopenharmony_ci 1353d8536b4Sopenharmony_ci intSave = LOS_IntLock(); 1363d8536b4Sopenharmony_ci LOS_DL_LIST_FOR_EACH_ENTRY(waitNode, &waitQueue->queue, struct PollWaitNode, node) { 1373d8536b4Sopenharmony_ci if (!event || (event & waitNode->table->event)) { 1383d8536b4Sopenharmony_ci if (LOS_SemPost(waitNode->table->sem) != LOS_OK) { 1393d8536b4Sopenharmony_ci PRINT_ERR("poll notify sem post failed!\n"); 1403d8536b4Sopenharmony_ci } 1413d8536b4Sopenharmony_ci } 1423d8536b4Sopenharmony_ci } 1433d8536b4Sopenharmony_ci LOS_IntRestore(intSave); 1443d8536b4Sopenharmony_ci} 1453d8536b4Sopenharmony_ci 1463d8536b4Sopenharmony_ciVOID PollWait(struct PollWaitQueue *waitQueue, struct PollTable *table) 1473d8536b4Sopenharmony_ci{ 1483d8536b4Sopenharmony_ci if ((waitQueue == NULL) || (table == NULL)) { 1493d8536b4Sopenharmony_ci return; 1503d8536b4Sopenharmony_ci } 1513d8536b4Sopenharmony_ci 1523d8536b4Sopenharmony_ci if (table->addQueueFlag == TRUE) { 1533d8536b4Sopenharmony_ci AddPollWaitQueue(waitQueue, table); 1543d8536b4Sopenharmony_ci } 1553d8536b4Sopenharmony_ci} 1563d8536b4Sopenharmony_ci 1573d8536b4Sopenharmony_ciSTATIC INLINE INT32 PollTimedWait(struct pollfd *fds, nfds_t nfds, struct PollTable *table, INT32 timeout) 1583d8536b4Sopenharmony_ci{ 1593d8536b4Sopenharmony_ci struct timespec startTime = {0}; 1603d8536b4Sopenharmony_ci struct timespec curTime = {0}; 1613d8536b4Sopenharmony_ci INT32 left, last; 1623d8536b4Sopenharmony_ci INT32 ret; 1633d8536b4Sopenharmony_ci INT32 count = 0; 1643d8536b4Sopenharmony_ci 1653d8536b4Sopenharmony_ci if (timeout > 0) { 1663d8536b4Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &startTime); 1673d8536b4Sopenharmony_ci } 1683d8536b4Sopenharmony_ci 1693d8536b4Sopenharmony_ci left = timeout; 1703d8536b4Sopenharmony_ci while (count == 0) { 1713d8536b4Sopenharmony_ci if (timeout < 0) { 1723d8536b4Sopenharmony_ci ret = WaitSemTime(table, 0); 1733d8536b4Sopenharmony_ci if (ret != 0) { 1743d8536b4Sopenharmony_ci break; 1753d8536b4Sopenharmony_ci } 1763d8536b4Sopenharmony_ci } else if (left <= 0) { 1773d8536b4Sopenharmony_ci break; 1783d8536b4Sopenharmony_ci } else { 1793d8536b4Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &curTime); 1803d8536b4Sopenharmony_ci last = (INT32)((curTime.tv_sec - startTime.tv_sec) * OS_SYS_MS_PER_SECOND + 1813d8536b4Sopenharmony_ci (curTime.tv_nsec - startTime.tv_nsec) / (OS_SYS_NS_PER_SECOND / OS_SYS_MS_PER_SECOND)); 1823d8536b4Sopenharmony_ci if (last >= timeout) { 1833d8536b4Sopenharmony_ci break; 1843d8536b4Sopenharmony_ci } else { 1853d8536b4Sopenharmony_ci left = timeout - last; 1863d8536b4Sopenharmony_ci } 1873d8536b4Sopenharmony_ci 1883d8536b4Sopenharmony_ci ret = WaitSemTime(table, left); 1893d8536b4Sopenharmony_ci if (ret == LOS_ERRNO_SEM_TIMEOUT) { 1903d8536b4Sopenharmony_ci errno = ETIMEDOUT; 1913d8536b4Sopenharmony_ci break; 1923d8536b4Sopenharmony_ci } 1933d8536b4Sopenharmony_ci } 1943d8536b4Sopenharmony_ci count = QueryFds(fds, nfds, table); 1953d8536b4Sopenharmony_ci } 1963d8536b4Sopenharmony_ci 1973d8536b4Sopenharmony_ci return count; 1983d8536b4Sopenharmony_ci} 1993d8536b4Sopenharmony_ci 2003d8536b4Sopenharmony_ciint poll(struct pollfd *fds, nfds_t nfds, int timeout) 2013d8536b4Sopenharmony_ci{ 2023d8536b4Sopenharmony_ci struct PollTable table = {0}; 2033d8536b4Sopenharmony_ci INT32 count; 2043d8536b4Sopenharmony_ci 2053d8536b4Sopenharmony_ci if (LOS_SemCreate(0, &table.sem) != LOS_OK) { 2063d8536b4Sopenharmony_ci errno = EINVAL; 2073d8536b4Sopenharmony_ci return -1; 2083d8536b4Sopenharmony_ci } 2093d8536b4Sopenharmony_ci 2103d8536b4Sopenharmony_ci SetAddPollWaitFlag(&table, ((timeout == 0) ? FALSE : TRUE)); 2113d8536b4Sopenharmony_ci 2123d8536b4Sopenharmony_ci count = QueryFds(fds, nfds, &table); 2133d8536b4Sopenharmony_ci if (count != 0) { 2143d8536b4Sopenharmony_ci goto DONE; 2153d8536b4Sopenharmony_ci } 2163d8536b4Sopenharmony_ci 2173d8536b4Sopenharmony_ci if (timeout == 0) { 2183d8536b4Sopenharmony_ci goto DONE; 2193d8536b4Sopenharmony_ci } 2203d8536b4Sopenharmony_ci 2213d8536b4Sopenharmony_ci SetAddPollWaitFlag(&table, FALSE); 2223d8536b4Sopenharmony_ci 2233d8536b4Sopenharmony_ci count = PollTimedWait(fds, nfds, &table, timeout); 2243d8536b4Sopenharmony_ci 2253d8536b4Sopenharmony_ciDONE: 2263d8536b4Sopenharmony_ci DestroyPollWait(&table); 2273d8536b4Sopenharmony_ci return count; 2283d8536b4Sopenharmony_ci} 229