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.

1187 lines
28KB

  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. EXPORT 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. EXPORT 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. EXPORT 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. /* Set the desired segment size. NOTE: the non-conformant Mac
  582. * OS X POSIX shm only allows ftruncate() on segment creation.
  583. */
  584. if (ftruncate (shm_fd, JACK_SHM_REGISTRY_SIZE) < 0) {
  585. int rc = errno;
  586. jack_error ("Cannot set registry size (%s)", strerror (errno));
  587. jack_remove_shm (&registry_id);
  588. close (shm_fd);
  589. return rc;
  590. }
  591. if ((ri->attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE,
  592. PROT_READ|PROT_WRITE,
  593. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  594. jack_error ("Cannot mmap shm registry segment (%s)",
  595. strerror (errno));
  596. jack_remove_shm (&registry_id);
  597. close (shm_fd);
  598. return EINVAL;
  599. }
  600. /* set up global pointers */
  601. ri->index = JACK_SHM_REGISTRY_INDEX;
  602. jack_shm_header = ri->attached_at;
  603. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  604. /* initialize registry contents */
  605. jack_shm_init_registry ();
  606. close (shm_fd); // steph
  607. return 0;
  608. }
  609. static void
  610. jack_remove_shm (jack_shm_id_t *id)
  611. {
  612. /* registry may or may not be locked */
  613. shm_unlink ((char *) id);
  614. }
  615. void
  616. jack_release_shm (jack_shm_info_t* si)
  617. {
  618. /* registry may or may not be locked */
  619. if (si->attached_at != MAP_FAILED) {
  620. munmap (si->attached_at, jack_shm_registry[si->index].size);
  621. }
  622. }
  623. /* allocate a POSIX shared memory segment */
  624. int
  625. jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
  626. {
  627. jack_shm_registry_t* registry;
  628. int shm_fd;
  629. int rc = -1;
  630. char name[SHM_NAME_MAX+1];
  631. jack_shm_lock_registry ();
  632. if ((registry = jack_get_free_shm_info ()) == NULL) {
  633. jack_error ("shm registry full");
  634. goto unlock;
  635. }
  636. /* On Mac OS X, the maximum length of a shared memory segment
  637. * name is SHM_NAME_MAX (instead of NAME_MAX or PATH_MAX as
  638. * defined by the standard). Unfortunately, Apple sets this
  639. * value so small (about 31 bytes) that it is useless for
  640. * actual names. So, we construct a short name from the
  641. * registry index for uniqueness and ignore the shm_name
  642. * parameter. Bah!
  643. */
  644. snprintf (name, sizeof (name), "/jackmp-%d", registry->index);
  645. if (strlen (name) >= sizeof (registry->id)) {
  646. jack_error ("shm segment name too long %s", name);
  647. goto unlock;
  648. }
  649. if ((shm_fd = shm_open (name, O_RDWR|O_CREAT, 0666)) < 0) {
  650. jack_error ("Cannot create shm segment %s (%s)",
  651. name, strerror (errno));
  652. goto unlock;
  653. }
  654. if (ftruncate (shm_fd, size) < 0) {
  655. jack_error ("Cannot set size of engine shm "
  656. "registry 0 (%s)",
  657. strerror (errno));
  658. close (shm_fd);
  659. goto unlock;
  660. }
  661. close (shm_fd);
  662. registry->size = size;
  663. strncpy (registry->id, name, sizeof (registry->id));
  664. registry->allocator = getpid();
  665. si->index = registry->index;
  666. si->attached_at = MAP_FAILED; /* not attached */
  667. rc = 0; /* success */
  668. unlock:
  669. jack_shm_unlock_registry ();
  670. return rc;
  671. }
  672. int
  673. jack_attach_shm (jack_shm_info_t* si)
  674. {
  675. int shm_fd;
  676. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  677. if ((shm_fd = shm_open (registry->id,
  678. O_RDWR, 0666)) < 0) {
  679. jack_error ("Cannot open shm segment %s (%s)", registry->id,
  680. strerror (errno));
  681. return -1;
  682. }
  683. if ((si->attached_at = mmap (0, registry->size, PROT_READ|PROT_WRITE,
  684. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  685. jack_error ("Cannot mmap shm segment %s (%s)",
  686. registry->id,
  687. strerror (errno));
  688. close (shm_fd);
  689. return -1;
  690. }
  691. close (shm_fd);
  692. return 0;
  693. }
  694. int
  695. jack_attach_shm_read (jack_shm_info_t* si)
  696. {
  697. int shm_fd;
  698. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  699. if ((shm_fd = shm_open (registry->id,
  700. O_RDONLY, 0666)) < 0) {
  701. jack_error ("Cannot open shm segment %s (%s)", registry->id,
  702. strerror (errno));
  703. return -1;
  704. }
  705. if ((si->attached_at = mmap (0, registry->size, PROT_READ,
  706. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  707. jack_error ("Cannot mmap shm segment %s (%s)",
  708. registry->id,
  709. strerror (errno));
  710. close (shm_fd);
  711. return -1;
  712. }
  713. close (shm_fd);
  714. return 0;
  715. }
  716. #elif WIN32
  717. static int
  718. jack_access_registry (jack_shm_info_t *ri)
  719. {
  720. /* registry must be locked */
  721. HANDLE shm_fd;
  722. LPSECURITY_ATTRIBUTES sec = 0;
  723. strncpy (registry_id, "jack-shm-registry", sizeof (registry_id));
  724. /* try to open an existing segment */
  725. if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry_id)) == NULL) {
  726. int rc = GetLastError();
  727. if (rc != ERROR_FILE_NOT_FOUND) {
  728. jack_error ("Cannot open existing shm registry segment (%ld)", rc);
  729. }
  730. return rc;
  731. }
  732. if ((ri->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) {
  733. jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
  734. jack_remove_shm (&registry_id);
  735. CloseHandle (shm_fd);
  736. return EINVAL;
  737. }
  738. /* set up global pointers */
  739. ri->index = JACK_SHM_REGISTRY_INDEX;
  740. jack_shm_header = ri->attached_at;
  741. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  742. //CloseHandle(shm_fd); // TO CHECK
  743. return 0;
  744. }
  745. static int
  746. jack_create_registry (jack_shm_info_t *ri)
  747. {
  748. /* registry must be locked */
  749. HANDLE shm_fd;
  750. strncpy (registry_id, "jack-shm-registry", sizeof (registry_id));
  751. if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE,
  752. 0, PAGE_READWRITE,
  753. 0, JACK_SHM_REGISTRY_SIZE,
  754. registry_id)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) {
  755. int rc = GetLastError();
  756. jack_error ("Cannot create shm registry segment (%ld)", rc);
  757. return rc;
  758. }
  759. if ((ri->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) {
  760. jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
  761. jack_remove_shm (&registry_id);
  762. CloseHandle (shm_fd);
  763. return EINVAL;
  764. }
  765. /* set up global pointers */
  766. ri->index = JACK_SHM_REGISTRY_INDEX;
  767. jack_shm_header = ri->attached_at;
  768. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  769. /* initialize registry contents */
  770. jack_shm_init_registry ();
  771. //CloseHandle(shm_fd); // TO CHECK
  772. return 0;
  773. }
  774. static void
  775. jack_remove_shm (jack_shm_id_t *id)
  776. {
  777. /* nothing to do */
  778. }
  779. void
  780. jack_release_shm (jack_shm_info_t* si)
  781. {
  782. /* registry may or may not be locked */
  783. if (si->attached_at != NULL) {
  784. UnmapViewOfFile (si->attached_at);
  785. }
  786. }
  787. int
  788. jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
  789. {
  790. jack_shm_registry_t* registry;
  791. HANDLE shm_fd;
  792. int rc = -1;
  793. char name[SHM_NAME_MAX+1];
  794. jack_shm_lock_registry ();
  795. if ((registry = jack_get_free_shm_info ()) == NULL) {
  796. jack_error ("shm registry full");
  797. goto unlock;
  798. }
  799. snprintf (name, sizeof (name), "jack-%d", registry->index);
  800. if (strlen (name) >= sizeof (registry->id)) {
  801. jack_error ("shm segment name too long %s", name);
  802. goto unlock;
  803. }
  804. if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE,
  805. 0, PAGE_READWRITE,
  806. 0, size,
  807. name)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) {
  808. int rc = GetLastError();
  809. jack_error ("Cannot create shm segment (%ld)",rc);
  810. goto unlock;
  811. }
  812. //CloseHandle (shm_fd); // TO CHECK
  813. registry->size = size;
  814. strncpy (registry->id, name, sizeof (registry->id));
  815. registry->allocator = _getpid();
  816. si->index = registry->index;
  817. si->attached_at = NULL; /* not attached */
  818. rc = 0; /* success */
  819. unlock:
  820. jack_shm_unlock_registry ();
  821. return rc;
  822. }
  823. int
  824. jack_attach_shm (jack_shm_info_t* si)
  825. {
  826. HANDLE shm_fd;
  827. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  828. if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) {
  829. int rc = GetLastError();
  830. jack_error ("Cannot open shm segment (%ld)",rc);
  831. return -1;
  832. }
  833. if ((si->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, registry->size)) == NULL) {
  834. jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
  835. jack_remove_shm (&registry_id);
  836. CloseHandle (shm_fd);
  837. return -1;
  838. }
  839. //CloseHandle (shm_fd); // TO CHECK
  840. return 0;
  841. }
  842. int
  843. jack_attach_shm_read (jack_shm_info_t* si)
  844. {
  845. HANDLE shm_fd;
  846. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  847. if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) {
  848. int rc = GetLastError();
  849. jack_error ("Cannot open shm segment (%ld)",rc);
  850. return -1;
  851. }
  852. if ((si->attached_at = MapViewOfFile (shm_fd, FILE_MAP_READ, 0, 0, registry->size)) == NULL) {
  853. jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
  854. jack_remove_shm (&registry_id);
  855. CloseHandle (shm_fd);
  856. return -1;
  857. }
  858. //CloseHandle (shm_fd); // TO CHECK
  859. return 0;
  860. }
  861. #else
  862. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  863. * System V interface-dependent functions
  864. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  865. /* gain addressability to existing SHM registry segment
  866. *
  867. * sets up global registry pointers, if successful
  868. *
  869. * returns: 0 if existing registry accessed successfully
  870. * ENOENT if registry does not exist
  871. * EINVAL if registry exists, but has the wrong size
  872. * other nonzero error code if unable to access registry
  873. */
  874. static int
  875. jack_access_registry (jack_shm_info_t *ri)
  876. {
  877. /* registry must be locked */
  878. /* try without IPC_CREAT to get existing segment */
  879. if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY,
  880. JACK_SHM_REGISTRY_SIZE, 0666)) < 0) {
  881. switch (errno) {
  882. case ENOENT: /* segment does not exist */
  883. return ENOENT;
  884. case EINVAL: /* segment exists, but too small */
  885. /* attempt minimum size access */
  886. registry_id = shmget (JACK_SHM_REGISTRY_KEY, 1, 0666);
  887. return EINVAL;
  888. default: /* or other error */
  889. jack_error ("unable to access shm registry (%s)",
  890. strerror (errno));
  891. return errno;
  892. }
  893. }
  894. if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) {
  895. jack_error ("Cannot attach shm registry segment (%s)",
  896. strerror (errno));
  897. return EINVAL;
  898. }
  899. /* set up global pointers */
  900. ri->index = JACK_SHM_REGISTRY_INDEX;
  901. jack_shm_header = ri->attached_at;
  902. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  903. return 0;
  904. }
  905. /* create a new SHM registry segment
  906. *
  907. * sets up global registry pointers, if successful
  908. *
  909. * returns: 0 if registry created successfully
  910. * nonzero error code if unable to allocate a new registry
  911. */
  912. static int
  913. jack_create_registry (jack_shm_info_t *ri)
  914. {
  915. /* registry must be locked */
  916. if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY,
  917. JACK_SHM_REGISTRY_SIZE,
  918. 0666|IPC_CREAT)) < 0) {
  919. jack_error ("Cannot create shm registry segment (%s)",
  920. strerror (errno));
  921. return errno;
  922. }
  923. if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) {
  924. jack_error ("Cannot attach shm registry segment (%s)",
  925. strerror (errno));
  926. return EINVAL;
  927. }
  928. /* set up global pointers */
  929. ri->index = JACK_SHM_REGISTRY_INDEX;
  930. jack_shm_header = ri->attached_at;
  931. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  932. /* initialize registry contents */
  933. jack_shm_init_registry ();
  934. return 0;
  935. }
  936. static void
  937. jack_remove_shm (jack_shm_id_t *id)
  938. {
  939. /* registry may or may not be locked */
  940. shmctl (*id, IPC_RMID, NULL);
  941. }
  942. void
  943. jack_release_shm (jack_shm_info_t* si)
  944. {
  945. /* registry may or may not be locked */
  946. if (si->attached_at != MAP_FAILED) {
  947. shmdt (si->attached_at);
  948. }
  949. }
  950. int
  951. jack_shmalloc (const char* name_not_used, jack_shmsize_t size,
  952. jack_shm_info_t* si)
  953. {
  954. int shmflags;
  955. int shmid;
  956. int rc = -1;
  957. jack_shm_registry_t* registry;
  958. jack_shm_lock_registry ();
  959. if ((registry = jack_get_free_shm_info ())) {
  960. shmflags = 0666 | IPC_CREAT | IPC_EXCL;
  961. if ((shmid = shmget (IPC_PRIVATE, size, shmflags)) >= 0) {
  962. registry->size = size;
  963. registry->id = shmid;
  964. registry->allocator = getpid();
  965. si->index = registry->index;
  966. si->attached_at = MAP_FAILED; /* not attached */
  967. rc = 0;
  968. } else {
  969. jack_error ("Cannot create shm segment %s (%s)",
  970. name_not_used, strerror (errno));
  971. }
  972. }
  973. jack_shm_unlock_registry ();
  974. return rc;
  975. }
  976. int
  977. jack_attach_shm (jack_shm_info_t* si)
  978. {
  979. if ((si->attached_at = shmat (jack_shm_registry[si->index].id, 0, 0)) < 0) {
  980. jack_error ("Cannot attach shm segment (%s)",
  981. strerror (errno));
  982. jack_release_shm_info (si->index);
  983. return -1;
  984. }
  985. return 0;
  986. }
  987. #endif /* !USE_POSIX_SHM */