|
From: David L. <lee...@ho...> - 2003-09-05 20:13:29
|
We've gotten sys_epoll support for valgrind working! It just needed the same sort of business that select and poll (and all the other blocking syscalls) needed. The patch is below. We did have to modify the epoll library to generate a shared library in addition to the static library, so that the vg_intercept stuff would work. I've included that patch as well, just in case you want to be able to use the valgrind patch :-) We also had to make sure that /usr/include/asm/unistd.h had the epoll syscall #defines. How do we go about getting this worked into the CVS tree? Enjoy! dave <>< -=- Teracruz -- Performance Made Simple Learn more about Teracruz database acceleration at http://www.teracruz.com -=- valgrind patch -=- diff -uar valgrind-20030725/coregrind/vg_intercept.c valgrind-20030725-tera/coregrind/vg_intercept.c --- valgrind-20030725/coregrind/vg_intercept.c 2003-07-13 14:20:57.000000000 -0500 +++ valgrind-20030725-tera/coregrind/vg_intercept.c 2003-09-05 14:16:02.000000000 -0500 @@ -59,10 +59,12 @@ #include <errno.h> #include <sys/types.h> #include <stdio.h> +#include <stdint.h> #include <sys/ipc.h> #include <sys/msg.h> #include <asm/ipc.h> /* for ipc_kludge */ #include <sys/poll.h> +#include <sys/epoll.h> #include <sys/socket.h> #include <sys/uio.h> #ifdef GLIBC_2_1 @@ -117,6 +119,21 @@ } static __inline__ +int my_do_syscall4 ( int syscallno, + int arg1, int arg2, int arg3, int arg4 ) +{ + int __res; + __asm__ volatile ("int $0x80" + : "=a" (__res) + : "0" (syscallno), + "b" (arg1), + "c" (arg2), + "d" (arg3), + "S" (arg4) ); + return __res; +} + +static __inline__ int my_do_syscall5 ( int syscallno, int arg1, int arg2, int arg3, int arg4, int arg5 ) { @@ -368,6 +385,117 @@ strong_alias(poll, __poll) +/* ================================ epoll ================================ */ + +/* This is the master implementation of epoll_wait(). It blocks only the + calling thread. +*/ + +int VGR_(epoll_wait) (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout) +{ + unsigned int ms_now, ms_end; + int res; + struct vki_timespec nanosleep_interval; + + __my_pthread_testcancel(); + ensure_valgrind("epoll_wait"); + + /* Detect the current time and simultaneously find out if we are + running on Valgrind. */ + VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */, + VG_USERREQ__READ_MILLISECOND_TIMER, + 0, 0, 0, 0); + + + /* CHECK SIZES FOR struct pollfd */ + my_assert(sizeof(struct timeval) == sizeof(struct vki_timeval)); + + /* dummy initialisation to keep gcc -Wall happy */ + ms_end = 0; + + /* If a zero timeout specified, this call is harmless. Also do + this if not running on Valgrind. */ + if (__timeout == 0 || ms_now == 0xFFFFFFFF) { + res = my_do_syscall4(__NR_epoll_wait, __epfd, (int)__events, __maxevents, __timeout); + if (is_kerror(res)) { + * (__errno_location()) = -res; + return -1; + } else { + return res; + } + } + + /* If a timeout was specified, set ms_end to be the end wallclock + time. Easy considering that __timeout is in milliseconds. */ + if (__timeout > 0) { + ms_end = ms_now + (unsigned int)__timeout; + } + + //fprintf(stderr, "MY_EPOLL_WAIT: before loop\n"); + + /* Either timeout < 0, meaning wait indefinitely, or timeout > 0, + in which case t_end holds the end time. */ + + my_assert(__timeout != 0); + + while (1) { + + /* Do a return-immediately poll. */ + + res = my_do_syscall4(__NR_epoll_wait, __epfd, (int)__events, __maxevents, 0 ); + if (is_kerror(res)) { + /* Some kind of error. Set errno and return. */ + * (__errno_location()) = -res; + return -1; + } + if (res > 0) { + /* One or more fds is ready. Return now. */ + return res; + } + + /* Nothing interesting happened, so we go to sleep for a + while. */ + + /* fprintf(stderr, "MY_EPOLL_WAIT: nanosleep\n"); */ + /* nanosleep and go round again */ + nanosleep_interval.tv_sec = 0; + nanosleep_interval.tv_nsec = 13 * 1000 * 1000; /* 13 milliseconds */ + /* It's critical here that valgrind's nanosleep implementation + is nonblocking. */ + res = my_do_syscall2(__NR_nanosleep, + (int)(&nanosleep_interval), (int)NULL); + if (res == -VKI_EINTR) { + /* The nanosleep was interrupted by a signal. So we do the + same. */ + * (__errno_location()) = EINTR; + return -1; + } + + /* Sleeping finished. If a finite timeout, check to see if it + has expired yet. */ + if (__timeout > 0) { + VALGRIND_MAGIC_SEQUENCE(ms_now, 0xFFFFFFFF /* default */, + VG_USERREQ__READ_MILLISECOND_TIMER, + 0, 0, 0, 0); + my_assert(ms_now != 0xFFFFFFFF); + if (ms_now >= ms_end) { + /* timeout; nothing interesting happened. */ + return 0; + } + } + } +} + +int epoll_wait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout) +{ + return VGR_(epoll_wait)(__epfd, __events, __maxevents, __timeout); +} + +strong_alias(epoll_wait, __epoll_wait) + + /* ================================ msgsnd ================================ */ /* Turn a blocking msgsnd() into a polling non-blocking one, so that diff -uar valgrind-20030725/coregrind/vg_syscalls.c valgrind-20030725-tera/coregrind/vg_syscalls.c --- valgrind-20030725/coregrind/vg_syscalls.c 2003-07-24 16:00:03.000000000 -0500 +++ valgrind-20030725-tera/coregrind/vg_syscalls.c 2003-09-05 14:14:20.000000000 -0500 @@ -3463,6 +3463,42 @@ VG_TRACK( post_mem_write, arg1, sizeof( vki_ksigset_t ) ) ; break ; +# if defined(__NR_epoll_create) + case __NR_epoll_create: /* syscall 254 */ + /* int epoll_create(int size) */ + MAYBE_PRINTF("epoll_create ( %d )\n", arg1); + KERNEL_DO_SYSCALL(tid,res); + break; +# endif + +# if defined(__NR_epoll_ctl) + case __NR_epoll_ctl: /* syscall 255 */ + /* int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) */ + MAYBE_PRINTF("epoll_ctl ( %d, %d, %d, %p )\n", arg1, arg2, arg3, arg4); + if (arg4 != (UInt)NULL) + { + SYSCALL_TRACK( pre_mem_read, tid, "epoll_ctl", arg4, + sizeof(struct epoll_event) ); + } + KERNEL_DO_SYSCALL(tid,res); + break; +# endif + +# if defined(__NR_epoll_wait) + case __NR_epoll_wait: /* syscall 256 */ + /* int epoll_wait(int epfd, struct epoll_event * events, int maxevents, + int timeout) */ + MAYBE_PRINTF("epoll_wait ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4); + SYSCALL_TRACK( pre_mem_write, tid, "epoll_wait", arg2, + arg3 * sizeof(struct epoll_event) ); + KERNEL_DO_SYSCALL(tid,res); + if (!VG_(is_kerror)(res) && res > 0 && arg2 != (UInt)NULL) + { + VG_TRACK( post_mem_write, arg2, res * sizeof(struct epoll_event)); + } + break; +# endif + default: VG_(message) (Vg_DebugMsg,"FATAL: unhandled syscall: %d",syscallno); diff -uar valgrind-20030725/coregrind/vg_unsafe.h valgrind-20030725-tera/coregrind/vg_unsafe.h --- valgrind-20030725/coregrind/vg_unsafe.h 2003-06-14 03:50:27.000000000 -0500 +++ valgrind-20030725-tera/coregrind/vg_unsafe.h 2003-09-05 14:14:20.000000000 -0500 @@ -88,6 +88,7 @@ #include <sys/poll.h> +#include <sys/epoll.h> /*--------------------------------------------------------------------*/ /*--- end vg_unsafe.h ---*/ -=- epoll-lib-0.9 diff -=- diff -ur epoll-lib-0.9/Makefile epoll-lib-0.9-tera/Makefile --- epoll-lib-0.9/Makefile 2003-09-05 13:39:09.000000000 -0500 +++ epoll-lib-0.9-tera/Makefile 2003-09-05 13:40:32.000000000 -0500 @@ -12,11 +12,14 @@ # PREFIX=/usr +KERNELDIR=/usr/src/linux OUTDIR = lib TARGET = $(OUTDIR)/libepoll.a +TARGET_SONAME = libepoll.so.0 +SO_TARGET = $(OUTDIR)/libepoll.so.0.9 SRCDIR = ./src -INCLUDE = -I- -I./include -I/usr/src/linux/include +INCLUDE = -I- -I./include -I$(KERNELDIR)/include CC = gcc LD = ld @@ -44,8 +47,9 @@ .depend: $(SOURCES) $(MKDEP) $(CFLAGS) $(SOURCES) -$(TARGET): $(OBJECTS) +$(TARGET) $(SO_TARGET): $(OBJECTS) $(AR) -cr $(TARGET) $(OBJECTS) + $(LD) -shared -soname $(TARGET_SONAME) -o $(SO_TARGET) $(OBJECTS) epoll-example: $(MAKE) -C examples @@ -61,7 +65,7 @@ $(MAKE) -C examples distclean clean: - @rm -f $(TARGET) + @rm -f $(TARGET) $(SO_TARGET) @rm -f $(OBJECTS) *~ $(MAKE) -C examples clean _________________________________________________________________ Use custom emotions -- try MSN Messenger 6.0! http://www.msnmessenger-download.com/tracking/reach_emoticon |
|
From: Bryan O'S. <bo...@se...> - 2003-09-05 20:36:27
|
On Fri, 2003-09-05 at 13:12, David Lee wrote: > We've gotten sys_epoll support for valgrind working! It just needed the > same sort of business that select and poll (and all the other blocking > syscalls) needed. The patch is below. Jeremy Fitzhardinge has been completely reworking vg's support for blocking syscalls to make it more robust and handle signals more correctly. You may want to take a look at his current changes, and consider rebasing your epoll patch off that: http://valgrind.bkbits.net/ <b |