diff options
author | sanine <sanine.not@pm.me> | 2022-08-27 23:52:56 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-08-27 23:52:56 -0500 |
commit | a4dd0ad63c00f4dee3b86dfd3075d1d61b2b3180 (patch) | |
tree | 13bd5bfa15e6fea2a12f176bae79adf9c6fd0933 /3rdparty/plibsys/src/pmem.c | |
parent | bde3e4f1bb7b8f8abca0884a7d994ee1c17a66b1 (diff) |
add plibsys
Diffstat (limited to '3rdparty/plibsys/src/pmem.c')
-rw-r--r-- | 3rdparty/plibsys/src/pmem.c | 357 |
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; +} |