diff options
author | Armin Weatherwax | 2010-06-14 12:04:49 +0200 |
---|---|---|
committer | Armin Weatherwax | 2010-09-23 15:38:25 +0200 |
commit | 35df5441d3e2789663532c948731aff3a1e04728 (patch) | |
tree | ac7674289784a5f96106ea507637055a8dada78a /linden/indra/llplugin/llpluginsharedmemory.cpp | |
parent | Changed version to Experimental 2010.09.18 (diff) | |
download | meta-impy-35df5441d3e2789663532c948731aff3a1e04728.zip meta-impy-35df5441d3e2789663532c948731aff3a1e04728.tar.gz meta-impy-35df5441d3e2789663532c948731aff3a1e04728.tar.bz2 meta-impy-35df5441d3e2789663532c948731aff3a1e04728.tar.xz |
llmediaplugins first step
Diffstat (limited to 'linden/indra/llplugin/llpluginsharedmemory.cpp')
-rw-r--r-- | linden/indra/llplugin/llpluginsharedmemory.cpp | 506 |
1 files changed, 506 insertions, 0 deletions
diff --git a/linden/indra/llplugin/llpluginsharedmemory.cpp b/linden/indra/llplugin/llpluginsharedmemory.cpp new file mode 100644 index 0000000..2be4648 --- /dev/null +++ b/linden/indra/llplugin/llpluginsharedmemory.cpp | |||
@@ -0,0 +1,506 @@ | |||
1 | /** | ||
2 | * @file llpluginsharedmemory.cpp | ||
3 | * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | |||
35 | #include "llpluginsharedmemory.h" | ||
36 | |||
37 | // on Mac and Linux, we use the native shm_open/mmap interface by using | ||
38 | // #define USE_SHM_OPEN_SHARED_MEMORY 1 | ||
39 | // in the appropriate sections below. | ||
40 | |||
41 | // For Windows, use: | ||
42 | // #define USE_WIN32_SHARED_MEMORY 1 | ||
43 | |||
44 | // If we ever want to fall back to the apr implementation for a platform, use: | ||
45 | // #define USE_APR_SHARED_MEMORY 1 | ||
46 | |||
47 | #if LL_WINDOWS | ||
48 | // #define USE_APR_SHARED_MEMORY 1 | ||
49 | #define USE_WIN32_SHARED_MEMORY 1 | ||
50 | #elif LL_DARWIN | ||
51 | #define USE_SHM_OPEN_SHARED_MEMORY 1 | ||
52 | #elif LL_LINUX | ||
53 | #define USE_SHM_OPEN_SHARED_MEMORY 1 | ||
54 | #endif | ||
55 | |||
56 | |||
57 | // FIXME: This path thing is evil and unacceptable. | ||
58 | #if LL_WINDOWS | ||
59 | #define APR_SHARED_MEMORY_PREFIX_STRING "C:\\LLPlugin_" | ||
60 | // Apparnently using the "Global\\" prefix here only works from administrative accounts under Vista. | ||
61 | // Other options I've seen referenced are "Local\\" and "Session\\". | ||
62 | #define WIN32_SHARED_MEMORY_PREFIX_STRING "Local\\LL_" | ||
63 | #else | ||
64 | // mac and linux | ||
65 | #define APR_SHARED_MEMORY_PREFIX_STRING "/tmp/LLPlugin_" | ||
66 | #define SHM_OPEN_SHARED_MEMORY_PREFIX_STRING "/LL" | ||
67 | #endif | ||
68 | |||
69 | #if USE_APR_SHARED_MEMORY | ||
70 | #include "llapr.h" | ||
71 | #include "apr_shm.h" | ||
72 | #elif USE_SHM_OPEN_SHARED_MEMORY | ||
73 | #include <sys/fcntl.h> | ||
74 | #include <sys/mman.h> | ||
75 | #include <errno.h> | ||
76 | #elif USE_WIN32_SHARED_MEMORY | ||
77 | #include <windows.h> | ||
78 | #endif // USE_APR_SHARED_MEMORY | ||
79 | |||
80 | |||
81 | int LLPluginSharedMemory::sSegmentNumber = 0; | ||
82 | |||
83 | std::string LLPluginSharedMemory::createName(void) | ||
84 | { | ||
85 | std::stringstream newname; | ||
86 | |||
87 | #if LL_WINDOWS | ||
88 | newname << GetCurrentProcessId(); | ||
89 | #else // LL_WINDOWS | ||
90 | newname << getpid(); | ||
91 | #endif // LL_WINDOWS | ||
92 | |||
93 | newname << "_" << sSegmentNumber++; | ||
94 | |||
95 | return newname.str(); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * @brief LLPluginSharedMemoryImpl is the platform-dependent implementation of LLPluginSharedMemory. TODO:DOC is this necessary/sufficient? kinda obvious. | ||
100 | * | ||
101 | */ | ||
102 | class LLPluginSharedMemoryPlatformImpl | ||
103 | { | ||
104 | public: | ||
105 | LLPluginSharedMemoryPlatformImpl(); | ||
106 | ~LLPluginSharedMemoryPlatformImpl(); | ||
107 | |||
108 | #if USE_APR_SHARED_MEMORY | ||
109 | apr_shm_t* mAprSharedMemory; | ||
110 | #elif USE_SHM_OPEN_SHARED_MEMORY | ||
111 | int mSharedMemoryFD; | ||
112 | #elif USE_WIN32_SHARED_MEMORY | ||
113 | HANDLE mMapFile; | ||
114 | #endif | ||
115 | |||
116 | }; | ||
117 | |||
118 | /** | ||
119 | * Constructor. Creates a shared memory segment. | ||
120 | */ | ||
121 | LLPluginSharedMemory::LLPluginSharedMemory() | ||
122 | { | ||
123 | mSize = 0; | ||
124 | mMappedAddress = NULL; | ||
125 | mNeedsDestroy = false; | ||
126 | |||
127 | mImpl = new LLPluginSharedMemoryPlatformImpl; | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * Destructor. Uses destroy() and detach() to ensure shared memory segment is cleaned up. | ||
132 | */ | ||
133 | LLPluginSharedMemory::~LLPluginSharedMemory() | ||
134 | { | ||
135 | if(mNeedsDestroy) | ||
136 | destroy(); | ||
137 | else | ||
138 | detach(); | ||
139 | |||
140 | unlink(); | ||
141 | |||
142 | delete mImpl; | ||
143 | } | ||
144 | |||
145 | #if USE_APR_SHARED_MEMORY | ||
146 | // MARK: apr implementation | ||
147 | |||
148 | LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl() | ||
149 | { | ||
150 | mAprSharedMemory = NULL; | ||
151 | } | ||
152 | |||
153 | LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl() | ||
154 | { | ||
155 | |||
156 | } | ||
157 | |||
158 | bool LLPluginSharedMemory::map(void) | ||
159 | { | ||
160 | mMappedAddress = apr_shm_baseaddr_get(mImpl->mAprSharedMemory); | ||
161 | if(mMappedAddress == NULL) | ||
162 | { | ||
163 | return false; | ||
164 | } | ||
165 | |||
166 | return true; | ||
167 | } | ||
168 | |||
169 | bool LLPluginSharedMemory::unmap(void) | ||
170 | { | ||
171 | // This is a no-op under apr. | ||
172 | return true; | ||
173 | } | ||
174 | |||
175 | bool LLPluginSharedMemory::close(void) | ||
176 | { | ||
177 | // This is a no-op under apr. | ||
178 | return true; | ||
179 | } | ||
180 | |||
181 | bool LLPluginSharedMemory::unlink(void) | ||
182 | { | ||
183 | // This is a no-op under apr. | ||
184 | return true; | ||
185 | } | ||
186 | |||
187 | |||
188 | bool LLPluginSharedMemory::create(size_t size) | ||
189 | { | ||
190 | mName = APR_SHARED_MEMORY_PREFIX_STRING; | ||
191 | mName += createName(); | ||
192 | mSize = size; | ||
193 | |||
194 | apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp ); | ||
195 | |||
196 | if(ll_apr_warn_status(status)) | ||
197 | { | ||
198 | return false; | ||
199 | } | ||
200 | |||
201 | mNeedsDestroy = true; | ||
202 | |||
203 | return map(); | ||
204 | } | ||
205 | |||
206 | bool LLPluginSharedMemory::destroy(void) | ||
207 | { | ||
208 | if(mImpl->mAprSharedMemory) | ||
209 | { | ||
210 | apr_status_t status = apr_shm_destroy(mImpl->mAprSharedMemory); | ||
211 | if(ll_apr_warn_status(status)) | ||
212 | { | ||
213 | // TODO: Is this a fatal error? I think not... | ||
214 | } | ||
215 | mImpl->mAprSharedMemory = NULL; | ||
216 | } | ||
217 | |||
218 | return true; | ||
219 | } | ||
220 | |||
221 | bool LLPluginSharedMemory::attach(const std::string &name, size_t size) | ||
222 | { | ||
223 | mName = name; | ||
224 | mSize = size; | ||
225 | |||
226 | apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp ); | ||
227 | |||
228 | if(ll_apr_warn_status(status)) | ||
229 | { | ||
230 | return false; | ||
231 | } | ||
232 | |||
233 | return map(); | ||
234 | } | ||
235 | |||
236 | |||
237 | bool LLPluginSharedMemory::detach(void) | ||
238 | { | ||
239 | if(mImpl->mAprSharedMemory) | ||
240 | { | ||
241 | apr_status_t status = apr_shm_detach(mImpl->mAprSharedMemory); | ||
242 | if(ll_apr_warn_status(status)) | ||
243 | { | ||
244 | // TODO: Is this a fatal error? I think not... | ||
245 | } | ||
246 | mImpl->mAprSharedMemory = NULL; | ||
247 | } | ||
248 | |||
249 | return true; | ||
250 | } | ||
251 | |||
252 | |||
253 | #elif USE_SHM_OPEN_SHARED_MEMORY | ||
254 | // MARK: shm_open/mmap implementation | ||
255 | |||
256 | LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl() | ||
257 | { | ||
258 | mSharedMemoryFD = -1; | ||
259 | } | ||
260 | |||
261 | LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl() | ||
262 | { | ||
263 | } | ||
264 | |||
265 | bool LLPluginSharedMemory::map(void) | ||
266 | { | ||
267 | mMappedAddress = ::mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mImpl->mSharedMemoryFD, 0); | ||
268 | if(mMappedAddress == NULL) | ||
269 | { | ||
270 | return false; | ||
271 | } | ||
272 | |||
273 | LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL; | ||
274 | |||
275 | return true; | ||
276 | } | ||
277 | |||
278 | bool LLPluginSharedMemory::unmap(void) | ||
279 | { | ||
280 | if(mMappedAddress != NULL) | ||
281 | { | ||
282 | LL_DEBUGS("Plugin") << "calling munmap(" << mMappedAddress << ", " << mSize << ")" << LL_ENDL; | ||
283 | if(::munmap(mMappedAddress, mSize) == -1) | ||
284 | { | ||
285 | // TODO: Is this a fatal error? I think not... | ||
286 | } | ||
287 | |||
288 | mMappedAddress = NULL; | ||
289 | } | ||
290 | |||
291 | return true; | ||
292 | } | ||
293 | |||
294 | bool LLPluginSharedMemory::close(void) | ||
295 | { | ||
296 | if(mImpl->mSharedMemoryFD != -1) | ||
297 | { | ||
298 | LL_DEBUGS("Plugin") << "calling close(" << mImpl->mSharedMemoryFD << ")" << LL_ENDL; | ||
299 | if(::close(mImpl->mSharedMemoryFD) == -1) | ||
300 | { | ||
301 | // TODO: Is this a fatal error? I think not... | ||
302 | } | ||
303 | |||
304 | mImpl->mSharedMemoryFD = -1; | ||
305 | } | ||
306 | return true; | ||
307 | } | ||
308 | |||
309 | bool LLPluginSharedMemory::unlink(void) | ||
310 | { | ||
311 | if(!mName.empty()) | ||
312 | { | ||
313 | if(::shm_unlink(mName.c_str()) == -1) | ||
314 | { | ||
315 | return false; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | return true; | ||
320 | } | ||
321 | |||
322 | |||
323 | bool LLPluginSharedMemory::create(size_t size) | ||
324 | { | ||
325 | mName = SHM_OPEN_SHARED_MEMORY_PREFIX_STRING; | ||
326 | mName += createName(); | ||
327 | mSize = size; | ||
328 | |||
329 | // Preemptive unlink, just in case something didn't get cleaned up. | ||
330 | unlink(); | ||
331 | |||
332 | mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); | ||
333 | if(mImpl->mSharedMemoryFD == -1) | ||
334 | { | ||
335 | return false; | ||
336 | } | ||
337 | |||
338 | mNeedsDestroy = true; | ||
339 | |||
340 | if(::ftruncate(mImpl->mSharedMemoryFD, mSize) == -1) | ||
341 | { | ||
342 | return false; | ||
343 | } | ||
344 | |||
345 | |||
346 | return map(); | ||
347 | } | ||
348 | |||
349 | bool LLPluginSharedMemory::destroy(void) | ||
350 | { | ||
351 | unmap(); | ||
352 | close(); | ||
353 | |||
354 | return true; | ||
355 | } | ||
356 | |||
357 | |||
358 | bool LLPluginSharedMemory::attach(const std::string &name, size_t size) | ||
359 | { | ||
360 | mName = name; | ||
361 | mSize = size; | ||
362 | |||
363 | mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); | ||
364 | if(mImpl->mSharedMemoryFD == -1) | ||
365 | { | ||
366 | return false; | ||
367 | } | ||
368 | |||
369 | // unlink here so the segment will be cleaned up automatically after the last close. | ||
370 | unlink(); | ||
371 | |||
372 | return map(); | ||
373 | } | ||
374 | |||
375 | bool LLPluginSharedMemory::detach(void) | ||
376 | { | ||
377 | unmap(); | ||
378 | close(); | ||
379 | return true; | ||
380 | } | ||
381 | |||
382 | #elif USE_WIN32_SHARED_MEMORY | ||
383 | // MARK: Win32 CreateFileMapping-based implementation | ||
384 | |||
385 | // Reference: http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx | ||
386 | |||
387 | LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl() | ||
388 | { | ||
389 | mMapFile = NULL; | ||
390 | } | ||
391 | |||
392 | LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl() | ||
393 | { | ||
394 | |||
395 | } | ||
396 | |||
397 | bool LLPluginSharedMemory::map(void) | ||
398 | { | ||
399 | mMappedAddress = MapViewOfFile( | ||
400 | mImpl->mMapFile, // handle to map object | ||
401 | FILE_MAP_ALL_ACCESS, // read/write permission | ||
402 | 0, | ||
403 | 0, | ||
404 | mSize); | ||
405 | |||
406 | if(mMappedAddress == NULL) | ||
407 | { | ||
408 | LL_WARNS("Plugin") << "MapViewOfFile failed: " << GetLastError() << LL_ENDL; | ||
409 | return false; | ||
410 | } | ||
411 | |||
412 | LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL; | ||
413 | |||
414 | return true; | ||
415 | } | ||
416 | |||
417 | bool LLPluginSharedMemory::unmap(void) | ||
418 | { | ||
419 | if(mMappedAddress != NULL) | ||
420 | { | ||
421 | UnmapViewOfFile(mMappedAddress); | ||
422 | mMappedAddress = NULL; | ||
423 | } | ||
424 | |||
425 | return true; | ||
426 | } | ||
427 | |||
428 | bool LLPluginSharedMemory::close(void) | ||
429 | { | ||
430 | if(mImpl->mMapFile != NULL) | ||
431 | { | ||
432 | CloseHandle(mImpl->mMapFile); | ||
433 | mImpl->mMapFile = NULL; | ||
434 | } | ||
435 | |||
436 | return true; | ||
437 | } | ||
438 | |||
439 | bool LLPluginSharedMemory::unlink(void) | ||
440 | { | ||
441 | // This is a no-op on Windows. | ||
442 | return true; | ||
443 | } | ||
444 | |||
445 | |||
446 | bool LLPluginSharedMemory::create(size_t size) | ||
447 | { | ||
448 | mName = WIN32_SHARED_MEMORY_PREFIX_STRING; | ||
449 | mName += createName(); | ||
450 | mSize = size; | ||
451 | |||
452 | mImpl->mMapFile = CreateFileMappingA( | ||
453 | INVALID_HANDLE_VALUE, // use paging file | ||
454 | NULL, // default security | ||
455 | PAGE_READWRITE, // read/write access | ||
456 | 0, // max. object size | ||
457 | mSize, // buffer size | ||
458 | mName.c_str()); // name of mapping object | ||
459 | |||
460 | if(mImpl->mMapFile == NULL) | ||
461 | { | ||
462 | LL_WARNS("Plugin") << "CreateFileMapping failed: " << GetLastError() << LL_ENDL; | ||
463 | return false; | ||
464 | } | ||
465 | |||
466 | mNeedsDestroy = true; | ||
467 | |||
468 | return map(); | ||
469 | } | ||
470 | |||
471 | bool LLPluginSharedMemory::destroy(void) | ||
472 | { | ||
473 | unmap(); | ||
474 | close(); | ||
475 | return true; | ||
476 | } | ||
477 | |||
478 | bool LLPluginSharedMemory::attach(const std::string &name, size_t size) | ||
479 | { | ||
480 | mName = name; | ||
481 | mSize = size; | ||
482 | |||
483 | mImpl->mMapFile = OpenFileMappingA( | ||
484 | FILE_MAP_ALL_ACCESS, // read/write access | ||
485 | FALSE, // do not inherit the name | ||
486 | mName.c_str()); // name of mapping object | ||
487 | |||
488 | if(mImpl->mMapFile == NULL) | ||
489 | { | ||
490 | LL_WARNS("Plugin") << "OpenFileMapping failed: " << GetLastError() << LL_ENDL; | ||
491 | return false; | ||
492 | } | ||
493 | |||
494 | return map(); | ||
495 | } | ||
496 | |||
497 | bool LLPluginSharedMemory::detach(void) | ||
498 | { | ||
499 | unmap(); | ||
500 | close(); | ||
501 | return true; | ||
502 | } | ||
503 | |||
504 | |||
505 | |||
506 | #endif | ||