Add CreateFileMapping file_segment implementation for win32

This commit is contained in:
Nick Mathewson 2010-10-25 12:29:39 -04:00
parent c2d9884a6a
commit 3f405d2d4b
2 changed files with 65 additions and 4 deletions

View File

@ -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);

View 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)