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. *
  16. * This program is free software; you can redistribute it and/or modify
  17. * it under the terms of the GNU General Public License as published by
  18. * the Free Software Foundation; either version 2 of the License, or
  19. * (at your option) any later version.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software
  28. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29. *
  30. * $Id: shm.c,v 1.8.2.16 2006/08/28 10:10:16 letz Exp $
  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 segements 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; // steph
  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) // steph
  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 (void)
  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. switch (rc) {
  244. case ENOENT: /* registry does not exist */
  245. rc = jack_create_registry (&registry_info);
  246. break;
  247. case 0: /* existing registry */
  248. if (jack_shm_validate_registry () == 0)
  249. break;
  250. /* else it was invalid, so fall through */
  251. case EINVAL: /* bad registry */
  252. /* Apparently, this registry was created by an older
  253. * JACK version. Delete it so we can try again. */
  254. jack_release_shm (&registry_info);
  255. jack_remove_shm (&registry_id);
  256. if ((rc = jack_create_registry (&registry_info)) != 0) {
  257. jack_error ("incompatible shm registry (%s)",
  258. strerror (errno));
  259. #ifndef USE_POSIX_SHM
  260. jack_error ("to delete, use `ipcrm -M 0x%0.8x'",
  261. JACK_SHM_REGISTRY_KEY);
  262. #endif
  263. }
  264. break;
  265. default: /* failure return code */
  266. break;
  267. }
  268. jack_shm_unlock_registry ();
  269. return rc;
  270. }
  271. /* gain client addressability to shared memory registration segment
  272. *
  273. * NOTE: this function is no longer used for server initialization,
  274. * instead it calls jack_register_server().
  275. *
  276. * returns: 0 if successful
  277. */
  278. int
  279. jack_initialize_shm (const char *server_name)
  280. {
  281. int rc;
  282. if (jack_shm_header)
  283. return 0; /* already initialized */
  284. jack_set_server_prefix (server_name);
  285. jack_shm_lock_registry ();
  286. if ((rc = jack_access_registry (&registry_info)) == 0) {
  287. if ((rc = jack_shm_validate_registry ()) != 0) {
  288. jack_error ("Incompatible shm registry, "
  289. "are jackd and libjack in sync?");
  290. }
  291. }
  292. jack_shm_unlock_registry ();
  293. return rc;
  294. }
  295. // steph
  296. int jack_initialize_shm_server()
  297. {
  298. return jack_initialize_shm("default");
  299. }
  300. int jack_initialize_shm_client()
  301. {
  302. return jack_initialize_shm("default");
  303. }
  304. char* jack_shm_addr (jack_shm_info_t* si)
  305. {
  306. return (char*)si->attached_at;
  307. }
  308. void
  309. jack_destroy_shm (jack_shm_info_t* si)
  310. {
  311. /* must NOT have the registry locked */
  312. if (si->index == JACK_SHM_NULL_INDEX)
  313. return; /* segment not allocated */
  314. jack_remove_shm (&jack_shm_registry[si->index].id);
  315. jack_release_shm_info (si->index);
  316. }
  317. jack_shm_registry_t *
  318. jack_get_free_shm_info ()
  319. {
  320. /* registry must be locked */
  321. jack_shm_registry_t* si = NULL;
  322. int i;
  323. for (i = 0; i < MAX_SHM_ID; ++i) {
  324. if (jack_shm_registry[i].size == 0) {
  325. break;
  326. }
  327. }
  328. if (i < MAX_SHM_ID) {
  329. si = &jack_shm_registry[i];
  330. }
  331. return si;
  332. }
  333. static void
  334. jack_release_shm_entry (jack_shm_registry_index_t index)
  335. {
  336. /* the registry must be locked */
  337. jack_shm_registry[index].size = 0;
  338. jack_shm_registry[index].allocator = 0;
  339. memset (&jack_shm_registry[index].id, 0,
  340. sizeof (jack_shm_registry[index].id));
  341. }
  342. void
  343. jack_release_shm_info (jack_shm_registry_index_t index)
  344. {
  345. #ifdef WIN32
  346. int my_pid = _getpid();
  347. #else
  348. pid_t my_pid = getpid();
  349. #endif
  350. /* must NOT have the registry locked */
  351. if (jack_shm_registry[index].allocator == my_pid) {
  352. jack_shm_lock_registry ();
  353. jack_release_shm_entry (index);
  354. jack_shm_unlock_registry ();
  355. }
  356. }
  357. /* Claim server_name for this process.
  358. *
  359. * returns 0 if successful
  360. * EEXIST if server_name was already active for this user
  361. * ENOSPC if server registration limit reached
  362. * ENOMEM if unable to access shared memory registry
  363. */
  364. EXPORT int
  365. jack_register_server (const char *server_name)
  366. {
  367. int i;
  368. #ifdef WIN32
  369. int my_pid = _getpid();
  370. #else
  371. pid_t my_pid = getpid();
  372. #endif
  373. jack_set_server_prefix (server_name);
  374. if (jack_server_initialize_shm ())
  375. return ENOMEM;
  376. jack_shm_lock_registry ();
  377. /* See if server_name already registered. Since server names
  378. * are per-user, we register the unique server prefix string.
  379. */
  380. for (i = 0; i < MAX_SERVERS; i++) {
  381. if (strncmp (jack_shm_header->server[i].name,
  382. jack_shm_server_prefix,
  383. JACK_SERVER_NAME_SIZE) != 0)
  384. continue; /* no match */
  385. if (jack_shm_header->server[i].pid == my_pid)
  386. return 0; /* it's me */
  387. /* see if server still exists */
  388. #ifndef WIN32 // steph TO CHECK
  389. if (kill (jack_shm_header->server[i].pid, 0) == 0) {
  390. return EEXIST; /* other server running */
  391. }
  392. #endif
  393. /* it's gone, reclaim this entry */
  394. memset (&jack_shm_header->server[i], 0,
  395. sizeof (jack_shm_server_t));
  396. }
  397. /* find a free entry */
  398. for (i = 0; i < MAX_SERVERS; i++) {
  399. if (jack_shm_header->server[i].pid == 0)
  400. break;
  401. }
  402. if (i >= MAX_SERVERS)
  403. return ENOSPC; /* out of space */
  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. jack_shm_unlock_registry ();
  410. return 0;
  411. }
  412. /* release server_name registration */
  413. EXPORT void
  414. jack_unregister_server (const char *server_name /* unused */)
  415. {
  416. int i;
  417. #ifdef WIN32
  418. int my_pid = _getpid();
  419. #else
  420. pid_t my_pid = getpid();
  421. #endif
  422. jack_shm_lock_registry ();
  423. for (i = 0; i < MAX_SERVERS; i++) {
  424. if (jack_shm_header->server[i].pid == my_pid) {
  425. memset (&jack_shm_header->server[i], 0,
  426. sizeof (jack_shm_server_t));
  427. }
  428. }
  429. jack_shm_unlock_registry ();
  430. }
  431. /* called for server startup and termination */
  432. EXPORT int
  433. jack_cleanup_shm ()
  434. {
  435. int i;
  436. int destroy;
  437. jack_shm_info_t copy;
  438. #ifdef WIN32
  439. int my_pid = _getpid();
  440. #else
  441. pid_t my_pid = getpid();
  442. #endif
  443. jack_shm_lock_registry ();
  444. for (i = 0; i < MAX_SHM_ID; i++) {
  445. jack_shm_registry_t* r;
  446. r = &jack_shm_registry[i];
  447. memcpy (&copy, r, sizeof (jack_shm_info_t));
  448. destroy = FALSE;
  449. /* ignore unused entries */
  450. if (r->allocator == 0)
  451. continue;
  452. /* is this my shm segment? */
  453. if (r->allocator == my_pid) {
  454. /* allocated by this process, so unattach
  455. and destroy. */
  456. jack_release_shm (&copy);
  457. destroy = TRUE;
  458. } else {
  459. /* see if allocator still exists */
  460. #ifdef WIN32 // steph
  461. printf("TODO: kill API not available !!\n");
  462. #else
  463. if (kill (r->allocator, 0)) {
  464. if (errno == ESRCH) {
  465. /* allocator no longer exists,
  466. * so destroy */
  467. destroy = TRUE;
  468. }
  469. }
  470. #endif
  471. }
  472. if (destroy) {
  473. int index = copy.index;
  474. if ((index >= 0) && (index < MAX_SHM_ID)) {
  475. jack_remove_shm (&jack_shm_registry[index].id);
  476. jack_release_shm_entry (index);
  477. }
  478. r->size = 0;
  479. r->allocator = 0;
  480. }
  481. }
  482. jack_shm_unlock_registry ();
  483. return TRUE;
  484. }
  485. /* resize a shared memory segment
  486. *
  487. * There is no way to resize a System V shm segment. Resizing is
  488. * possible with POSIX shm, but not with the non-conformant Mac OS X
  489. * implementation. Since POSIX shm is mainly used on that platform,
  490. * it's simpler to treat them both the same.
  491. *
  492. * So, we always resize by deleting and reallocating. This is
  493. * tricky, because the old segment will not disappear until
  494. * all the clients have released it. We only do what we can
  495. * from here.
  496. *
  497. * This is not done under a single lock. I don't even want to think
  498. * about all the things that could possibly go wrong if multple
  499. * processes tried to resize the same segment concurrently. That
  500. * probably doesn't happen.
  501. */
  502. int
  503. jack_resize_shm (jack_shm_info_t* si, jack_shmsize_t size)
  504. {
  505. jack_shm_id_t id;
  506. /* The underlying type of `id' differs for SYSV and POSIX */
  507. memcpy (&id, &jack_shm_registry[si->index].id, sizeof (id));
  508. jack_release_shm (si);
  509. jack_destroy_shm (si);
  510. if (jack_shmalloc ((char *) id, size, si)) {
  511. return -1;
  512. }
  513. return jack_attach_shm (si);
  514. }
  515. #ifdef USE_POSIX_SHM
  516. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  517. * POSIX interface-dependent functions
  518. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  519. /* gain addressability to existing SHM registry segment
  520. *
  521. * sets up global registry pointers, if successful
  522. *
  523. * returns: 0 if existing registry accessed successfully
  524. * ENOENT if registry does not exist
  525. * EINVAL if registry exists, but has the wrong size
  526. */
  527. static int
  528. jack_access_registry (jack_shm_info_t *ri)
  529. {
  530. /* registry must be locked */
  531. int shm_fd;
  532. strncpy (registry_id, "/jack-shm-registry", sizeof (registry_id));
  533. /* try to open an existing segment */
  534. if ((shm_fd = shm_open (registry_id, O_RDWR, 0666)) < 0) {
  535. int rc = errno;
  536. if (errno != ENOENT) {
  537. jack_error ("Cannot open existing shm registry segment"
  538. " (%s)", strerror (errno));
  539. }
  540. close (shm_fd);
  541. return rc;
  542. }
  543. if ((ri->attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE,
  544. PROT_READ|PROT_WRITE,
  545. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  546. jack_error ("Cannot mmap shm registry segment (%s)",
  547. strerror (errno));
  548. close (shm_fd);
  549. return EINVAL;
  550. }
  551. /* set up global pointers */
  552. ri->index = JACK_SHM_REGISTRY_INDEX;
  553. jack_shm_header = ri->attached_at;
  554. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  555. close (shm_fd); // steph
  556. return 0;
  557. }
  558. /* create a new SHM registry segment
  559. *
  560. * sets up global registry pointers, if successful
  561. *
  562. * returns: 0 if registry created successfully
  563. * nonzero error code if unable to allocate a new registry
  564. */
  565. static int
  566. jack_create_registry (jack_shm_info_t *ri)
  567. {
  568. /* registry must be locked */
  569. int shm_fd;
  570. strncpy (registry_id, "/jack-shm-registry", sizeof (registry_id));
  571. if ((shm_fd = shm_open (registry_id, O_RDWR|O_CREAT, 0666)) < 0) {
  572. int rc = errno;
  573. jack_error ("Cannot create shm registry segment (%s)",
  574. strerror (errno));
  575. return rc;
  576. }
  577. /* Set the desired segment size. NOTE: the non-conformant Mac
  578. * OS X POSIX shm only allows ftruncate() on segment creation.
  579. */
  580. if (ftruncate (shm_fd, JACK_SHM_REGISTRY_SIZE) < 0) {
  581. int rc = errno;
  582. jack_error ("Cannot set registry size (%s)", strerror (errno));
  583. jack_remove_shm (&registry_id);
  584. close (shm_fd);
  585. return rc;
  586. }
  587. if ((ri->attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE,
  588. PROT_READ|PROT_WRITE,
  589. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  590. jack_error ("Cannot mmap shm registry segment (%s)",
  591. strerror (errno));
  592. jack_remove_shm (&registry_id);
  593. close (shm_fd);
  594. return EINVAL;
  595. }
  596. /* set up global pointers */
  597. ri->index = JACK_SHM_REGISTRY_INDEX;
  598. jack_shm_header = ri->attached_at;
  599. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  600. /* initialize registry contents */
  601. jack_shm_init_registry ();
  602. close (shm_fd); // steph
  603. return 0;
  604. }
  605. static void
  606. jack_remove_shm (jack_shm_id_t *id)
  607. {
  608. /* registry may or may not be locked */
  609. shm_unlink ((char *) id);
  610. }
  611. void
  612. jack_release_shm (jack_shm_info_t* si)
  613. {
  614. /* registry may or may not be locked */
  615. if (si->attached_at != MAP_FAILED) {
  616. munmap (si->attached_at, jack_shm_registry[si->index].size);
  617. }
  618. }
  619. /* allocate a POSIX shared memory segment */
  620. int
  621. jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
  622. {
  623. jack_shm_registry_t* registry;
  624. int shm_fd;
  625. int rc = -1;
  626. char name[SHM_NAME_MAX+1];
  627. jack_shm_lock_registry ();
  628. if ((registry = jack_get_free_shm_info ()) == NULL) {
  629. jack_error ("shm registry full");
  630. goto unlock;
  631. }
  632. /* On Mac OS X, the maximum length of a shared memory segment
  633. * name is SHM_NAME_MAX (instead of NAME_MAX or PATH_MAX as
  634. * defined by the standard). Unfortunately, Apple sets this
  635. * value so small (about 31 bytes) that it is useless for
  636. * actual names. So, we construct a short name from the
  637. * registry index for uniqueness and ignore the shm_name
  638. * parameter. Bah!
  639. */
  640. snprintf (name, sizeof (name), "/jack-%d", registry->index);
  641. if (strlen (name) >= sizeof (registry->id)) {
  642. jack_error ("shm segment name too long %s", name);
  643. goto unlock;
  644. }
  645. if ((shm_fd = shm_open (name, O_RDWR|O_CREAT, 0666)) < 0) {
  646. jack_error ("Cannot create shm segment %s (%s)",
  647. name, strerror (errno));
  648. goto unlock;
  649. }
  650. if (ftruncate (shm_fd, size) < 0) {
  651. jack_error ("Cannot set size of engine shm "
  652. "registry 0 (%s)",
  653. strerror (errno));
  654. close (shm_fd);
  655. goto unlock;
  656. }
  657. close (shm_fd);
  658. registry->size = size;
  659. strncpy (registry->id, name, sizeof (registry->id));
  660. registry->allocator = getpid();
  661. si->index = registry->index;
  662. si->attached_at = MAP_FAILED; /* not attached */
  663. rc = 0; /* success */
  664. unlock:
  665. jack_shm_unlock_registry ();
  666. return rc;
  667. }
  668. int
  669. jack_attach_shm (jack_shm_info_t* si)
  670. {
  671. int shm_fd;
  672. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  673. if ((shm_fd = shm_open (registry->id,
  674. O_RDWR, 0666)) < 0) {
  675. jack_error ("Cannot open shm segment %s (%s)", registry->id,
  676. strerror (errno));
  677. return -1;
  678. }
  679. if ((si->attached_at = mmap (0, registry->size, PROT_READ|PROT_WRITE,
  680. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  681. jack_error ("Cannot mmap shm segment %s (%s)",
  682. registry->id,
  683. strerror (errno));
  684. close (shm_fd);
  685. return -1;
  686. }
  687. close (shm_fd);
  688. return 0;
  689. }
  690. int
  691. jack_attach_shm_read (jack_shm_info_t* si)
  692. {
  693. int shm_fd;
  694. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  695. if ((shm_fd = shm_open (registry->id,
  696. O_RDONLY, 0666)) < 0) {
  697. jack_error ("Cannot open shm segment %s (%s)", registry->id,
  698. strerror (errno));
  699. return -1;
  700. }
  701. if ((si->attached_at = mmap (0, registry->size, PROT_READ,
  702. MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
  703. jack_error ("Cannot mmap shm segment %s (%s)",
  704. registry->id,
  705. strerror (errno));
  706. close (shm_fd);
  707. return -1;
  708. }
  709. close (shm_fd);
  710. return 0;
  711. }
  712. #elif WIN32
  713. static int
  714. jack_access_registry (jack_shm_info_t *ri)
  715. {
  716. /* registry must be locked */
  717. HANDLE shm_fd;
  718. LPSECURITY_ATTRIBUTES sec = 0;
  719. strncpy (registry_id, "jack-shm-registry", sizeof (registry_id));
  720. /* try to open an existing segment */
  721. if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry_id)) == NULL) {
  722. int rc = GetLastError();
  723. if (rc != ERROR_FILE_NOT_FOUND) {
  724. jack_error ("Cannot open existing shm registry segment (%ld)", rc);
  725. }
  726. return rc;
  727. }
  728. if ((ri->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) {
  729. jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
  730. jack_remove_shm (&registry_id);
  731. CloseHandle (shm_fd);
  732. return EINVAL;
  733. }
  734. /* set up global pointers */
  735. ri->index = JACK_SHM_REGISTRY_INDEX;
  736. jack_shm_header = ri->attached_at;
  737. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  738. //CloseHandle(shm_fd); // TO CHECK
  739. return 0;
  740. }
  741. static int
  742. jack_create_registry (jack_shm_info_t *ri)
  743. {
  744. /* registry must be locked */
  745. HANDLE shm_fd;
  746. strncpy (registry_id, "jack-shm-registry", sizeof (registry_id));
  747. if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE,
  748. 0, PAGE_READWRITE,
  749. 0, JACK_SHM_REGISTRY_SIZE,
  750. registry_id)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) {
  751. int rc = GetLastError();
  752. jack_error ("Cannot create shm registry segment (%ld)", rc);
  753. return rc;
  754. }
  755. if ((ri->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) {
  756. jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
  757. jack_remove_shm (&registry_id);
  758. CloseHandle (shm_fd);
  759. return EINVAL;
  760. }
  761. /* set up global pointers */
  762. ri->index = JACK_SHM_REGISTRY_INDEX;
  763. jack_shm_header = ri->attached_at;
  764. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  765. /* initialize registry contents */
  766. jack_shm_init_registry ();
  767. //CloseHandle(shm_fd); // TO CHECK
  768. return 0;
  769. }
  770. static void
  771. jack_remove_shm (jack_shm_id_t *id)
  772. {
  773. /* nothing to do */
  774. }
  775. void
  776. jack_release_shm (jack_shm_info_t* si)
  777. {
  778. /* registry may or may not be locked */
  779. if (si->attached_at != NULL) {
  780. UnmapViewOfFile (si->attached_at);
  781. }
  782. }
  783. int
  784. jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
  785. {
  786. jack_shm_registry_t* registry;
  787. HANDLE shm_fd;
  788. int rc = -1;
  789. char name[SHM_NAME_MAX+1];
  790. jack_shm_lock_registry ();
  791. if ((registry = jack_get_free_shm_info ()) == NULL) {
  792. jack_error ("shm registry full");
  793. goto unlock;
  794. }
  795. snprintf (name, sizeof (name), "jack-%d", registry->index);
  796. if (strlen (name) >= sizeof (registry->id)) {
  797. jack_error ("shm segment name too long %s", name);
  798. goto unlock;
  799. }
  800. if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE,
  801. 0, PAGE_READWRITE,
  802. 0, size,
  803. name)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) {
  804. int rc = GetLastError();
  805. jack_error ("Cannot create shm segment (%ld)",rc);
  806. goto unlock;
  807. }
  808. //CloseHandle (shm_fd); // TO CHECK
  809. registry->size = size;
  810. strncpy (registry->id, name, sizeof (registry->id));
  811. registry->allocator = _getpid();
  812. si->index = registry->index;
  813. si->attached_at = NULL; /* not attached */
  814. rc = 0; /* success */
  815. unlock:
  816. jack_shm_unlock_registry ();
  817. return rc;
  818. }
  819. int
  820. jack_attach_shm (jack_shm_info_t* si)
  821. {
  822. HANDLE shm_fd;
  823. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  824. if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) {
  825. int rc = GetLastError();
  826. jack_error ("Cannot open shm segment (%ld)",rc);
  827. return -1;
  828. }
  829. if ((si->attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, registry->size)) == NULL) {
  830. jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
  831. jack_remove_shm (&registry_id);
  832. CloseHandle (shm_fd);
  833. return -1;
  834. }
  835. //CloseHandle (shm_fd); // TO CHECK
  836. return 0;
  837. }
  838. int
  839. jack_attach_shm_read (jack_shm_info_t* si)
  840. {
  841. HANDLE shm_fd;
  842. jack_shm_registry_t *registry = &jack_shm_registry[si->index];
  843. if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) {
  844. int rc = GetLastError();
  845. jack_error ("Cannot open shm segment (%ld)",rc);
  846. return -1;
  847. }
  848. if ((si->attached_at = MapViewOfFile (shm_fd, FILE_MAP_READ, 0, 0, registry->size)) == NULL) {
  849. jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
  850. jack_remove_shm (&registry_id);
  851. CloseHandle (shm_fd);
  852. return -1;
  853. }
  854. //CloseHandle (shm_fd); // TO CHECK
  855. return 0;
  856. }
  857. #else
  858. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  859. * System V interface-dependent functions
  860. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  861. /* gain addressability to existing SHM registry segment
  862. *
  863. * sets up global registry pointers, if successful
  864. *
  865. * returns: 0 if existing registry accessed successfully
  866. * ENOENT if registry does not exist
  867. * EINVAL if registry exists, but has the wrong size
  868. * other nonzero error code if unable to access registry
  869. */
  870. static int
  871. jack_access_registry (jack_shm_info_t *ri)
  872. {
  873. /* registry must be locked */
  874. /* try without IPC_CREAT to get existing segment */
  875. if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY,
  876. JACK_SHM_REGISTRY_SIZE, 0666)) < 0) {
  877. switch (errno) {
  878. case ENOENT: /* segment does not exist */
  879. return ENOENT;
  880. case EINVAL: /* segment exists, but too small */
  881. /* attempt minimum size access */
  882. registry_id = shmget (JACK_SHM_REGISTRY_KEY, 1, 0666);
  883. return EINVAL;
  884. default: /* or other error */
  885. jack_error ("unable to access shm registry (%s)",
  886. strerror (errno));
  887. return errno;
  888. }
  889. }
  890. if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) {
  891. jack_error ("Cannot attach shm registry segment (%s)",
  892. strerror (errno));
  893. return EINVAL;
  894. }
  895. /* set up global pointers */
  896. ri->index = JACK_SHM_REGISTRY_INDEX;
  897. jack_shm_header = ri->attached_at;
  898. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  899. return 0;
  900. }
  901. /* create a new SHM registry segment
  902. *
  903. * sets up global registry pointers, if successful
  904. *
  905. * returns: 0 if registry created successfully
  906. * nonzero error code if unable to allocate a new registry
  907. */
  908. static int
  909. jack_create_registry (jack_shm_info_t *ri)
  910. {
  911. /* registry must be locked */
  912. if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY,
  913. JACK_SHM_REGISTRY_SIZE,
  914. 0666|IPC_CREAT)) < 0) {
  915. jack_error ("Cannot create shm registry segment (%s)",
  916. strerror (errno));
  917. return errno;
  918. }
  919. if ((ri->attached_at = shmat (registry_id, 0, 0)) < 0) {
  920. jack_error ("Cannot attach shm registry segment (%s)",
  921. strerror (errno));
  922. return EINVAL;
  923. }
  924. /* set up global pointers */
  925. ri->index = JACK_SHM_REGISTRY_INDEX;
  926. jack_shm_header = ri->attached_at;
  927. jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
  928. /* initialize registry contents */
  929. jack_shm_init_registry ();
  930. return 0;
  931. }
  932. static void
  933. jack_remove_shm (jack_shm_id_t *id)
  934. {
  935. /* registry may or may not be locked */
  936. shmctl (*id, IPC_RMID, NULL);
  937. }
  938. void
  939. jack_release_shm (jack_shm_info_t* si)
  940. {
  941. /* registry may or may not be locked */
  942. if (si->attached_at != MAP_FAILED) {
  943. shmdt (si->attached_at);
  944. }
  945. }
  946. int
  947. jack_shmalloc (const char* name_not_used, jack_shmsize_t size,
  948. jack_shm_info_t* si)
  949. {
  950. int shmflags;
  951. int shmid;
  952. int rc = -1;
  953. jack_shm_registry_t* registry;
  954. jack_shm_lock_registry ();
  955. if ((registry = jack_get_free_shm_info ())) {
  956. shmflags = 0666 | IPC_CREAT | IPC_EXCL;
  957. if ((shmid = shmget (IPC_PRIVATE, size, shmflags)) >= 0) {
  958. registry->size = size;
  959. registry->id = shmid;
  960. registry->allocator = getpid();
  961. si->index = registry->index;
  962. si->attached_at = MAP_FAILED; /* not attached */
  963. rc = 0;
  964. } else {
  965. jack_error ("Cannot create shm segment %s (%s)",
  966. name_not_used, strerror (errno));
  967. }
  968. }
  969. jack_shm_unlock_registry ();
  970. return rc;
  971. }
  972. int
  973. jack_attach_shm (jack_shm_info_t* si)
  974. {
  975. if ((si->attached_at = shmat (jack_shm_registry[si->index].id, 0, 0)) < 0) {
  976. jack_error ("Cannot attach shm segment (%s)",
  977. strerror (errno));
  978. jack_release_shm_info (si->index);
  979. return -1;
  980. }
  981. return 0;
  982. }
  983. #endif /* !USE_POSIX_SHM */