llpluginsharedmemory.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:10k
源码类别:

游戏引擎

开发平台:

C++ Builder

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