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.

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