1 /* sagittarius-process.c -*- mode:c; coding:utf-8; -*-
2 *
3 * Copyright (c) 2010-2015 Takashi Kato <ktakashi@ymail.com>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id: $
29 */
30 #include <string.h>
31 #include <sagittarius.h>
32 #define LIBSAGITTARIUS_EXT_BODY
33 #include <sagittarius/extend.h>
34 #include "sagittarius-process.h"
35
shm_printer(SgObject self,SgPort * port,SgWriteContext * ctx)36 static void shm_printer(SgObject self, SgPort *port, SgWriteContext *ctx)
37 {
38 Sg_Printf(port, UC("#<shared-memory %A>"), SG_SHARED_MEMORY(self)->name);
39 }
40
41 SG_DEFINE_BUILTIN_CLASS_SIMPLE(Sg_SharedMemoryClass, shm_printer);
42
make_shared_memory(SgString * name,InternalHandle handle,SgObject bv)43 static SgSharedMemory * make_shared_memory(SgString *name,
44 InternalHandle handle,
45 SgObject bv)
46 {
47 SgSharedMemory *z = SG_NEW(SgSharedMemory);
48 SG_SET_CLASS(z, SG_CLASS_SHARED_MEMORY);
49 z->handle = handle;
50 z->name = SG_OBJ(name);
51 z->memory = bv;
52 return z;
53 }
54
55 #ifndef _WIN32
Sg_OpenSharedMemory(SgString * name,size_t size,int flags)56 SgObject Sg_OpenSharedMemory(SgString *name, size_t size, int flags)
57 {
58 char *memname = Sg_Utf32sToUtf8s(name);
59 int fd, f = O_RDWR, truncp = FALSE;
60 uint8_t *ptr;
61 SgSharedMemory *shm;
62 SgObject bv;
63
64 if (flags & SG_TRUNCATE) {
65 /* f |= O_TRUNC; */
66 truncp = TRUE;
67 }
68 if (flags & SG_CREATE) f |= O_CREAT;
69
70 /* TODO mode? should we make it executable? */
71 fd = shm_open(memname, f, 0666);
72 if (fd < 0) {
73 int e = errno;
74 const char *msg = strerror(e);
75 if (e == ENOENT) {
76 Sg_IOError(SG_IO_FILE_NOT_EXIST_ERROR,
77 SG_INTERN("open-shared-memory"),
78 Sg_Utf8sToUtf32s(msg, strlen(msg)),
79 name, SG_UNDEF);
80 } else {
81 Sg_SystemError(e, UC("open-shared-memory: shm_open failed. %A"),
82 Sg_Utf8sToUtf32s(msg, strlen(msg)));
83 }
84 }
85 /* TODO if not created? */
86 if (truncp) {
87 ftruncate(fd, size); /* don't check return value */
88 }
89 ptr = (uint8_t *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
90 bv = Sg_MakeByteVectorFromU8Array(ptr, size);
91 shm = make_shared_memory(name, fd, bv);
92 close(fd);
93 return SG_OBJ(shm);
94 }
95
Sg_CloseSharedMemory(SgSharedMemory * shm)96 SgObject Sg_CloseSharedMemory(SgSharedMemory *shm)
97 {
98 munmap(SG_BVECTOR_ELEMENTS(shm->memory), SG_BVECTOR_SIZE(shm->memory));
99 /* I don't care */
100 shm_unlink(Sg_Utf32sToUtf8s(SG_STRING(shm->name)));
101 SG_BVECTOR_ELEMENTS(shm->memory) = NULL;
102 SG_BVECTOR_SIZE(shm->memory) = 0;
103 return SG_TRUE;
104 }
105 #else
Sg_OpenSharedMemory(SgString * name,size_t size,int flags)106 SgObject Sg_OpenSharedMemory(SgString *name, size_t size, int flags)
107 {
108 HANDLE hMapFile;
109 uint8_t *ptr;
110 wchar_t *memname = Sg_StringToWCharTs(name);
111 DWORD high, low;
112 SgObject bv;
113
114 high = size>>32;
115 low = size&((1LL<<32)-1);
116 if (flags & SG_CREATE) {
117 hMapFile = CreateFileMappingW(INVALID_HANDLE_VALUE,
118 NULL,
119 PAGE_READWRITE,
120 high,
121 low,
122 memname);
123 } else {
124 hMapFile = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, memname);
125 }
126 if (hMapFile == NULL) {
127 int err = GetLastError();
128 if (err == ERROR_FILE_NOT_FOUND) {
129 Sg_IOError(SG_IO_FILE_NOT_EXIST_ERROR,
130 SG_INTERN("open-shared-memory"),
131 Sg_GetLastErrorMessageWithErrorCode(err),
132 name, SG_UNDEF);
133 } else {
134 Sg_SystemError(err,
135 UC("open-shared-memory: CreateFileMapping failed. %A"),
136 Sg_GetLastErrorMessageWithErrorCode(err));
137 }
138 }
139 ptr = (uint8_t *)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, high, low);
140
141 if (ptr == NULL) {
142 int err = GetLastError();
143 CloseHandle(hMapFile);
144 Sg_SystemError(err,
145 UC("open-shared-memory: MapViewOfFile failed. %A"),
146 Sg_GetLastErrorMessageWithErrorCode(err));
147 }
148 if (flags & SG_TRUNCATE) {
149 SecureZeroMemory(ptr, size);
150 }
151 bv = Sg_MakeByteVectorFromU8Array(ptr, size);
152 return SG_OBJ(make_shared_memory(name, hMapFile, bv));
153 }
154
Sg_CloseSharedMemory(SgSharedMemory * shm)155 SgObject Sg_CloseSharedMemory(SgSharedMemory *shm)
156 {
157 UnmapViewOfFile(SG_BVECTOR_ELEMENTS(shm->memory));
158 CloseHandle(shm->handle);
159 return SG_TRUE;
160 }
161 #endif
162
163 extern void Sg__Init_process_stub(SgLibrary *lib);
164
Sg_Init_sagittarius__process()165 SG_EXTENSION_ENTRY void CDECL Sg_Init_sagittarius__process()
166 {
167 SgLibrary *lib;
168 SG_INIT_EXTENSION(sagittarius__process);
169 lib = SG_LIBRARY(Sg_FindLibrary(SG_INTERN("(sagittarius process)"), FALSE));
170
171 Sg_InitStaticClassWithMeta(SG_CLASS_SHARED_MEMORY, UC("<shared-memory>"),
172 lib, NULL, SG_FALSE, NULL, 0);
173
174 Sg__Init_process_stub(lib);
175 }
176