1 /* select filedescriptor handling, taken from:
2 * userspace logging daemon for the iptables ULOG target
3 * of the linux 2.4 netfilter subsystem.
5 * (C) 2000-2009 by Harald Welte <laforge@gnumonks.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <osmocom/core/select.h>
26 #include <osmocom/core/linuxlist.h>
27 #include <osmocom/core/timer.h>
29 #include "../config.h"
31 #ifdef HAVE_SYS_SELECT_H
33 /*! \addtogroup select
38 * \brief select loop abstraction
42 static LLIST_HEAD(osmo_fds
);
43 static int unregistered_count
;
45 /*! \brief Register a new file descriptor with select loop abstraction
46 * \param[in] fd osmocom file descriptor to be registered
48 int osmo_fd_register(struct osmo_fd
*fd
)
52 /* make FD nonblocking */
53 flags
= fcntl(fd
->fd
, F_GETFL
);
57 flags
= fcntl(fd
->fd
, F_SETFL
, flags
);
61 /* set close-on-exec flag */
62 flags
= fcntl(fd
->fd
, F_GETFD
);
66 flags
= fcntl(fd
->fd
, F_SETFD
, flags
);
75 struct osmo_fd
*entry
;
76 llist_for_each_entry(entry
, &osmo_fds
, list
) {
78 fprintf(stderr
, "Adding a osmo_fd that is already in the list.\n");
84 llist_add_tail(&fd
->list
, &osmo_fds
);
89 /*! \brief Unregister a file descriptor from select loop abstraction
90 * \param[in] fd osmocom file descriptor to be unregistered
92 void osmo_fd_unregister(struct osmo_fd
*fd
)
98 /*! \brief select main loop integration
99 * \param[in] polling should we pollonly (1) or block on select (0)
101 int osmo_select_main(int polling
)
103 struct osmo_fd
*ufd
, *tmp
;
104 fd_set readset
, writeset
, exceptset
;
106 struct timeval no_time
= {0, 0};
112 /* prepare read and write fdsets */
113 llist_for_each_entry(ufd
, &osmo_fds
, list
) {
114 if (ufd
->when
& BSC_FD_READ
)
115 FD_SET(ufd
->fd
, &readset
);
117 if (ufd
->when
& BSC_FD_WRITE
)
118 FD_SET(ufd
->fd
, &writeset
);
120 if (ufd
->when
& BSC_FD_EXCEPT
)
121 FD_SET(ufd
->fd
, &exceptset
);
127 osmo_timers_prepare();
128 rc
= select(maxfd
+1, &readset
, &writeset
, &exceptset
, polling
? &no_time
: osmo_timers_nearest());
133 osmo_timers_update();
135 /* call registered callback functions */
137 unregistered_count
= 0;
138 llist_for_each_entry_safe(ufd
, tmp
, &osmo_fds
, list
) {
141 if (FD_ISSET(ufd
->fd
, &readset
)) {
142 flags
|= BSC_FD_READ
;
143 FD_CLR(ufd
->fd
, &readset
);
146 if (FD_ISSET(ufd
->fd
, &writeset
)) {
147 flags
|= BSC_FD_WRITE
;
148 FD_CLR(ufd
->fd
, &writeset
);
151 if (FD_ISSET(ufd
->fd
, &exceptset
)) {
152 flags
|= BSC_FD_EXCEPT
;
153 FD_CLR(ufd
->fd
, &exceptset
);
160 /* ugly, ugly hack. If more than one filedescriptors were
161 * unregistered, they might have been consecutive and
162 * llist_for_each_entry_safe() is no longer safe */
163 /* this seems to happen with the last element of the list as well */
164 if (unregistered_count
>= 1)
172 #endif /* _HAVE_SYS_SELECT_H */