Skip to content

Commit 8625fb4

Browse files
committed
SCP: NAT poll() optimizations
- Manage poll() file descriptors more efficiently. Both Linux() poll and Windows WSAPoll() ignore file descriptors that are negative in the pollfd array. Set the pollfd.fd file descriptor to INVALID_SOCKET when no longer needed. Reuse the pollfd array element if have_valid_socket() returns false. - sim_slirp_dispath(): Removed, empty function no longer required.
1 parent 70120dd commit 8625fb4

File tree

4 files changed

+69
-57
lines changed

4 files changed

+69
-57
lines changed

sim_slirp/sim_slirp.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,9 +584,9 @@ t_stat sim_slirp_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, con
584584
/* Initialize the select/poll file descriptor arrays. */
585585
static int initialize_poll_fds(SimSlirpNetwork *slirp)
586586
{
587-
#if SIM_USE_SELECT
588587
size_t i;
589588

589+
#if SIM_USE_SELECT
590590
FD_ZERO(&slirp->readfds);
591591
FD_ZERO(&slirp->writefds);
592592
FD_ZERO(&slirp->exceptfds);
@@ -599,9 +599,14 @@ static int initialize_poll_fds(SimSlirpNetwork *slirp)
599599
slirp->lut[i] = INVALID_SOCKET;
600600
#else
601601
/* poll()-based file descriptor polling. */
602+
static const sim_pollfd_t poll_initializer = { INVALID_SOCKET, 0, 0};
603+
602604
slirp->n_fds = FDS_ALLOC_INIT;
603605
slirp->fd_idx = 0;
604-
slirp->fds = (sim_pollfd_t *) calloc(slirp->n_fds, sizeof(sim_pollfd_t));
606+
slirp->fds = (sim_pollfd_t *) malloc(slirp->n_fds * sizeof(sim_pollfd_t));
607+
for (i = 0; i < slirp->n_fds; ++i) {
608+
slirp->fds[i] = poll_initializer;
609+
}
605610
#endif
606611

607612
return 0;

sim_slirp/sim_slirp.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ SimSlirpNetwork *sim_slirp_open (const char *args, void *pkt_opaque, packet_call
1414
void sim_slirp_close (SimSlirpNetwork *slirp);
1515
int sim_slirp_send (SimSlirpNetwork *slirp, const char *msg, size_t len, int flags);
1616
int sim_slirp_select (SimSlirpNetwork *slirp, int ms_timeout);
17-
void sim_slirp_dispatch (SimSlirpNetwork *slirp);
1817
t_stat sim_slirp_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
1918
void sim_slirp_show (SimSlirpNetwork *slirp, FILE *st);
2019

sim_slirp/sim_slirp_network.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
/* Abstract the poll structure as sim_pollfd_t */
4040
#if SIM_USE_POLL
41-
# if (defined(_WIN32) || defined(_WIN64))
41+
# if defined(_WIN32) || defined(_WIN64)
4242
typedef WSAPOLLFD sim_pollfd_t;
4343
# else
4444
# include <poll.h>

sim_slirp/slirp_poll.c

Lines changed: 61 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
# if defined(PRIu32)
5555
# define SIM_PRIsocket PRIu32
5656
# else
57-
# define SIM_PRIsocket "lu"
57+
# define SIM_PRIsocket "u"
5858
# endif
5959
#else
6060
# define SIM_PRIsocket "u"
@@ -75,21 +75,21 @@ static inline uint32_t slirp_dbg_mask(const SimSlirpNetwork *slirp, size_t flag)
7575
return (slirp != NULL && slirp->dptr != NULL) ? slirp->dptr->debflags[slirp->flag_offset + flag].mask : 0;
7676
}
7777

78-
#if SIM_USE_SELECT
79-
/* Socket identifier pretty-printer: */
80-
static const char *print_socket(slirp_os_socket s)
78+
/* Socket error check */
79+
static inline int have_valid_socket(slirp_os_socket s)
8180
{
82-
static char retbuf[64];
83-
84-
#if defined(_WIN64)
85-
sprintf(retbuf, "%llu", s);
86-
#elif defined(_WIN32)
87-
sprintf(retbuf, "%u", s);
81+
#if !defined(_WIN32) && !defined(_WIN64)
82+
return (s >= 0);
8883
#else
89-
sprintf(retbuf, "%d", s);
84+
return (s != SLIRP_INVALID_SOCKET);
9085
#endif
86+
}
9187

92-
return retbuf;
88+
#if (defined(_WIN32) || defined(_WIN64)) && SIM_USE_POLL
89+
/* poll() wrapper for Windows: */
90+
static inline int poll(WSAPOLLFD *fds, size_t n_fds, int timeout)
91+
{
92+
return WSAPoll(fds, (ULONG) n_fds, timeout);
9393
}
9494
#endif
9595

@@ -145,13 +145,6 @@ int sim_slirp_select(SimSlirpNetwork *slirp, int ms_timeout)
145145
* "Protocol" functions. These functions abide by the one function definition rule.
146146
*~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=*/
147147

148-
#if (defined(_WIN32) || defined(_WIN64)) && SIM_USE_POLL
149-
static inline int poll(WSAPOLLFD *fds, size_t n_fds, int timeout)
150-
{
151-
return WSAPoll(fds, (ULONG) n_fds, timeout);
152-
}
153-
#endif
154-
155148
static void initialize_poll(SimSlirpNetwork *slirp, uint32 tmo, struct timeval *tv)
156149
{
157150
#if SIM_USE_SELECT
@@ -164,9 +157,7 @@ static void initialize_poll(SimSlirpNetwork *slirp, uint32 tmo, struct timeval *
164157

165158
slirp->max_fd = SIM_INVALID_MAX_FD;
166159
#elif SIM_USE_POLL
167-
/* Reinitialize and reset */
168-
memset(slirp->fds, 0, slirp->fd_idx * sizeof(sim_pollfd_t));
169-
slirp->fd_idx = 0;
160+
/* Nothing to do. */
170161
#endif
171162
}
172163

@@ -238,10 +229,10 @@ static void report_error(SimSlirpNetwork *slirp)
238229
/* Add new socket file descriptors to the Slirp I/O event tracking state. */
239230
void register_poll_socket(slirp_os_socket fd, void *opaque)
240231
{
241-
#if SIM_USE_SELECT
242232
SimSlirpNetwork *slirp = (SimSlirpNetwork *) opaque;
243233
size_t i;
244234

235+
#if SIM_USE_SELECT
245236
for (i = 0; i < slirp->lut_alloc; ++i) {
246237
if (slirp->lut[i] == INVALID_SOCKET) {
247238
slirp->lut[i] = fd;
@@ -264,34 +255,55 @@ void register_poll_socket(slirp_os_socket fd, void *opaque)
264255
slirp->lut[i] = fd;
265256
}
266257

267-
sim_debug(slirp_dbg_mask(slirp, DBG_SOCKET), slirp->dptr, "register_poll_socket(%s) index %" SIZE_T_FMT "d\n",
268-
print_socket(fd), i);
258+
sim_debug(slirp_dbg_mask(slirp, DBG_SOCKET), slirp->dptr, "register_poll_socket(%" SIM_PRIsocket " index %" SIZE_T_FMT "d\n",
259+
fd, i);
269260
#elif SIM_USE_POLL
270-
/* Not necessary for poll(). */
271-
(void) opaque;
261+
for (i = 0; i < slirp->fd_idx && have_valid_socket(slirp->fds[i].fd); ++i)
262+
/* NOP */;
263+
264+
if (i >= slirp->n_fds) {
265+
/* Resize the array... */
266+
size_t j = slirp->n_fds;
267+
sim_pollfd_t *new_fds;
268+
269+
slirp->n_fds += FDS_ALLOC_INCR;
270+
new_fds = (sim_pollfd_t *) realloc(slirp->fds, slirp->n_fds * sizeof(sim_pollfd_t));
271+
ASSURE(new_fds != NULL);
272+
memset(new_fds + j, 0, (slirp->n_fds - j) * sizeof(sim_pollfd_t));
273+
slirp->fds = new_fds;
274+
}
275+
276+
slirp->fds[i].fd = fd;
277+
slirp->fds[i].events = slirp->fds[i].revents = 0;
278+
279+
if (i == slirp->fd_idx)
280+
++slirp->fd_idx;
272281
#endif
273282
}
274283

275284
/* Reap a disused socket. */
276285
void unregister_poll_socket(slirp_os_socket fd, void *opaque)
277286
{
278-
GLIB_UNUSED_PARAM(opaque);
279-
280-
#if SIM_USE_SELECT
281287
SimSlirpNetwork *slirp = (SimSlirpNetwork *) opaque;
282288
size_t i;
283289

290+
#if SIM_USE_SELECT
284291
for (i = 0; i < slirp->lut_alloc; ++i) {
285292
if (slirp->lut[i] == fd) {
286293
slirp->lut[i] = INVALID_SOCKET;
287294
sim_debug(slirp_dbg_mask(slirp, DBG_SOCKET), slirp->dptr,
288-
"unregister_poll_socket(%s) index %" SIZE_T_FMT "d\n", print_socket(fd), i);
295+
"unregister_poll_socket(%" SIM_PRIsocket ") index %" SIZE_T_FMT "d\n", fd, i);
289296
break;
290297
}
291298
}
292299
#elif SIM_USE_POLL
293-
/* Not necessary for poll(). */
294-
(void) opaque;
300+
for (i = 0; i < slirp->fd_idx && slirp->fds[i].fd != fd; ++i)
301+
/* NOP */;
302+
303+
if (i < slirp->fd_idx) {
304+
slirp->fds[i].fd = INVALID_SOCKET;
305+
slirp->fds[i].events = slirp->fds[i].revents = 0;
306+
}
295307
#endif
296308
}
297309

@@ -339,9 +351,9 @@ static int add_poll_callback(slirp_os_socket fd, int events, void *opaque)
339351
SimSlirpNetwork *slirp = (SimSlirpNetwork *) opaque;
340352
int retval = -1;
341353
char prefix[128];
354+
size_t i;
342355

343356
#if SIM_USE_SELECT
344-
size_t i;
345357
const int event_mask = (SLIRP_POLL_IN | SLIRP_POLL_OUT | SLIRP_POLL_PRI);
346358

347359
for (i = 0; i < slirp->lut_alloc; ++i) {
@@ -364,21 +376,10 @@ static int add_poll_callback(slirp_os_socket fd, int events, void *opaque)
364376
break;
365377
}
366378

367-
sprintf(prefix, "add_poll_callback(%s)/select (0x%04x)", print_socket(fd), events & event_mask);
379+
sprintf(prefix, "add_poll_callback(%" SIM_PRIsocket ")/select (0x%04x)", fd, events & event_mask);
368380
poll_debugging(slirp_dbg_mask(slirp, DBG_POLL), slirp->dptr, prefix, events & event_mask);
369381
}
370382
#elif SIM_USE_POLL
371-
if (slirp->fd_idx == slirp->n_fds) {
372-
size_t j = slirp->n_fds;
373-
sim_pollfd_t *new_fds;
374-
375-
slirp->n_fds += FDS_ALLOC_INCR;
376-
new_fds = (sim_pollfd_t *) realloc(slirp->fds, slirp->n_fds * sizeof(sim_pollfd_t));
377-
ASSURE(new_fds != NULL);
378-
memset(new_fds + j, 0, (slirp->n_fds - j) * sizeof(sim_pollfd_t));
379-
slirp->fds = new_fds;
380-
}
381-
382383
short poll_events = 0;
383384

384385
if (events & SLIRP_POLL_IN) {
@@ -387,7 +388,7 @@ static int add_poll_callback(slirp_os_socket fd, int events, void *opaque)
387388
if (events & SLIRP_POLL_OUT) {
388389
poll_events |= POLLOUT;
389390
}
390-
#if !defined(_WIN32) && !defined(_WIN64)
391+
# if !defined(_WIN32) && !defined(_WIN64)
391392
/* Not supported on Windows. Unless you like EINVAL. :-) */
392393
if (events & SLIRP_POLL_PRI) {
393394
poll_events |= POLLPRI;
@@ -398,16 +399,23 @@ static int add_poll_callback(slirp_os_socket fd, int events, void *opaque)
398399
if (events & SLIRP_POLL_HUP) {
399400
poll_events |= POLLHUP;
400401
}
401-
#endif
402+
# endif
403+
for (i = 0; i < slirp->fd_idx && slirp->fds[i].fd != fd; ++i)
404+
/* NOP */ ;
405+
406+
if (i >= slirp->fd_idx) {
407+
sim_messagef(SCPE_IOERR, "add_poll_callback: Unregistered/unknown fd %" SIM_PRIsocket "\n", fd);
408+
return -1;
409+
}
402410

403411
sprintf(prefix, "add_poll_callback(%" SIM_PRIsocket ")/poll (0x%04x)", fd, events);
404412
poll_debugging(slirp_dbg_mask(slirp, DBG_POLL), slirp->dptr, prefix, events);
405413

406-
slirp->fds[slirp->fd_idx].fd = fd;
407-
slirp->fds[slirp->fd_idx].events = poll_events;
408-
slirp->fds[slirp->fd_idx].revents = 0;
414+
slirp->fds[i].fd = fd;
415+
slirp->fds[i].events = poll_events;
416+
slirp->fds[i].revents = 0;
409417

410-
retval = (int) slirp->fd_idx++;
418+
retval = (int) i;
411419
#endif
412420

413421
return retval;
@@ -435,7 +443,7 @@ static int get_events_callback(int idx, void *opaque)
435443
event |= SLIRP_POLL_PRI;
436444
}
437445

438-
sprintf(prefix, "get_events_callback(%s)/select (0x%04x)", print_socket(fd), event & event_mask);
446+
sprintf(prefix, "get_events_callback(%" SIM_PRIsocket ")/select (0x%04x)", fd, event & event_mask);
439447
poll_debugging(slirp_dbg_mask(slirp, DBG_POLL), slirp->dptr, prefix, event & event_mask);
440448
}
441449
#elif SIM_USE_POLL

0 commit comments

Comments
 (0)