select.diff

nthery, 12/26/2007 06:15 PM

Download (15 KB)

View differences:

dfly/src/sys/kern/sys_generic.c 2007-12-25 13:10:32.000000000 +0100
77 77
static MALLOC_DEFINE(M_SELECT, "select", "select() buffer");
78 78
MALLOC_DEFINE(M_IOV, "iov", "large iov's");
79 79

  
80
static int 	doselect(int nd, fd_set *in, fd_set *ou, fd_set *ex,
81
			struct timeval *tv, int *res);
80 82
static int	pollscan (struct proc *, struct pollfd *, u_int, int *);
81 83
static int	selscan (struct proc *, fd_mask **, fd_mask **,
82 84
			int, int *);
......
760 762
int
761 763
sys_select(struct select_args *uap)
762 764
{
765
	struct timeval ktv;
766
	struct timeval *ktvp;
767
	int error;
768

  
769
	/*
770
	 * Get timeout if any.
771
	 */
772
	if (uap->tv != NULL) {
773
		error = copyin(uap->tv, &ktv, sizeof (ktv));
774
		if (error)
775
			return (error);
776
		error = itimerfix(&ktv);
777
		if (error)
778
			return (error);
779
		ktvp = &ktv;
780
	} else {
781
		ktvp = NULL;
782
	}
783

  
784

  
785
	/*
786
	 * Do real work.
787
	 */
788
	error = doselect(uap->nd, uap->in, uap->ou, uap->ex, ktvp,
789
			&uap->sysmsg_result);
790

  
791

  
792
	/*
793
	 * XXX write back updated timeout value to userland if any.
794
	 */
795

  
796
	return (error);
797
}
798

  
799

  
800
/*
801
 * Pselect system call.
802
 */
803
int
804
sys_pselect(struct pselect_args *uap)
805
{
806
	struct timespec kts;
807
	struct timeval ktv;
808
	struct timeval *ktvp;
809
	sigset_t sigmask;
810
	sigset_t osigmask;
811
	int error;
812

  
813
	/*
814
	 * Get timeout if any and convert it.
815
	 * Round up during conversion to avoid timeout going off early.
816
	 */
817
	if (uap->ts != NULL) {
818
		error = copyin(uap->ts, &kts, sizeof (kts));
819
		if (error)
820
			return (error);
821
		ktv.tv_sec = kts.tv_sec;
822
		ktv.tv_usec = (kts.tv_nsec + 999) / 1000;
823
		error = itimerfix(&ktv);
824
		if (error)
825
			return (error);
826
		ktvp = &ktv;
827
	} else {
828
		ktvp = NULL;
829
	}
830

  
831
	/*
832
	 * Install temporary signal mask if any.
833
	 */
834
	if (uap->sigmask != NULL) {
835
		error = copyin(uap->sigmask, &sigmask, sizeof(sigmask));
836
		if (error)
837
			return (error);
838
		(void) kern_sigprocmask(SIG_SETMASK, &sigmask, &osigmask);
839
	}
840

  
841
	/*
842
	 * Do real job.
843
	 */
844
	error = doselect(uap->nd, uap->in, uap->ou, uap->ex, ktvp,
845
			&uap->sysmsg_result);
846

  
847
	/*
848
	 * Restore previous signal mask if necessary.
849
	 */
850
	if (uap->sigmask != NULL) {
851
		(void) kern_sigprocmask(SIG_SETMASK, &osigmask, NULL);
852
	}
853

  
854
	return (error);
855
}
856

  
857
/*
858
 * Common code for sys_select() and sys_pselect().
859
 *
860
 * in, out and ex are userland pointers.  tv must point to validated
861
 * kernel-side timeout value or NULL for infinite timeout.  res must
862
 * point to syscall return value.
863
 */
864
static int
865
doselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv,
866
		int *res)
867
{
763 868
	struct lwp *lp = curthread->td_lwp;
764 869
	struct proc *p = curproc;
765 870

  
......
775 880
	int ncoll, error, timo;
776 881
	u_int nbufbytes, ncpbytes, nfdbits;
777 882

  
778
	if (uap->nd < 0)
883
	if (nd < 0)
779 884
		return (EINVAL);
780
	if (uap->nd > p->p_fd->fd_nfiles)
781
		uap->nd = p->p_fd->fd_nfiles;   /* forgiving; slightly wrong */
885
	if (nd > p->p_fd->fd_nfiles)
886
		nd = p->p_fd->fd_nfiles;   /* forgiving; slightly wrong */
782 887

  
783 888
	/*
784 889
	 * Allocate just enough bits for the non-null fd_sets.  Use the
785 890
	 * preallocated auto buffer if possible.
786 891
	 */
787
	nfdbits = roundup(uap->nd, NFDBITS);
892
	nfdbits = roundup(nd, NFDBITS);
788 893
	ncpbytes = nfdbits / NBBY;
789 894
	nbufbytes = 0;
790
	if (uap->in != NULL)
895
	if (in != NULL)
791 896
		nbufbytes += 2 * ncpbytes;
792
	if (uap->ou != NULL)
897
	if (ou != NULL)
793 898
		nbufbytes += 2 * ncpbytes;
794
	if (uap->ex != NULL)
899
	if (ex != NULL)
795 900
		nbufbytes += 2 * ncpbytes;
796 901
	if (nbufbytes <= sizeof s_selbits)
797 902
		selbits = &s_selbits[0];
......
806 911
	sbp = selbits;
807 912
#define	getbits(name, x) \
808 913
	do {								\
809
		if (uap->name == NULL)					\
914
		if (name == NULL)					\
810 915
			ibits[x] = NULL;				\
811 916
		else {							\
812 917
			ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp;	\
813 918
			obits[x] = sbp;					\
814 919
			sbp += ncpbytes / sizeof *sbp;			\
815
			error = copyin(uap->name, ibits[x], ncpbytes);	\
920
			error = copyin(name, ibits[x], ncpbytes);	\
816 921
			if (error != 0)					\
817 922
				goto done;				\
818 923
		}							\
......
824 929
	if (nbufbytes != 0)
825 930
		bzero(selbits, nbufbytes / 2);
826 931

  
827
	if (uap->tv) {
828
		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
829
			sizeof (atv));
830
		if (error)
831
			goto done;
832
		if (itimerfix(&atv)) {
833
			error = EINVAL;
834
			goto done;
835
		}
932
	if (tv != NULL) {
933
		atv = *tv;
836 934
		getmicrouptime(&rtv);
837 935
		timevaladd(&atv, &rtv);
838 936
	} else {
......
843 941
retry:
844 942
	ncoll = nselcoll;
845 943
	lp->lwp_flag |= LWP_SELECT;
846
	error = selscan(p, ibits, obits, uap->nd, &uap->sysmsg_result);
847
	if (error || uap->sysmsg_result)
944
	error = selscan(p, ibits, obits, nd, res);
945
	if (error || *res)
848 946
		goto done;
849 947
	if (atv.tv_sec || atv.tv_usec) {
850 948
		getmicrouptime(&rtv);
851
		if (timevalcmp(&rtv, &atv, >=)) 
949
		if (timevalcmp(&rtv, &atv, >=))
852 950
			goto done;
853 951
		ttv = atv;
854 952
		timevalsub(&ttv, &rtv);
......
875 973
	if (error == EWOULDBLOCK)
876 974
		error = 0;
877 975
#define	putbits(name, x) \
878
	if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \
976
	if (name && (error2 = copyout(obits[x], name, ncpbytes))) \
879 977
		error = error2;
880 978
	if (error == 0) {
881 979
		int error2;
dfly/src/sys/kern/syscalls.master 2007-12-25 13:10:32.000000000 +0100
681 681
496	STD	BSD	{ lwpid_t lwp_gettid(void); }
682 682
497	STD	BSD	{ int lwp_kill(pid_t pid, lwpid_t tid, int signum); }
683 683
498	STD	BSD	{ int lwp_rtprio(int function, pid_t pid, lwpid_t tid, struct rtprio *rtp); }
684
499	STD	BSD	{ int pselect(int nd, fd_set *in, fd_set *ou, \
685
			    fd_set *ex, const struct timespec *ts,    \
686
			    const sigset_t *sigmask); }
dfly/src/include/unistd.h 2007-12-25 13:10:32.000000000 +0100
195 195
struct timeval;				/* select(2) */
196 196
int	 select(int, fd_set * __restrict, fd_set * __restrict,
197 197
		fd_set * __restrict, struct timeval * __restrict);
198
struct timespec;			/* pselect(2) */
199
int	 pselect(int, fd_set * __restrict, fd_set * __restrict,
200
		fd_set * __restrict, const struct timespec * __restrict,
201
		const sigset_t * __restrict);
198 202
#endif
199 203
int	 setdomainname(const char *, int);
200 204
int	 setegid(gid_t);
dfly/src/sys/sys/select.h 2007-12-25 13:10:33.000000000 +0100
85 85
struct timeval;
86 86
int	select(int, fd_set * __restrict, fd_set * __restrict,
87 87
	       fd_set * __restrict, struct timeval * __restrict);
88
struct timespec;
89
int	 pselect(int, fd_set * __restrict, fd_set * __restrict,
90
		fd_set * __restrict, const struct timespec * __restrict,
91
		const sigset_t * __restrict);
88 92
#endif
89 93
__END_DECLS
90 94

  
dfly/src/lib/libthread_xu/thread/thr_syscalls.c 2007-12-25 13:10:33.000000000 +0100
95 95

  
96 96
extern int	__creat(const char *, mode_t);
97 97
extern int	__pause(void);
98
extern int	__pselect(int, fd_set *, fd_set *, fd_set *,
98
extern int	__sys_pselect(int, fd_set *, fd_set *, fd_set *,
99 99
			const struct timespec *, const sigset_t *);
100 100
extern unsigned	__sleep(unsigned int);
101 101
extern int	__system(const char *);
......
382 382
}
383 383

  
384 384
__strong_reference(__poll, poll);
385
#if 0
386 385

  
387 386
int 
388
_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, 
387
__pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
389 388
	const struct timespec *timo, const sigset_t *mask)
390 389
{
391 390
	struct pthread *curthread = tls_get_curthread();
......
393 392
	int ret;
394 393

  
395 394
	oldcancel = _thr_cancel_enter(curthread);
396
	ret = __pselect(count, rfds, wfds, efds, timo, mask);
395
	ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
397 396
	_thr_cancel_leave(curthread, oldcancel);
398 397

  
399 398
	return (ret);
400 399
}
401
__strong_reference(_pselect, pselect);
402
#endif
400
__strong_reference(__pselect, pselect);
403 401

  
404 402

  
405 403
int
dfly/src/lib/libc_r/uthread/uthread_select.c 2007-12-25 13:18:13.000000000 +0100
228 228

  
229 229
	return ret;
230 230
}
231

  
232

  
233
int
234
pselect(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
235
	const struct timespec *timeout, const sigset_t *mask)
236
{
237
	sigset_t omask;
238
	struct timeval tv;
239
	struct timeval *tvp;
240
	int ret;
241

  
242
	_thread_enter_cancellation_point();
243

  
244
	if (timeout != NULL) {
245
		tv.tv_sec = timeout->tv_sec;
246
		tv.tv_usec = (timeout->tv_nsec + 999) / 1000;
247
		tvp = &tv;
248
	} else {
249
		tvp = NULL;
250
	}
251

  
252
	/*
253
	 * XXX The masking/select/unmasking sequence below is not atomic.  See
254
	 * man page.
255
	 *
256
	 * The Right Thing would be to mask/unmask signals kernel-side.  We do
257
	 * this for single-threaded and libthread_xu processes but this is far
258
	 * from trivial for libc_r because select() is actually a poll()
259
	 * wrapper there and not using poll() would involve complex changes in
260
	 * the user thread scheduler.  We're deprecating libc_r in favor of
261
	 * libthread_xu so the usefulness of such a change is questionable.
262
	 */
263

  
264
	if (mask != NULL)
265
		(void) sigprocmask(SIG_SETMASK, mask, &omask);
266

  
267
	ret = _select(numfds, readfds, writefds, exceptfds, tvp);
268

  
269
	if (mask != NULL)
270
		(void) sigprocmask(SIG_SETMASK, &omask, NULL);
271

  
272
	_thread_leave_cancellation_point();
273

  
274
	return ret;
275
}
dfly/src/lib/libc/sys/Makefile.inc 2007-12-25 13:10:33.000000000 +0100
91 91
	sigstack.2 sigsuspend.2 socket.2 socketpair.2 stat.2 statfs.2 \
92 92
	swapon.2 symlink.2 sync.2 sysarch.2 syscall.2 syslink.2 \
93 93
	truncate.2 tls.2 umask.2 umtx.2 undelete.2 \
94
	unlink.2 utimes.2 upc_register.2 usched_set.2 uuidgen.2 vfork.2 wait.2 write.2
94
	unlink.2 utimes.2 upc_register.2 usched_set.2 uuidgen.2 vfork.2 \
95
	wait.2 write.2 pselect.2
96

  
95 97
.if !defined(NO_P1003_1B)
96 98
MAN+=	sched_get_priority_max.2 sched_setparam.2 \
97 99
	sched_setscheduler.2 sched_yield.2
dfly/src/lib/libc/sys/pselect.2 2007-12-25 13:13:39.000000000 +0100
1
.\"
2
.\" Copyright 2002 Massachusetts Institute of Technology
3
.\"
4
.\" Permission to use, copy, modify, and distribute this software and
5
.\" its documentation for any purpose and without fee is hereby
6
.\" granted, provided that both the above copyright notice and this
7
.\" permission notice appear in all copies, that both the above
8
.\" copyright notice and this permission notice appear in all
9
.\" supporting documentation, and that the name of M.I.T. not be used
10
.\" in advertising or publicity pertaining to distribution of the
11
.\" software without specific, written prior permission.  M.I.T. makes
12
.\" no representations about the suitability of this software for any
13
.\" purpose.  It is provided "as is" without express or implied
14
.\" warranty.
15
.\"
16
.\" THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
17
.\" ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20
.\" SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26
.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
.\" SUCH DAMAGE.
28
.\"
29
.\" $FreeBSD: src/lib/libc/gen/pselect.3,v 1.4 2002/12/18 10:13:54 ru Exp $
30
.\"
31
.Dd December 24, 2007
32
.Dt PSELECT 2
33
.Os
34
.Sh NAME
35
.Nm pselect
36
.Nd synchronous I/O multiplexing a la POSIX.1g
37
.Sh LIBRARY
38
.Lb libc
39
.Sh SYNOPSIS
40
.In sys/select.h
41
.Ft int
42
.Fo pselect
43
.Fa "int nfds"
44
.Fa "fd_set * restrict readfds"
45
.Fa "fd_set * restrict writefds"
46
.Fa "fd_set * restrict exceptfds"
47
.Fa "const struct timespec * restrict timeout"
48
.Fa "const sigset_t * restrict newsigmask"
49
.Fc
50
.Sh DESCRIPTION
51
The
52
.Fn pselect
53
function was introduced by
54
.St -p1003.1g-2000
55
as a slightly stronger version of
56
.Xr select 2 .
57
The
58
.Fa nfds , readfds , writefds ,
59
and
60
.Fa exceptfds
61
arguments are all identical to the analogous arguments of
62
.Fn select .
63
The
64
.Fa timeout
65
argument in
66
.Fn pselect
67
points to a
68
.Vt "const struct timespec"
69
rather than the (modifiable)
70
.Vt "struct timeval"
71
used by
72
.Fn select ;
73
as in
74
.Fn select ,
75
a null pointer may be passed to indicate that
76
.Fn pselect
77
should wait indefinitely.
78
Finally,
79
.Fa newsigmask
80
specifies a signal mask which is set while waiting for input.
81
When
82
.Fn pselect
83
returns, the original signal mask is restored.
84
.Pp
85
See
86
.Xr select 2
87
for a more detailed discussion of the semantics of this interface, and
88
for macros used to manipulate the
89
.Vt "fd_set"
90
data type.
91
.Sh RETURN VALUES
92
The
93
.Fn pselect
94
function returns the same values and under the same conditions as
95
.Fn select .
96
.Sh ERRORS
97
The
98
.Fn pselect
99
function may fail for any of the reasons documented for
100
.Xr select 2
101
and (if a signal mask is provided)
102
.Xr sigprocmask 2 .
103
.Sh SEE ALSO
104
.Xr kqueue 2 ,
105
.Xr poll 2 ,
106
.Xr select 2 ,
107
.Xr sigprocmask 2
108
.Sh STANDARDS
109
The
110
.Fn pselect
111
function conforms to
112
.St -p1003.1-2001 .
113
.Sh BUGS
114
The
115
.Fn pselect
116
implementation in libc_r (user multi-threading) does not mask signals, calls
117
.Fn select ,
118
and restores the original signal mask atomically.  A calling user thread
119
using
120
.Fn pselect
121
to block until either a signal occurs or some descriptor changes may therefore
122
block forever.
123
The
124
.Fn pselect
125
implementations in libthread_xu (kernel multi-threading) and libc
126
(single-threading) operate atomically and are therefore race-free.
127
.Sh HISTORY
128
The
129
.Fn pselect
130
function first appeared in
131
.Dx 1.11 .
132
.Sh AUTHORS
133
This manual page was originally written by
134
.An Garrett Wollman Aq wollman@FreeBSD.org
135
for FreeBSD and later modified for DragonFly.
dfly/src/lib/libbind/port_after.h 2007-12-25 13:11:50.000000000 +0100
13 13
#include <inttypes.h>
14 14
#endif
15 15

  
16
#define NEED_PSELECT
17 16
#define HAVE_SA_LEN 1
18 17
#define HAVE_MINIMUM_IFREQ 1
19 18
#undef NEED_DAEMON