Merge with git+ssh://master.kernel.org/pub/scm/libs/klibc/klibc.git
diff --git a/usr/include/sys/time.h b/usr/include/sys/time.h
index 65115b5..7a2f8b9 100644
--- a/usr/include/sys/time.h
+++ b/usr/include/sys/time.h
@@ -6,9 +6,45 @@
#define _SYS_TIME_H
#include <klibc/extern.h>
+#include <stddef.h>
#include <sys/types.h>
#include <linux/time.h>
+/* The 2.6.20 Linux headers always #define FD_ZERO __FD_ZERO, etc, in
+ <linux/time.h> but not all architectures define the
+ double-underscore ones, except __NFDBITS, __FD_SETSIZE and
+ __FDSET_LONGS which are defined in <linux/posix_types.h>.
+
+ Unfortunately, some architectures define the double-underscore ones
+ as inlines, so we can't use a simple #ifdef test. Thus, the only
+ safe option remaining is to #undef the top-level macros. */
+
+#undef FD_ZERO
+#undef FD_SET
+#undef FD_CLR
+#undef FD_ISSET
+
+__extern void *memset(void *, int, size_t);
+static inline void FD_ZERO(fd_set *__fdsetp)
+{
+ memset(__fdsetp, 0, sizeof(fd_set));
+}
+static inline void FD_SET(int __fd, fd_set *__fdsetp)
+{
+ __fdsetp->fds_bits[__fd/BITS_PER_LONG] |=
+ (1UL << (__fd % BITS_PER_LONG));
+}
+static inline void FD_CLR(int __fd, fd_set *__fdsetp)
+{
+ __fdsetp->fds_bits[__fd/BITS_PER_LONG] &=
+ ~(1UL << (__fd % BITS_PER_LONG));
+}
+static inline int FD_ISSET(int __fd, fd_set *__fdsetp)
+{
+ return (__fdsetp->fds_bits[__fd/BITS_PER_LONG] >>
+ (__fd % BITS_PER_LONG)) & 1;
+}
+
__extern int gettimeofday(struct timeval *, struct timezone *);
__extern int settimeofday(const struct timeval *, const struct timezone *);
__extern int getitimer(int, struct itimerval *);
diff --git a/usr/klibc/tests/Kbuild b/usr/klibc/tests/Kbuild
index 75d8bb3..07e8d64 100644
--- a/usr/klibc/tests/Kbuild
+++ b/usr/klibc/tests/Kbuild
@@ -31,6 +31,7 @@
opentest.shared-y := opentest.o
pipetest.shared-y := pipetest.o
rtsig.shared-y := rtsig.o
+select.shared-y := select.o
setenvtest.shared-y := setenvtest.o
setjmptest.shared-y := setjmptest.o
sigint.shared-y := sigint.o
diff --git a/usr/klibc/tests/select.c b/usr/klibc/tests/select.c
new file mode 100644
index 0000000..db75c55
--- /dev/null
+++ b/usr/klibc/tests/select.c
@@ -0,0 +1,55 @@
+/*
+ * Simple test of select()
+ */
+
+#include <sys/select.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ int fdn, fdz, pfd[2], rv;
+ fd_set readset;
+ struct timeval timeout;
+ int err = 0;
+
+ /* We can always read from /dev/zero; open a pipe that is never
+ ready for a "never readable" file descriptor */
+ fdz = open("/dev/zero", O_RDONLY);
+ pipe(pfd);
+ fdn = pfd[0];
+
+ FD_ZERO(&readset);
+ FD_SET(fdn, &readset);
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 100000;
+
+ rv = select(FD_SETSIZE, &readset, NULL, NULL, &timeout);
+
+ if (rv != 0) {
+ fprintf(stderr,
+ "select with timeout failed (rv = %d, errno = %s)\n",
+ rv, strerror(errno));
+ err++;
+ }
+
+ FD_ZERO(&readset);
+ FD_SET(fdn, &readset);
+ FD_SET(fdz, &readset);
+
+ rv = select(FD_SETSIZE, &readset, NULL, NULL, &timeout);
+
+ if (rv != 1 || !FD_ISSET(fdz, &readset) ||
+ FD_ISSET(fdn, &readset)) {
+ fprintf(stderr,
+ "select with /dev/zero failed (rv = %d, errno = %s)\n",
+ rv, strerror(errno));
+ err++;
+ }
+
+ return err;
+}