• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "poll.h"
32 #include <sys/time.h>
33 #include <time.h>
34 #include "securec.h"
35 #include "poll_impl.h"
36 #include "los_interrupt.h"
37 #include "los_memory.h"
38 
PollWaitQueueInit(struct PollWaitQueue * waitQueue)39 VOID PollWaitQueueInit(struct PollWaitQueue *waitQueue)
40 {
41     if (waitQueue == NULL) {
42         return;
43     }
44     LOS_ListInit(&waitQueue->queue);
45 }
46 
SetAddPollWaitFlag(struct PollTable * table,BOOL addQueueFlag)47 STATIC INLINE VOID SetAddPollWaitFlag(struct PollTable *table, BOOL addQueueFlag)
48 {
49     table->addQueueFlag = addQueueFlag;
50 }
51 
DestroyPollWait(struct PollTable * table)52 STATIC VOID DestroyPollWait(struct PollTable *table)
53 {
54     UINT32 intSave;
55     struct PollWaitNode *waitNode = table->node;
56 
57     intSave = LOS_IntLock();
58     LOS_ListDelete(&waitNode->node);
59     LOS_IntRestore(intSave);
60 
61     (VOID)LOS_MemFree(OS_SYS_MEM_ADDR, waitNode);
62     if (LOS_SemDelete(table->sem) != LOS_OK) {
63         PRINT_ERR("destroy poll sem failed!\n");
64     }
65 }
66 
AddPollWaitQueue(struct PollWaitQueue * waitQueue,struct PollTable * table)67 STATIC VOID AddPollWaitQueue(struct PollWaitQueue *waitQueue, struct PollTable *table)
68 {
69     UINT32 intSave;
70     struct PollWaitNode *waitNode = LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct PollWaitNode));
71     if (waitNode == NULL) {
72         return;
73     }
74 
75     intSave = LOS_IntLock();
76     waitNode->table = table;
77     LOS_ListAdd(&waitQueue->queue, &waitNode->node);
78     table->node = waitNode;
79     LOS_IntRestore(intSave);
80 }
81 
WaitSemTime(struct PollTable * table,UINT32 timeout)82 STATIC INT32 WaitSemTime(struct PollTable *table, UINT32 timeout)
83 {
84     if (timeout != 0) {
85         return LOS_SemPend(table->sem, LOS_MS2Tick(timeout));
86     } else {
87         return LOS_SemPend(table->sem, LOS_WAIT_FOREVER);
88     }
89 }
90 
QueryFds(struct pollfd * fds,nfds_t nfds,struct PollTable * table)91 STATIC INT32 QueryFds(struct pollfd *fds, nfds_t nfds, struct PollTable *table)
92 {
93     UINT32 i;
94     INT32 ret;
95     INT32 count = 0;
96 
97     if (((nfds != 0) && (fds == NULL)) || (table == NULL)) {
98         errno = EINVAL;
99         return -1;
100     }
101 
102     for (i = 0; i < nfds; i++) {
103         struct pollfd *tmpFds = &fds[i];
104         if (tmpFds->fd < 0) {
105             errno = EBADF;
106             return -1;
107         }
108         table->event = tmpFds->events | POLLERR | POLLHUP;
109 
110         ret = PollQueryFd(tmpFds->fd, table);
111         if (ret < 0) {
112             errno = -ret;
113             return -1;
114         }
115 
116         tmpFds->revents = (tmpFds->events | POLLERR | POLLHUP) & (PollEvent)ret;
117         if (tmpFds->revents != 0) {
118             count++;
119             SetAddPollWaitFlag(table, FALSE);
120         }
121     }
122 
123     return count;
124 }
125 
PollNotify(struct PollWaitQueue * waitQueue,PollEvent event)126 VOID PollNotify(struct PollWaitQueue *waitQueue, PollEvent event)
127 {
128     UINT32 intSave;
129     struct PollWaitNode *waitNode = NULL;
130 
131     if (waitQueue == NULL) {
132         return;
133     }
134 
135     intSave = LOS_IntLock();
136     LOS_DL_LIST_FOR_EACH_ENTRY(waitNode, &waitQueue->queue, struct PollWaitNode, node) {
137         if (!event || (event & waitNode->table->event)) {
138             if (LOS_SemPost(waitNode->table->sem) != LOS_OK) {
139                 PRINT_ERR("poll notify sem post failed!\n");
140             }
141         }
142     }
143     LOS_IntRestore(intSave);
144 }
145 
PollWait(struct PollWaitQueue * waitQueue,struct PollTable * table)146 VOID PollWait(struct PollWaitQueue *waitQueue, struct PollTable *table)
147 {
148     if ((waitQueue == NULL) || (table == NULL)) {
149         return;
150     }
151 
152     if (table->addQueueFlag == TRUE) {
153         AddPollWaitQueue(waitQueue, table);
154     }
155 }
156 
PollTimedWait(struct pollfd * fds,nfds_t nfds,struct PollTable * table,INT32 timeout)157 STATIC INLINE INT32 PollTimedWait(struct pollfd *fds, nfds_t nfds, struct PollTable *table, INT32 timeout)
158 {
159     struct timespec startTime = {0};
160     struct timespec curTime = {0};
161     INT32 left, last;
162     INT32 ret;
163     INT32 count = 0;
164 
165     if (timeout > 0) {
166         clock_gettime(CLOCK_REALTIME, &startTime);
167     }
168 
169     left = timeout;
170     while (count == 0) {
171         if (timeout < 0) {
172             ret = WaitSemTime(table, 0);
173             if (ret != 0) {
174                 break;
175             }
176         } else if (left <= 0) {
177             break;
178         } else {
179             clock_gettime(CLOCK_REALTIME, &curTime);
180             last = (INT32)((curTime.tv_sec - startTime.tv_sec) * OS_SYS_MS_PER_SECOND +
181                    (curTime.tv_nsec - startTime.tv_nsec) / (OS_SYS_NS_PER_SECOND / OS_SYS_MS_PER_SECOND));
182             if (last >= timeout) {
183                 break;
184             } else {
185                 left = timeout - last;
186             }
187 
188             ret = WaitSemTime(table, left);
189             if (ret == LOS_ERRNO_SEM_TIMEOUT) {
190                 errno = ETIMEDOUT;
191                 break;
192             }
193         }
194         count = QueryFds(fds, nfds, table);
195     }
196 
197     return count;
198 }
199 
poll(struct pollfd * fds,nfds_t nfds,int timeout)200 int poll(struct pollfd *fds, nfds_t nfds, int timeout)
201 {
202     struct PollTable table = {0};
203     INT32 count;
204 
205     if (LOS_SemCreate(0, &table.sem) != LOS_OK) {
206         errno = EINVAL;
207         return -1;
208     }
209 
210     SetAddPollWaitFlag(&table, ((timeout == 0) ? FALSE : TRUE));
211 
212     count = QueryFds(fds, nfds, &table);
213     if (count != 0) {
214         goto DONE;
215     }
216 
217     if (timeout == 0) {
218         goto DONE;
219     }
220 
221     SetAddPollWaitFlag(&table, FALSE);
222 
223     count = PollTimedWait(fds, nfds, &table, timeout);
224 
225 DONE:
226     DestroyPollWait(&table);
227     return count;
228 }
229