shmrot.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #ifdef _WIN32
  2. #define _CRT_SECURE_NO_WARNINGS
  3. #define _CRT_NONSTDC_NO_WARNINGS
  4. #include <windows.h>
  5. #include <io.h>
  6. #include "../Win32/w32def.h"
  7. #endif // _WIN32
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <errno.h>
  11. #include <unistd.h>
  12. #ifdef __linux__
  13. #include <sys/file.h>
  14. #include <sys/ipc.h>
  15. #include <sys/sem.h>
  16. #include <linux/limits.h>
  17. #include <sys/shm.h>
  18. #endif // __linux__
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <fcntl.h>
  22. #include "defines.h"
  23. #include "shmrot.h"
  24. /////////////////////////////////////////////////////////////////////////////
  25. #define _FILES_DIRECTORY "/tmp"
  26. /////////////////////////////////////////////////////////////////////////////
  27. #define _SHMROT_ENTRY_FLAG_VALID 0x00000001
  28. /////////////////////////////////////////////////////////////////////////////
  29. // {99df2b86-f904-425d-9fcc-c83c329d0937}
  30. DEFINE_UUID(GUID_SHMROT, 0x99df2b86, 0xf904, 0x425d, 0x9f, 0xcc, 0xc8, 0x3c, 0x32, 0x9d, 0x09, 0x37);
  31. /////////////////////////////////////////////////////////////////////////////
  32. CShmROT::CShmROT(void) : m_pTable(NULL)
  33. {
  34. }
  35. CShmROT::~CShmROT(void)
  36. {
  37. Release();
  38. }
  39. bool CShmROT::Create(void)
  40. {
  41. TRACE("CShmROT::Create!\n");
  42. int nRet = m_shmRot.Create(GUID_SHMROT, sizeof(SHMROT));
  43. if( nRet >= 0 &&
  44. (m_pTable = (LPSHMROT)m_shmRot.Attach()))
  45. {
  46. if(nRet == 1)
  47. {
  48. m_pTable->version = _ROT_CURRENT_VERSION;
  49. m_pTable->maxEntries = _ROT_MAX_TABLE_ENTRIES;
  50. m_pTable->entrySize = (uint32_t)sizeof(SHMROT_ENTRY);
  51. }
  52. else if(nRet == 0)
  53. {
  54. if(m_pTable->version != _ROT_CURRENT_VERSION)
  55. {
  56. // ...
  57. }
  58. }
  59. return true;
  60. }
  61. return false;
  62. }
  63. void CShmROT::Release(void)
  64. {
  65. if(m_pTable)
  66. {
  67. TRACE("CShmROT::Release!\n");
  68. m_shmRot.Detach(m_pTable);
  69. m_shmRot.Release();
  70. m_pTable = NULL;
  71. }
  72. }
  73. void CShmROT::ForceReleaseMutex(void)
  74. {
  75. m_shmRot.ForceReleaseMutex();
  76. }
  77. CShm* CShmROT::AcquireShm(const char *pszUuid, size_t nSizeElement, size_t nCntElements, const char *pszDescName)
  78. {
  79. if(!m_pTable)
  80. {
  81. TRACE("CShmROT::AcquireShm: ROT not initialized!\n");
  82. return NULL;
  83. }
  84. uuid_t uuid;
  85. CShm *pShm = NULL;
  86. if(!_uuid_parse(pszUuid, &uuid))
  87. {
  88. TRACE("CShmROT::AcquireShm: invalid uuid!\n");
  89. return NULL;
  90. }
  91. int nIndexFound = -1;
  92. int nFirstUnusedIndex = -1;
  93. for(int i = 0; i < (int)m_pTable->maxEntries; i++)
  94. {
  95. SHMROT_ENTRY &re = m_pTable->rot[i];
  96. if(re.flags & _SHMROT_ENTRY_FLAG_VALID)
  97. {
  98. if(!_uuid_compare(&re.uuid, &uuid))
  99. {
  100. nIndexFound = i;
  101. break;
  102. }
  103. }
  104. else if(nFirstUnusedIndex == -1)
  105. {
  106. nFirstUnusedIndex = i;
  107. }
  108. }
  109. if(nIndexFound >= 0) // found existing entry
  110. {
  111. SHMROT_ENTRY &re = m_pTable->rot[nIndexFound];
  112. bool bMatch = (re.nSizeElement == nSizeElement) && (re.nCntElements == nCntElements);
  113. if(bMatch)
  114. {
  115. TRACE("CShmROT::AcquireShm: Found matching SHM entry!\n");
  116. if((pShm = new CShm))
  117. {
  118. if(pShm->Create(uuid, nSizeElement * nCntElements) < 0)
  119. {
  120. pShm->Release();
  121. delete pShm;
  122. pShm = NULL;
  123. TRACE("CShmROT::AcquireShm: Failed to create new CShm!\n");
  124. }
  125. else
  126. {
  127. re.nCntHandles++;
  128. }
  129. }
  130. else
  131. {
  132. TRACE("CShmROT::AcquireShm: Failed to allocate new CShm!\n");
  133. }
  134. }
  135. else
  136. {
  137. TRACE("CShmROT::AcquireShm: SHM uuid exists, but size does not match!\n");
  138. }
  139. }
  140. else if(nFirstUnusedIndex >= 0) // next free slot
  141. {
  142. TRACE("CShmROT::AcquireShm: Create new SHM entry!\n");
  143. SHMROT_ENTRY &re = m_pTable->rot[nFirstUnusedIndex];
  144. if((pShm = new CShm))
  145. {
  146. if(pShm->Create(uuid, nSizeElement * nCntElements) < 0)
  147. {
  148. pShm->Release();
  149. delete pShm;
  150. pShm = NULL;
  151. TRACE("CShmROT::AcquireShm: Failed to create new CShm!\n");
  152. }
  153. else
  154. {
  155. re.flags = _SHMROT_ENTRY_FLAG_VALID;
  156. re.nSizeElement = (uint32_t)nSizeElement;
  157. re.nCntElements = (uint32_t)nCntElements;
  158. re.nCntHandles = 1;
  159. _uuid_copy(&re.uuid, &uuid);
  160. memset(re.szDescName, 0, sizeof(re.szDescName));
  161. if(pszDescName)
  162. {
  163. size_t nLen = strlen(pszDescName);
  164. if(nLen > 0)
  165. {
  166. if(nLen >= _ROT_MAX_ENTRY_NAME)
  167. nLen = _ROT_MAX_ENTRY_NAME - 1;
  168. memcpy(re.szDescName, pszDescName, nLen);
  169. re.szDescName[nLen] = '\0';
  170. }
  171. }
  172. }
  173. }
  174. else
  175. {
  176. TRACE("CShmROT::AcquireShm: Failed to allocate new CShm!\n");
  177. }
  178. }
  179. else
  180. {
  181. TRACE("CShmROT::AcquireShm: SHM uuid not found and no slot available!\n");
  182. }
  183. return pShm;
  184. }
  185. void CShmROT::ReleaseShm(CShm *pShm)
  186. {
  187. if(pShm)
  188. {
  189. const uuid_t &ruuid = pShm->Uuid();
  190. for(int i = 0; i < (int)m_pTable->maxEntries; i++)
  191. {
  192. SHMROT_ENTRY &re = m_pTable->rot[i];
  193. if(!_uuid_compare(&re.uuid, &ruuid))
  194. {
  195. if(re.flags & _SHMROT_ENTRY_FLAG_VALID)
  196. {
  197. if(re.nCntHandles > 0)
  198. --re.nCntHandles;
  199. if(re.nCntHandles == 0)
  200. re.flags &= ~_SHMROT_ENTRY_FLAG_VALID;
  201. }
  202. break;
  203. }
  204. }
  205. pShm->Release();
  206. delete pShm;
  207. }
  208. }
  209. int CShmROT::Lock(void)
  210. {
  211. return m_shmRot.Lock();
  212. }
  213. int CShmROT::Unlock(void)
  214. {
  215. return m_shmRot.Unlock();
  216. }
  217. void CShmROT::DumpEntries(CShmHandleMap &map)
  218. {
  219. if(!m_pTable)
  220. {
  221. printf("CShmROT::DumpEntries: ROT not initialized!\n");
  222. return;
  223. }
  224. char szUuid[_UUID_STRING_LEN + 1];
  225. Lock();
  226. for(int i = 0; i < (int)m_pTable->maxEntries; i++)
  227. {
  228. SHMROT_ENTRY &re = m_pTable->rot[i];
  229. if(re.flags & _SHMROT_ENTRY_FLAG_VALID)
  230. {
  231. unsigned long nAttached = 0;
  232. _uuid_unparse(&re.uuid, szUuid, sizeof(szUuid));
  233. if(re.nCntHandles > 0)
  234. {
  235. CShm *pShm = map.LookupShm(re.uuid);
  236. if(pShm)
  237. nAttached = pShm->GetNumAttached();
  238. }
  239. printf( "uuid: '%s',\n" \
  240. " flags: 0x%08x,\n" \
  241. " size of element: %u,\n" \
  242. " number of elements: %u,\n" \
  243. " name: '%s',\n" \
  244. " number of handles: %u,\n" \
  245. " number of pointers: %lu\n",
  246. szUuid,
  247. re.flags,
  248. re.nSizeElement,
  249. re.nCntElements,
  250. re.szDescName,
  251. re.nCntHandles,
  252. nAttached);
  253. fflush(stdout);
  254. }
  255. }
  256. Unlock();
  257. }