xref: /nrf52832-nimble/rt-thread/components/dfs/src/poll.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  * 2016-12-28     Bernard      first version
9*10465441SEvalZero  * 2018-03-09     Bernard      Add protection for pt->triggered.
10*10465441SEvalZero  */
11*10465441SEvalZero #include <stdint.h>
12*10465441SEvalZero 
13*10465441SEvalZero #include <rthw.h>
14*10465441SEvalZero #include <rtdevice.h>
15*10465441SEvalZero #include <rtthread.h>
16*10465441SEvalZero 
17*10465441SEvalZero #include <dfs.h>
18*10465441SEvalZero #include <dfs_file.h>
19*10465441SEvalZero #include <dfs_posix.h>
20*10465441SEvalZero #include <dfs_poll.h>
21*10465441SEvalZero 
22*10465441SEvalZero struct rt_poll_node;
23*10465441SEvalZero 
24*10465441SEvalZero struct rt_poll_table
25*10465441SEvalZero {
26*10465441SEvalZero     rt_pollreq_t req;
27*10465441SEvalZero     rt_uint32_t triggered; /* the waited thread whether triggered */
28*10465441SEvalZero     rt_thread_t polling_thread;
29*10465441SEvalZero     struct rt_poll_node *nodes;
30*10465441SEvalZero };
31*10465441SEvalZero 
32*10465441SEvalZero struct rt_poll_node
33*10465441SEvalZero {
34*10465441SEvalZero     struct rt_wqueue_node wqn;
35*10465441SEvalZero     struct rt_poll_table *pt;
36*10465441SEvalZero     struct rt_poll_node *next;
37*10465441SEvalZero };
38*10465441SEvalZero 
__wqueue_pollwake(struct rt_wqueue_node * wait,void * key)39*10465441SEvalZero static int __wqueue_pollwake(struct rt_wqueue_node *wait, void *key)
40*10465441SEvalZero {
41*10465441SEvalZero     struct rt_poll_node *pn;
42*10465441SEvalZero 
43*10465441SEvalZero     if (key && !((rt_ubase_t)key & wait->key))
44*10465441SEvalZero         return -1;
45*10465441SEvalZero 
46*10465441SEvalZero     pn = rt_container_of(wait, struct rt_poll_node, wqn);
47*10465441SEvalZero     pn->pt->triggered = 1;
48*10465441SEvalZero 
49*10465441SEvalZero     return __wqueue_default_wake(wait, key);
50*10465441SEvalZero }
51*10465441SEvalZero 
_poll_add(rt_wqueue_t * wq,rt_pollreq_t * req)52*10465441SEvalZero static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req)
53*10465441SEvalZero {
54*10465441SEvalZero     struct rt_poll_table *pt;
55*10465441SEvalZero     struct rt_poll_node *node;
56*10465441SEvalZero 
57*10465441SEvalZero     node = rt_malloc(sizeof(struct rt_poll_node));
58*10465441SEvalZero     if (node == RT_NULL)
59*10465441SEvalZero         return;
60*10465441SEvalZero 
61*10465441SEvalZero     pt = rt_container_of(req, struct rt_poll_table, req);
62*10465441SEvalZero 
63*10465441SEvalZero     node->wqn.key = req->_key;
64*10465441SEvalZero     rt_list_init(&(node->wqn.list));
65*10465441SEvalZero     node->wqn.polling_thread = pt->polling_thread;
66*10465441SEvalZero     node->wqn.wakeup = __wqueue_pollwake;
67*10465441SEvalZero     node->next = pt->nodes;
68*10465441SEvalZero     node->pt = pt;
69*10465441SEvalZero     pt->nodes = node;
70*10465441SEvalZero     rt_wqueue_add(wq, &node->wqn);
71*10465441SEvalZero }
72*10465441SEvalZero 
poll_table_init(struct rt_poll_table * pt)73*10465441SEvalZero static void poll_table_init(struct rt_poll_table *pt)
74*10465441SEvalZero {
75*10465441SEvalZero     pt->req._proc = _poll_add;
76*10465441SEvalZero     pt->triggered = 0;
77*10465441SEvalZero     pt->nodes = RT_NULL;
78*10465441SEvalZero     pt->polling_thread = rt_thread_self();
79*10465441SEvalZero }
80*10465441SEvalZero 
poll_wait_timeout(struct rt_poll_table * pt,int msec)81*10465441SEvalZero static int poll_wait_timeout(struct rt_poll_table *pt, int msec)
82*10465441SEvalZero {
83*10465441SEvalZero     rt_int32_t timeout;
84*10465441SEvalZero     int ret = 0;
85*10465441SEvalZero     struct rt_thread *thread;
86*10465441SEvalZero     rt_base_t level;
87*10465441SEvalZero 
88*10465441SEvalZero     thread = pt->polling_thread;
89*10465441SEvalZero 
90*10465441SEvalZero     timeout = rt_tick_from_millisecond(msec);
91*10465441SEvalZero 
92*10465441SEvalZero     level = rt_hw_interrupt_disable();
93*10465441SEvalZero 
94*10465441SEvalZero     if (timeout != 0 && !pt->triggered)
95*10465441SEvalZero     {
96*10465441SEvalZero         rt_thread_suspend(thread);
97*10465441SEvalZero         if (timeout > 0)
98*10465441SEvalZero         {
99*10465441SEvalZero             rt_timer_control(&(thread->thread_timer),
100*10465441SEvalZero                              RT_TIMER_CTRL_SET_TIME,
101*10465441SEvalZero                              &timeout);
102*10465441SEvalZero             rt_timer_start(&(thread->thread_timer));
103*10465441SEvalZero         }
104*10465441SEvalZero 
105*10465441SEvalZero         rt_hw_interrupt_enable(level);
106*10465441SEvalZero 
107*10465441SEvalZero         rt_schedule();
108*10465441SEvalZero 
109*10465441SEvalZero         level = rt_hw_interrupt_disable();
110*10465441SEvalZero     }
111*10465441SEvalZero 
112*10465441SEvalZero     ret = !pt->triggered;
113*10465441SEvalZero     rt_hw_interrupt_enable(level);
114*10465441SEvalZero 
115*10465441SEvalZero     return ret;
116*10465441SEvalZero }
117*10465441SEvalZero 
do_pollfd(struct pollfd * pollfd,rt_pollreq_t * req)118*10465441SEvalZero static int do_pollfd(struct pollfd *pollfd, rt_pollreq_t *req)
119*10465441SEvalZero {
120*10465441SEvalZero     int mask = 0;
121*10465441SEvalZero     int fd;
122*10465441SEvalZero 
123*10465441SEvalZero     fd = pollfd->fd;
124*10465441SEvalZero 
125*10465441SEvalZero     if (fd >= 0)
126*10465441SEvalZero     {
127*10465441SEvalZero         struct dfs_fd *f = fd_get(fd);
128*10465441SEvalZero         mask = POLLNVAL;
129*10465441SEvalZero 
130*10465441SEvalZero         if (f)
131*10465441SEvalZero         {
132*10465441SEvalZero             mask = POLLMASK_DEFAULT;
133*10465441SEvalZero             if (f->fops->poll)
134*10465441SEvalZero             {
135*10465441SEvalZero                 req->_key = pollfd->events | POLLERR| POLLHUP;
136*10465441SEvalZero 
137*10465441SEvalZero                 mask = f->fops->poll(f, req);
138*10465441SEvalZero             }
139*10465441SEvalZero             /* Mask out unneeded events. */
140*10465441SEvalZero             mask &= pollfd->events | POLLERR | POLLHUP;
141*10465441SEvalZero             fd_put(f);
142*10465441SEvalZero         }
143*10465441SEvalZero     }
144*10465441SEvalZero     pollfd->revents = mask;
145*10465441SEvalZero 
146*10465441SEvalZero     return mask;
147*10465441SEvalZero }
148*10465441SEvalZero 
poll_do(struct pollfd * fds,nfds_t nfds,struct rt_poll_table * pt,int msec)149*10465441SEvalZero static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, int msec)
150*10465441SEvalZero {
151*10465441SEvalZero     int num;
152*10465441SEvalZero     int istimeout = 0;
153*10465441SEvalZero     int n;
154*10465441SEvalZero     struct pollfd *pf;
155*10465441SEvalZero 
156*10465441SEvalZero     if (msec == 0)
157*10465441SEvalZero     {
158*10465441SEvalZero         pt->req._proc = RT_NULL;
159*10465441SEvalZero         istimeout = 1;
160*10465441SEvalZero     }
161*10465441SEvalZero 
162*10465441SEvalZero     while (1)
163*10465441SEvalZero     {
164*10465441SEvalZero         pf = fds;
165*10465441SEvalZero         num = 0;
166*10465441SEvalZero 
167*10465441SEvalZero         for (n = 0; n < nfds; n ++)
168*10465441SEvalZero         {
169*10465441SEvalZero             if (do_pollfd(pf, &pt->req))
170*10465441SEvalZero             {
171*10465441SEvalZero                 num ++;
172*10465441SEvalZero                 pt->req._proc = RT_NULL;
173*10465441SEvalZero             }
174*10465441SEvalZero             pf ++;
175*10465441SEvalZero         }
176*10465441SEvalZero 
177*10465441SEvalZero         pt->req._proc = RT_NULL;
178*10465441SEvalZero 
179*10465441SEvalZero         if (num || istimeout)
180*10465441SEvalZero             break;
181*10465441SEvalZero 
182*10465441SEvalZero         if (poll_wait_timeout(pt, msec))
183*10465441SEvalZero             istimeout = 1;
184*10465441SEvalZero     }
185*10465441SEvalZero 
186*10465441SEvalZero     return num;
187*10465441SEvalZero }
188*10465441SEvalZero 
poll_teardown(struct rt_poll_table * pt)189*10465441SEvalZero static void poll_teardown(struct rt_poll_table *pt)
190*10465441SEvalZero {
191*10465441SEvalZero     struct rt_poll_node *node, *next;
192*10465441SEvalZero 
193*10465441SEvalZero     next = pt->nodes;
194*10465441SEvalZero     while (next)
195*10465441SEvalZero     {
196*10465441SEvalZero         node = next;
197*10465441SEvalZero         rt_wqueue_remove(&node->wqn);
198*10465441SEvalZero         next = node->next;
199*10465441SEvalZero         rt_free(node);
200*10465441SEvalZero     }
201*10465441SEvalZero }
202*10465441SEvalZero 
poll(struct pollfd * fds,nfds_t nfds,int timeout)203*10465441SEvalZero int poll(struct pollfd *fds, nfds_t nfds, int timeout)
204*10465441SEvalZero {
205*10465441SEvalZero     int num;
206*10465441SEvalZero     struct rt_poll_table table;
207*10465441SEvalZero 
208*10465441SEvalZero     poll_table_init(&table);
209*10465441SEvalZero 
210*10465441SEvalZero     num = poll_do(fds, nfds, &table, timeout);
211*10465441SEvalZero 
212*10465441SEvalZero     poll_teardown(&table);
213*10465441SEvalZero 
214*10465441SEvalZero     return num;
215*10465441SEvalZero }
216*10465441SEvalZero 
217