ovr_sdk
diff LibOVR/Src/Kernel/OVR_SharedMemory.cpp @ 0:1b39a1b46319
initial 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 14 Jan 2015 06:51:16 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/Kernel/OVR_SharedMemory.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,691 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_SharedMemory.cpp 1.7 +Content : Inter-process shared memory subsystem 1.8 +Created : June 1, 2014 1.9 +Notes : 1.10 + 1.11 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.12 + 1.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.15 +which is provided at the time of installation or download, or which 1.16 +otherwise accompanies this software in either electronic or hard copy form. 1.17 + 1.18 +You may obtain a copy of the License at 1.19 + 1.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.21 + 1.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.23 +distributed under the License is distributed on an "AS IS" BASIS, 1.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.25 +See the License for the specific language governing permissions and 1.26 +limitations under the License. 1.27 + 1.28 +************************************************************************************/ 1.29 + 1.30 +#include "OVR_SharedMemory.h" 1.31 +#include "OVR_Atomic.h" 1.32 +#include "OVR_Log.h" 1.33 +#include "OVR_String.h" 1.34 +#include "OVR_Array.h" 1.35 + 1.36 +#if defined(OVR_OS_WIN32) && !defined(OVR_FAKE_SHAREDMEMORY) 1.37 +#include <Sddl.h> // ConvertStringSecurityDescriptorToSecurityDescriptor 1.38 +#endif // OVR_OS_WIN32 1.39 + 1.40 +#if (defined(OVR_OS_LINUX) || defined(OVR_OS_MAC)) && !defined(OVR_FAKE_SHAREDMEMORY) 1.41 +#include <sys/mman.h> // shm_open(), mmap() 1.42 +#include <errno.h> // error results for mmap 1.43 +#include <sys/stat.h> // mode constants 1.44 +#include <fcntl.h> // O_ constants 1.45 +#include <unistd.h> // close() 1.46 +#endif // OVR_OS_LINUX 1.47 + 1.48 +OVR_DEFINE_SINGLETON(OVR::SharedMemoryFactory); 1.49 + 1.50 +namespace OVR { 1.51 + 1.52 + 1.53 + //// Fake version 1.54 + 1.55 +#if defined(OVR_FAKE_SHAREDMEMORY) 1.56 + 1.57 + class FakeMemoryBlock : public RefCountBase<FakeMemoryBlock> 1.58 + { 1.59 + String Name; 1.60 + char* Data; 1.61 + int SizeBytes; 1.62 + int References; 1.63 + 1.64 + public: 1.65 + FakeMemoryBlock(const String& name, int size) : 1.66 + Name(name), 1.67 + Data(NULL), 1.68 + SizeBytes(size), 1.69 + References(1) 1.70 + { 1.71 + Data = new char[SizeBytes]; 1.72 + } 1.73 + ~FakeMemoryBlock() 1.74 + { 1.75 + delete[] Data; 1.76 + } 1.77 + 1.78 + bool IsNamed(const String& name) 1.79 + { 1.80 + return Name.CompareNoCase(name) == 0; 1.81 + } 1.82 + void* GetData() 1.83 + { 1.84 + return Data; 1.85 + } 1.86 + int GetSizeI() 1.87 + { 1.88 + return SizeBytes; 1.89 + } 1.90 + void IncrementReferences() 1.91 + { 1.92 + ++References; 1.93 + } 1.94 + bool DecrementReferences() 1.95 + { 1.96 + return --References <= 0; 1.97 + } 1.98 + }; 1.99 + 1.100 + class SharedMemoryInternal : public NewOverrideBase 1.101 + { 1.102 + public: 1.103 + void* FileView; 1.104 + Ptr<FakeMemoryBlock> Block; 1.105 + 1.106 + void Close(); 1.107 + 1.108 + SharedMemoryInternal(FakeMemoryBlock* block) : 1.109 + Block(block) 1.110 + { 1.111 + FileView = Block->GetData(); 1.112 + } 1.113 + ~SharedMemoryInternal() 1.114 + { 1.115 + Close(); 1.116 + } 1.117 + 1.118 + static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params); 1.119 + }; 1.120 + 1.121 + 1.122 + //// FakeMemoryManager 1.123 + 1.124 + class FakeMemoryManager : public NewOverrideBase, public SystemSingletonBase<FakeMemoryManager> 1.125 + { 1.126 + OVR_DECLARE_SINGLETON(FakeMemoryManager); 1.127 + 1.128 + Lock FakeLock; 1.129 + Array< Ptr<FakeMemoryBlock> > FakeArray; 1.130 + 1.131 + public: 1.132 + SharedMemoryInternal* Open(const char *name, int bytes, bool openOnly) 1.133 + { 1.134 + Lock::Locker locker(&FakeLock); 1.135 + 1.136 + const int count = FakeArray.GetSizeI(); 1.137 + for (int ii = 0; ii < count; ++ii) 1.138 + { 1.139 + if (FakeArray[ii]->IsNamed(name)) 1.140 + { 1.141 + FakeArray[ii]->IncrementReferences(); 1.142 + return new SharedMemoryInternal(FakeArray[ii]); 1.143 + } 1.144 + } 1.145 + 1.146 + if (openOnly) 1.147 + { 1.148 + return NULL; 1.149 + } 1.150 + 1.151 + Ptr<FakeMemoryBlock> data = *new FakeMemoryBlock(name, bytes); 1.152 + FakeArray.PushBack(data); 1.153 + return new SharedMemoryInternal(data); 1.154 + } 1.155 + 1.156 + void Free(FakeMemoryBlock* block) 1.157 + { 1.158 + Lock::Locker locker(&FakeLock); 1.159 + 1.160 + const int count = FakeArray.GetSizeI(); 1.161 + for (int ii = 0; ii < count; ++ii) 1.162 + { 1.163 + if (FakeArray[ii].GetPtr() == block) 1.164 + { 1.165 + // If the reference count hit zero, 1.166 + if (FakeArray[ii]->DecrementReferences()) 1.167 + { 1.168 + // Toast 1.169 + FakeArray.RemoveAtUnordered(ii); 1.170 + } 1.171 + break; 1.172 + } 1.173 + } 1.174 + } 1.175 + }; 1.176 + 1.177 + FakeMemoryManager::FakeMemoryManager() 1.178 + { 1.179 + PushDestroyCallbacks(); 1.180 + } 1.181 + 1.182 + FakeMemoryManager::~FakeMemoryManager() 1.183 + { 1.184 + OVR_ASSERT(FakeArray.GetSizeI() == 0); 1.185 + } 1.186 + 1.187 + void FakeMemoryManager::OnSystemDestroy() 1.188 + { 1.189 + delete this; 1.190 + } 1.191 + 1.192 + 1.193 +} // namespace OVR 1.194 + 1.195 +OVR_DEFINE_SINGLETON(FakeMemoryManager); 1.196 + 1.197 +namespace OVR { 1.198 + 1.199 + 1.200 +void SharedMemoryInternal::Close() 1.201 +{ 1.202 + FakeMemoryManager::GetInstance()->Free(Block); 1.203 + Block.Clear(); 1.204 +} 1.205 + 1.206 +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params) 1.207 +{ 1.208 + return FakeMemoryManager::GetInstance()->Open(params.globalName, params.minSizeBytes, params.openMode == SharedMemory::OpenMode_OpenOnly); 1.209 +} 1.210 + 1.211 +#endif 1.212 + 1.213 + 1.214 +//// Windows version 1.215 + 1.216 +#if defined(OVR_OS_WIN32) && !defined(OVR_FAKE_SHAREDMEMORY) 1.217 + 1.218 +#pragma comment(lib, "advapi32.lib") 1.219 + 1.220 +// Hidden implementation class for OS-specific behavior 1.221 +class SharedMemoryInternal : public NewOverrideBase 1.222 +{ 1.223 +public: 1.224 + HANDLE FileMapping; 1.225 + void* FileView; 1.226 + 1.227 + SharedMemoryInternal(HANDLE fileMapping, void* fileView) : 1.228 + FileMapping(fileMapping), 1.229 + FileView(fileView) 1.230 + { 1.231 + } 1.232 + 1.233 + ~SharedMemoryInternal() 1.234 + { 1.235 + // If file view is set, 1.236 + if (FileView) 1.237 + { 1.238 + UnmapViewOfFile(FileView); 1.239 + FileView = NULL; 1.240 + } 1.241 + 1.242 + // If file mapping is set, 1.243 + if (FileMapping != NULL) 1.244 + { 1.245 + CloseHandle(FileMapping); 1.246 + FileMapping = NULL; 1.247 + } 1.248 + } 1.249 + 1.250 + static SharedMemoryInternal* DoFileMap(HANDLE hFileMapping, const char* fileName, bool openReadOnly, int minSize); 1.251 + static SharedMemoryInternal* AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly); 1.252 + static SharedMemoryInternal* AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite); 1.253 + static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params); 1.254 +}; 1.255 + 1.256 +SharedMemoryInternal* SharedMemoryInternal::DoFileMap(HANDLE hFileMapping, const char* fileName, bool openReadOnly, int minSize) 1.257 +{ 1.258 + // Interpret the access mode as a map desired access code 1.259 + DWORD mapDesiredAccess = openReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE; 1.260 + 1.261 + // Map view of the file to this process 1.262 + void* pFileView = MapViewOfFile(hFileMapping, mapDesiredAccess, 0, 0, minSize); 1.263 + 1.264 + // If mapping could not be created, 1.265 + if (!pFileView) 1.266 + { 1.267 + CloseHandle(hFileMapping); 1.268 + 1.269 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to map view of file for %s error code = %d", fileName, GetLastError())); 1.270 + OVR_UNUSED(fileName); 1.271 + return NULL; 1.272 + } 1.273 + 1.274 + // Create internal representation 1.275 + SharedMemoryInternal* pimple = new SharedMemoryInternal(hFileMapping, pFileView); 1.276 + 1.277 + // If memory allocation fails, 1.278 + if (!pimple) 1.279 + { 1.280 + UnmapViewOfFile(pFileView); 1.281 + CloseHandle(hFileMapping); 1.282 + 1.283 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Out of memory")); 1.284 + return NULL; 1.285 + } 1.286 + 1.287 + return pimple; 1.288 +} 1.289 + 1.290 +SharedMemoryInternal* SharedMemoryInternal::AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly) 1.291 +{ 1.292 + // Interpret the access mode as a map desired access code 1.293 + DWORD mapDesiredAccess = openReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE; 1.294 + 1.295 + // Open file mapping 1.296 + HANDLE hFileMapping = OpenFileMappingA(mapDesiredAccess, TRUE, fileName); 1.297 + 1.298 + // If file was mapped unsuccessfully, 1.299 + if (NULL == hFileMapping) 1.300 + { 1.301 + OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to open file mapping for %s error code = %d (not necessarily bad)", fileName, GetLastError())); 1.302 + return NULL; 1.303 + } 1.304 + 1.305 + // Map the file 1.306 + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); 1.307 +} 1.308 + 1.309 +SharedMemoryInternal* SharedMemoryInternal::AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite) 1.310 +{ 1.311 + // Prepare a SECURITY_ATTRIBUTES object 1.312 + SECURITY_ATTRIBUTES security; 1.313 + ZeroMemory(&security, sizeof(security)); 1.314 + security.nLength = sizeof(security); 1.315 + 1.316 + // Security descriptor by DACL strings: 1.317 + // ACE strings grant Allow(A), Object/Contains Inheritance (OICI) of: 1.318 + // + Grant All (GA) to System (SY) 1.319 + // + Grant All (GA) to Built-in Administrators (BA) 1.320 + // + Grant Read-Only (GR) or Read-Write (GWGR) to Interactive Users (IU) - ie. games 1.321 + static const char* DACLString_ReadOnly = "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GR;;;IU)"; 1.322 + static const char* DACLString_ReadWrite = "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GWGR;;;IU)"; 1.323 + 1.324 + // Select the remote process access mode 1.325 + const char* remoteAccessString = 1.326 + allowRemoteWrite ? DACLString_ReadWrite : DACLString_ReadOnly; 1.327 + 1.328 + // Attempt to convert access string to security attributes 1.329 + // Note: This will allocate the security descriptor with LocalAlloc() and must be freed later 1.330 + BOOL bConvertOkay = ConvertStringSecurityDescriptorToSecurityDescriptorA( 1.331 + remoteAccessString, SDDL_REVISION_1, &security.lpSecurityDescriptor, NULL); 1.332 + 1.333 + // If conversion fails, 1.334 + if (!bConvertOkay) 1.335 + { 1.336 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to convert access string, error code = %d", GetLastError())); 1.337 + return NULL; 1.338 + } 1.339 + 1.340 + // Interpret the access mode as a page protection code 1.341 + int pageProtectCode = openReadOnly ? PAGE_READONLY : PAGE_READWRITE; 1.342 + 1.343 + // Attempt to create a file mapping 1.344 + HANDLE hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, // From page file 1.345 + &security, // Security attributes 1.346 + pageProtectCode, // Read-only? 1.347 + 0, // High word for size = 0 1.348 + minSize, // Low word for size 1.349 + fileName); // Name of global shared memory file 1.350 + 1.351 + // Free the security descriptor buffer 1.352 + LocalFree(security.lpSecurityDescriptor); 1.353 + 1.354 + // If mapping could not be created, 1.355 + if (NULL == hFileMapping) 1.356 + { 1.357 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to create file mapping for %s error code = %d", fileName, GetLastError())); 1.358 + return NULL; 1.359 + } 1.360 + 1.361 +#ifndef OVR_ALLOW_CREATE_FILE_MAPPING_IF_EXISTS 1.362 + // If the file mapping already exists, 1.363 + if (GetLastError() == ERROR_ALREADY_EXISTS) 1.364 + { 1.365 + CloseHandle(hFileMapping); 1.366 + 1.367 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: File mapping at %s already exists", fileName)); 1.368 + return NULL; 1.369 + } 1.370 +#endif 1.371 + 1.372 + // Map the file 1.373 + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); 1.374 +} 1.375 + 1.376 +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params) 1.377 +{ 1.378 + SharedMemoryInternal* retval = NULL; 1.379 + 1.380 + // Construct the file mapping name in a Windows-specific way 1.381 + OVR::String fileMappingName = params.globalName; 1.382 + const char *fileName = fileMappingName.ToCStr(); 1.383 + 1.384 + // Is being opened read-only? 1.385 + const bool openReadOnly = (params.accessMode == SharedMemory::AccessMode_ReadOnly); 1.386 + 1.387 + // Try up to 3 times to reduce low-probability failures: 1.388 + static const int ATTEMPTS_MAX = 3; 1.389 + for (int attempts = 0; attempts < ATTEMPTS_MAX; ++attempts) 1.390 + { 1.391 + // If opening should be attempted first, 1.392 + if (params.openMode != SharedMemory::OpenMode_CreateOnly) 1.393 + { 1.394 + // Attempt to open a shared memory map 1.395 + retval = AttemptOpenSharedMemory(fileName, params.minSizeBytes, openReadOnly); 1.396 + 1.397 + // If successful, 1.398 + if (retval) 1.399 + { 1.400 + // Done! 1.401 + break; 1.402 + } 1.403 + } 1.404 + 1.405 + // If creating the shared memory is also acceptable, 1.406 + if (params.openMode != SharedMemory::OpenMode_OpenOnly) 1.407 + { 1.408 + // Interpret create mode 1.409 + const bool allowRemoteWrite = (params.remoteMode == SharedMemory::RemoteMode_ReadWrite); 1.410 + 1.411 + // Attempt to create a shared memory map 1.412 + retval = AttemptCreateSharedMemory(fileName, params.minSizeBytes, openReadOnly, allowRemoteWrite); 1.413 + 1.414 + // If successful, 1.415 + if (retval) 1.416 + { 1.417 + // Done! 1.418 + break; 1.419 + } 1.420 + } 1.421 + } // Re-attempt create/open 1.422 + 1.423 + // Note: On Windows the initial contents of the region are guaranteed to be zero. 1.424 + return retval; 1.425 +} 1.426 + 1.427 +#endif // OVR_OS_WIN32 1.428 + 1.429 + 1.430 +#if (defined(OVR_OS_LINUX) || defined(OVR_OS_MAC)) && !defined(OVR_FAKE_SHAREDMEMORY) 1.431 + 1.432 +// Hidden implementation class for OS-specific behavior 1.433 +class SharedMemoryInternal 1.434 +{ 1.435 +public: 1.436 + int FileMapping; 1.437 + void* FileView; 1.438 + int FileSize; 1.439 + 1.440 + SharedMemoryInternal(int fileMapping, void* fileView, int fileSize) : 1.441 + FileMapping(fileMapping), 1.442 + FileView(fileView), 1.443 + FileSize(fileSize) 1.444 + { 1.445 + } 1.446 + 1.447 + ~SharedMemoryInternal() 1.448 + { 1.449 + // If file view is set, 1.450 + if (FileView) 1.451 + { 1.452 + munmap(FileView, FileSize); 1.453 + FileView = MAP_FAILED; 1.454 + } 1.455 + 1.456 + // If file mapping is set, 1.457 + if (FileMapping >= 0) 1.458 + { 1.459 + close(FileMapping); 1.460 + FileMapping = -1; 1.461 + } 1.462 + } 1.463 + 1.464 + static SharedMemoryInternal* DoFileMap(int hFileMapping, const char* fileName, bool openReadOnly, int minSize); 1.465 + static SharedMemoryInternal* AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly); 1.466 + static SharedMemoryInternal* AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite); 1.467 + static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params); 1.468 +}; 1.469 + 1.470 +SharedMemoryInternal* SharedMemoryInternal::DoFileMap(int hFileMapping, const char* fileName, bool openReadOnly, int minSize) 1.471 +{ 1.472 + // Calculate the required flags based on read/write mode 1.473 + int prot = openReadOnly ? PROT_READ : (PROT_READ|PROT_WRITE); 1.474 + 1.475 + // Map the file view 1.476 + void* pFileView = mmap(NULL, minSize, prot, MAP_SHARED, hFileMapping, 0); 1.477 + 1.478 + if (pFileView == MAP_FAILED) 1.479 + { 1.480 + close(hFileMapping); 1.481 + 1.482 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to map view of file for %s error code = %d", fileName, errno)); 1.483 + OVR_UNUSED(fileName); 1.484 + return NULL; 1.485 + } 1.486 + 1.487 + // Create internal representation 1.488 + SharedMemoryInternal* pimple = new SharedMemoryInternal(hFileMapping, pFileView, minSize); 1.489 + 1.490 + // If memory allocation fails, 1.491 + if (!pimple) 1.492 + { 1.493 + munmap(pFileView, minSize); 1.494 + close(hFileMapping); 1.495 + 1.496 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Out of memory")); 1.497 + return NULL; 1.498 + } 1.499 + 1.500 + return pimple; 1.501 +} 1.502 + 1.503 +SharedMemoryInternal* SharedMemoryInternal::AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly) 1.504 +{ 1.505 + // Calculate permissions and flags based on read/write mode 1.506 + int flags = openReadOnly ? O_RDONLY : O_RDWR; 1.507 + int perms = openReadOnly ? S_IRUSR : (S_IRUSR | S_IWUSR); 1.508 + 1.509 + // Attempt to open the shared memory file 1.510 + int hFileMapping = shm_open(fileName, flags, perms); 1.511 + 1.512 + // If file was not opened successfully, 1.513 + if (hFileMapping < 0) 1.514 + { 1.515 + OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to open file mapping for %s error code = %d (not necessarily bad)", fileName, errno)); 1.516 + return NULL; 1.517 + } 1.518 + 1.519 + // Map the file 1.520 + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); 1.521 +} 1.522 + 1.523 +SharedMemoryInternal* SharedMemoryInternal::AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite) 1.524 +{ 1.525 + // Create mode 1.526 + // Note: Cannot create the shared memory file read-only because then ftruncate() will fail. 1.527 + int flags = O_CREAT | O_RDWR; 1.528 + 1.529 +#ifndef OVR_ALLOW_CREATE_FILE_MAPPING_IF_EXISTS 1.530 + // Require exclusive access when creating (seems like a good idea without trying it yet..) 1.531 + if (shm_unlink(fileName) < 0) 1.532 + { 1.533 + OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to unlink shared memory file %s error code = %d", fileName, errno)); 1.534 + } 1.535 + flags |= O_EXCL; 1.536 +#endif 1.537 + 1.538 + // Set own read/write permissions 1.539 + int perms = openReadOnly ? S_IRUSR : (S_IRUSR|S_IWUSR); 1.540 + 1.541 + // Allow other users to read/write the shared memory file 1.542 + perms |= allowRemoteWrite ? (S_IWGRP|S_IWOTH|S_IRGRP|S_IROTH) : (S_IRGRP|S_IROTH); 1.543 + 1.544 + // Attempt to open the shared memory file 1.545 + int hFileMapping = shm_open(fileName, flags, perms); 1.546 + 1.547 + // If file was not opened successfully, 1.548 + if (hFileMapping < 0) 1.549 + { 1.550 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to create file mapping for %s error code = %d", fileName, errno)); 1.551 + return NULL; 1.552 + } 1.553 + 1.554 + int truncRes = ftruncate(hFileMapping, minSize); 1.555 + 1.556 + // If file was not opened successfully, 1.557 + if (truncRes < 0) 1.558 + { 1.559 + close(hFileMapping); 1.560 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to truncate file for %s to %d error code = %d", fileName, minSize, errno)); 1.561 + return NULL; 1.562 + } 1.563 + 1.564 + // Map the file 1.565 + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); 1.566 +} 1.567 + 1.568 +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params) 1.569 +{ 1.570 + SharedMemoryInternal* retval = NULL; 1.571 + 1.572 + // Construct the file mapping name in a Linux-specific way 1.573 + OVR::String fileMappingName = "/"; 1.574 + fileMappingName += params.globalName; 1.575 + const char *fileName = fileMappingName.ToCStr(); 1.576 + 1.577 + // Is being opened read-only? 1.578 + const bool openReadOnly = (params.accessMode == SharedMemory::AccessMode_ReadOnly); 1.579 + 1.580 + // Try up to 3 times to reduce low-probability failures: 1.581 + static const int ATTEMPTS_MAX = 3; 1.582 + for (int attempts = 0; attempts < ATTEMPTS_MAX; ++attempts) 1.583 + { 1.584 + // If opening should be attempted first, 1.585 + if (params.openMode != SharedMemory::OpenMode_CreateOnly) 1.586 + { 1.587 + // Attempt to open a shared memory map 1.588 + retval = AttemptOpenSharedMemory(fileName, params.minSizeBytes, openReadOnly); 1.589 + 1.590 + // If successful, 1.591 + if (retval) 1.592 + { 1.593 + // Done! 1.594 + break; 1.595 + } 1.596 + } 1.597 + 1.598 + // If creating the shared memory is also acceptable, 1.599 + if (params.openMode != SharedMemory::OpenMode_OpenOnly) 1.600 + { 1.601 + // Interpret create mode 1.602 + const bool allowRemoteWrite = (params.remoteMode == SharedMemory::RemoteMode_ReadWrite); 1.603 + 1.604 + // Attempt to create a shared memory map 1.605 + retval = AttemptCreateSharedMemory(fileName, params.minSizeBytes, openReadOnly, allowRemoteWrite); 1.606 + 1.607 + // If successful, 1.608 + if (retval) 1.609 + { 1.610 + // Done! 1.611 + break; 1.612 + } 1.613 + } 1.614 + } // Re-attempt create/open 1.615 + 1.616 + // Note: On Windows the initial contents of the region are guaranteed to be zero. 1.617 + return retval; 1.618 +} 1.619 + 1.620 +#endif // OVR_OS_LINUX 1.621 + 1.622 + 1.623 +//// SharedMemory 1.624 + 1.625 +SharedMemory::SharedMemory(int size, void* data, SharedMemoryInternal* pInternal) : 1.626 + Size(size), 1.627 + Data(data), 1.628 + Internal(pInternal) 1.629 +{ 1.630 +} 1.631 +// Call close when it goes out of scope 1.632 +SharedMemory::~SharedMemory() 1.633 +{ 1.634 + Close(); 1.635 + delete Internal; 1.636 +} 1.637 + 1.638 +void SharedMemory::Close() 1.639 +{ 1.640 + if (Internal) 1.641 + { 1.642 + delete Internal; 1.643 + Internal = NULL; 1.644 + } 1.645 +} 1.646 + 1.647 + 1.648 +//// SharedMemoryFactory 1.649 + 1.650 +Ptr<SharedMemory> SharedMemoryFactory::Open(const SharedMemory::OpenParameters& params) 1.651 +{ 1.652 + Ptr<SharedMemory> retval; 1.653 + 1.654 + // If no name specified or no size requested, 1.655 + if (!params.globalName || (params.minSizeBytes <= 0)) 1.656 + { 1.657 + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Invalid parameters to Create()")); 1.658 + return NULL; 1.659 + } 1.660 + 1.661 + OVR_DEBUG_LOG(("[SharedMemory] Creating shared memory region: %s > %d bytes", 1.662 + params.globalName, params.minSizeBytes)); 1.663 + 1.664 + // Attempt to create a shared memory region from the parameters 1.665 + SharedMemoryInternal* pInternal = SharedMemoryInternal::CreateSharedMemory(params); 1.666 + 1.667 + if (pInternal) 1.668 + { 1.669 + // Create the wrapper object 1.670 + retval = *new SharedMemory(params.minSizeBytes, pInternal->FileView, pInternal); 1.671 + } 1.672 + 1.673 + return retval; 1.674 +} 1.675 + 1.676 +SharedMemoryFactory::SharedMemoryFactory() 1.677 +{ 1.678 + OVR_DEBUG_LOG(("[SharedMemory] Creating factory")); 1.679 + 1.680 + PushDestroyCallbacks(); 1.681 +} 1.682 + 1.683 +SharedMemoryFactory::~SharedMemoryFactory() 1.684 +{ 1.685 + OVR_DEBUG_LOG(("[SharedMemory] Destroying factory")); 1.686 +} 1.687 + 1.688 +void SharedMemoryFactory::OnSystemDestroy() 1.689 +{ 1.690 + delete this; 1.691 +} 1.692 + 1.693 + 1.694 +} // namespace OVR