]> granicus.if.org Git - libevent/commitdiff
fix some of the windows compile issues; make buffer.c faster; support
authorNiels Provos <provos@gmail.com>
Mon, 24 May 2004 00:19:52 +0000 (00:19 +0000)
committerNiels Provos <provos@gmail.com>
Mon, 24 May 2004 00:19:52 +0000 (00:19 +0000)
signals via pipes.

svn:r105

WIN32-Code/config.h
WIN32-Code/misc.c
buffer.c
event.c
event.h
sample/event-test.c
sample/signal-test.c
sample/time-test.c
signal.c
test/regress.c

index 2f65ac07c6b82fbf8bbf037adeaffe112ba9abb6..71b373efa8e4869094b40059c5ecb3a58240d4dd 100644 (file)
@@ -16,7 +16,7 @@
 /* #undef u_int8_t */
 
 /* Define if timeradd is defined in <sys/time.h> */
-#define HAVE_TIMERADD 1
+/* #undef HAVE_TIMERADD */
 #ifndef HAVE_TIMERADD
 #define timeradd(tvp, uvp, vvp)           \
   do {                \
 #define HAVE_SYS_STAT_H 1
 
 /* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
+/* #undef HAVE_SYS_TIME_H */
 
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
 /* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
+/* #undef HAVE_UNISTD_H */
 
 /* Define to 1 if you have the `warnx' function. */
 #define HAVE_WARNX 1
 
 /* Version number of package */
 #define VERSION "0.6"
+
+typedef unsigned char u_char;
+
+/* Winsock compatibility */
+#define SHUT_WR SD_SEND
+
+struct timeval;
+struct timezone;
+int gettimeofday(struct timeval *tv, struct timezone *tz);
+
+#define read win_read
+#define write win_write
+
+int win_read(int, void *, unsigned int);
+int win_write(int, void *, unsigned int);
+int socketpair(int d, int type, int protocol, int *sv);
+
+#define __func__ __FILE__
\ No newline at end of file
index f3458f24af2d1b7d4066f75ceb7250b93cd59881..7329242b4edd97eb8ea7a8616dad11c889ffe33c 100644 (file)
@@ -28,3 +28,56 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) {
        tv->tv_usec = ((int) tb.millitm) * 1000;
        return 0;
 }
+
+int
+win_read(int fd, void *buf, unsigned int length)
+{
+       DWORD dwBytesRead;
+       int res = ReadFile((HANDLE) fd, buf, length, &dwBytesRead, NULL);
+       if (res == 0) {
+               DWORD error = GetLastError();
+               if (error == ERROR_NO_DATA)
+                       return (0);
+               return (-1);
+       } else
+               return (dwBytesRead);
+}
+
+int
+win_write(int fd, void *buf, unsigned int length)
+{
+       DWORD dwBytesWritten;
+       int res = WriteFile((HANDLE) fd, buf, length, &dwBytesWritten, NULL);
+       if (res == 0) {
+               DWORD error = GetLastError();
+               if (error == ERROR_NO_DATA)
+                       return (0);
+               return (-1);
+       } else
+               return (dwBytesWritten);
+}
+
+int
+socketpair(int d, int type, int protocol, int *sv)
+{
+       static int count;
+       char buf[64];
+       HANDLE fd;
+       DWORD dwMode;
+       sprintf(buf, "\\\\.\\pipe\\levent-%d", count++);
+       /* Create a duplex pipe which will behave like a socket pair */
+       fd = CreateNamedPipe(buf, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_NOWAIT, 
+               PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL);
+       if (fd == INVALID_HANDLE_VALUE)
+               return (-1);
+       sv[0] = (int)fd;
+
+       fd = CreateFile(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+       if (fd == INVALID_HANDLE_VALUE)
+               return (-1);
+       dwMode = PIPE_NOWAIT;
+       SetNamedPipeHandleState(fd, &dwMode, NULL, NULL);
+       sv[1] = (int)fd;
+
+       return (0);
+}
\ No newline at end of file
index 393188b4c0cd1e79e1a95e74ed926453d6689537..bbd9378f56148e297c3acb4ef2cc0232d1e259b7 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -62,8 +62,8 @@ evbuffer_new(void)
 void
 evbuffer_free(struct evbuffer *buffer)
 {
-       if (buffer->buffer != NULL)
-               free(buffer->buffer);
+       if (buffer->orig_buffer != NULL)
+               free(buffer->orig_buffer);
        free(buffer);
 }
 
@@ -72,10 +72,42 @@ evbuffer_free(struct evbuffer *buffer)
  * the other buffer.
  */
 
+#define SWAP(x,y) do { \
+       (x)->buffer = (y)->buffer; \
+       (x)->orig_buffer = (y)->orig_buffer; \
+       (x)->misalign = (y)->misalign; \
+       (x)->totallen = (y)->totallen; \
+       (x)->off = (y)->off; \
+} while (0)
+
 int
 evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
 {
        int res;
+
+       /* Short cut for better performance */
+       if (outbuf->off == 0) {
+               struct evbuffer tmp;
+               size_t oldoff = inbuf->off;
+
+               /* Swap them directly */
+               SWAP(&tmp, outbuf);
+               SWAP(outbuf, inbuf);
+               SWAP(inbuf, &tmp);
+
+               /* 
+                * Optimization comes with a price; we need to notify the
+                * buffer if necessary of the changes. oldoff is the amount
+                * of data that we tranfered from inbuf to outbuf
+                */
+               if (inbuf->off != oldoff && inbuf->cb != NULL)
+                       (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
+               if (oldoff && outbuf->cb != NULL)
+                       (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
+               
+               return (0);
+       }
+
        res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
        if (res == 0)
                evbuffer_drain(inbuf, inbuf->off);
@@ -88,44 +120,86 @@ evbuffer_add_printf(struct evbuffer *buf, char *fmt, ...)
 {
        int res = -1;
        char *msg;
+#ifdef WIN32
+       static char buffer[4096];
+#endif
        va_list ap;
 
        va_start(ap, fmt);
 
+#ifndef WIN32
        if (vasprintf(&msg, fmt, ap) == -1)
                goto end;
+#else
+       _vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap);
+       buffer[sizeof(buffer)-1] = '\0';
+       msg = buffer;
+#endif
        
        res = strlen(msg);
        if (evbuffer_add(buf, msg, res) == -1)
                res = -1;
+#ifndef WIN32
        free(msg);
 
- end:
+end:
+#endif
        va_end(ap);
 
        return (res);
 }
 
+/* Reads data from an event buffer and drains the bytes read */
+
 int
-evbuffer_add(struct evbuffer *buf, u_char *data, size_t datlen)
+evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
 {
-       size_t need = buf->off + datlen;
-       size_t oldoff = buf->off;
+       int nread = datlen;
+       if (nread >= buf->off)
+               nread = buf->off;
 
-       if (buf->totallen < need) {
-               void *newbuf;
-               int length = buf->totallen;
+       memcpy(data, buf->buffer, nread);
+       evbuffer_drain(buf, nread);
+       
+       return (nread);
+}
+
+/* Adds data to an event buffer */
 
-               if (length < 256)
-                       length = 256;
-               while (length < need)
-                       length <<= 1;
+static __inline void
+evbuffer_align(struct evbuffer *buf)
+{
+       memmove(buf->orig_buffer, buf->buffer, buf->off);
+       buf->buffer = buf->orig_buffer;
+       buf->misalign = 0;
+}
 
-               if ((newbuf = realloc(buf->buffer, length)) == NULL)
-                       return (-1);
+int
+evbuffer_add(struct evbuffer *buf, void *data, size_t datlen)
+{
+       size_t need = buf->misalign + buf->off + datlen;
+       size_t oldoff = buf->off;
 
-               buf->buffer = newbuf;
-               buf->totallen = length;
+       if (buf->totallen < need) {
+               if (buf->misalign >= datlen) {
+                       evbuffer_align(buf);
+               } else {
+                       void *newbuf;
+                       size_t length = buf->totallen;
+
+                       if (length < 256)
+                               length = 256;
+                       while (length < need)
+                               length <<= 1;
+
+                       if (buf->orig_buffer != buf->buffer)
+                               evbuffer_align(buf);
+                       if ((newbuf = realloc(buf->buffer, length)) == NULL)
+                               return (-1);
+
+                       buf->orig_buffer = buf->buffer = newbuf;
+                       buf->totallen = length;
+               }
        }
 
        memcpy(buf->buffer + buf->off, data, datlen);
@@ -144,10 +218,14 @@ evbuffer_drain(struct evbuffer *buf, size_t len)
 
        if (len >= buf->off) {
                buf->off = 0;
+               buf->buffer = buf->orig_buffer;
+               buf->misalign = 0;
                goto done;
        }
 
-       memmove(buf->buffer, buf->buffer + len, buf->off - len);
+       buf->buffer += len;
+       buf->misalign += len;
+
        buf->off -= len;
 
  done:
@@ -162,15 +240,27 @@ evbuffer_read(struct evbuffer *buffer, int fd, int howmuch)
 {
        u_char inbuf[4096];
        int n;
+#ifdef WIN32
+       DWORD dwBytesRead;
+#endif
        
        if (howmuch < 0 || howmuch > sizeof(inbuf))
                howmuch = sizeof(inbuf);
 
+#ifndef WIN32
        n = read(fd, inbuf, howmuch);
        if (n == -1)
                return (-1);
        if (n == 0)
                return (0);
+#else
+       n = ReadFile((HANDLE)fd, inbuf, howmuch, &dwBytesRead, NULL);
+       if (n == 0)
+               return (-1);
+       if (dwBytesRead == 0)
+               return (0);
+       n = dwBytesRead;
+#endif
 
        evbuffer_add(buffer, inbuf, n);
 
@@ -181,13 +271,24 @@ int
 evbuffer_write(struct evbuffer *buffer, int fd)
 {
        int n;
+#ifdef WIN32
+       DWORD dwBytesWritten;
+#endif
 
+#ifndef WIN32
        n = write(fd, buffer->buffer, buffer->off);
        if (n == -1)
                return (-1);
        if (n == 0)
                return (0);
-
+#else
+       n = WriteFile((HANDLE)fd, buffer->buffer, buffer->off, &dwBytesWritten, NULL);
+       if (n == 0)
+               return (-1);
+       if (dwBytesWritten == 0)
+               return (0);
+       n = dwBytesWritten;
+#endif
        evbuffer_drain(buffer, n);
 
        return (n);
diff --git a/event.c b/event.c
index 92eadde76d51bdd9f6b78799aaf8edb8ece71a15..f5e0c7626243a7c0dfa075e55e4dc8bf7db3cbcd 100644 (file)
--- a/event.c
+++ b/event.c
@@ -103,8 +103,11 @@ const struct eventop *eventops[] = {
        NULL
 };
 
+/* Global state */
+
 const struct eventop *evsel;
 void *evbase;
+static int event_count;
 
 /* Handle signals - This is a deprecated interface */
 int (*event_sigcb)(void);      /* Signal callback when gotsig is set */
@@ -133,7 +136,7 @@ compare(struct event *a, struct event *b)
                return (1);
        if (a < b)
                return (-1);
-       if (a > b)
+       else if (a > b)
                return (1);
        return (0);
 }
@@ -152,6 +155,11 @@ event_init(void)
        event_gotsig = 0;
        gettimeofday(&event_tv, NULL);
        
+#if defined(USE_LOG) && defined(USE_DEBUG)
+       log_to(stderr);
+       log_debug_cmd(LOG_MISC, 80);
+#endif
+
        RB_INIT(&timetree);
        TAILQ_INIT(&eventqueue);
        TAILQ_INIT(&activequeue);
@@ -169,18 +177,12 @@ event_init(void)
 
        if (getenv("EVENT_SHOW_METHOD")) 
                fprintf(stderr, "libevent using: %s\n", evsel->name); 
-
-#if defined(USE_LOG) && defined(USE_DEBUG)
-       log_to(stderr);
-       log_debug_cmd(LOG_MISC, 80);
-#endif
 }
 
 int
 event_haveevents(void)
 {
-       return (RB_ROOT(&timetree) || TAILQ_FIRST(&eventqueue) ||
-           TAILQ_FIRST(&signalqueue) || TAILQ_FIRST(&activequeue));
+       return (event_count > 0);
 }
 
 static void
@@ -582,6 +584,9 @@ event_queue_remove(struct event *ev, int queue)
                errx(1, "%s: %p(fd %d) not on queue %x", __func__,
                    ev, ev->ev_fd, queue);
 
+       if (!(ev->ev_flags & EVLIST_INTERNAL))
+               event_count--;
+
        ev->ev_flags &= ~queue;
        switch (queue) {
        case EVLIST_ACTIVE:
@@ -608,6 +613,9 @@ event_queue_insert(struct event *ev, int queue)
                errx(1, "%s: %p(fd %d) already on queue %x", __func__,
                    ev, ev->ev_fd, queue);
 
+       if (!(ev->ev_flags & EVLIST_INTERNAL))
+               event_count++;
+
        ev->ev_flags |= queue;
        switch (queue) {
        case EVLIST_ACTIVE:
diff --git a/event.h b/event.h
index eddb0e96b58b625dcef44a2201bf816ed45c7803..96a725c5747c4b878a469a3f4b70e2c9e1b8701d 100644 (file)
--- a/event.h
+++ b/event.h
@@ -39,10 +39,11 @@ extern "C" {
 #define EVLIST_INSERTED        0x02
 #define EVLIST_SIGNAL  0x04
 #define EVLIST_ACTIVE  0x08
+#define EVLIST_INTERNAL        0x10
 #define EVLIST_INIT    0x80
 
 /* EVLIST_X_ Private space: 0x1000-0xf000 */
-#define EVLIST_ALL     (0xf000 | 0x8f)
+#define EVLIST_ALL     (0xf000 | 0x9f)
 
 #define EV_TIMEOUT     0x01
 #define EV_READ                0x02
@@ -170,7 +171,9 @@ int event_pending(struct event *, short, struct timeval *);
 
 struct evbuffer {
        u_char *buffer;
+       u_char *orig_buffer;
 
+       size_t misalign;
        size_t totallen;
        size_t off;
 
@@ -233,7 +236,8 @@ void bufferevent_settimeout(struct bufferevent *bufev,
 
 struct evbuffer *evbuffer_new(void);
 void evbuffer_free(struct evbuffer *);
-int evbuffer_add(struct evbuffer *, u_char *, size_t);
+int evbuffer_add(struct evbuffer *, void *, size_t);
+int evbuffer_remove(struct evbuffer *, void *, size_t);
 int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);
 int evbuffer_add_printf(struct evbuffer *, char *fmt, ...);
 void evbuffer_drain(struct evbuffer *, size_t);
index 0eac37e7001f7274a44b51215c5395f8c6d41227..965984d4e6aa80566824fed926dfed6f9857fef9 100644 (file)
@@ -45,7 +45,7 @@ fifo_read(int fd, short event, void *arg)
                return;
        }
 
-       buf[dwBytesRead + 1] = '\0';
+       buf[dwBytesRead] = '\0';
 #else
        len = read(fd, buf, sizeof(buf) - 1);
 
index 7a1fefec8050d367a089123e4c78d5d81966f68d..98650ca11d59c2b29a3e6404ba0c79d6cf4958a4 100644 (file)
@@ -4,6 +4,11 @@
  */
 
 #include <sys/types.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <sys/stat.h>
 #ifndef WIN32
 #include <sys/queue.h>
index da508ff88ed0f31ba8020d79eb7a380b11996bba..f0f93995124cdc41483625195ea2d9be0b6e5ca2 100644 (file)
@@ -4,6 +4,11 @@
  */
 
 #include <sys/types.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <sys/stat.h>
 #ifndef WIN32
 #include <sys/queue.h>
@@ -11,7 +16,9 @@
 #else
 #include <time.h>
 #endif
+#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
 #include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
index c748927a74eb7d5602de9458edcd462b8293115e..073450021fb2673997107fd4004d75aa0a2a158e 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -35,6 +35,7 @@
 #include <sys/_time.h>
 #endif
 #include <sys/queue.h>
+#include <sys/socket.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -63,10 +64,39 @@ void evsignal_process(void);
 int evsignal_recalc(sigset_t *);
 int evsignal_deliver(sigset_t *);
 
+static struct event ev_signal;
+static int ev_signal_pair[2];
+static int ev_signal_added;
+
+/* Callback for when the signal handler write a byte to our signaling socket */
+static void evsignal_cb(int fd, short what, void *arg)
+{
+       static char signals[100];
+       struct event *ev = arg;
+       int n;
+
+       n = read(fd, signals, sizeof(signals));
+       if (n == -1)
+               err(1, "%s: read");
+       event_add(ev, NULL);
+}
+
 void
 evsignal_init(sigset_t *evsigmask)
 {
        sigemptyset(evsigmask);
+
+       /* 
+        * Our signal handler is going to write to one end of the socket
+        * pair to wake up our event loop.  The event loop then scans for
+        * signals that got delivered.
+        */
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1)
+               err(1, "%s: socketpair", __func__);
+
+       event_set(&ev_signal, ev_signal_pair[1], EV_READ,
+           evsignal_cb, &ev_signal);
+       ev_signal.ev_flags |= EVLIST_INTERNAL;
 }
 
 int
@@ -103,6 +133,9 @@ evsignal_handler(int sig)
 {
        evsigcaught[sig]++;
        evsignal_caught = 1;
+
+       /* Wake up our notification mechanism */
+       write(ev_signal_pair[0], "a", 1);
 }
 
 int
@@ -110,6 +143,11 @@ evsignal_recalc(sigset_t *evsigmask)
 {
        struct sigaction sa;
        struct event *ev;
+       
+       if (!ev_signal_added) {
+               ev_signal_added = 1;
+               event_add(&ev_signal, NULL);
+       }
 
        if (TAILQ_FIRST(&signalqueue) == NULL && !needrecalc)
                return (0);
index 7361f2277f89746f7f45120ee6852a4426f8a543..2ac4b113a93709f2ac5234bd88e837093811d4ab 100644 (file)
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
+#ifndef WIN32
 #include <sys/socket.h>
 #include <sys/signal.h>
+#include <unistd.h>
+#endif
 #include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <unistd.h>
 #include <errno.h>
 
 #include <event.h>
@@ -232,9 +241,13 @@ setup_test(char *name)
 int
 cleanup_test(void)
 {
+#ifndef WIN32
        close(pair[0]);
        close(pair[1]);
-
+#else
+       CloseHandle((HANDLE)pair[0]);
+       CloseHandle((HANDLE)pair[1]);
+#endif
        if (test_ok)
                fprintf(stdout, "OK\n");
        else {
@@ -382,6 +395,7 @@ test6(void)
        cleanup_test();
 }
 
+#ifndef WIN32
 void
 test7(void)
 {
@@ -403,6 +417,7 @@ test7(void)
 
        cleanup_test();
 }
+#endif
 
 void
 test8(void)
@@ -490,6 +505,16 @@ test9(void)
 int
 main (int argc, char **argv)
 {
+#ifdef WIN32
+       WORD wVersionRequested;
+       WSADATA wsaData;
+       int     err;
+       wVersionRequested = MAKEWORD( 2, 2 );
+       err = WSAStartup( wVersionRequested, &wsaData );
+#endif
+
        setvbuf(stdout, NULL, _IONBF, 0);
 
        /* Initalize the event library */
@@ -506,9 +531,9 @@ main (int argc, char **argv)
        test5();
 
        test6();
-
+#ifndef WIN32
        test7();
-
+#endif
        test8();
 
        test9();