Browse Source

Justin Cormack <justin@street-vision.com> writes:
Here is a small patch to add epoll support to uclibc.

The only thing I am not sure about is what needs to be done (if anything)
to make it work on 2.4/2.2 kernels (are the syscall numbers defined but
give errors when called or not?).

Tested on 2.6, though some other issues prevent more extensive testing at
the minute.

Mike Frysinger:
cleaned up patch and added checks to make sure that the syscall actually
exists, returning ENOSYS in cases where it doesn't.

Mike Frysinger 20 năm trước cách đây
mục cha
commit
7334cfc680
3 tập tin đã thay đổi với 173 bổ sung1 xóa
  1. 107 0
      include/sys/epoll.h
  2. 1 1
      libc/sysdeps/linux/common/Makefile
  3. 65 0
      libc/sysdeps/linux/common/epoll.c

+ 107 - 0
include/sys/epoll.h

@@ -0,0 +1,107 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef	_SYS_EPOLL_H
+#define	_SYS_EPOLL_H	1
+
+#include <stdint.h>
+#include <sys/types.h>
+
+
+enum EPOLL_EVENTS
+  {
+    EPOLLIN = 0x001,
+#define EPOLLIN EPOLLIN
+    EPOLLPRI = 0x002,
+#define EPOLLPRI EPOLLPRI
+    EPOLLOUT = 0x004,
+#define EPOLLOUT EPOLLOUT
+    EPOLLRDNORM = 0x040,
+#define EPOLLRDNORM EPOLLRDNORM
+    EPOLLRDBAND = 0x080,
+#define EPOLLRDBAND EPOLLRDBAND
+    EPOLLWRNORM = 0x100,
+#define EPOLLWRNORM EPOLLWRNORM
+    EPOLLWRBAND = 0x200,
+#define EPOLLWRBAND EPOLLWRBAND
+    EPOLLMSG = 0x400,
+#define EPOLLMSG EPOLLMSG
+    EPOLLERR = 0x008,
+#define EPOLLERR EPOLLERR
+    EPOLLHUP = 0x010,
+#define EPOLLHUP EPOLLHUP
+    EPOLLONESHOT = (1 << 30),
+#define EPOLLONESHOT EPOLLONESHOT
+    EPOLLET = (1 << 31)
+#define EPOLLET EPOLLET
+  };
+
+
+/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl().  */
+#define EPOLL_CTL_ADD 1	/* Add a file decriptor to the interface.  */
+#define EPOLL_CTL_DEL 2	/* Remove a file decriptor from the interface.  */
+#define EPOLL_CTL_MOD 3	/* Change file decriptor epoll_event structure.  */
+
+
+typedef union epoll_data
+{
+  void *ptr;
+  int fd;
+  uint32_t u32;
+  uint64_t u64;
+} epoll_data_t;
+
+struct epoll_event
+{
+  uint32_t events;	/* Epoll events */
+  epoll_data_t data;	/* User data variable */
+} __attribute__ ((__packed__));
+
+
+__BEGIN_DECLS
+
+/* Creates an epoll instance.  Returns an fd for the new instance.
+   The "size" parameter is a hint specifying the number of file
+   descriptors to be associated with the new instance.  The fd
+   returned by epoll_create() should be closed with close().  */
+extern int epoll_create (int __size) __THROW;
+
+
+/* Manipulate an epoll instance "epfd". Returns 0 in case of success,
+   -1 in case of error ( the "errno" variable will contain the
+   specific error code ) The "op" parameter is one of the EPOLL_CTL_*
+   constants defined above. The "fd" parameter is the target of the
+   operation. The "event" parameter describes which events the caller
+   is interested in and any associated user data.  */
+extern int epoll_ctl (int __epfd, int __op, int __fd,
+		      struct epoll_event *__event) __THROW;
+
+
+/* Wait for events on an epoll instance "epfd". Returns the number of
+   triggered events returned in "events" buffer. Or -1 in case of
+   error with the "errno" variable set to the specific error code. The
+   "events" parameter is a buffer that will contain triggered
+   events. The "maxevents" is the maximum number of events to be
+   returned ( usually size of "events" ). The "timeout" parameter
+   specifies the maximum wait time in milliseconds (-1 == infinite).  */
+extern int epoll_wait (int __epfd, struct epoll_event *__events,
+		       int __maxevents, int __timeout) __THROW;
+
+__END_DECLS
+
+#endif /* sys/epoll.h */

+ 1 - 1
libc/sysdeps/linux/common/Makefile

@@ -24,7 +24,7 @@ CSRC=	__rt_sigtimedwait.c __socketcall.c __syscall_fcntl.c \
 	__syscall_sigaction.c _exit.c access.c acct.c adjtimex.c alarm.c \
 	bdflush.c capget.c capset.c chdir.c chmod.c chown.c chroot.c \
 	close.c cmsg_nxthdr.c creat64.c create_module.c delete_module.c \
-	dup.c dup2.c execve.c fchdir.c fchmod.c fchown.c fdatasync.c \
+	dup.c dup2.c epoll.c execve.c fchdir.c fchmod.c fchown.c fdatasync.c \
 	flock.c fork.c fstat.c fstat64.c fstatfs.c fsync.c ftruncate.c \
 	ftruncate64.c get_kernel_syms.c getcwd.c getdents.c getdents64.c \
 	getdirname.c getdnnm.c getdtablesize.c getegid.c geteuid.c \

+ 65 - 0
libc/sysdeps/linux/common/epoll.c

@@ -0,0 +1,65 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * epoll_create() / epoll_ctl() / epoll_wait() for uClibc
+ *
+ * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
+ *
+ * GNU Library General Public License (LGPL) version 2 or later.
+ */
+
+#include "syscalls.h"
+#include <sys/epoll.h>
+
+/*
+ * epoll_create()
+ */
+#ifdef __NR_epoll_create
+#define __NR___syscall_epoll_create __NR_epoll_create
+static inline _syscall1(int, __syscall_epoll_create, int, size);
+#endif
+
+int epoll_create(int size)
+{
+#ifdef __NR_epoll_create
+	return (__syscall_epoll_create(size));
+#else
+    __set_errno(ENOSYS);
+    return -1;
+#endif
+}
+
+/*
+ * epoll_ctl()
+ */
+#ifdef __NR_epoll_ctl
+#define __NR___syscall_epoll_ctl __NR_epoll_ctl
+static inline _syscall4(int, __syscall_epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, event);
+#endif
+
+int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
+{
+#ifdef __NR_epoll_ctl
+	return (__syscall_epoll_ctl(epfd, op, fd, event));
+#else
+	__set_errno(ENOSYS);
+	return -1;
+#endif
+}
+
+/*
+ * epoll_wait()
+ */
+#ifdef __NR_epoll_wait
+#define __NR___syscall_epoll_wait __NR_epoll_wait
+static inline _syscall4(int, __syscall_epoll_wait, int, epfd, struct epoll_event *, events, int, maxevents, int, timeout);
+#endif
+
+int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
+{
+#ifdef __NR_epoll_wait
+	return (__syscall_epoll_wait(epfd, events, maxevents, timeout));
+#else
+	__set_errno(ENOSYS);
+	return -1;
+#endif
+}