Home | History | Annotate | Line # | Download | only in rpc
svc_fdset.c revision 1.16.24.1
      1  1.16.24.1  perseant /*	$NetBSD: svc_fdset.c,v 1.16.24.1 2025/08/02 05:54:40 perseant Exp $	*/
      2        1.4  christos 
      3        1.4  christos /*-
      4        1.4  christos  * Copyright (c) 2015 The NetBSD Foundation, Inc.
      5        1.8  christos  * All rights reserved.
      6        1.4  christos  *
      7        1.4  christos  * This code is derived from software contributed to The NetBSD Foundation
      8        1.4  christos  * by Christos Zoulas.
      9        1.4  christos  *
     10        1.4  christos  * Redistribution and use in source and binary forms, with or without
     11        1.4  christos  * modification, are permitted provided that the following conditions
     12        1.4  christos  * are met:
     13        1.4  christos  * 1. Redistributions of source code must retain the above copyright
     14        1.4  christos  *    notice, this list of conditions and the following disclaimer.
     15        1.4  christos  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.4  christos  *    notice, this list of conditions and the following disclaimer in the
     17        1.4  christos  *    documentation and/or other materials provided with the distribution.
     18        1.4  christos  *
     19        1.4  christos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20        1.4  christos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21        1.4  christos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22        1.4  christos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23        1.4  christos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24        1.4  christos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25        1.4  christos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26        1.4  christos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27        1.4  christos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28        1.4  christos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29        1.4  christos  * POSSIBILITY OF SUCH DAMAGE.
     30        1.4  christos  */
     31        1.1  christos 
     32        1.1  christos #include <sys/cdefs.h>
     33  1.16.24.1  perseant __RCSID("$NetBSD: svc_fdset.c,v 1.16.24.1 2025/08/02 05:54:40 perseant Exp $");
     34        1.2  christos 
     35        1.2  christos 
     36        1.2  christos #include "reentrant.h"
     37        1.2  christos 
     38        1.2  christos #include <sys/fd_set.h>
     39        1.2  christos 
     40        1.2  christos #include <rpc/rpc.h>
     41        1.1  christos 
     42        1.5  christos #ifdef FDSET_DEBUG
     43        1.5  christos #include <stdio.h>
     44        1.5  christos #include <stdarg.h>
     45        1.5  christos #include <unistd.h>
     46        1.5  christos #include <lwp.h>
     47        1.5  christos #endif
     48        1.1  christos #include <stdlib.h>
     49        1.1  christos #include <string.h>
     50        1.9  christos #include <poll.h>
     51        1.1  christos 
     52        1.5  christos #include "svc_fdset.h"
     53        1.5  christos 
     54        1.4  christos #undef svc_fdset
     55        1.4  christos #undef svc_maxfd
     56       1.11  christos #ifdef _LIBC
     57        1.5  christos extern __fd_set_256 svc_fdset;
     58       1.11  christos #endif
     59        1.4  christos extern int svc_maxfd;
     60        1.9  christos int __svc_flags;
     61        1.4  christos 
     62        1.4  christos struct svc_fdset {
     63        1.9  christos 	/* select */
     64        1.2  christos 	fd_set *fdset;
     65        1.2  christos 	int	fdmax;
     66        1.2  christos 	int	fdsize;
     67        1.9  christos 	/* poll */
     68        1.9  christos 	struct pollfd *fdp;
     69        1.9  christos 	int	fdnum;
     70        1.9  christos 	int	fdused;
     71        1.2  christos };
     72        1.2  christos 
     73        1.2  christos /* The single threaded, one global fd_set version */
     74        1.4  christos static struct svc_fdset __svc_fdset;
     75        1.2  christos 
     76  1.16.24.1  perseant #ifdef _REENTRANT
     77        1.2  christos static thread_key_t fdsetkey = -2;
     78  1.16.24.1  perseant #endif
     79        1.2  christos 
     80        1.2  christos #ifdef FDSET_DEBUG
     81        1.2  christos 
     82        1.2  christos static void  __printflike(3, 0)
     83        1.2  christos svc_header(const char *func, size_t line, const char *fmt, va_list ap)
     84        1.2  christos {
     85        1.2  christos 	fprintf(stderr, "%s[%d.%d]: %s, %zu: ", getprogname(), (int)getpid(),
     86        1.2  christos 	    (int)_lwp_self(), func, line);
     87        1.2  christos 	vfprintf(stderr, fmt, ap);
     88        1.2  christos 	va_end(ap);
     89        1.2  christos }
     90        1.2  christos 
     91        1.4  christos static void __printflike(4, 5)
     92        1.4  christos svc_fdset_print(const char *func, size_t line, struct svc_fdset *fds,
     93        1.2  christos     const char *fmt, ...)
     94        1.2  christos {
     95        1.2  christos 	va_list ap;
     96        1.2  christos 	const char *did = "";
     97        1.2  christos 
     98        1.2  christos 	va_start(ap, fmt);
     99        1.2  christos 	svc_header(func, line, fmt, ap);
    100        1.2  christos 	va_end(ap);
    101        1.2  christos 
    102       1.12  christos 	fprintf(stderr, "%p[%d] fd_set<", fds->fdset, fds->fdmax);
    103        1.4  christos 	for (int i = 0; i <= fds->fdmax; i++) {
    104        1.4  christos 		if (!FD_ISSET(i, fds->fdset))
    105        1.2  christos 			continue;
    106        1.2  christos 		fprintf(stderr, "%s%d", did, i);
    107        1.2  christos 		did = ", ";
    108        1.2  christos 	}
    109       1.12  christos 	did = "";
    110       1.12  christos 	fprintf(stderr, "> poll<");
    111       1.12  christos 	for (int i = 0; i < fds->fdused; i++) {
    112       1.12  christos 		int fd = fds->fdp[i].fd;
    113       1.12  christos 		if (fd == -1)
    114       1.12  christos 			continue;
    115       1.12  christos 		fprintf(stderr, "%s%d", did, fd);
    116       1.12  christos 		did = ", ";
    117       1.12  christos 	}
    118        1.2  christos 	fprintf(stderr, ">\n");
    119        1.2  christos }
    120        1.2  christos 
    121        1.2  christos static void __printflike(3, 4)
    122        1.2  christos svc_print(const char *func, size_t line, const char *fmt, ...)
    123        1.2  christos {
    124        1.2  christos 	va_list ap;
    125        1.2  christos 
    126        1.2  christos 	va_start(ap, fmt);
    127        1.2  christos 	svc_header(func, line, fmt, ap);
    128        1.2  christos 	va_end(ap);
    129        1.2  christos 	fprintf(stderr, "\n");
    130        1.2  christos }
    131        1.2  christos 
    132        1.4  christos #define DPRINTF(...)		svc_print(__func__, __LINE__, __VA_ARGS__)
    133        1.2  christos #define DPRINTF_FDSET(...)	svc_fdset_print(__func__, __LINE__, __VA_ARGS__)
    134        1.4  christos 
    135        1.2  christos #else
    136        1.4  christos 
    137        1.4  christos #define DPRINTF(...)
    138        1.2  christos #define DPRINTF_FDSET(...)
    139        1.4  christos 
    140        1.2  christos #endif
    141        1.2  christos 
    142        1.2  christos 
    143        1.4  christos static inline void
    144        1.4  christos svc_fdset_sanitize(struct svc_fdset *fds)
    145        1.4  christos {
    146        1.4  christos 	while (fds->fdmax >= 0 && !FD_ISSET(fds->fdmax, fds->fdset))
    147        1.4  christos 		fds->fdmax--;
    148       1.11  christos #ifdef _LIBC
    149        1.4  christos 	/* Compat update */
    150        1.4  christos 	if (fds == &__svc_fdset) {
    151       1.15  christos 		svc_fdset = *(__fd_set_256 *)(void *)__svc_fdset.fdset;
    152        1.4  christos 		svc_maxfd = __svc_fdset.fdmax;
    153        1.4  christos 	}
    154       1.11  christos #endif
    155        1.4  christos }
    156        1.4  christos 
    157  1.16.24.1  perseant #ifdef _REENTRANT
    158        1.2  christos static void
    159        1.2  christos svc_fdset_free(void *v)
    160        1.2  christos {
    161        1.4  christos 	struct svc_fdset *fds = v;
    162        1.4  christos 	DPRINTF_FDSET(fds, "free");
    163        1.2  christos 
    164        1.9  christos 	free(fds->fdp);
    165        1.4  christos 	free(fds->fdset);
    166        1.4  christos 	free(fds);
    167        1.2  christos }
    168  1.16.24.1  perseant #endif
    169        1.2  christos 
    170        1.9  christos static void
    171        1.9  christos svc_pollfd_init(struct pollfd *pfd, int nfd)
    172        1.9  christos {
    173        1.9  christos 	for (int i = 0; i < nfd; i++) {
    174        1.9  christos 		pfd[i].fd = -1;
    175        1.9  christos 		pfd[i].events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND;
    176       1.10  christos 		pfd[i].revents = 0;
    177        1.9  christos 	}
    178        1.9  christos }
    179        1.9  christos 
    180        1.9  christos static struct pollfd *
    181        1.9  christos svc_pollfd_alloc(struct svc_fdset *fds)
    182        1.9  christos {
    183       1.12  christos 	if (fds->fdp != NULL)
    184       1.12  christos 		return fds->fdp;
    185       1.12  christos 
    186        1.9  christos 	fds->fdnum = FD_SETSIZE;
    187        1.9  christos 	fds->fdp = calloc(fds->fdnum, sizeof(*fds->fdp));
    188        1.9  christos 	if (fds->fdp == NULL)
    189        1.9  christos 		return NULL;
    190        1.9  christos 	svc_pollfd_init(fds->fdp, fds->fdnum);
    191        1.9  christos 	return fds->fdp;
    192        1.9  christos }
    193        1.9  christos 
    194        1.9  christos 
    195        1.9  christos static struct svc_fdset *
    196        1.9  christos svc_pollfd_add(int fd, struct svc_fdset *fds)
    197        1.9  christos {
    198        1.9  christos 	struct pollfd *pfd;
    199        1.9  christos 
    200        1.9  christos 	if ((pfd = svc_pollfd_alloc(fds)) == NULL)
    201        1.9  christos 		return NULL;
    202        1.9  christos 
    203        1.9  christos 	for (int i = 0; i < fds->fdnum; i++)
    204        1.9  christos 		if (pfd[i].fd == -1) {
    205       1.12  christos 			if (i >= fds->fdused)
    206        1.9  christos 				fds->fdused = i + 1;
    207       1.12  christos 			DPRINTF("add fd=%d slot=%d fdused=%d",
    208       1.12  christos 			    fd, i, fds->fdused);
    209        1.9  christos 			pfd[i].fd = fd;
    210        1.9  christos 			return fds;
    211        1.9  christos 		}
    212        1.9  christos 
    213        1.9  christos 	pfd = realloc(fds->fdp, (fds->fdnum + FD_SETSIZE) * sizeof(*fds->fdp));
    214        1.9  christos 	if (pfd == NULL)
    215        1.9  christos 		return NULL;
    216        1.9  christos 
    217        1.9  christos 	svc_pollfd_init(pfd + fds->fdnum, FD_SETSIZE);
    218        1.9  christos 	pfd[fds->fdnum].fd = fd;
    219        1.9  christos 	fds->fdused = fds->fdnum + 1;
    220       1.12  christos 	DPRINTF("add fd=%d slot=%d fdused=%d", fd, fds->fdnum, fds->fdused);
    221        1.9  christos 	fds->fdnum += FD_SETSIZE;
    222       1.14  christos 	fds->fdp = pfd;
    223        1.9  christos 	return fds;
    224        1.9  christos }
    225        1.9  christos 
    226        1.9  christos static struct svc_fdset *
    227        1.9  christos svc_pollfd_del(int fd, struct svc_fdset *fds)
    228        1.9  christos {
    229        1.9  christos 	struct pollfd *pfd;
    230        1.9  christos 
    231        1.9  christos 	if ((pfd = svc_pollfd_alloc(fds)) == NULL)
    232        1.9  christos 		return NULL;
    233        1.9  christos 
    234        1.9  christos 	for (int i = 0; i < fds->fdnum; i++) {
    235        1.9  christos 		if (pfd[i].fd != fd)
    236        1.9  christos 			continue;
    237        1.9  christos 
    238        1.9  christos 		pfd[i].fd = -1;
    239       1.12  christos 		DPRINTF("del fd=%d slot=%d", fd, fds->fdused);
    240        1.9  christos 		if (i != fds->fdused - 1)
    241        1.9  christos 			return fds;
    242        1.9  christos 
    243        1.9  christos 		do
    244        1.9  christos 			if (pfd[i].fd != -1)
    245        1.9  christos 				break;
    246        1.9  christos 		while (--i >= 0);
    247       1.12  christos 
    248        1.9  christos 		fds->fdused = i + 1;
    249       1.12  christos 		DPRINTF("del fd=%d fdused=%d", fd, fds->fdused);
    250        1.9  christos 		return fds;
    251        1.9  christos 	}
    252       1.12  christos 	DPRINTF("del fd=%d not found", fd);
    253        1.9  christos 	return NULL;
    254        1.9  christos }
    255        1.9  christos 
    256        1.4  christos static struct svc_fdset *
    257        1.4  christos svc_fdset_resize(int fd, struct svc_fdset *fds)
    258        1.2  christos {
    259        1.4  christos 	if (fds->fdset && fd < fds->fdsize) {
    260        1.4  christos 		DPRINTF_FDSET(fds, "keeping %d < %d", fd, fds->fdsize);
    261        1.4  christos 		return fds;
    262        1.2  christos 	}
    263        1.2  christos 
    264        1.2  christos 	fd += FD_SETSIZE;
    265        1.2  christos 
    266        1.4  christos 	char *newfdset = realloc(fds->fdset, __NFD_BYTES(fd));
    267        1.2  christos 	if (newfdset == NULL)
    268        1.2  christos 		return NULL;
    269        1.2  christos 
    270        1.4  christos 	memset(newfdset + __NFD_BYTES(fds->fdsize), 0,
    271        1.4  christos 	    __NFD_BYTES(fd) - __NFD_BYTES(fds->fdsize));
    272        1.2  christos 
    273        1.2  christos 
    274        1.4  christos 	fds->fdset = (void *)newfdset;
    275        1.4  christos 	DPRINTF_FDSET(fds, "resize %d > %d", fd, fds->fdsize);
    276        1.4  christos 	fds->fdsize = fd;
    277        1.2  christos 
    278        1.4  christos 	return fds;
    279        1.2  christos }
    280        1.2  christos 
    281        1.4  christos static struct svc_fdset *
    282        1.2  christos svc_fdset_alloc(int fd)
    283        1.2  christos {
    284  1.16.24.1  perseant #ifdef _REENTRANT
    285        1.4  christos 	struct svc_fdset *fds;
    286        1.2  christos 
    287        1.6  christos 	if (!__isthreaded || fdsetkey == -2)
    288        1.6  christos 		return svc_fdset_resize(fd, &__svc_fdset);
    289        1.6  christos 
    290        1.2  christos 	if (fdsetkey == -1)
    291        1.2  christos 		thr_keycreate(&fdsetkey, svc_fdset_free);
    292        1.2  christos 
    293        1.4  christos 	if ((fds = thr_getspecific(fdsetkey)) == NULL) {
    294        1.2  christos 
    295        1.4  christos 		fds = calloc(1, sizeof(*fds));
    296        1.4  christos 		if (fds == NULL)
    297        1.2  christos 			return NULL;
    298        1.2  christos 
    299        1.4  christos 		(void)thr_setspecific(fdsetkey, fds);
    300        1.2  christos 
    301        1.4  christos 		if (__svc_fdset.fdsize != 0) {
    302        1.4  christos 			*fds = __svc_fdset;
    303        1.4  christos 			DPRINTF("switching to %p", fds->fdset);
    304        1.2  christos 		} else {
    305        1.4  christos 			DPRINTF("first thread time %p", fds->fdset);
    306        1.2  christos 		}
    307        1.2  christos 	} else {
    308        1.4  christos 		DPRINTF("again for %p", fds->fdset);
    309        1.4  christos 		if (fd < fds->fdsize)
    310        1.4  christos 			return fds;
    311        1.2  christos 	}
    312        1.4  christos 
    313        1.4  christos 	return svc_fdset_resize(fd, fds);
    314  1.16.24.1  perseant #else
    315  1.16.24.1  perseant 	return svc_fdset_resize(fd, &__svc_fdset);
    316  1.16.24.1  perseant #endif
    317        1.2  christos }
    318        1.2  christos 
    319        1.2  christos /* allow each thread to have their own copy */
    320        1.2  christos void
    321        1.2  christos svc_fdset_init(int flags)
    322        1.2  christos {
    323        1.2  christos 	DPRINTF("%x", flags);
    324        1.9  christos 	__svc_flags = flags;
    325  1.16.24.1  perseant #ifdef _REENTRANT
    326        1.2  christos 	if ((flags & SVC_FDSET_MT) && fdsetkey == -2)
    327        1.2  christos 		fdsetkey = -1;
    328  1.16.24.1  perseant #endif
    329        1.2  christos }
    330        1.1  christos 
    331        1.1  christos void
    332        1.2  christos svc_fdset_zero(void)
    333        1.1  christos {
    334        1.2  christos 	DPRINTF("zero");
    335        1.9  christos 
    336        1.6  christos 	struct svc_fdset *fds = svc_fdset_alloc(0);
    337       1.14  christos 	if (fds == NULL)
    338       1.14  christos 		return;
    339        1.4  christos 	memset(fds->fdset, 0, fds->fdsize);
    340        1.6  christos 	fds->fdmax = -1;
    341        1.9  christos 
    342        1.9  christos 	free(fds->fdp);
    343        1.9  christos 	fds->fdp = NULL;
    344        1.9  christos 	fds->fdnum = fds->fdused = 0;
    345        1.1  christos }
    346        1.1  christos 
    347        1.7  christos int
    348        1.2  christos svc_fdset_set(int fd)
    349        1.1  christos {
    350        1.6  christos 	struct svc_fdset *fds = svc_fdset_alloc(fd);
    351        1.6  christos 
    352        1.7  christos 	if (fds == NULL)
    353        1.7  christos 		return -1;
    354        1.7  christos 
    355        1.4  christos 	FD_SET(fd, fds->fdset);
    356        1.4  christos 	if (fd > fds->fdmax)
    357        1.4  christos 		fds->fdmax = fd;
    358        1.6  christos 
    359       1.12  christos 	int rv = svc_pollfd_add(fd, fds) ? 0 : -1;
    360        1.4  christos 	DPRINTF_FDSET(fds, "%d", fd);
    361        1.1  christos 
    362        1.4  christos 	svc_fdset_sanitize(fds);
    363       1.12  christos 	return rv;
    364        1.2  christos }
    365        1.2  christos 
    366        1.2  christos int
    367        1.2  christos svc_fdset_isset(int fd)
    368        1.2  christos {
    369        1.6  christos 	struct svc_fdset *fds = svc_fdset_alloc(fd);
    370        1.6  christos 
    371        1.7  christos 	if (fds == NULL)
    372        1.7  christos 		return -1;
    373        1.7  christos 
    374        1.4  christos 	DPRINTF_FDSET(fds, "%d", fd);
    375        1.6  christos 
    376        1.7  christos 	return FD_ISSET(fd, fds->fdset) != 0;
    377        1.2  christos }
    378        1.2  christos 
    379        1.7  christos int
    380        1.2  christos svc_fdset_clr(int fd)
    381        1.2  christos {
    382        1.6  christos 	struct svc_fdset *fds = svc_fdset_alloc(fd);
    383        1.6  christos 
    384        1.7  christos 	if (fds == NULL)
    385        1.7  christos 		return -1;
    386        1.7  christos 
    387        1.4  christos 	FD_CLR(fd, fds->fdset);
    388       1.12  christos 
    389       1.12  christos 	int rv = svc_pollfd_del(fd, fds) ? 0 : -1;
    390        1.6  christos 	DPRINTF_FDSET(fds, "%d", fd);
    391        1.6  christos 
    392        1.4  christos 	svc_fdset_sanitize(fds);
    393       1.12  christos 	return rv;
    394        1.1  christos }
    395        1.1  christos 
    396        1.1  christos fd_set *
    397        1.2  christos svc_fdset_copy(const fd_set *orig)
    398        1.1  christos {
    399        1.4  christos 	int size = svc_fdset_getsize(0);
    400       1.16      maya 	if (size == -1)
    401       1.16      maya 		return NULL;
    402        1.4  christos 	fd_set *copy = calloc(1, __NFD_BYTES(size));
    403        1.4  christos 	if (copy == NULL)
    404        1.2  christos 		return NULL;
    405        1.2  christos 	if (orig)
    406        1.4  christos 		memcpy(copy, orig, __NFD_BYTES(size));
    407        1.4  christos 	return copy;
    408        1.2  christos }
    409        1.1  christos 
    410        1.2  christos fd_set *
    411        1.2  christos svc_fdset_get(void)
    412        1.2  christos {
    413        1.6  christos 	struct svc_fdset *fds = svc_fdset_alloc(0);
    414        1.4  christos 
    415        1.7  christos 	if (fds == NULL)
    416        1.7  christos 		return NULL;
    417        1.7  christos 
    418        1.4  christos 	DPRINTF_FDSET(fds, "get");
    419        1.6  christos 	svc_fdset_sanitize(fds);
    420        1.4  christos 	return fds->fdset;
    421        1.1  christos }
    422        1.1  christos 
    423        1.1  christos int *
    424        1.2  christos svc_fdset_getmax(void)
    425        1.2  christos {
    426        1.6  christos 	struct svc_fdset *fds = svc_fdset_alloc(0);
    427        1.2  christos 
    428        1.7  christos 	if (fds == NULL)
    429        1.7  christos 		return NULL;
    430        1.7  christos 
    431        1.6  christos 	DPRINTF_FDSET(fds, "getmax");
    432        1.6  christos 	svc_fdset_sanitize(fds);
    433        1.4  christos 	return &fds->fdmax;
    434        1.2  christos }
    435        1.2  christos 
    436        1.2  christos int
    437        1.2  christos svc_fdset_getsize(int fd)
    438        1.1  christos {
    439        1.6  christos 	struct svc_fdset *fds = svc_fdset_alloc(fd);
    440        1.2  christos 
    441        1.7  christos 	if (fds == NULL)
    442        1.7  christos 		return -1;
    443        1.7  christos 
    444        1.6  christos 	DPRINTF_FDSET(fds, "getsize");
    445        1.4  christos 	return fds->fdsize;
    446        1.1  christos }
    447        1.9  christos 
    448        1.9  christos struct pollfd *
    449        1.9  christos svc_pollfd_copy(const struct pollfd *orig)
    450        1.9  christos {
    451        1.9  christos 	int size = svc_fdset_getsize(0);
    452       1.13  christos 	if (size == -1)
    453       1.13  christos 		return NULL;
    454        1.9  christos 	struct pollfd *copy = calloc(size, sizeof(*orig));
    455        1.9  christos 	if (copy == NULL)
    456        1.9  christos 		return NULL;
    457        1.9  christos 	if (orig)
    458        1.9  christos 		memcpy(copy, orig, size * sizeof(*orig));
    459        1.9  christos 	return copy;
    460        1.9  christos }
    461        1.9  christos 
    462        1.9  christos struct pollfd *
    463        1.9  christos svc_pollfd_get(void)
    464        1.9  christos {
    465        1.9  christos 	struct svc_fdset *fds = svc_fdset_alloc(0);
    466        1.9  christos 
    467        1.9  christos 	if (fds == NULL)
    468        1.9  christos 		return NULL;
    469        1.9  christos 
    470        1.9  christos 	DPRINTF_FDSET(fds, "getpoll");
    471        1.9  christos 	return fds->fdp;
    472        1.9  christos }
    473        1.9  christos 
    474        1.9  christos int *
    475        1.9  christos svc_pollfd_getmax(void)
    476        1.9  christos {
    477        1.9  christos 	struct svc_fdset *fds = svc_fdset_alloc(0);
    478        1.9  christos 
    479        1.9  christos 	if (fds == NULL)
    480        1.9  christos 		return NULL;
    481        1.9  christos 	return &fds->fdused;
    482        1.9  christos }
    483        1.9  christos 
    484        1.9  christos int
    485        1.9  christos svc_pollfd_getsize(int fd)
    486        1.9  christos {
    487        1.9  christos 	struct svc_fdset *fds = svc_fdset_alloc(fd);
    488        1.9  christos 
    489        1.9  christos 	if (fds == NULL)
    490        1.9  christos 		return -1;
    491        1.9  christos 
    492        1.9  christos 	DPRINTF_FDSET(fds, "getsize");
    493        1.9  christos 	return fds->fdnum;
    494        1.9  christos }
    495