From: Nick Mathewson Date: Mon, 25 Oct 2010 16:29:39 +0000 (-0400) Subject: Add CreateFileMapping file_segment implementation for win32 X-Git-Tag: release-2.1.1-alpha~323^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3f405d2d4b583a4211a685e6425b1d7fc5797538;p=libevent Add CreateFileMapping file_segment implementation for win32 --- diff --git a/buffer.c b/buffer.c index bad57d3f..8a32b7ef 100644 --- 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); diff --git a/evbuffer-internal.h b/evbuffer-internal.h index ebbbe58e..e5937b05 100644 --- a/evbuffer-internal.h +++ b/evbuffer-internal.h @@ -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)