summaryrefslogtreecommitdiffstats
path: root/otherlibs/bigarray/mmap_win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'otherlibs/bigarray/mmap_win32.c')
-rw-r--r--otherlibs/bigarray/mmap_win32.c65
1 files changed, 49 insertions, 16 deletions
diff --git a/otherlibs/bigarray/mmap_win32.c b/otherlibs/bigarray/mmap_win32.c
index 35cbbe4d5..3a64e7b67 100644
--- a/otherlibs/bigarray/mmap_win32.c
+++ b/otherlibs/bigarray/mmap_win32.c
@@ -24,26 +24,38 @@
#include "sys.h"
#include "unixsupport.h"
-/* TODO: handle mappings larger than 2^32 bytes on Win64 */
-
extern int caml_ba_element_size[]; /* from bigarray_stubs.c */
static void caml_ba_sys_error(void);
+static __int64 caml_ba_set_file_pointer(HANDLE h, __int64 dist, DWORD mode)
+{
+ LARGE_INTEGER i;
+ DWORD err;
+
+ i.QuadPart = dist;
+ i.LowPart = SetFilePointer(h, i.LowPart, &i.HighPart, mode);
+ if (i.LowPart == INVALID_SET_FILE_POINTER) return -1;
+ return i.QuadPart;
+}
+
CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
- value vshared, value vdim)
+ value vshared, value vdim, value vstart)
{
HANDLE fd, fmap;
int flags, major_dim, mode, perm;
intnat num_dims, i;
intnat dim[MAX_NUM_DIMS];
- DWORD currpos, file_size;
- uintnat array_size;
+ __int64 currpos, startpos, file_size, data_size;
+ uintnat array_size, page, delta;
char c;
void * addr;
+ LARGE_INTEGER li;
+ SYSTEM_INFO sysinfo;
fd = Handle_val(vfd);
flags = Int_val(vkind) | Int_val(vlayout);
+ startpos = Int64_val(vstart);
num_dims = Wosize_val(vdim);
major_dim = flags & BIGARRAY_FORTRAN_LAYOUT ? num_dims - 1 : 0;
/* Extract dimensions from Caml array */
@@ -57,10 +69,10 @@ CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
invalid_argument("Bigarray.create: negative dimension");
}
/* Determine file size */
- currpos = SetFilePointer(fd, 0, NULL, FILE_CURRENT);
- if (currpos == INVALID_SET_FILE_POINTER) caml_ba_sys_error();
- file_size = SetFilePointer(fd, 0, NULL, FILE_END);
- if (file_size == INVALID_SET_FILE_POINTER) caml_ba_sys_error();
+ currpos = caml_ba_set_file_pointer(fd, 0, FILE_CURRENT);
+ if (currpos == -1) caml_ba_sys_error();
+ file_size = caml_ba_set_file_pointer(fd, 0, FILE_END);
+ if (file_size == -1) caml_ba_sys_error();
/* Determine array size in bytes (or size of array without the major
dimension if that dimension wasn't specified) */
array_size = bigarray_element_size[flags & BIGARRAY_KIND_MASK];
@@ -69,13 +81,16 @@ CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
/* Check if the first/last dimension is unknown */
if (dim[major_dim] == -1) {
/* Determine first/last dimension from file size */
- if ((uintnat) file_size % array_size != 0)
+ if (file_size < startpos)
+ failwith("Bigarray.mmap: file position exceeds file size");
+ data_size = file_size - startpos;
+ dim[major_dim] = (uintnat) (data_size / array_size);
+ array_size = dim[major_dim] * array_size;
+ if (array_size != data_size)
failwith("Bigarray.mmap: file size doesn't match array dimensions");
- dim[major_dim] = (uintnat) file_size / array_size;
- array_size = file_size;
}
/* Restore original file position */
- SetFilePointer(fd, currpos, NULL, FILE_BEGIN);
+ caml_ba_set_file_pointer(fd, currpos, FILE_BEGIN);
/* Create the file mapping */
if (Bool_val(vshared)) {
perm = PAGE_READWRITE;
@@ -84,20 +99,38 @@ CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
perm = PAGE_READONLY; /* doesn't work under Win98 */
mode = FILE_MAP_COPY;
}
- fmap = CreateFileMapping(fd, NULL, perm, 0, array_size, NULL);
+ li.QuadPart = startpos + array_size;
+ fmap = CreateFileMapping(fd, NULL, perm, li.HighPart, li.LowPart, NULL);
if (fmap == NULL) caml_ba_sys_error();
+ /* Determine offset so that the mapping starts at the given file pos */
+ GetSystemInfo(&sysinfo);
+ delta = (uintnat) (startpos % sysinfo.dwPageSize);
/* Map the mapping in memory */
- addr = MapViewOfFile(fmap, mode, 0, 0, array_size);
+ li.QuadPart = startpos - delta;
+ addr =
+ MapViewOfFile(fmap, mode, li.HighPart, li.LowPart, array_size + delta);
if (addr == NULL) caml_ba_sys_error();
+ addr = (void *) ((uintnat) addr + delta);
/* Close the file mapping */
CloseHandle(fmap);
/* Build and return the Caml bigarray */
return alloc_bigarray(flags | BIGARRAY_MAPPED_FILE, num_dims, addr, dim);
}
+CAMLprim value caml_ba_map_file_bytecode(value * argv, int argn)
+{
+ return caml_ba_map_file(argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5]);
+}
+
void caml_ba_unmap_file(void * addr, uintnat len)
{
- UnmapViewOfFile(addr);
+ SYSTEM_INFO sysinfo;
+ uintnat delta;
+
+ GetSystemInfo(&sysinfo);
+ delta = (uintnat) (startpos % sysinfo.dwPageSize);
+ UnmapViewOfFile((void *)((uintnat)addr - delta));
}
static void caml_ba_sys_error(void)