[klibc] Support for pselect, ppoll, sync_file_range, splice, tee
New system call bonanza. Defined splice() and tee() in <sys/splice.h>;
sync_file_range() in <unistd.h>, pselect() in <sys/select.h> (per POSIX)
and ppoll in <sys/poll.h>. Make <poll.h> -> <sys/poll.h>.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
diff --git a/include/poll.h b/include/poll.h
index 8710d92..06fb41a 100644
--- a/include/poll.h
+++ b/include/poll.h
@@ -1,16 +1 @@
-/*
- * poll.h
- */
-
-#ifndef _POLL_H
-#define _POLL_H
-
-#include <klibc/extern.h>
-#include <linux/poll.h>
-
-/* POSIX specifies "int" for the timeout, Linux seems to use long... */
-
-typedef unsigned int nfds_t;
-__extern int poll(struct pollfd *, nfds_t, long);
-
-#endif /* _POLL_H */
+#include <sys/poll.h>
diff --git a/include/sys/poll.h b/include/sys/poll.h
new file mode 100644
index 0000000..56feade
--- /dev/null
+++ b/include/sys/poll.h
@@ -0,0 +1,20 @@
+/*
+ * poll.h
+ */
+
+#ifndef _POLL_H
+#define _POLL_H
+
+#include <klibc/extern.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <linux/poll.h>
+
+/* POSIX specifies "int" for the timeout, Linux seems to use long... */
+
+typedef unsigned int nfds_t;
+__extern int poll(struct pollfd *, nfds_t, long);
+__extern int ppoll(struct pollfd *, nfds_t, struct timespec *,
+ const sigset_t *);
+
+#endif /* _POLL_H */
diff --git a/include/sys/select.h b/include/sys/select.h
index 361a1a5..5a7dcf7 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -8,7 +8,10 @@
#include <klibc/extern.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <signal.h>
__extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+__extern int pselect(int, fd_set *, fd_set *, fd_set *,
+ const struct timespec *, const sigset_t *);
#endif /* _SYS_SELECT_H */
diff --git a/include/sys/splice.h b/include/sys/splice.h
new file mode 100644
index 0000000..5f30982
--- /dev/null
+++ b/include/sys/splice.h
@@ -0,0 +1,19 @@
+/*
+ * sys/splice.h
+ */
+
+#ifndef _SYS_SPLICE_H
+#define _SYS_SPLICE_H
+
+/* move pages instead of copying */
+#define SPLICE_F_MOVE 1
+/* don't block on the pipe splicing (but we may still block on the fd
+ we splice from/to, of course */
+#define SPLICE_F_NONBLOCK 2
+/* expect more data */
+#define SPLICE_F_MORE 4
+
+__extern int splice(int, off_t *, int, off_t *, size_t, unsigned int);
+__extern int tee(int, int, size_t, unsigned int);
+
+#endif /* _SYS_SPLICE_H */
diff --git a/include/unistd.h b/include/unistd.h
index d0f9392..ceb97fc 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -81,8 +81,6 @@
__extern int lchown(const char *, uid_t, gid_t);
__extern char *getcwd(char *, size_t);
-__extern int sync(void);
-
/* Also in <fcntl.h> */
#ifndef _KLIBC_IN_OPEN_C
__extern int open(const char *, int, ...);
@@ -105,9 +103,19 @@
__extern int fcntl(int, int, ...);
__extern int ioctl(int, int, void *);
__extern int flock(int, int);
+__extern int ftruncate(int, off_t);
+
+/*
+ * Macros for sync_file_range()
+ */
+#define SYNC_FILE_RANGE_WAIT_BEFORE 1
+#define SYNC_FILE_RANGE_WRITE 2
+#define SYNC_FILE_RANGE_WAIT_AFTER 4
+
+__extern int sync(void);
__extern int fsync(int);
__extern int fdatasync(int);
-__extern int ftruncate(int, off_t);
+__extern int sync_file_range(int, off_t, off_t, unsigned int);
__extern int pause(void);
__extern unsigned int alarm(unsigned int);
diff --git a/klibc/Kbuild b/klibc/Kbuild
index fb50a1c..c324909 100644
--- a/klibc/Kbuild
+++ b/klibc/Kbuild
@@ -25,6 +25,7 @@
__signal.o sysv_signal.o bsd_signal.o siglist.o sigabbrev.o \
siglongjmp.o \
sigaction.o sigpending.o sigprocmask.o sigsuspend.o \
+ pselect.o ppoll.o \
brk.o sbrk.o malloc.o realloc.o calloc.o mmap.o \
memcpy.o memcmp.o memset.o memccpy.o memmem.o memswap.o \
memmove.o memchr.o memrchr.o \
diff --git a/klibc/SYSCALLS.def b/klibc/SYSCALLS.def
index b7d0daf..89c0550 100644
--- a/klibc/SYSCALLS.def
+++ b/klibc/SYSCALLS.def
@@ -155,7 +155,15 @@
int ioctl(int, int, void *)
int flock(int, int)
int _newselect,select::select(int, fd_set *, fd_set *, fd_set *, struct timeval *)
+#if defined(__NR_pselect) && !_KLIBC_USE_RT_SIG
+int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *)
+#elif defined(__NR_pselect7)
+int pselect7::__pselect7(int, fd_set *, fd_set *, fd_set *, struct timespec *, const sigset_t *, size_t)
+#elif defined(__NR_pselect6)
+int pselect6::__pselect6(int, fd_set *, fd_set *, fd_set *, struct timespec *, const struct __pselect6 *)
+#endif
int poll(struct pollfd *, nfds_t, long)
+<?> int ppoll::__ppoll(struct pollfd *, nfds_t, struct timespec *, const sigset_t *, size_t)
int fsync(int)
int fdatasync,fsync::fdatasync(int)
int readv(int, const struct iovec *, int)
@@ -163,6 +171,9 @@
int ftruncate64,ftruncate::ftruncate(int, off_t)
ssize_t pread64,pread::pread(int, void *, size_t, off_t)
ssize_t pwrite64,pwrite::pwrite(int, void *, size_t, off_t)
+int sync_file_range,fdatasync,fsync::sync_file_range(int, off_t, off_t, unsigned int)
+<?> int splice(int, off_t *, int, off_t *, size_t, unsigned int)
+<?> int tee(int, int, size_t, unsigned int)
;
; Signal operations
diff --git a/klibc/ppoll.c b/klibc/ppoll.c
new file mode 100644
index 0000000..f314be6
--- /dev/null
+++ b/klibc/ppoll.c
@@ -0,0 +1,14 @@
+/*
+ * ppoll.c
+ */
+
+#include <sys/poll.h>
+
+__extern int __ppoll(struct pollfd *, nfds_t, struct timespec *,
+ const sigset_t *, size_t);
+
+int ppoll(struct pollfd *ufds, nfds_t nfds, struct timespec *timeout,
+ const sigset_t *sigmask)
+{
+ return __ppoll(ufds, nfds, timeout, sigmask, sizeof *sigmask);
+}
diff --git a/klibc/pselect.c b/klibc/pselect.c
new file mode 100644
index 0000000..5266501
--- /dev/null
+++ b/klibc/pselect.c
@@ -0,0 +1,40 @@
+/*
+ * pselect.c
+ */
+
+#include <sys/select.h>
+#include <sys/syscall.h>
+
+#if defined(__NR_pselect) && !_KLIBC_USE_RT_SIG
+
+/* Don't need to do anything here; use syscall stub directly */
+
+#elif defined(__NR_pselect7)
+
+__extern int __pselect7(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *, size_t);
+
+int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ const struct timespec *timeout, const sigset_t *sigmask)
+{
+ return __pselect7(n, readfds, writefds, exceptfds,
+ timeout, sigmask, sizeof *sigmask);
+}
+
+#else
+
+struct __pselect6 {
+ const sigset_t *sigmask;
+ size_t sigsize;
+};
+
+__extern int __pselect6(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const struct __pselect6 *);
+
+int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ const struct timespec *timeout, const sigset_t *sigmask)
+{
+ struct __pselect6 extended_sigmask = { sigmask, sizeof *sigmask };
+ return __pselect6(n, readfds, writefds, exceptfds,
+ timeout, &extended_sigmask);
+}
+
+#endif