summaryrefslogtreecommitdiff
path: root/3rdparty/plibsys/src/pmem.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/plibsys/src/pmem.c')
-rw-r--r--3rdparty/plibsys/src/pmem.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/3rdparty/plibsys/src/pmem.c b/3rdparty/plibsys/src/pmem.c
new file mode 100644
index 0000000..04701fa
--- /dev/null
+++ b/3rdparty/plibsys/src/pmem.c
@@ -0,0 +1,357 @@
+/*
+ * The MIT License
+ *
+ * Copyright (C) 2010-2017 Alexander Saprykin <saprykin.spb@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "perror.h"
+#include "pmem.h"
+#include "perror-private.h"
+#include "psysclose-private.h"
+
+#ifndef P_OS_WIN
+# if defined (P_OS_BEOS)
+# include <be/kernel/OS.h>
+# elif defined (P_OS_OS2)
+# define INCL_DOSMEMMGR
+# define INCL_DOSERRORS
+# include <os2.h>
+# elif !defined (P_OS_AMIGA)
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# endif
+#endif
+
+static pboolean p_mem_table_inited = FALSE;
+static PMemVTable p_mem_table;
+
+void
+p_mem_init (void)
+{
+ if (P_UNLIKELY (p_mem_table_inited == TRUE))
+ return;
+
+ p_mem_restore_vtable ();
+}
+
+void
+p_mem_shutdown (void)
+{
+ if (P_UNLIKELY (!p_mem_table_inited))
+ return;
+
+ p_mem_table.malloc = NULL;
+ p_mem_table.realloc = NULL;
+ p_mem_table.free = NULL;
+
+ p_mem_table_inited = FALSE;
+}
+
+P_LIB_API ppointer
+p_malloc (psize n_bytes)
+{
+ if (P_LIKELY (n_bytes > 0))
+ return p_mem_table.malloc (n_bytes);
+ else
+ return NULL;
+}
+
+P_LIB_API ppointer
+p_malloc0 (psize n_bytes)
+{
+ ppointer ret;
+
+ if (P_LIKELY (n_bytes > 0)) {
+ if (P_UNLIKELY ((ret = p_mem_table.malloc (n_bytes)) == NULL))
+ return NULL;
+
+ memset (ret, 0, n_bytes);
+ return ret;
+ } else
+ return NULL;
+}
+
+P_LIB_API ppointer
+p_realloc (ppointer mem, psize n_bytes)
+{
+ if (P_UNLIKELY (n_bytes == 0))
+ return NULL;
+
+ if (P_UNLIKELY (mem == NULL))
+ return p_mem_table.malloc (n_bytes);
+ else
+ return p_mem_table.realloc (mem, n_bytes);
+}
+
+P_LIB_API void
+p_free (ppointer mem)
+{
+ if (P_LIKELY (mem != NULL))
+ p_mem_table.free (mem);
+}
+
+P_LIB_API pboolean
+p_mem_set_vtable (const PMemVTable *table)
+{
+ if (P_UNLIKELY (table == NULL))
+ return FALSE;
+
+ if (P_UNLIKELY (table->free == NULL || table->malloc == NULL || table->realloc == NULL))
+ return FALSE;
+
+ p_mem_table.malloc = table->malloc;
+ p_mem_table.realloc = table->realloc;
+ p_mem_table.free = table->free;
+
+ p_mem_table_inited = TRUE;
+
+ return TRUE;
+}
+
+P_LIB_API void
+p_mem_restore_vtable (void)
+{
+ p_mem_table.malloc = (ppointer (*)(psize)) malloc;
+ p_mem_table.realloc = (ppointer (*)(ppointer, psize)) realloc;
+ p_mem_table.free = (void (*)(ppointer)) free;
+
+ p_mem_table_inited = TRUE;
+}
+
+P_LIB_API ppointer
+p_mem_mmap (psize n_bytes,
+ PError **error)
+{
+ ppointer addr;
+#if defined (P_OS_WIN)
+ HANDLE hdl;
+#elif defined (P_OS_BEOS)
+ area_id area;
+#elif defined (P_OS_OS2)
+ APIRET ulrc;
+#elif !defined (P_OS_AMIGA)
+ int fd;
+ int map_flags = MAP_PRIVATE;
+#endif
+
+ if (P_UNLIKELY (n_bytes == 0)) {
+ p_error_set_error_p (error,
+ (pint) P_ERROR_IO_INVALID_ARGUMENT,
+ 0,
+ "Invalid input argument");
+ return NULL;
+ }
+
+#if defined (P_OS_WIN)
+ if (P_UNLIKELY ((hdl = CreateFileMappingA (INVALID_HANDLE_VALUE,
+ NULL,
+ PAGE_READWRITE,
+ 0,
+ (DWORD) n_bytes,
+ NULL)) == NULL)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to call CreateFileMapping() to create file mapping");
+ return NULL;
+ }
+
+ if (P_UNLIKELY ((addr = MapViewOfFile (hdl,
+ FILE_MAP_READ | FILE_MAP_WRITE,
+ 0,
+ 0,
+ n_bytes)) == NULL)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to call MapViewOfFile() to map file view");
+ CloseHandle (hdl);
+ return NULL;
+ }
+
+ if (P_UNLIKELY (!CloseHandle (hdl))) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to call CloseHandle() to close file mapping");
+ UnmapViewOfFile (addr);
+ return NULL;
+ }
+#elif defined (P_OS_BEOS)
+ if (P_LIKELY ((n_bytes % B_PAGE_SIZE)) != 0)
+ n_bytes = (n_bytes / B_PAGE_SIZE + 1) * B_PAGE_SIZE;
+
+ area = create_area ("", &addr, B_ANY_ADDRESS, n_bytes, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
+
+ if (P_UNLIKELY (area < B_NO_ERROR)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to call create_area() to create memory area");
+ return NULL;
+ }
+#elif defined (P_OS_OS2)
+ if (P_UNLIKELY ((ulrc = DosAllocMem ((PPVOID) &addr,
+ (ULONG) n_bytes,
+ PAG_READ | PAG_WRITE | PAG_COMMIT |
+ OBJ_ANY)) != NO_ERROR)) {
+ /* Try to remove OBJ_ANY */
+ if (P_UNLIKELY ((ulrc = DosAllocMem ((PPVOID) &addr,
+ (ULONG) n_bytes,
+ PAG_READ | PAG_WRITE)) != NO_ERROR)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_io_from_system ((pint) ulrc),
+ ulrc,
+ "Failed to call DosAllocMemory() to alocate memory");
+ return NULL;
+ }
+ }
+#elif defined (P_OS_AMIGA)
+ addr = malloc (n_bytes);
+
+ if (P_UNLIKELY (addr == NULL)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to allocate system memory");
+ return NULL;
+ }
+#else
+# if !defined (PLIBSYS_MMAP_HAS_MAP_ANONYMOUS) && !defined (PLIBSYS_MMAP_HAS_MAP_ANON)
+ if (P_UNLIKELY ((fd = open ("/dev/zero", O_RDWR | O_EXCL, 0754)) == -1)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to open /dev/zero for file mapping");
+ return NULL;
+ }
+# else
+ fd = -1;
+# endif
+
+# ifdef PLIBSYS_MMAP_HAS_MAP_ANONYMOUS
+ map_flags |= MAP_ANONYMOUS;
+# elif defined (PLIBSYS_MMAP_HAS_MAP_ANON)
+ map_flags |= MAP_ANON;
+# endif
+
+ if (P_UNLIKELY ((addr = mmap (NULL,
+ n_bytes,
+ PROT_READ | PROT_WRITE,
+ map_flags,
+ fd,
+ 0)) == (void *) -1)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to call mmap() to create file mapping");
+# if !defined (PLIBSYS_MMAP_HAS_MAP_ANONYMOUS) && !defined (PLIBSYS_MMAP_HAS_MAP_ANON)
+ if (P_UNLIKELY (p_sys_close (fd) != 0))
+ P_WARNING ("PMem::p_mem_mmap: failed to close file descriptor to /dev/zero");
+# endif
+ return NULL;
+ }
+
+# if !defined (PLIBSYS_MMAP_HAS_MAP_ANONYMOUS) && !defined (PLIBSYS_MMAP_HAS_MAP_ANON)
+ if (P_UNLIKELY (p_sys_close (fd) != 0)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to close /dev/zero handle");
+ munmap (addr, n_bytes);
+ return NULL;
+ }
+# endif
+#endif
+
+ return addr;
+}
+
+P_LIB_API pboolean
+p_mem_munmap (ppointer mem,
+ psize n_bytes,
+ PError **error)
+{
+#if defined (P_OS_BEOS)
+ area_id area;
+#elif defined (P_OS_OS2)
+ APIRET ulrc;
+#elif defined (P_OS_AMIGA)
+ P_UNUSED (n_bytes);
+ P_UNUSED (error);
+#endif
+
+ if (P_UNLIKELY (mem == NULL || n_bytes == 0)) {
+ p_error_set_error_p (error,
+ (pint) P_ERROR_IO_INVALID_ARGUMENT,
+ 0,
+ "Invalid input argument");
+ return FALSE;
+ }
+
+#if defined (P_OS_WIN)
+ if (P_UNLIKELY (UnmapViewOfFile (mem) == 0)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to call UnmapViewOfFile() to remove file mapping");
+#elif defined (P_OS_BEOS)
+ if (P_UNLIKELY ((area = area_for (mem)) == B_ERROR)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to call area_for() to find allocated memory area");
+ return FALSE;
+ }
+
+ if (P_UNLIKELY ((delete_area (area)) != B_OK)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to call delete_area() to remove memory area");
+#elif defined (P_OS_OS2)
+ if (P_UNLIKELY ((ulrc = DosFreeMem ((PVOID) mem)) != NO_ERROR)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_io_from_system ((pint) ulrc),
+ ulrc,
+ "Failed to call DosFreeMem() to free memory");
+#elif defined (P_OS_AMIGA)
+ free (mem);
+
+ if (P_UNLIKELY (FALSE)) {
+#else
+ if (P_UNLIKELY (munmap (mem, n_bytes) != 0)) {
+ p_error_set_error_p (error,
+ (pint) p_error_get_last_io (),
+ p_error_get_last_system (),
+ "Failed to call munmap() to remove file mapping");
+#endif
+ return FALSE;
+ } else
+ return TRUE;
+}