jack2 codebase
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.

1192 lines
29KB

  1. /* This module provides a set of abstract shared memory interfaces
  2. * with support using both System V and POSIX shared memory
  3. * implementations. The code is divided into three sections:
  4. *
  5. * - common (interface-independent) code
  6. * - POSIX implementation
  7. * - System V implementation
  8. *
  9. * The implementation used is determined by whether USE_POSIX_SHM was
  10. * set in the ./configure step.
  11. */
  12. /*
  13. * Copyright (C) 2003 Paul Davis
  14. * Copyright (C) 2004 Jack O'Quin
  15. * Copyright (C) 2006-2007 Grame
  16. *
  17. * This program is free software; you can redistribute it and/or modify
  18. * it under the terms of the GNU General Public License as published by
  19. * the Free Software Foundation; either version 2 of the License, or
  20. * (at your option) any later version.
  21. *
  22. * This program is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU General Public License for more details.
  26. *
  27. * You should have received a copy of the GNU General Public License
  28. * along with this program; if not, write to the Free Software
  29. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  30. *
  31. */
  32. #if defined(HAVE_CONFIG_H)
  33. #include "config.h"
  34. #endif
  35. #ifdef WIN32
  36. #include <process.h>
  37. #else
  38. #include <unistd.h>
  39. #include <fcntl.h>
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <signal.h>
  43. #include <limits.h>
  44. #include <errno.h>
  45. #include <dirent.h>
  46. #include <sys/mman.h>
  47. #include <sys/types.h>
  48. #include <sys/stat.h>
  49. #include <sys/shm.h>
  50. #include <sys/sem.h>
  51. #include <stdlib.h>
  52. #endif
  53. #include "shm.h"
  54. #include "JackError.h"
  55. #ifdef USE_POSIX_SHM
  56. static jack_shmtype_t jack_shmtype = shm_POSIX;
  57. #elif WIN32
  58. static jack_shmtype_t jack_shmtype = shm_WIN32;
  59. #else
  60. static jack_shmtype_t jack_shmtype = shm_SYSV;
  61. #endif
  62. /* interface-dependent forward declarations */
  63. static int jack_access_registry (jack_shm_info_t *ri);
  64. static int jack_create_registry (jack_shm_info_t *ri);
  65. static void jack_remove_shm (jack_shm_id_t *id);
  66. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  67. * common interface-independent section
  68. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  69. /* The JACK SHM registry is a chunk of memory for keeping track of the
  70. * shared memory used by each active JACK server. This allows the
  71. * server to clean up shared memory when it exits. To avoid memory
  72. * leakage due to kill -9, crashes or debugger-driven exits, this
  73. * cleanup is also done when a new instance of that server starts.
  74. */
  75. /* per-process global data for the SHM interfaces */
  76. static jack_shm_id_t registry_id; /* SHM id for the registry */
  77. #ifdef WIN32
  78. static jack_shm_info_t registry_info = {/* SHM info for the registry */
  79. JACK_SHM_NULL_INDEX,
  80. NULL
  81. };
  82. #else
  83. static jack_shm_info_t registry_info = { /* SHM info for the registry */
  84. .index = JACK_SHM_NULL_INDEX,
  85. .attached_at = MAP_FAILED
  86. };
  87. #endif
  88. /* pointers to registry header and array */
  89. static jack_shm_header_t *jack_shm_header = NULL;
  90. static jack_shm_registry_t *jack_shm_registry = NULL;
  91. static char jack_shm_server_prefix[JACK_SERVER_NAME_SIZE] = "";
  92. /* jack_shm_lock_registry() serializes updates to the shared memory
  93. * segment JACK uses to keep track of the SHM segments allocated to
  94. * all its processes, including multiple servers.
  95. *
  96. * This is not a high-contention lock, but it does need to work across
  97. * multiple processes. High transaction rates and realtime safety are
  98. * not required. Any solution needs to at least be portable to POSIX
  99. * and POSIX-like systems.
  100. *
  101. * We must be particularly careful to ensure that the lock be released
  102. * if the owning process terminates abnormally. Otherwise, a segfault
  103. * or kill -9 at the wrong moment could prevent JACK from ever running
  104. * again on that machine until after a reboot.
  105. */
  106. #define JACK_SEMAPHORE_KEY 0x282929
  107. #ifndef USE_POSIX_SHM
  108. #define JACK_SHM_REGISTRY_KEY JACK_SEMAPHORE_KEY
  109. #endif
  110. static int semid = -1;
  111. #ifdef WIN32
  112. // steph TODO
  113. static void
  114. semaphore_init () {}
  115. static void
  116. semaphore_add (int value) {}
  117. #else
  118. /* all semaphore errors are fatal -- issue message, but do not return */
  119. static void
  120. semaphore_error (char *msg)
  121. {
  122. jack_error ("Fatal JACK semaphore error: %s (%s)",
  123. msg, strerror (errno));
  124. abort ();
  125. }
  126. static void
  127. semaphore_init ()
  128. {
  129. key_t semkey = JACK_SEMAPHORE_KEY;
  130. struct sembuf sbuf;
  131. int create_flags = IPC_CREAT | IPC_EXCL
  132. | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
  133. /* Get semaphore ID associated with this key. */
  134. if ((semid = semget(semkey, 0, 0)) == -1) {
  135. /* Semaphore does not exist - Create. */
  136. if ((semid = semget(semkey, 1, create_flags)) != -1) {
  137. /* Initialize the semaphore, allow one owner. */
  138. sbuf.sem_num = 0;
  139. sbuf.sem_op = 1;
  140. sbuf.sem_flg = 0;
  141. if (semop(semid, &sbuf, 1) == -1) {
  142. semaphore_error ("semop");
  143. }
  144. } else if (errno == EEXIST) {
  145. if ((semid = semget(semkey, 0, 0)) == -1) {
  146. semaphore_error ("semget");
  147. }
  148. } else {
  149. semaphore_error ("semget creation");
  150. }
  151. }
  152. }
  153. static inline void
  154. semaphore_add (int value)
  155. {
  156. struct sembuf sbuf;
  157. sbuf.sem_num = 0;
  158. sbuf.sem_op = value;
  159. sbuf.sem_flg = SEM_UNDO;
  160. if (semop(semid, &sbuf, 1) == -1) {
  161. semaphore_error ("semop");
  162. }
  163. }
  164. #endif
  165. static void
  166. jack_shm_lock_registry (void)
  167. {
  168. if (semid == -1)
  169. semaphore_init ();
  170. semaphore_add (-1);
  171. }
  172. static void
  173. jack_shm_unlock_registry (void)
  174. {
  175. semaphore_add (1);
  176. }
  177. static void
  178. jack_shm_init_registry ()
  179. {
  180. /* registry must be locked */
  181. int i;
  182. memset (jack_shm_header, 0, JACK_SHM_REGISTRY_SIZE);
  183. jack_shm_header->magic = JACK_SHM_MAGIC;
  184. //jack_shm_header->protocol = JACK_PROTOCOL_VERSION;
  185. jack_shm_header->type = jack_shmtype;
  186. jack_shm_header->size = JACK_SHM_REGISTRY_SIZE;
  187. jack_shm_header->hdr_len = sizeof (jack_shm_header_t);
  188. jack_shm_header->entry_len = sizeof (jack_shm_registry_t);
  189. for (i = 0; i < MAX_SHM_ID; ++i) {
  190. jack_shm_registry[i].index = i;
  191. }
  192. }
  193. static int
  194. jack_shm_validate_registry ()
  195. {
  196. /* registry must be locked */
  197. if ((jack_shm_header->magic == JACK_SHM_MAGIC)
  198. //&& (jack_shm_header->protocol == JACK_PROTOCOL_VERSION)
  199. && (jack_shm_header->type == jack_shmtype)
  200. && (jack_shm_header->size == JACK_SHM_REGISTRY_SIZE)
  201. && (jack_shm_header->hdr_len == sizeof (jack_shm_header_t))
  202. && (jack_shm_header->entry_len == sizeof (jack_shm_registry_t))) {
  203. return 0; /* registry OK */
  204. }
  205. return -1;
  206. }
  207. /* set a unique per-user, per-server shm prefix string
  208. *
  209. * According to the POSIX standard:
  210. *
  211. * "The name argument conforms to the construction rules for a
  212. * pathname. If name begins with the slash character, then processes
  213. * calling shm_open() with the same value of name refer to the same
  214. * shared memory object, as long as that name has not been
  215. * removed. If name does not begin with the slash character, the
  216. * effect is implementation-defined. The interpretation of slash
  217. * characters other than the leading slash character in name is
  218. * implementation-defined."
  219. *
  220. * Since the Linux implementation does not allow slashes *within* the
  221. * name, in the interest of portability we use colons instead.
  222. */
  223. static void
  224. jack_set_server_prefix (const char *server_name)
  225. {
  226. #ifdef WIN32
  227. snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix),
  228. "jack-%d:%s:", _getpid (), server_name); // steph TO CHECK
  229. #else
  230. snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix),
  231. "/jack-%d:%s:", getuid (), server_name);
  232. #endif
  233. }
  234. /* gain server addressability to shared memory registration segment
  235. *
  236. * returns: 0 if successful
  237. */
  238. static int
  239. jack_server_initialize_shm (int new_registry)
  240. {
  241. int rc;
  242. if (jack_shm_header)
  243. return 0; /* already initialized */
  244. jack_shm_lock_registry ();
  245. rc = jack_access_registry (&registry_info);
  246. if (new_registry) {
  247. jack_remove_shm (&registry_id);
  248. rc = ENOENT;
  249. }
  250. switch (rc) {
  251. case ENOENT: /* registry does not exist */
  252. rc = jack_create_registry (&registry_info);
  253. break;
  254. case 0: /* existing registry */
  255. if (jack_shm_validate_registry () == 0)
  256. break;
  257. /* else it was invalid, so fall through */
  258. case EINVAL: /* bad registry */
  259. /* Apparently, this registry was created by an older
  260. * JACK version. Delete it so we can try again. */
  261. jack_release_shm (&registry_info);
  262. jack_remove_shm (&registry_id);
  263. if ((rc = jack_create_registry (&registry_info)) != 0) {
  264. jack_error ("incompatible shm registry (%s)",
  265. strerror (errno));
  266. #ifndef USE_POSIX_SHM
  267. jack_error ("to delete, use `ipcrm -M 0x%0.8x'",
  268. JACK_SHM_REGISTRY_KEY);
  269. #endif
  270. }
  271. break;
  272. default: /* failure return code */
  273. break;
  274. }
  275. jack_shm_unlock_registry ();
  276. return rc;
  277. }
  278. /* gain client addressability to shared memory registration segment
  279. *
  280. * NOTE: this function is no longer used for server initialization,
  281. * instead it calls jack_register_server().
  282. *
  283. * returns: 0 if successful
  284. */
  285. int
  286. jack_initialize_shm (const char *server_name)
  287. {
  288. int rc;
  289. if (jack_shm_header)
  290. return 0; /* already initialized */
  291. jack_set_server_prefix (server_name);
  292. jack_shm_lock_registry ();
  293. if ((rc = jack_access_registry (&registry_info)) == 0) {
  294. if ((rc = jack_shm_validate_registry ()) != 0) {
  295. jack_error ("Incompatible shm registry, "
  296. "are jackd and libjack in sync?");
  297. }
  298. }
  299. jack_shm_unlock_registry ();
  300. return rc;
  301. }
  302. char* jack_shm_addr (jack_shm_info_t* si)
  303. {
  304. return (char*)si->attached_at;
  305. }
  306. void
  307. jack_destroy_shm (jack_shm_info_t* si)
  308. {
  309. /* must NOT have the registry locked */
  310. if (si->index == JACK_SHM_NULL_INDEX)
  311. return; /* segment not allocated */
  312. jack_remove_shm (&jack_shm_registry[si->index].id);
  313. jack_release_shm_info (si->index);
  314. }
  315. jack_shm_registry_t *
  316. jack_get_free_shm_info ()
  317. {
  318. /* registry must be locked */
  319. jack_shm_registry_t* si = NULL;
  320. int i;
  321. for (i = 0; i < MAX_SHM_ID; ++i) {
  322. if (jack_shm_registry[i].size == 0) {
  323. break;
  324. }
  325. }
  326. if (i < MAX_SHM_ID) {
  327. si = &jack_shm_registry[i];
  328. }
  329. return si;
  330. }
  331. static void
  332. jack_release_shm_entry (jack_shm_registry_index_t index)
  333. {
  334. /* the registry must be locked */
  335. jack_shm_registry[index].size = 0;
  336. jack_shm_registry[index].allocator = 0;
  337. memset (&jack_shm_registry[index].id, 0,
  338. sizeof (jack_shm_registry[index].id));
  339. }
  340. void
  341. jack_release_shm_info (jack_shm_registry_index_t index)
  342. {
  343. #ifdef WIN32
  344. int my_pid = _getpid();
  345. #else
  346. pid_t my_pid = getpid();
  347. #endif
  348. /* must NOT have the registry locked */
  349. if (jack_shm_registry[index].allocator == my_pid) {
  350. jack_shm_lock_registry ();
  351. jack_release_shm_entry (index);
  352. jack_shm_unlock_registry ();
  353. }
  354. }
  355. /* Claim server_name for this process.
  356. *
  357. * returns 0 if successful
  358. * EEXIST if server_name was already active for this user
  359. * ENOSPC if server registration limit reached
  360. * ENOMEM if unable to access shared memory registry
  361. */
  362. int
  363. jack_register_server (const char *server_name, int new_registry)
  364. {
  365. int i, res = 0;
  366. #ifdef WIN32
  367. int my_pid = _getpid();
  368. #else
  369. pid_t my_pid = getpid();
  370. #endif
  371. jack_set_server_prefix (server_name);
  372. if (jack_server_initialize_shm (new_registry))
  373. return ENOMEM;
  374. jack_shm_lock_registry ();
  375. /* See if server_name already registered. Since server names
  376. * are per-user, we register the unique server prefix string.
  377. */
  378. for (i = 0; i < MAX_SERVERS; i++) {
  379. if (strncmp (jack_shm_header->server[i].name,
  380. jack_shm_server_prefix,
  381. JACK_SERVER_NAME_SIZE) != 0)
  382. continue; /* no match */
  383. if (jack_shm_header->server[i].pid == my_pid){
  384. res = 0; /* it's me */
  385. goto unlock;
  386. }
  387. /* see if server still exists */
  388. #ifndef WIN32 // steph TO CHECK
  389. if (kill (jack_shm_header->server[i].pid, 0) == 0) {
  390. res = EEXIST; /* other server running */
  391. goto unlock;
  392. }
  393. #endif
  394. /* it's gone, reclaim this entry */
  395. memset (&jack_shm_header->server[i], 0,
  396. sizeof (jack_shm_server_t));
  397. }
  398. /* find a free entry */
  399. for (i = 0; i < MAX_SERVERS; i++) {
  400. if (jack_shm_header->server[i].pid == 0)
  401. break;
  402. }
  403. if (i >= MAX_SERVERS){
  404. res = ENOSPC; /* out of space */
  405. goto unlock;
  406. }
  407. /* claim it */
  408. jack_shm_header->server[i].pid = my_pid;
  409. strncpy (jack_shm_header->server[i].name,
  410. jack_shm_server_prefix,
  411. JACK_SERVER_NAME_SIZE);
  412. unlock:
  413. jack_shm_unlock_registry ();
  414. return 0;
  415. }
  416. /* release server_name registration */
  417. void
  418. jack_unregister_server (const char *server_name /* unused */)
  419. {
  420. int i;
  421. #ifdef WIN32
  422. int my_pid = _getpid();
  423. #else
  424. pid_t my_pid = getpid();
  425. #endif
  426. jack_shm_lock_registry ();
  427. for (i = 0; i < MAX_SERVERS; i++) {
  428. if (jack_shm_header->server[i].pid == my_pid) {
  429. memset (&jack_shm_header->server[i], 0,
  430. sizeof (jack_shm_server_t));
  431. }
  432. }
  433. jack_shm_unlock_registry ();
  434. }
  435. /* called for server startup and termination */
  436. int
  437. jack_cleanup_shm ()
  438. {
  439. int i;
  440. int destroy;
  441. jack_shm_info_t copy;
  442. #ifdef WIN32
  443. int my_pid = _getpid();
  444. #else
  445. pid_t my_pid = getpid();
  446. #endif
  447. jack_shm_lock_registry ();
  448. for (i = 0; i < MAX_SHM_ID; i++) {
  449. jack_shm_registry_t* r;
  450. r = &jack_shm_registry[i];
  451. memcpy (&copy, r, sizeof (jack_shm_info_t));
  452. destroy = FALSE;
  453. /* ignore unused entries */
  454. if (r->allocator == 0)
  455. continue;
  456. /* is this my shm segment? */
  457. if (r->allocator == my_pid) {
  458. /* allocated by this process, so unattach
  459. and destroy. */
  460. jack_release_shm (&copy);
  461. destroy = TRUE;
  462. } else {
  463. /* see if allocator still exists */
  464. #ifdef WIN32 // steph
  465. jack_info("TODO: kill API not available !!");
  466. #else
  467. if (kill (r->allocator, 0)) {
  468. if (errno == ESRCH) {
  469. /* allocator no longer exists,
  470. * so destroy */
  471. destroy = TRUE;
  472. }
  473. }
  474. #endif
  475. }
  476. if (destroy) {
  477. int index = copy.index;
  478. if ((index >= 0) && (index < MAX_SHM_ID)) {
  479. jack_remove_shm (&jack_shm_registry[index].id);
  480. jack_release_shm_entry (index);
  481. }
  482. r->size = 0;
  483. r->allocator = 0;
  484. }
  485. }
  486. jack_shm_unlock_registry ();
  487. return TRUE;
  488. }
  489. /* resize a shared memory segment
  490. *
  491. * There is no way to resize a System V shm segment. Resizing is
  492. * possible with POSIX shm, but not with the non-conformant Mac OS X
  493. * implementation. Since POSIX shm is mainly used on that platform,
  494. * it's simpler to treat them both the same.
  495. *
  496. * So, we always resize by deleting and reallocating. This is
  497. * tricky, because the old segment will not disappear until
  498. * all the clients have released it. We only do what we can
  499. * from here.
  500. *
  501. * This is not done under a single lock. I don't even want to think
  502. * about all the things that could possibly go wrong if multple
  503. * processes tried to resize the same segment concurrently. That
  504. * probably doesn't happen.
  505. */
  506. int
  507. jack_resize_shm (jack_shm_info_t* si, jack_shmsize_t size)
  508. {
  509. jack_shm_id_t id;
  510. /* The underlying type of `id' differs for SYSV and POSIX */
  511. memcpy (&id, &jack_shm_registry[si->index].id, sizeof (id));
  512. jack_release_shm (si);
  513. jack_destroy_shm (si);
  514. if (jack_shmalloc ((char *) id, size, si)) {
  515. return -1;
  516. }
  517. return jack_attach_shm (si);
  518. }
  519. #ifdef USE_POSIX_SHM
  520. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  521. * POSIX interface-dependent functions
  522. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  523. /* gain addressability to existing SHM registry segment
  524. *
  525. * sets up global registry pointers, if successful
  526. *
  527. * returns: 0 if existing registry accessed successfully
  528. * ENOENT if registry does not exist
  529. * EINVAL if registry exists, but has the wrong size
  530. */
  531. static int
  532. jack_access_registry (jack_shm_info_t *ri)
  533. {
  534. /* registry must be locked */
  535. int shm_fd;
  536. strncpy (registry_id, "/jack-shm-registry", sizeof (registry_id));
  537. /* try to open an existing segment */
  538. if ((shm_fd = shm_open (registry_id, O_RDWR, 0666)) < 0) {
  539. int rc = errno;
  540. if (errno != ENOENT) {
  541. jack_error ("Cannot open existing shm registry segment"
  542. " (%s)", strerror (errno));
  543. }
  544. close (shm_fd);
  545. return rc;
  546. }
  547. if ((ri->attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE,
  548. PROT_READ|PROT_WRITE,
  549. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  550. jack_error ("Cannot mmap shm registry segment (%s)",
  551. strerror (errno));
  552. close (shm_fd);
  553. return EINVAL;
  554. }
  555. /* set up global pointers */
  556. ri->index = JACK_SHM_REGISTRY_INDEX;
  557. jack_shm_header = ri->attached_at;
  558. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  559. close (shm_fd); // steph
  560. return 0;
  561. }
  562. /* create a new SHM registry segment
  563. *
  564. * sets up global registry pointers, if successful
  565. *
  566. * returns: 0 if registry created successfully
  567. * nonzero error code if unable to allocate a new registry
  568. */
  569. static int
  570. jack_create_registry (jack_shm_info_t *ri)
  571. {
  572. /* registry must be locked */
  573. int shm_fd;
  574. strncpy (registry_id, "/jack-shm-registry", sizeof (registry_id));
  575. if ((shm_fd = shm_open (registry_id, O_RDWR|O_CREAT, 0666)) < 0) {
  576. int rc = errno;
  577. jack_error ("Cannot create shm registry segment (%s)",
  578. strerror (errno));
  579. return rc;
  580. }
  581. /* Previous shm_open result depends of the actual value of umask, force correct file permisssion here */
  582. if (fchmod(shm_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) < 0) {
  583. jack_log("Cannot chmod jack-shm-registry (%s) %d %d", strerror (errno));
  584. }
  585. /* Set the desired segment size. NOTE: the non-conformant Mac
  586. * OS X POSIX shm only allows ftruncate() on segment creation.
  587. */
  588. if (ftruncate (shm_fd, JACK_SHM_REGISTRY_SIZE) < 0) {
  589. int rc = errno;
  590. jack_error ("Cannot set registry size (%s)", strerror (errno));
  591. jack_remove_shm (&registry_id);
  592. close (shm_fd);
  593. return rc;
  594. }
  595. if ((ri->attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE,
  596. PROT_READ|PROT_WRITE,
  597. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  598. jack_error ("Cannot mmap shm registry segment (%s)",
  599. strerror (errno));
  600. jack_remove_shm (&registry_id);
  601. close (shm_fd);
  602. return EINVAL;
  603. }
  604. /* set up global pointers */
  605. ri->index = JACK_SHM_REGISTRY_INDEX;
  606. jack_shm_header = ri->attached_at;
  607. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  608. /* initialize registry contents */
  609. jack_shm_init_registry ();
  610. close (shm_fd); // steph
  611. return 0;
  612. }
  613. static void
  614. jack_remove_shm (jack_shm_id_t *id)
  615. {
  616. /* registry may or may not be locked */
  617. shm_unlink ((char *) id);
  618. }
  619. void
  620. jack_release_shm (jack_shm_info_t* si)
  621. {
  622. /* registry may or may not be locked */
  623. if (si->attached_at != MAP_FAILED) {
  624. munmap (si->attached_at, jack_shm_registry[si->index].size);
  625. }
  626. }
  627. /* allocate a POSIX shared memory segment */
  628. int
  629. jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
  630. {
  631. jack_shm_registry_t* registry;
  632. int shm_fd;
  633. int rc = -1;
  634. char name[SHM_NAME_MAX+1];
  635. jack_shm_lock_registry ();
  636. if ((registry = jack_get_free_shm_info ()) == NULL) {
  637. jack_error ("shm registry full");
  638. goto unlock;
  639. }
  640. /* On Mac OS X, the maximum length of a shared memory segment
  641. * name is SHM_NAME_MAX (instead of NAME_MAX or PATH_MAX as
  642. * defined by the standard). Unfortunately, Apple sets this
  643. * value so small (about 31 bytes) that it is useless for
  644. * actual names. So, we construct a short name from the
  645. * registry index for uniqueness and ignore the shm_name
  646. * parameter. Bah!
  647. */
  648. snprintf (name, sizeof (name), "/jackmp-%d", registry->index);
  649. if (strlen (name) >= sizeof (registry->id)) {
  650. jack_error ("shm segment name too long %s", name);
  651. goto unlock;
  652. }
  653. if ((shm_fd = shm_open (name, O_RDWR|O_CREAT, 0666)) < 0) {
  654. jack_error ("Cannot create shm segment %s (%s)",
  655. name, strerror (errno));
  656. goto unlock;
  657. }
  658. if (ftruncate (shm_fd, size) < 0) {
  659. jack_error ("Cannot set size of engine shm "
  660. "registry 0 (%s)",
  661. strerror (errno));
  662. close (shm_fd);
  663. goto unlock;
  664. }
  665. close (shm_fd);
  666. registry->size = size;
  667. strncpy (registry->id, name, sizeof (registry->id));
  668. registry->allocator = getpid();
  669. si->index = registry->index;
  670. si->attached_at = MAP_FAILED; /* not attached */
  671. rc = 0; /* success */
  672. unlock:
  673. jack_shm_unlock_registry ();
  674. return rc;
  675. }
  676. int
  677. jack_attach_shm (jack_shm_info_t* si)
  678. {
  679. int shm_fd;
  680. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  681. if ((shm_fd = shm_open (registry->id,
  682. O_RDWR, 0666)) < 0) {
  683. jack_error ("Cannot open shm segment %s (%s)", registry->id,
  684. strerror (errno));
  685. return -1;
  686. }
  687. if ((si->attached_at = mmap (0, registry->size, PROT_READ|PROT_WRITE,
  688. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  689. jack_error ("Cannot mmap shm segment %s (%s)",
  690. registry->id,
  691. strerror (errno));
  692. close (shm_fd);
  693. return -1;
  694. }
  695. close (shm_fd);
  696. return 0;
  697. }
  698. int
  699. jack_attach_shm_read (jack_shm_info_t* si)
  700. {
  701. int shm_fd;
  702. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  703. if ((shm_fd = shm_open (registry->id,
  704. O_RDONLY, 0666)) < 0) {
  705. jack_error ("Cannot open shm segment %s (%s)", registry->id,
  706. strerror (errno));
  707. return -1;
  708. }
  709. if ((si->attached_at = mmap (0, registry->size, PROT_READ,
  710. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  711. jack_error ("Cannot mmap shm segment %s (%s)",
  712. registry->id,
  713. strerror (errno));
  714. close (shm_fd);
  715. return -1;
  716. }
  717. close (shm_fd);
  718. return 0;
  719. }
  720. #elif WIN32
  721. static int
  722. jack_access_registry (jack_shm_info_t *ri)
  723. {
  724. /* registry must be locked */
  725. HANDLE shm_fd;
  726. LPSECURITY_ATTRIBUTES sec = 0;
  727. strncpy (registry_id, "jack-shm-registry", sizeof (registry_id));
  728. /* try to open an existing segment */
  729. if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry_id)) == NULL) {
  730. int rc = GetLastError();
  731. if (rc != ERROR_FILE_NOT_FOUND) {
  732. jack_error ("Cannot open existing shm registry segment (%ld)", rc);
  733. }
  734. return rc;
  735. }
  736. if ((ri->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) {
  737. jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
  738. jack_remove_shm (&registry_id);
  739. CloseHandle (shm_fd);
  740. return EINVAL;
  741. }
  742. /* set up global pointers */
  743. ri->index = JACK_SHM_REGISTRY_INDEX;
  744. jack_shm_header = ri->attached_at;
  745. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  746. //CloseHandle(shm_fd); // TO CHECK
  747. return 0;
  748. }
  749. static int
  750. jack_create_registry (jack_shm_info_t *ri)
  751. {
  752. /* registry must be locked */
  753. HANDLE shm_fd;
  754. strncpy (registry_id, "jack-shm-registry", sizeof (registry_id));
  755. if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE,
  756. 0, PAGE_READWRITE,
  757. 0, JACK_SHM_REGISTRY_SIZE,
  758. registry_id)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) {
  759. int rc = GetLastError();
  760. jack_error ("Cannot create shm registry segment (%ld)", rc);
  761. return rc;
  762. }
  763. if ((ri->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) {
  764. jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
  765. jack_remove_shm (&registry_id);
  766. CloseHandle (shm_fd);
  767. return EINVAL;
  768. }
  769. /* set up global pointers */
  770. ri->index = JACK_SHM_REGISTRY_INDEX;
  771. jack_shm_header = ri->attached_at;
  772. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  773. /* initialize registry contents */
  774. jack_shm_init_registry ();
  775. //CloseHandle(shm_fd); // TO CHECK
  776. return 0;
  777. }
  778. static void
  779. jack_remove_shm (jack_shm_id_t *id)
  780. {
  781. /* nothing to do */
  782. }
  783. void
  784. jack_release_shm (jack_shm_info_t* si)
  785. {
  786. /* registry may or may not be locked */
  787. if (si->attached_at != NULL) {
  788. UnmapViewOfFile (si->attached_at);
  789. }
  790. }
  791. int
  792. jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
  793. {
  794. jack_shm_registry_t* registry;
  795. HANDLE shm_fd;
  796. int rc = -1;
  797. char name[SHM_NAME_MAX+1];
  798. jack_shm_lock_registry ();
  799. if ((registry = jack_get_free_shm_info ()) == NULL) {
  800. jack_error ("shm registry full");
  801. goto unlock;
  802. }
  803. snprintf (name, sizeof (name), "jack-%d", registry->index);
  804. if (strlen (name) >= sizeof (registry->id)) {
  805. jack_error ("shm segment name too long %s", name);
  806. goto unlock;
  807. }
  808. if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE,
  809. 0, PAGE_READWRITE,
  810. 0, size,
  811. name)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) {
  812. int rc = GetLastError();
  813. jack_error ("Cannot create shm segment (%ld)",rc);
  814. goto unlock;
  815. }
  816. //CloseHandle (shm_fd); // TO CHECK
  817. registry->size = size;
  818. strncpy (registry->id, name, sizeof (registry->id));
  819. registry->allocator = _getpid();
  820. si->index = registry->index;
  821. si->attached_at = NULL; /* not attached */
  822. rc = 0; /* success */
  823. unlock:
  824. jack_shm_unlock_registry ();
  825. return rc;
  826. }
  827. int
  828. jack_attach_shm (jack_shm_info_t* si)
  829. {
  830. HANDLE shm_fd;
  831. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  832. if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) {
  833. int rc = GetLastError();
  834. jack_error ("Cannot open shm segment (%ld)",rc);
  835. return -1;
  836. }
  837. if ((si->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, registry->size)) == NULL) {
  838. jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
  839. jack_remove_shm (&registry_id);
  840. CloseHandle (shm_fd);
  841. return -1;
  842. }
  843. //CloseHandle (shm_fd); // TO CHECK
  844. return 0;
  845. }
  846. int
  847. jack_attach_shm_read (jack_shm_info_t* si)
  848. {
  849. HANDLE shm_fd;
  850. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  851. if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) {
  852. int rc = GetLastError();
  853. jack_error ("Cannot open shm segment (%ld)",rc);
  854. return -1;
  855. }
  856. if ((si->attached_at = MapViewOfFile (shm_fd, FILE_MAP_READ, 0, 0, registry->size)) == NULL) {
  857. jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
  858. jack_remove_shm (&registry_id);
  859. CloseHandle (shm_fd);
  860. return -1;
  861. }
  862. //CloseHandle (shm_fd); // TO CHECK
  863. return 0;
  864. }
  865. #else
  866. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  867. * System V interface-dependent functions
  868. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  869. /* gain addressability to existing SHM registry segment
  870. *
  871. * sets up global registry pointers, if successful
  872. *
  873. * returns: 0 if existing registry accessed successfully
  874. * ENOENT if registry does not exist
  875. * EINVAL if registry exists, but has the wrong size
  876. * other nonzero error code if unable to access registry
  877. */
  878. static int
  879. jack_access_registry (jack_shm_info_t *ri)
  880. {
  881. /* registry must be locked */
  882. /* try without IPC_CREAT to get existing segment */
  883. if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY,
  884. JACK_SHM_REGISTRY_SIZE, 0666)) < 0) {
  885. switch (errno) {
  886. case ENOENT: /* segment does not exist */
  887. return ENOENT;
  888. case EINVAL: /* segment exists, but too small */
  889. /* attempt minimum size access */
  890. registry_id = shmget (JACK_SHM_REGISTRY_KEY, 1, 0666);
  891. return EINVAL;
  892. default: /* or other error */
  893. jack_error ("unable to access shm registry (%s)",
  894. strerror (errno));
  895. return errno;
  896. }
  897. }
  898. if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) {
  899. jack_error ("Cannot attach shm registry segment (%s)",
  900. strerror (errno));
  901. return EINVAL;
  902. }
  903. /* set up global pointers */
  904. ri->index = JACK_SHM_REGISTRY_INDEX;
  905. jack_shm_header = ri->attached_at;
  906. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  907. return 0;
  908. }
  909. /* create a new SHM registry segment
  910. *
  911. * sets up global registry pointers, if successful
  912. *
  913. * returns: 0 if registry created successfully
  914. * nonzero error code if unable to allocate a new registry
  915. */
  916. static int
  917. jack_create_registry (jack_shm_info_t *ri)
  918. {
  919. /* registry must be locked */
  920. if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY,
  921. JACK_SHM_REGISTRY_SIZE,
  922. 0666|IPC_CREAT)) < 0) {
  923. jack_error ("Cannot create shm registry segment (%s)",
  924. strerror (errno));
  925. return errno;
  926. }
  927. if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) {
  928. jack_error ("Cannot attach shm registry segment (%s)",
  929. strerror (errno));
  930. return EINVAL;
  931. }
  932. /* set up global pointers */
  933. ri->index = JACK_SHM_REGISTRY_INDEX;
  934. jack_shm_header = ri->attached_at;
  935. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  936. /* initialize registry contents */
  937. jack_shm_init_registry ();
  938. return 0;
  939. }
  940. static void
  941. jack_remove_shm (jack_shm_id_t *id)
  942. {
  943. /* registry may or may not be locked */
  944. shmctl (*id, IPC_RMID, NULL);
  945. }
  946. void
  947. jack_release_shm (jack_shm_info_t* si)
  948. {
  949. /* registry may or may not be locked */
  950. if (si->attached_at != MAP_FAILED) {
  951. shmdt (si->attached_at);
  952. }
  953. }
  954. int
  955. jack_shmalloc (const char* name_not_used, jack_shmsize_t size,
  956. jack_shm_info_t* si)
  957. {
  958. int shmflags;
  959. int shmid;
  960. int rc = -1;
  961. jack_shm_registry_t* registry;
  962. jack_shm_lock_registry ();
  963. if ((registry = jack_get_free_shm_info ())) {
  964. shmflags = 0666 | IPC_CREAT | IPC_EXCL;
  965. if ((shmid = shmget (IPC_PRIVATE, size, shmflags)) >= 0) {
  966. registry->size = size;
  967. registry->id = shmid;
  968. registry->allocator = getpid();
  969. si->index = registry->index;
  970. si->attached_at = MAP_FAILED; /* not attached */
  971. rc = 0;
  972. } else {
  973. jack_error ("Cannot create shm segment %s (%s)",
  974. name_not_used, strerror (errno));
  975. }
  976. }
  977. jack_shm_unlock_registry ();
  978. return rc;
  979. }
  980. int
  981. jack_attach_shm (jack_shm_info_t* si)
  982. {
  983. if ((si->attached_at = shmat (jack_shm_registry[si->index].id, 0, 0)) < 0) {
  984. jack_error ("Cannot attach shm segment (%s)",
  985. strerror (errno));
  986. jack_release_shm_info (si->index);
  987. return -1;
  988. }
  989. return 0;
  990. }
  991. #endif /* !USE_POSIX_SHM */