aboutsummaryrefslogtreecommitdiff
path: root/src/utils/storage.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/storage.cc')
-rw-r--r--src/utils/storage.cc175
1 files changed, 175 insertions, 0 deletions
diff --git a/src/utils/storage.cc b/src/utils/storage.cc
new file mode 100644
index 00000000..4db7f302
--- /dev/null
+++ b/src/utils/storage.cc
@@ -0,0 +1,175 @@
+// Copyright (C) 2010, Gabriel Dos Reis.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of The Numerical Algorithms Group Ltd. nor the
+// names of its contributors may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "openaxiom-c-macros.h"
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <sys/types.h>
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+#ifdef OPENAXIOM_MS_WINDOWS_HOST
+# include <windows.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include "storage.H"
+
+namespace OpenAxiom {
+ // ----------------
+ // -- SystemError --
+ // ----------------
+ SystemError::SystemError(std::string s) : text(s) { }
+
+ SystemError::~SystemError() { }
+
+ const std::string&
+ SystemError::message() const {
+ return text;
+ }
+
+ void
+ filesystem_error(std::string s) {
+ throw SystemError(s);
+ }
+
+ namespace Memory {
+ // Return storage page allocation unit in byte count.
+ size_t page_size() {
+#if defined(OPENAXIOM_MS_WINDOWS_HOST)
+ SYSTEM_INFO si = { };
+ GetSystemInfo(&si);
+ return si.dwPageSize;
+#elif defined(HAVE_UNISTD_H)
+ return sysconf(_SC_PAGESIZE);
+#else
+ // Well, we have to return a number.
+ return 4096;
+#endif
+ }
+
+ // Subroutine of os_acquire_raw_memory. Attempt to acquire
+ // storage from the host OS. Return null on failure.
+ static inline Pointer
+ os_allocate_read_write_raw_memory(size_t nbytes) {
+#if defined(OPENAXIOM_MS_WINDOWS_HOST)
+ return VirtualAlloc(Pointer(), nbytes,
+ MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+#elif defined(HAVE_SYS_MMAN_H)
+ Pointer p = mmap(Pointer(), nbytes, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | OPENAXIOM_MM_ANONYMOUS_MAP_FLAG,
+ -1, 0);
+ return p == MAP_FAILED ? Pointer() : p;
+#else
+ return malloc(byte_count);
+#endif
+ }
+
+ Pointer
+ os_acquire_raw_memory(size_t nbytes) {
+ Pointer p = os_allocate_read_write_raw_memory(nbytes);
+ if (p == 0)
+ throw SystemError("cannot acquire more memory");
+ return memset(p, nbytes, 0);
+ }
+
+ void
+ os_release_raw_memory(Pointer p, size_t n) {
+#if defined(OPENAXIOM_MS_WINDOWS_HOST)
+ VirtualFree(p, 0, MEM_RELEASE);
+#elif defined(HAVE_SYS_MMAN_H)
+ munmap(p, n);
+#else
+ free(p);
+#endif
+ }
+
+ // -----------------
+ // -- FileMapping --
+ // -----------------
+ FileMapping::FileMapping(std::string path)
+ : start(), extent() {
+#if defined(OPENAXIOM_MS_WINDOWS_HOST)
+ HANDLE file = CreateFile(path.c_str(), GENERIC_READ, 0, 0,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ if (file == INVALID_HANDLE_VALUE)
+ filesystem_error("could not access file " + path);
+ HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, 0, 0);
+ if (mapping == 0)
+ filesystem_error("could not map file " + path);
+ start = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
+ extent = GetFileSize(file, 0);
+ CloseHandle(mapping);
+ CloseHandle(file);
+#elif defined(HAVE_SYS_STAT_H) && defined(HAVE_SYS_MMAN_H) && defined(HAVE_FCNTL_H)
+ struct stat s;
+ errno = 0;
+ if (stat(path.c_str(), &s) < 0)
+ filesystem_error("could not access file " + path);
+ else if (!S_ISREG(s.st_mode))
+ filesystem_error(path + " is not a regular file");
+ int fd = open(path.c_str(), O_RDONLY);
+ if (fd < 0)
+ filesystem_error("could not open " + path);
+ start = mmap(Pointer(), s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ close(fd);
+ if (start == MAP_FAILED)
+ filesystem_error("could not map file " + path);
+ extent = s.st_size;
+#else
+# error "Don't know how to map a file on this platform"
+#endif // OPENAXIOM_MS_WINDOWS_HOST
+ }
+
+ FileMapping::~FileMapping() {
+#if defined(OPENAXIOM_MS_WINDOWS_HOST)
+ UnmapViewOfFile(start);
+#elif defined(HAVE_SYS_MMAN_H)
+ munmap(start, extent);
+#else
+# error "Don't know how to unmap a file on this platform"
+#endif
+ }
+ }
+}