]> granicus.if.org Git - libevent/commitdiff
Add CreateFileMapping file_segment implementation for win32
authorNick Mathewson <nickm@torproject.org>
Mon, 25 Oct 2010 16:29:39 +0000 (12:29 -0400)
committerNick Mathewson <nickm@torproject.org>
Tue, 21 Dec 2010 00:25:15 +0000 (19:25 -0500)
buffer.c
evbuffer-internal.h

index bad57d3f50726c53c639eef3515512db04d8905d..8a32b7efcda5680661367665b121f7f8e111c083 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -192,8 +192,13 @@ evbuffer_chain_free(struct evbuffer_chain *chain)
                    EVBUFFER_CHAIN_EXTRA(
                            struct evbuffer_chain_file_segment,
                            chain);
-               if (info->segment)
+               if (info->segment) {
+#ifdef WIN32
+                       if (info->segment->type == EVBUF_FS_MMAP)
+                               UnmapViewOfFile(chain->buffer);
+#endif
                        evbuffer_file_segment_free(info->segment);
+               }
        }
 
        mm_free(chain);
@@ -2615,7 +2620,6 @@ evbuffer_file_segment_new(
        }
 #endif
 #if defined(_EVENT_HAVE_MMAP)
-       /* TODO: Implement an mmap-alike for windows. */
        if (!(flags & EVBUF_FS_DISABLE_MMAP)) {
                off_t offset_rounded = 0, offset_leftover = 0;
                void *mapped;
@@ -2656,6 +2660,24 @@ evbuffer_file_segment_new(
                }
        }
 #endif
+#ifdef WIN32
+       if (!(flags & EVBUF_FS_DISABLE_MMAP)) {
+               long h = (long)_get_osfhandle(fd);
+               HANDLE m;
+               ev_uint64_t total_size = length+offset;
+               if (h == (long)INVALID_HANDLE_VALUE)
+                       return NULL;
+               m = CreateFileMapping((HANDLE)h, NULL, PAGE_READONLY,
+                   (total_size >> 32), total_size & 0xfffffffful,
+                   NULL);
+               if (m != INVALID_HANDLE_VALUE) { /* Does h leak? */
+                       seg->mapping_handle = m;
+                       seg->offset = offset;
+                       seg->type = EVBUF_FS_MMAP;
+                       goto done;
+               }
+       }
+#endif
 
        {
                ev_off_t start_pos = lseek(fd, 0, SEEK_CUR), pos;
@@ -2719,8 +2741,12 @@ evbuffer_file_segment_free(struct evbuffer_file_segment *seg)
        if (seg->type == EVBUF_FS_SENDFILE) {
                ;
        } else if (seg->type == EVBUF_FS_MMAP) {
+#ifdef WIN32
+               CloseHandle(seg->mapping_handle);
+#elif defined (_EVENT_HAVE_MMAP)
                if (munmap(seg->mapping, seg->length) == -1)
                        event_warn("%s: munmap failed", __func__);
+#endif
        } else {
                EVUTIL_ASSERT(seg->type == EVBUF_FS_IO);
                mm_free(seg->contents);
@@ -2772,9 +2798,36 @@ evbuffer_add_file_segment(struct evbuffer *buf,
                chain->off = length;
                chain->buffer_len = chain->misalign + length;
        } else if (seg->type == EVBUF_FS_MMAP) {
+#ifdef WIN32
+               ev_uint64_t total_offset = seg->offset+offset;
+               ev_uint64_t offset_rounded=0, offset_remaining=0;
+               LPVOID data;
+               if (total_offset) {
+                       SYSTEM_INFO si;
+                       memset(&si, 0, sizeof(si)); /* cargo cult */
+                       GetSystemInfo(&si);
+                       offset_remaining = total_offset % si.dwAllocationGranularity;
+                       offset_rounded = total_offset - offset_remaining;
+               }
+               data = MapViewOfFile(
+                       seg->mapping_handle,
+                       FILE_MAP_READ,
+                       offset_rounded >> 32,
+                       offset_rounded & 0xfffffffful,
+                       length);
+               if (data == NULL) {
+                       mm_free(chain);
+                       goto err;
+               }
+               chain->buffer = (unsigned char*) data;
+               chain->buffer_len = length+offset_remaining;
+               chain->misalign = offset_remaining;
+               chain->off = length;
+#else
                chain->buffer = (unsigned char*)(seg->contents + offset);
                chain->buffer_len = length;
                chain->off = length;
+#endif
        } else {
                EVUTIL_ASSERT(seg->type == EVBUF_FS_IO);
                chain->buffer = (unsigned char*)(seg->contents + offset);
index ebbbe58eb717742f7550214fcab840f730438bc6..e5937b05e468f187170b0f32baf45243b581443f 100644 (file)
@@ -204,6 +204,10 @@ struct evbuffer_chain_reference {
  * evbuffer_chain with the EVBUFFER_FILESEGMENT flag set.  */
 struct evbuffer_chain_file_segment {
        struct evbuffer_file_segment *segment;
+#ifdef WIN32
+       /** If we're using CreateFileMapping, this is the handle to the view. */
+       HANDLE view_handle;
+#endif
 };
 
 /* Declared in event2/buffer.h; defined here. */
@@ -219,6 +223,10 @@ struct evbuffer_file_segment {
        int fd;
        /** If we're using mmap, this is the raw mapped memory. */
        void *mapping;
+#ifdef WIN32
+       /** If we're using CreateFileMapping, this is the mapping */
+       HANDLE mapping_handle;
+#endif
        /** If we're using mmap or IO, this is the content of the file
         * segment. */
        char *contents;
@@ -226,9 +234,9 @@ struct evbuffer_file_segment {
         * this data segment begins.  If we're using sendfile, this is the
         * offset within the file where this data begins.  If we're using IO,
         * this is 0. */
-       off_t offset;
+       ev_off_t offset;
        /** The length of this segment. */
-       off_t length;
+       ev_off_t length;
 };
 
 #define EVBUFFER_CHAIN_SIZE sizeof(struct evbuffer_chain)