1 /*
2 +----------------------------------------------------------------------+
3 | Swoole |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 2.0 of the Apache license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | http://www.apache.org/licenses/LICENSE-2.0.html |
9 | If you did not receive a copy of the Apache2.0 license and are unable|
10 | to obtain it through the world-wide-web, please send a note to |
11 | license@swoole.com so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Tianfeng Han <mikan.tenny@gmail.com> |
14 +----------------------------------------------------------------------+
15 */
16
17 #include "swoole.h"
18 #include "swoole_file.h"
19 #include "swoole_memory.h"
20
21 #include <sys/mman.h>
22
23 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
24 #define MAP_ANONYMOUS MAP_ANON
25 #endif
26
27 namespace swoole {
28
29 struct SharedMemory {
30 size_t size_;
31
32 static void *alloc(size_t size);
33 static void free(void *ptr);
34
fetch_objectswoole::SharedMemory35 static SharedMemory *fetch_object(void *ptr) {
36 return (SharedMemory *) ((char *) ptr - sizeof(SharedMemory));
37 }
38 };
39
alloc(size_t size)40 void *SharedMemory::alloc(size_t size) {
41 void *mem;
42 int tmpfd = -1;
43 int flags = MAP_SHARED;
44 SharedMemory object;
45
46 size = SW_MEM_ALIGNED_SIZE(size);
47 size += sizeof(SharedMemory);
48
49 #ifdef MAP_ANONYMOUS
50 flags |= MAP_ANONYMOUS;
51 #else
52 File zerofile("/dev/zero", O_RDWR);
53 if (!zerofile.ready()) {
54 return nullptr;
55 }
56 tmpfd = zerofile.get_fd();
57 #endif
58 mem = mmap(nullptr, size, PROT_READ | PROT_WRITE, flags, tmpfd, 0);
59 #ifdef MAP_FAILED
60 if (mem == MAP_FAILED)
61 #else
62 if (!mem)
63 #endif
64 {
65 swoole_sys_warning("mmap(%lu) failed", size);
66 return nullptr;
67 } else {
68 object.size_ = size;
69 memcpy(mem, &object, sizeof(object));
70 return (char *) mem + sizeof(object);
71 }
72 }
73
free(void * ptr)74 void SharedMemory::free(void *ptr) {
75 SharedMemory *object = SharedMemory::fetch_object(ptr);
76 size_t size = object->size_;
77 if (munmap(object, size) < 0) {
78 swoole_sys_warning("munmap(%p, %lu) failed", object, size);
79 }
80 }
81
82 } // namespace swoole
83
84 using swoole::SharedMemory;
85
sw_shm_malloc(size_t size)86 void *sw_shm_malloc(size_t size) {
87 return SharedMemory::alloc(size);
88 }
89
sw_shm_calloc(size_t num,size_t _size)90 void *sw_shm_calloc(size_t num, size_t _size) {
91 return SharedMemory::alloc(num * _size);
92 }
93
sw_shm_protect(void * ptr,int flags)94 int sw_shm_protect(void *ptr, int flags) {
95 SharedMemory *object = SharedMemory::fetch_object(ptr);
96 return mprotect(object, object->size_, flags);
97 }
98
sw_shm_free(void * ptr)99 void sw_shm_free(void *ptr) {
100 SharedMemory::free(ptr);
101 }
102
sw_shm_realloc(void * ptr,size_t new_size)103 void *sw_shm_realloc(void *ptr, size_t new_size) {
104 SharedMemory *object = SharedMemory::fetch_object(ptr);
105 void *new_ptr = sw_shm_malloc(new_size);
106 if (new_ptr == nullptr) {
107 return nullptr;
108 }
109 memcpy(new_ptr, ptr, object->size_);
110 SharedMemory::free(ptr);
111 return new_ptr;
112 }
113