diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/unix/os_unix.cpp | 2 | ||||
-rw-r--r-- | drivers/unix/shared_mem_access_posix.cpp | 184 | ||||
-rw-r--r-- | drivers/unix/shared_mem_access_posix.h | 68 |
3 files changed, 254 insertions, 0 deletions
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index e7550903a8..292e2d2219 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -40,6 +40,7 @@ #include "drivers/unix/net_socket_posix.h" #include "drivers/unix/rw_lock_posix.h" #include "drivers/unix/semaphore_posix.h" +#include "drivers/unix/shared_mem_access_posix.h" #include "drivers/unix/thread_posix.h" #include "servers/visual_server.h" @@ -140,6 +141,7 @@ void OS_Unix::initialize_core() { MutexPosix::make_default(); RWLockPosix::make_default(); #endif + SharedMemAccessPosix::make_default(); FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES); FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA); FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM); diff --git a/drivers/unix/shared_mem_access_posix.cpp b/drivers/unix/shared_mem_access_posix.cpp new file mode 100644 index 0000000000..f50e177a8b --- /dev/null +++ b/drivers/unix/shared_mem_access_posix.cpp @@ -0,0 +1,184 @@ +/*************************************************************************/ +/* shared_mem_access_posix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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 "shared_mem_access_posix.h" + +#if defined(UNIX_ENABLED) + +//#include "core/os/memory.h" +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> +//#include <stdio.h> +#include <fcntl.h> +//#include <sys/mman.h> +//#include <sys/stat.h> + +SharedMemAccess *SharedMemAccessPosix::create_func_posix(const String &p_name) { + + return memnew(SharedMemAccessPosix(p_name)); +} + +void SharedMemAccessPosix::make_default() { + + create_func = create_func_posix; +} + +Error SharedMemAccessPosix::open() { + + ERR_EXPLAIN("Already open."); + ERR_FAIL_COND_V(fd != -1, ERR_ALREADY_IN_USE); + + fd = shm_open(("/" + name).utf8().get_data(), O_CREAT | O_RDWR, 0600); + if (fd == -1) { + ERR_EXPLAIN("Cannot create/open."); + ERR_FAIL_V(ERR_CANT_OPEN); + } + + return OK; +} + +Error SharedMemAccessPosix::close() { + + ERR_EXPLAIN("Not open."); + ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); + + if (!lock()) { + ERR_EXPLAIN("Cannot lock."); + ERR_FAIL_V(ERR_BUSY); + } + + if (is_allocator) { + shm_unlink(("/" + name).utf8().get_data()); + is_allocator = false; + } + + ::close(fd); + fd = -1; + + unlock(); + + return OK; +} + +_FORCE_INLINE_ bool SharedMemAccessPosix::is_open() { + + return fd != -1; +} + +void *SharedMemAccessPosix::lock() { + + ERR_EXPLAIN("Not open."); + ERR_FAIL_COND_V(!is_open(), NULL); + + ERR_EXPLAIN("Lock already held."); + ERR_FAIL_COND_V(is_locking(), NULL); + + size = lseek(fd, 0, SEEK_END); + + lock_addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (lock_addr == MAP_FAILED) { + ERR_EXPLAIN("Cannot map memory."); + ERR_FAIL_V(NULL); + } + + return lock_addr; +} + +void SharedMemAccessPosix::unlock() { + + ERR_EXPLAIN("Lock not held."); + ERR_FAIL_COND(!is_locking()); + + munmap(lock_addr, size); + lock_addr = NULL; + size = 0; +} + +_FORCE_INLINE_ bool SharedMemAccessPosix::is_locking() { + + return lock_addr; +} + +void *SharedMemAccessPosix::set_size(uint64_t p_size) { + + ERR_EXPLAIN("Lock must be held to set the size."); + ERR_FAIL_COND_V(!is_locking(), NULL); + + if (ftruncate(fd, p_size) == -1) { + ERR_EXPLAIN("Cannot set new size. (Out of memory?)"); + ERR_FAIL_V(NULL); + } + + munmap(lock_addr, size); + + // Try to remap at former address + lock_addr = mmap(lock_addr, p_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (lock_addr == MAP_FAILED) { + unlock(); + + ERR_EXPLAIN("Cannot remap memory. Lock released."); + ERR_FAIL_V(NULL); + } + + return lock_addr; +} + +uint64_t SharedMemAccessPosix::get_size() { + + ERR_EXPLAIN("Lock must be held to get the size."); + ERR_FAIL_COND_V(!is_locking(), 0); + + return size; +} + +SharedMemAccessPosix::SharedMemAccessPosix(const String &p_name) : + name(p_name), + is_allocator(false), + size(0), + fd(-1), + lock_addr(NULL) { +} + +SharedMemAccessPosix::~SharedMemAccessPosix() { + + if (is_open()) { + + if (is_locking()) { + unlock(); + } + + if (close() != OK && is_allocator) { + ERR_PRINTS("Leaking shared memory '" + name + "'."); + } + } +} + +#endif diff --git a/drivers/unix/shared_mem_access_posix.h b/drivers/unix/shared_mem_access_posix.h new file mode 100644 index 0000000000..df955e1add --- /dev/null +++ b/drivers/unix/shared_mem_access_posix.h @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* shared_mem_access_posix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifndef SHARED_MEM_ACCESS_POSIX_H +#define SHARED_MEM_ACCESS_POSIX_H + +#include "core/os/shared_mem_access.h" +#include "core/ustring.h" + +#if defined(UNIX_ENABLED) + +class SharedMemAccessPosix : public SharedMemAccess { + + String name; + bool is_allocator; + uint64_t size; + int fd; + void *lock_addr; + + static SharedMemAccess *create_func_posix(const String &p_name); + +public: + static void make_default(); + + virtual Error open(); + virtual Error close(); + virtual bool is_open(); + + virtual void *lock(); + virtual void unlock(); + virtual bool is_locking(); + + virtual void *set_size(uint64_t p_size); + virtual uint64_t get_size(); + + SharedMemAccessPosix(const String &p_name); + virtual ~SharedMemAccessPosix(); +}; + +#endif +#endif |