args[3] = (int)exceptfds;
args[4] = (int)timeout;
res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
- if (is_kerror(res)) {
- * (__errno_location()) = -res;
- return -1;
- } else {
- return res;
- }
+ return res;
}
indicating something interesting happened, or until our time is up.
Space out the polls with nanosleeps of say 20 milliseconds, which
is required to be nonblocking; this allows other threads to run.
+
+ Assumes:
+ * (checked via assert) types fd_set and vki_fd_set are identical.
+ * (checked via assert) types timeval and vki_timeval are identical.
+ * (unchecked) libc error numbers (EINTR etc) are the negation of the
+ kernel's error numbers (VKI_EINTR etc).
*/
#include <assert.h>
struct vki_timeval t_end;
struct vki_timeval zero_timeout;
struct vki_timespec nanosleep_interval;
+ int nanosleep_usec;
ensure_valgrind("select");
barf("valgrind's hacky non-blocking select(): data sizes error");
/* If a zero timeout specified, this call is harmless. */
- if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
- return do_syscall_select( n, (vki_fd_set*)rfds,
+ if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
+ res = do_syscall_select( n, (vki_fd_set*)rfds,
(vki_fd_set*)wfds,
(vki_fd_set*)xfds,
(struct vki_timeval*)timeout);
+ if (is_kerror(res)) {
+ * (__errno_location()) = -res;
+ return -1;
+ } else {
+ return res;
+ }
+ }
/* If a timeout was specified, set t_end to be the end wallclock
time. */
+
+ /* Sleep in 50 millisecond intervals, unless the total duration is
+ one second or less, in which case sleep in 20 millisecond
+ intervals. */
+ nanosleep_usec = 50 * 1000;
+
if (timeout) {
res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
assert(res == 0);
assert (t_end.tv_sec > t_now.tv_sec
|| (t_end.tv_sec == t_now.tv_sec
&& t_end.tv_usec >= t_now.tv_usec));
+ if (timeout->tv_sec == 0)
+ nanosleep_usec = 20 * 1000;
}
/* fprintf(stderr, "MY_SELECT: before loop\n"); */
wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
& zero_timeout );
- if (res < 0) {
- /* some kind of error (including EINTR); errno is set, so just
+ if (is_kerror(res)) {
+ /* Some kind of error (including EINTR). Set errno and
return. The sets are unspecified in this case. */
- return res;
+ * (__errno_location()) = -res;
+ return -1;
}
if (res > 0) {
/* one or more fds is ready. Copy out resulting sets and
}
/* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
/* nanosleep and go round again */
- nanosleep_interval.tv_sec = 0;
- nanosleep_interval.tv_nsec = 20 * 1000 * 1000; /* 20 milliseconds */
+ nanosleep_interval.tv_sec = 0;
+ nanosleep_interval.tv_nsec = 1000 * nanosleep_usec;
/* It's critical here that valgrind's nanosleep implementation
is nonblocking. */
(void)my_do_syscall2(__NR_nanosleep,
args[3] = (int)exceptfds;
args[4] = (int)timeout;
res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
- if (is_kerror(res)) {
- * (__errno_location()) = -res;
- return -1;
- } else {
- return res;
- }
+ return res;
}
indicating something interesting happened, or until our time is up.
Space out the polls with nanosleeps of say 20 milliseconds, which
is required to be nonblocking; this allows other threads to run.
+
+ Assumes:
+ * (checked via assert) types fd_set and vki_fd_set are identical.
+ * (checked via assert) types timeval and vki_timeval are identical.
+ * (unchecked) libc error numbers (EINTR etc) are the negation of the
+ kernel's error numbers (VKI_EINTR etc).
*/
#include <assert.h>
struct vki_timeval t_end;
struct vki_timeval zero_timeout;
struct vki_timespec nanosleep_interval;
+ int nanosleep_usec;
ensure_valgrind("select");
barf("valgrind's hacky non-blocking select(): data sizes error");
/* If a zero timeout specified, this call is harmless. */
- if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
- return do_syscall_select( n, (vki_fd_set*)rfds,
+ if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
+ res = do_syscall_select( n, (vki_fd_set*)rfds,
(vki_fd_set*)wfds,
(vki_fd_set*)xfds,
(struct vki_timeval*)timeout);
+ if (is_kerror(res)) {
+ * (__errno_location()) = -res;
+ return -1;
+ } else {
+ return res;
+ }
+ }
/* If a timeout was specified, set t_end to be the end wallclock
time. */
+
+ /* Sleep in 50 millisecond intervals, unless the total duration is
+ one second or less, in which case sleep in 20 millisecond
+ intervals. */
+ nanosleep_usec = 50 * 1000;
+
if (timeout) {
res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
assert(res == 0);
assert (t_end.tv_sec > t_now.tv_sec
|| (t_end.tv_sec == t_now.tv_sec
&& t_end.tv_usec >= t_now.tv_usec));
+ if (timeout->tv_sec == 0)
+ nanosleep_usec = 20 * 1000;
}
/* fprintf(stderr, "MY_SELECT: before loop\n"); */
wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
& zero_timeout );
- if (res < 0) {
- /* some kind of error (including EINTR); errno is set, so just
+ if (is_kerror(res)) {
+ /* Some kind of error (including EINTR). Set errno and
return. The sets are unspecified in this case. */
- return res;
+ * (__errno_location()) = -res;
+ return -1;
}
if (res > 0) {
/* one or more fds is ready. Copy out resulting sets and
}
/* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
/* nanosleep and go round again */
- nanosleep_interval.tv_sec = 0;
- nanosleep_interval.tv_nsec = 20 * 1000 * 1000; /* 20 milliseconds */
+ nanosleep_interval.tv_sec = 0;
+ nanosleep_interval.tv_nsec = 1000 * nanosleep_usec;
/* It's critical here that valgrind's nanosleep implementation
is nonblocking. */
(void)my_do_syscall2(__NR_nanosleep,
args[3] = (int)exceptfds;
args[4] = (int)timeout;
res = my_do_syscall1(__NR_select, (int)(&(args[0])) );
- if (is_kerror(res)) {
- * (__errno_location()) = -res;
- return -1;
- } else {
- return res;
- }
+ return res;
}
indicating something interesting happened, or until our time is up.
Space out the polls with nanosleeps of say 20 milliseconds, which
is required to be nonblocking; this allows other threads to run.
+
+ Assumes:
+ * (checked via assert) types fd_set and vki_fd_set are identical.
+ * (checked via assert) types timeval and vki_timeval are identical.
+ * (unchecked) libc error numbers (EINTR etc) are the negation of the
+ kernel's error numbers (VKI_EINTR etc).
*/
#include <assert.h>
struct vki_timeval t_end;
struct vki_timeval zero_timeout;
struct vki_timespec nanosleep_interval;
+ int nanosleep_usec;
ensure_valgrind("select");
barf("valgrind's hacky non-blocking select(): data sizes error");
/* If a zero timeout specified, this call is harmless. */
- if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
- return do_syscall_select( n, (vki_fd_set*)rfds,
+ if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
+ res = do_syscall_select( n, (vki_fd_set*)rfds,
(vki_fd_set*)wfds,
(vki_fd_set*)xfds,
(struct vki_timeval*)timeout);
+ if (is_kerror(res)) {
+ * (__errno_location()) = -res;
+ return -1;
+ } else {
+ return res;
+ }
+ }
/* If a timeout was specified, set t_end to be the end wallclock
time. */
+
+ /* Sleep in 50 millisecond intervals, unless the total duration is
+ one second or less, in which case sleep in 20 millisecond
+ intervals. */
+ nanosleep_usec = 50 * 1000;
+
if (timeout) {
res = my_do_syscall2(__NR_gettimeofday, (int)&t_now, (int)NULL);
assert(res == 0);
assert (t_end.tv_sec > t_now.tv_sec
|| (t_end.tv_sec == t_now.tv_sec
&& t_end.tv_usec >= t_now.tv_usec));
+ if (timeout->tv_sec == 0)
+ nanosleep_usec = 20 * 1000;
}
/* fprintf(stderr, "MY_SELECT: before loop\n"); */
wfds ? (vki_fd_set*)(&wfds_copy) : NULL,
xfds ? (vki_fd_set*)(&xfds_copy) : NULL,
& zero_timeout );
- if (res < 0) {
- /* some kind of error (including EINTR); errno is set, so just
+ if (is_kerror(res)) {
+ /* Some kind of error (including EINTR). Set errno and
return. The sets are unspecified in this case. */
- return res;
+ * (__errno_location()) = -res;
+ return -1;
}
if (res > 0) {
/* one or more fds is ready. Copy out resulting sets and
}
/* fprintf(stderr, "MY_SELECT: nanosleep\n"); */
/* nanosleep and go round again */
- nanosleep_interval.tv_sec = 0;
- nanosleep_interval.tv_nsec = 20 * 1000 * 1000; /* 20 milliseconds */
+ nanosleep_interval.tv_sec = 0;
+ nanosleep_interval.tv_nsec = 1000 * nanosleep_usec;
/* It's critical here that valgrind's nanosleep implementation
is nonblocking. */
(void)my_do_syscall2(__NR_nanosleep,