Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
4.7KB

  1. /*
  2. * Carla shared memory utils
  3. * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_SHM_UTILS_HPP_INCLUDED
  18. #define CARLA_SHM_UTILS_HPP_INCLUDED
  19. #include "CarlaUtils.hpp"
  20. #ifdef CARLA_OS_WIN
  21. struct shm_t { HANDLE shm; HANDLE map; };
  22. #else
  23. # include <fcntl.h>
  24. # include <sys/mman.h>
  25. typedef int shm_t;
  26. #endif
  27. #ifdef CARLA_OS_WIN
  28. static shm_t gNullCarlaShm = { nullptr, nullptr };
  29. #else
  30. static shm_t gNullCarlaShm = -1;
  31. #endif
  32. // -----------------------------------------------------------------------
  33. // shared memory calls
  34. static inline
  35. bool carla_is_shm_valid(const shm_t& shm)
  36. {
  37. #ifdef CARLA_OS_WIN
  38. return (shm.shm != nullptr && shm.shm != INVALID_HANDLE_VALUE);
  39. #else
  40. return (shm >= 0);
  41. #endif
  42. }
  43. static inline
  44. void carla_shm_init(shm_t& shm)
  45. {
  46. #ifdef CARLA_OS_WIN
  47. shm.shm = nullptr;
  48. shm.map = nullptr;
  49. #else
  50. shm = -1;
  51. #endif
  52. }
  53. #ifdef CARLA_OS_WIN
  54. static inline
  55. shm_t carla_shm_create(const char* const name)
  56. {
  57. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullShm);
  58. shm_t ret;
  59. ret.shm = nullptr; // TODO
  60. ret.map = nullptr;
  61. return ret;
  62. }
  63. static inline
  64. shm_t carla_shm_attach(const char* const name)
  65. {
  66. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullShm);
  67. shm_t ret;
  68. ret.shm = CreateFileA(name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  69. ret.map = nullptr;
  70. return ret;
  71. }
  72. static inline
  73. shm_t carla_shm_attach_linux(const char* const name)
  74. {
  75. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullShm);
  76. char shmName[std::strlen(name)+10];
  77. std::strcpy(shmName, "/dev/shm/");
  78. std::strcat(shmName, name);
  79. shm_t ret;
  80. ret.shm = CreateFileA(shmName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  81. ret.map = nullptr;
  82. return ret;
  83. }
  84. #else
  85. static inline
  86. shm_t carla_shm_create(const char* const name)
  87. {
  88. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1);
  89. return shm_open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
  90. }
  91. static inline
  92. shm_t carla_shm_attach(const char* const name)
  93. {
  94. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1);
  95. return shm_open(name, O_RDWR, 0);
  96. }
  97. #endif
  98. static inline
  99. void carla_shm_close(shm_t& shm)
  100. {
  101. CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm),);
  102. #ifdef CARLA_OS_WIN
  103. CARLA_SAFE_ASSERT_RETURN(shm.map == nullptr,);
  104. CloseHandle(shm.shm);
  105. shm.shm = nullptr;
  106. #else
  107. close(shm);
  108. shm = -1;
  109. #endif
  110. }
  111. static inline
  112. void* carla_shm_map(shm_t& shm, const size_t size)
  113. {
  114. CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm), nullptr);
  115. CARLA_SAFE_ASSERT_RETURN(size > 0, nullptr);
  116. #ifdef CARLA_OS_WIN
  117. CARLA_SAFE_ASSERT_RETURN(shm.map == nullptr, nullptr);
  118. HANDLE map = CreateFileMapping(shm.shm, NULL, PAGE_READWRITE, size, size, NULL);
  119. if (map == nullptr)
  120. return nullptr;
  121. HANDLE ptr = MapViewOfFile(map, FILE_MAP_COPY, 0, 0, size);
  122. if (ptr == nullptr)
  123. {
  124. CloseHandle(map);
  125. return nullptr;
  126. }
  127. shm.map = map;
  128. return ptr;
  129. #else
  130. if (ftruncate(shm, static_cast<off_t>(size)) != 0)
  131. return nullptr;
  132. return mmap(nullptr, size, PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0);
  133. #endif
  134. }
  135. static inline
  136. void carla_shm_unmap(shm_t& shm, void* const ptr, const size_t size)
  137. {
  138. CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm),);
  139. CARLA_SAFE_ASSERT_RETURN(ptr != nullptr,);
  140. CARLA_SAFE_ASSERT_RETURN(size > 0,);
  141. #ifdef CARLA_OS_WIN
  142. CARLA_SAFE_ASSERT_RETURN(shm.map != nullptr,);
  143. UnmapViewOfFile(ptr);
  144. CloseHandle(shm.map);
  145. shm.map = nullptr;
  146. return;
  147. // unused
  148. (void)size;
  149. #else
  150. munmap(ptr, size);
  151. return;
  152. // unused
  153. (void)shm;
  154. #endif
  155. }
  156. // -----------------------------------------------------------------------
  157. // shared memory, templated calls
  158. template<typename T>
  159. static inline
  160. bool carla_shm_map(shm_t& shm, T*& value)
  161. {
  162. value = (T*)carla_shm_map(shm, sizeof(T));
  163. return (value != nullptr);
  164. }
  165. template<typename T>
  166. static inline
  167. void carla_shm_unmap(shm_t& shm, T*& value)
  168. {
  169. carla_shm_unmap(shm, value, sizeof(T));
  170. value = nullptr;
  171. }
  172. // -----------------------------------------------------------------------
  173. #endif // CARLA_SHM_UTILS_HPP_INCLUDED