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:
5 * - common (interface-independent) code
6 * - POSIX implementation
7 * - System V implementation
8 * - Windows implementation
10 * The implementation used is determined by whether USE_POSIX_SHM was
11 * set in the ./configure step.
15 Copyright (C) 2001-2003 Paul Davis
16 Copyright (C) 2005-2012 Grame
18 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU Lesser General Public License as published by
20 the Free Software Foundation; either version 2.1 of the License, or
21 (at your option) any later version.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU Lesser General Public License for more details.
28 You should have received a copy of the GNU Lesser General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include "JackConstants.h"
50 #include <sys/types.h>
59 #include "JackError.h"
65 //#error "No getuid function available"
81 static jack_shmtype_t jack_shmtype
= shm_POSIX
;
83 static jack_shmtype_t jack_shmtype
= shm_WIN32
;
85 static jack_shmtype_t jack_shmtype
= shm_SYSV
;
88 /* interface-dependent forward declarations */
89 static int jack_access_registry (jack_shm_info_t
*ri
);
90 static int jack_create_registry (jack_shm_info_t
*ri
);
91 static void jack_remove_shm (jack_shm_id_t
*id
);
93 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
94 * common interface-independent section
95 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
97 /* The JACK SHM registry is a chunk of memory for keeping track of the
98 * shared memory used by each active JACK server. This allows the
99 * server to clean up shared memory when it exits. To avoid memory
100 * leakage due to kill -9, crashes or debugger-driven exits, this
101 * cleanup is also done when a new instance of that server starts.
104 /* per-process global data for the SHM interfaces */
105 static jack_shm_id_t registry_id
; /* SHM id for the registry */
108 static jack_shm_info_t registry_info
= {/* SHM info for the registry */
113 static jack_shm_info_t registry_info
= { /* SHM info for the registry */
114 .index
= JACK_SHM_NULL_INDEX
,
115 .ptr
.attached_at
= MAP_FAILED
119 /* pointers to registry header and array */
120 static jack_shm_header_t
*jack_shm_header
= NULL
;
121 static jack_shm_registry_t
*jack_shm_registry
= NULL
;
122 static char jack_shm_server_prefix
[JACK_SERVER_NAME_SIZE
] = "";
124 /* jack_shm_lock_registry() serializes updates to the shared memory
125 * segment JACK uses to keep track of the SHM segments allocated to
126 * all its processes, including multiple servers.
128 * This is not a high-contention lock, but it does need to work across
129 * multiple processes. High transaction rates and realtime safety are
130 * not required. Any solution needs to at least be portable to POSIX
131 * and POSIX-like systems.
133 * We must be particularly careful to ensure that the lock be released
134 * if the owning process terminates abnormally. Otherwise, a segfault
135 * or kill -9 at the wrong moment could prevent JACK from ever running
136 * again on that machine until after a reboot.
139 #define JACK_SEMAPHORE_KEY 0x282929
140 #ifndef USE_POSIX_SHM
141 #define JACK_SHM_REGISTRY_KEY JACK_SEMAPHORE_KEY
144 static int semid
= -1;
151 static BOOL
check_process_running(DWORD process_id
)
153 DWORD aProcesses
[2048], cbNeeded
, cProcesses
;
156 // Enumerate all processes
157 if (!EnumProcesses(aProcesses
, sizeof(aProcesses
), &cbNeeded
)) {
161 // Calculate how many process identifiers were returned.
162 cProcesses
= cbNeeded
/ sizeof(DWORD
);
164 for (i
= 0; i
< cProcesses
; i
++) {
165 if (aProcesses
[i
] == process_id
) {
166 // Process process_id is running...
174 semaphore_init () {return 0;}
177 semaphore_add (int value
) {return 0;}
180 /* all semaphore errors are fatal -- issue message, but do not return */
182 semaphore_error (char *msg
)
184 jack_error ("JACK semaphore error: %s (%s)",
185 msg
, strerror (errno
));
191 key_t semkey
= JACK_SEMAPHORE_KEY
;
193 int create_flags
= IPC_CREAT
| IPC_EXCL
194 | S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
;
196 /* Get semaphore ID associated with this key. */
197 if ((semid
= semget(semkey
, 0, 0)) == -1) {
199 /* Semaphore does not exist - Create. */
200 if ((semid
= semget(semkey
, 1, create_flags
)) != -1) {
202 /* Initialize the semaphore, allow one owner. */
206 if (semop(semid
, &sbuf
, 1) == -1) {
207 semaphore_error ("semop");
211 } else if (errno
== EEXIST
) {
212 if ((semid
= semget(semkey
, 0, 0)) == -1) {
213 semaphore_error ("semget");
218 semaphore_error ("semget creation");
227 semaphore_add (int value
)
233 sbuf
.sem_flg
= SEM_UNDO
;
235 if (semop(semid
, &sbuf
, 1) == -1) {
236 semaphore_error ("semop");
246 jack_shm_lock_registry (void)
249 if (semaphore_init () < 0)
253 return semaphore_add (-1);
257 jack_shm_unlock_registry (void)
263 jack_shm_init_registry ()
265 /* registry must be locked */
268 memset (jack_shm_header
, 0, JACK_SHM_REGISTRY_SIZE
);
270 jack_shm_header
->magic
= JACK_SHM_MAGIC
;
271 //jack_shm_header->protocol = JACK_PROTOCOL_VERSION;
272 jack_shm_header
->type
= jack_shmtype
;
273 jack_shm_header
->size
= JACK_SHM_REGISTRY_SIZE
;
274 jack_shm_header
->hdr_len
= sizeof (jack_shm_header_t
);
275 jack_shm_header
->entry_len
= sizeof (jack_shm_registry_t
);
277 for (i
= 0; i
< MAX_SHM_ID
; ++i
) {
278 jack_shm_registry
[i
].index
= i
;
283 jack_shm_validate_registry ()
285 /* registry must be locked */
287 if ((jack_shm_header
->magic
== JACK_SHM_MAGIC
)
288 //&& (jack_shm_header->protocol == JACK_PROTOCOL_VERSION)
289 && (jack_shm_header
->type
== jack_shmtype
)
290 && (jack_shm_header
->size
== JACK_SHM_REGISTRY_SIZE
)
291 && (jack_shm_header
->hdr_len
== sizeof (jack_shm_header_t
))
292 && (jack_shm_header
->entry_len
== sizeof (jack_shm_registry_t
))) {
294 return 0; /* registry OK */
300 /* set a unique per-user, per-server shm prefix string
302 * According to the POSIX standard:
304 * "The name argument conforms to the construction rules for a
305 * pathname. If name begins with the slash character, then processes
306 * calling shm_open() with the same value of name refer to the same
307 * shared memory object, as long as that name has not been
308 * removed. If name does not begin with the slash character, the
309 * effect is implementation-defined. The interpretation of slash
310 * characters other than the leading slash character in name is
311 * implementation-defined."
313 * Since the Linux implementation does not allow slashes *within* the
314 * name, in the interest of portability we use colons instead.
317 jack_set_server_prefix (const char *server_name
)
320 char buffer
[UNLEN
+1]={0};
322 GetUserName(buffer
, &len
);
323 snprintf (jack_shm_server_prefix
, sizeof (jack_shm_server_prefix
),
324 "jack-%s:%s:", buffer
, server_name
);
326 snprintf (jack_shm_server_prefix
, sizeof (jack_shm_server_prefix
),
327 "jack-%d:%s:", GetUID(), server_name
);
331 /* gain server addressability to shared memory registration segment
333 * returns: 0 if successful
336 jack_server_initialize_shm (int new_registry
)
341 return 0; /* already initialized */
343 if (jack_shm_lock_registry () < 0) {
344 jack_error ("jack_shm_lock_registry fails...");
348 rc
= jack_access_registry (®istry_info
);
351 jack_remove_shm (®istry_id
);
356 case ENOENT
: /* registry does not exist */
357 rc
= jack_create_registry (®istry_info
);
359 case 0: /* existing registry */
360 if (jack_shm_validate_registry () == 0)
362 /* else it was invalid, so fall through */
363 case EINVAL
: /* bad registry */
364 /* Apparently, this registry was created by an older
365 * JACK version. Delete it so we can try again. */
366 jack_release_shm (®istry_info
);
367 jack_remove_shm (®istry_id
);
368 if ((rc
= jack_create_registry (®istry_info
)) != 0) {
369 jack_error ("incompatible shm registry (%s)",
371 #ifndef USE_POSIX_SHM
372 jack_error ("to delete, use `ipcrm -M 0x%0.8x'",
373 JACK_SHM_REGISTRY_KEY
);
377 default: /* failure return code */
381 jack_shm_unlock_registry ();
385 /* gain client addressability to shared memory registration segment
387 * NOTE: this function is no longer used for server initialization,
388 * instead it calls jack_register_server().
390 * returns: 0 if successful
393 jack_initialize_shm (const char *server_name
)
398 return 0; /* already initialized */
400 jack_set_server_prefix (server_name
);
402 if (jack_shm_lock_registry () < 0) {
403 jack_error ("jack_shm_lock_registry fails...");
407 if ((rc
= jack_access_registry (®istry_info
)) == 0) {
408 if ((rc
= jack_shm_validate_registry ()) != 0) {
409 jack_error ("Incompatible shm registry, "
410 "are jackd and libjack in sync?");
413 jack_shm_unlock_registry ();
419 char* jack_shm_addr (jack_shm_info_t
* si
)
421 return (char*)si
->ptr
.attached_at
;
425 jack_destroy_shm (jack_shm_info_t
* si
)
427 /* must NOT have the registry locked */
428 if (si
->index
== JACK_SHM_NULL_INDEX
)
429 return; /* segment not allocated */
431 jack_remove_shm (&jack_shm_registry
[si
->index
].id
);
432 jack_release_shm_info (si
->index
);
435 jack_shm_registry_t
*
436 jack_get_free_shm_info ()
438 /* registry must be locked */
439 jack_shm_registry_t
* si
= NULL
;
442 for (i
= 0; i
< MAX_SHM_ID
; ++i
) {
443 if (jack_shm_registry
[i
].size
== 0) {
448 if (i
< MAX_SHM_ID
) {
449 si
= &jack_shm_registry
[i
];
456 jack_release_shm_entry (jack_shm_registry_index_t index
)
458 /* the registry must be locked */
459 jack_shm_registry
[index
].size
= 0;
460 jack_shm_registry
[index
].allocator
= 0;
461 memset (&jack_shm_registry
[index
].id
, 0,
462 sizeof (jack_shm_registry
[index
].id
));
466 jack_release_shm_info (jack_shm_registry_index_t index
)
468 /* must NOT have the registry locked */
469 if (jack_shm_registry
[index
].allocator
== GetPID()) {
470 if (jack_shm_lock_registry () < 0) {
471 jack_error ("jack_shm_lock_registry fails...");
474 jack_release_shm_entry (index
);
475 jack_shm_unlock_registry ();
481 /* Claim server_name for this process.
483 * returns 0 if successful
484 * EEXIST if server_name was already active for this user
485 * ENOSPC if server registration limit reached
486 * ENOMEM if unable to access shared memory registry
489 jack_register_server (const char *server_name
, int new_registry
)
493 jack_set_server_prefix (server_name
);
495 if (jack_server_initialize_shm (new_registry
))
498 if (jack_shm_lock_registry () < 0) {
499 jack_error ("jack_shm_lock_registry fails...");
503 /* See if server_name already registered. Since server names
504 * are per-user, we register the unique server prefix string.
506 for (i
= 0; i
< MAX_SERVERS
; i
++) {
508 if (strncmp (jack_shm_header
->server
[i
].name
,
509 jack_shm_server_prefix
,
510 JACK_SERVER_NAME_SIZE
) != 0)
511 continue; /* no match */
513 if (jack_shm_header
->server
[i
].pid
== GetPID()){
514 res
= 0; /* it's me */
518 /* see if server still exists */
520 if (check_process_running(jack_shm_header
->server
[i
].pid
)) {
521 res
= EEXIST
; /* other server running */
525 if (kill (jack_shm_header
->server
[i
].pid
, 0) == 0) {
526 res
= EEXIST
; /* other server running */
531 /* it's gone, reclaim this entry */
532 memset (&jack_shm_header
->server
[i
], 0,
533 sizeof (jack_shm_server_t
));
536 /* find a free entry */
537 for (i
= 0; i
< MAX_SERVERS
; i
++) {
538 if (jack_shm_header
->server
[i
].pid
== 0)
542 if (i
>= MAX_SERVERS
){
543 res
= ENOSPC
; /* out of space */
548 jack_shm_header
->server
[i
].pid
= GetPID();
549 strncpy (jack_shm_header
->server
[i
].name
,
550 jack_shm_server_prefix
,
551 JACK_SERVER_NAME_SIZE
);
554 jack_shm_unlock_registry ();
558 /* release server_name registration */
560 jack_unregister_server (const char *server_name
/* unused */)
563 if (jack_shm_lock_registry () < 0) {
564 jack_error ("jack_shm_lock_registry fails...");
568 for (i
= 0; i
< MAX_SERVERS
; i
++) {
569 if (jack_shm_header
->server
[i
].pid
== GetPID()) {
570 memset (&jack_shm_header
->server
[i
], 0,
571 sizeof (jack_shm_server_t
));
575 jack_shm_unlock_registry ();
579 /* called for server startup and termination */
585 jack_shm_info_t copy
;
587 if (jack_shm_lock_registry () < 0) {
588 jack_error ("jack_shm_lock_registry fails...");
592 for (i
= 0; i
< MAX_SHM_ID
; i
++) {
593 jack_shm_registry_t
* r
;
595 r
= &jack_shm_registry
[i
];
596 memcpy (©
, r
, sizeof (jack_shm_info_t
));
599 /* ignore unused entries */
600 if (r
->allocator
== 0)
603 /* is this my shm segment? */
604 if (r
->allocator
== GetPID()) {
606 /* allocated by this process, so unattach
608 jack_release_shm (©
);
613 /* see if allocator still exists */
614 #ifdef WIN32 // steph
615 //jack_info("TODO: kill API not available !!");
617 if (kill (r
->allocator
, 0)) {
618 if (errno
== ESRCH
) {
619 /* allocator no longer exists,
629 int index
= copy
.index
;
631 if ((index
>= 0) && (index
< MAX_SHM_ID
)) {
632 jack_remove_shm (&jack_shm_registry
[index
].id
);
633 jack_release_shm_entry (index
);
640 jack_shm_unlock_registry ();
644 /* resize a shared memory segment
646 * There is no way to resize a System V shm segment. Resizing is
647 * possible with POSIX shm, but not with the non-conformant Mac OS X
648 * implementation. Since POSIX shm is mainly used on that platform,
649 * it's simpler to treat them both the same.
651 * So, we always resize by deleting and reallocating. This is
652 * tricky, because the old segment will not disappear until
653 * all the clients have released it. We only do what we can
656 * This is not done under a single lock. I don't even want to think
657 * about all the things that could possibly go wrong if multple
658 * processes tried to resize the same segment concurrently. That
659 * probably doesn't happen.
662 jack_resize_shm (jack_shm_info_t
* si
, jack_shmsize_t size
)
666 /* The underlying type of `id' differs for SYSV and POSIX */
667 memcpy (&id
, &jack_shm_registry
[si
->index
].id
, sizeof (id
));
669 jack_release_shm (si
);
670 jack_destroy_shm (si
);
672 if (jack_shmalloc ((char *) id
, size
, si
)) {
676 return jack_attach_shm (si
);
680 jack_attach_lib_shm (jack_shm_info_t
* si
)
682 int res
= jack_attach_shm(si
);
684 si
->size
= jack_shm_registry
[si
->index
].size
; // Keep size in si struct
689 jack_attach_lib_shm_read (jack_shm_info_t
* si
)
691 int res
= jack_attach_shm_read(si
);
693 si
->size
= jack_shm_registry
[si
->index
].size
; // Keep size in si struct
699 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
700 * POSIX interface-dependent functions
701 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
703 /* gain addressability to existing SHM registry segment
705 * sets up global registry pointers, if successful
707 * returns: 0 if existing registry accessed successfully
708 * ENOENT if registry does not exist
709 * EINVAL if registry exists, but has the wrong size
712 jack_access_registry (jack_shm_info_t
*ri
)
714 /* registry must be locked */
717 strncpy (registry_id
, "/jack-shm-registry", sizeof (registry_id
));
719 /* try to open an existing segment */
720 if ((shm_fd
= shm_open (registry_id
, O_RDWR
, 0666)) < 0) {
722 if (errno
!= ENOENT
) {
723 jack_error ("Cannot open existing shm registry segment"
724 " (%s)", strerror (errno
));
730 if ((ri
->ptr
.attached_at
= mmap (0, JACK_SHM_REGISTRY_SIZE
,
731 PROT_READ
|PROT_WRITE
,
732 MAP_SHARED
, shm_fd
, 0)) == MAP_FAILED
) {
733 jack_error ("Cannot mmap shm registry segment (%s)",
739 /* set up global pointers */
740 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
741 jack_shm_header
= ri
->ptr
.attached_at
;
742 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
744 close (shm_fd
); // steph
748 /* create a new SHM registry segment
750 * sets up global registry pointers, if successful
752 * returns: 0 if registry created successfully
753 * nonzero error code if unable to allocate a new registry
756 jack_create_registry (jack_shm_info_t
*ri
)
758 /* registry must be locked */
761 strncpy (registry_id
, "/jack-shm-registry", sizeof (registry_id
));
763 if ((shm_fd
= shm_open (registry_id
, O_RDWR
|O_CREAT
, 0666)) < 0) {
765 jack_error ("Cannot create shm registry segment (%s)",
770 /* Previous shm_open result depends of the actual value of umask, force correct file permisssion here */
771 if (fchmod(shm_fd
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
) < 0) {
772 jack_log("Cannot chmod jack-shm-registry (%s) %d %d", strerror (errno
));
775 /* Set the desired segment size. NOTE: the non-conformant Mac
776 * OS X POSIX shm only allows ftruncate() on segment creation.
778 if (ftruncate (shm_fd
, JACK_SHM_REGISTRY_SIZE
) < 0) {
780 jack_error ("Cannot set registry size (%s)", strerror (errno
));
781 jack_remove_shm (®istry_id
);
786 if ((ri
->ptr
.attached_at
= mmap (0, JACK_SHM_REGISTRY_SIZE
,
787 PROT_READ
|PROT_WRITE
,
788 MAP_SHARED
, shm_fd
, 0)) == MAP_FAILED
) {
789 jack_error ("Cannot mmap shm registry segment (%s)",
791 jack_remove_shm (®istry_id
);
796 /* set up global pointers */
797 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
798 jack_shm_header
= ri
->ptr
.attached_at
;
799 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
801 /* initialize registry contents */
802 jack_shm_init_registry ();
803 close (shm_fd
); // steph
808 jack_remove_shm (jack_shm_id_t
*id
)
810 /* registry may or may not be locked */
811 shm_unlink ((char *) id
);
815 jack_release_shm (jack_shm_info_t
* si
)
817 /* registry may or may not be locked */
818 if (si
->ptr
.attached_at
!= MAP_FAILED
) {
819 munmap (si
->ptr
.attached_at
, jack_shm_registry
[si
->index
].size
);
824 jack_release_lib_shm (jack_shm_info_t
* si
)
826 /* registry may or may not be locked */
827 if (si
->ptr
.attached_at
!= MAP_FAILED
) {
828 munmap (si
->ptr
.attached_at
, si
->size
);
832 /* allocate a POSIX shared memory segment */
834 jack_shmalloc (const char *shm_name
, jack_shmsize_t size
, jack_shm_info_t
* si
)
836 jack_shm_registry_t
* registry
;
839 char name
[SHM_NAME_MAX
+1];
841 if (jack_shm_lock_registry () < 0) {
842 jack_error ("jack_shm_lock_registry fails...");
846 if ((registry
= jack_get_free_shm_info ()) == NULL
) {
847 jack_error ("shm registry full");
851 /* On Mac OS X, the maximum length of a shared memory segment
852 * name is SHM_NAME_MAX (instead of NAME_MAX or PATH_MAX as
853 * defined by the standard). Unfortunately, Apple sets this
854 * value so small (about 31 bytes) that it is useless for
855 * actual names. So, we construct a short name from the
856 * registry index for uniqueness and ignore the shm_name
859 snprintf (name
, sizeof (name
), "/jack-%d-%d", GetUID(), registry
->index
);
861 if (strlen (name
) >= sizeof (registry
->id
)) {
862 jack_error ("shm segment name too long %s", name
);
866 if ((shm_fd
= shm_open (name
, O_RDWR
|O_CREAT
, 0666)) < 0) {
867 jack_error ("Cannot create shm segment %s (%s)",
868 name
, strerror (errno
));
872 if (ftruncate (shm_fd
, size
) < 0) {
873 jack_error ("Cannot set size of engine shm "
881 registry
->size
= size
;
882 strncpy (registry
->id
, name
, sizeof (registry
->id
));
883 registry
->allocator
= GetPID();
884 si
->index
= registry
->index
;
885 si
->ptr
.attached_at
= MAP_FAILED
; /* not attached */
886 rc
= 0; /* success */
889 jack_shm_unlock_registry ();
894 jack_attach_shm (jack_shm_info_t
* si
)
897 jack_shm_registry_t
*registry
= &jack_shm_registry
[si
->index
];
899 if ((shm_fd
= shm_open (registry
->id
,
900 O_RDWR
, 0666)) < 0) {
901 jack_error ("Cannot open shm segment %s (%s)", registry
->id
,
906 if ((si
->ptr
.attached_at
= mmap (0, registry
->size
, PROT_READ
|PROT_WRITE
,
907 MAP_SHARED
, shm_fd
, 0)) == MAP_FAILED
) {
908 jack_error ("Cannot mmap shm segment %s (%s)",
920 jack_attach_shm_read (jack_shm_info_t
* si
)
923 jack_shm_registry_t
*registry
= &jack_shm_registry
[si
->index
];
925 if ((shm_fd
= shm_open (registry
->id
,
926 O_RDONLY
, 0666)) < 0) {
927 jack_error ("Cannot open shm segment %s (%s)", registry
->id
,
932 if ((si
->ptr
.attached_at
= mmap (0, registry
->size
, PROT_READ
,
933 MAP_SHARED
, shm_fd
, 0)) == MAP_FAILED
) {
934 jack_error ("Cannot mmap shm segment %s (%s)",
948 jack_access_registry (jack_shm_info_t
*ri
)
950 /* registry must be locked */
952 strncpy (registry_id
, "jack-shm-registry", sizeof (registry_id
));
954 /* try to open an existing segment */
956 if ((shm_fd
= OpenFileMapping(FILE_MAP_ALL_ACCESS
, FALSE
, registry_id
)) == NULL
) {
957 int rc
= GetLastError();
958 if (rc
!= ERROR_FILE_NOT_FOUND
) {
959 jack_error ("Cannot open existing shm registry segment (%ld)", rc
);
964 if ((ri
->ptr
.attached_at
= MapViewOfFile (shm_fd
, FILE_MAP_ALL_ACCESS
, 0, 0, JACK_SHM_REGISTRY_SIZE
)) == NULL
) {
965 jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
966 jack_remove_shm (®istry_id
);
967 CloseHandle (shm_fd
);
971 /* set up global pointers */
972 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
973 jack_shm_header
= ri
->ptr
.attached_at
;
974 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
976 //CloseHandle(shm_fd); // TO CHECK
981 jack_create_registry (jack_shm_info_t
*ri
)
983 /* registry must be locked */
986 strncpy (registry_id
, "jack-shm-registry", sizeof (registry_id
));
988 if ((shm_fd
= CreateFileMapping(INVALID_HANDLE_VALUE
,
990 0, JACK_SHM_REGISTRY_SIZE
,
991 registry_id
)) == NULL
|| (shm_fd
== INVALID_HANDLE_VALUE
)) {
992 int rc
= GetLastError();
993 jack_error ("Cannot create shm registry segment (%ld)", rc
);
997 if ((ri
->ptr
.attached_at
= MapViewOfFile (shm_fd
, FILE_MAP_ALL_ACCESS
, 0, 0, JACK_SHM_REGISTRY_SIZE
)) == NULL
) {
998 jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
999 jack_remove_shm (®istry_id
);
1000 CloseHandle (shm_fd
);
1004 /* set up global pointers */
1005 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
1006 jack_shm_header
= ri
->ptr
.attached_at
;
1007 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
1009 /* initialize registry contents */
1010 jack_shm_init_registry ();
1012 //CloseHandle(shm_fd); // TO CHECK
1017 jack_remove_shm (jack_shm_id_t
*id
)
1023 jack_release_shm (jack_shm_info_t
* si
)
1025 /* registry may or may not be locked */
1026 if (si
->ptr
.attached_at
!= NULL
) {
1027 UnmapViewOfFile (si
->ptr
.attached_at
);
1032 jack_release_lib_shm (jack_shm_info_t
* si
)
1034 jack_release_shm(si
);
1038 jack_shmalloc (const char *shm_name
, jack_shmsize_t size
, jack_shm_info_t
* si
)
1040 jack_shm_registry_t
* registry
;
1043 char name
[SHM_NAME_MAX
+1];
1045 if (jack_shm_lock_registry () < 0) {
1046 jack_error ("jack_shm_lock_registry fails...");
1050 if ((registry
= jack_get_free_shm_info ()) == NULL
) {
1051 jack_error ("shm registry full");
1055 snprintf (name
, sizeof (name
), "jack-%d-%d", GetUID(), registry
->index
);
1057 if (strlen (name
) >= sizeof (registry
->id
)) {
1058 jack_error ("shm segment name too long %s", name
);
1062 if ((shm_fd
= CreateFileMapping(INVALID_HANDLE_VALUE
,
1065 name
)) == NULL
|| (shm_fd
== INVALID_HANDLE_VALUE
)) {
1066 int rc
= GetLastError();
1067 jack_error ("Cannot create shm segment (%ld)",rc
);
1071 //CloseHandle (shm_fd); // TO CHECK
1073 registry
->size
= size
;
1074 strncpy (registry
->id
, name
, sizeof (registry
->id
));
1075 registry
->allocator
= _getpid();
1076 si
->index
= registry
->index
;
1077 si
->ptr
.attached_at
= NULL
; /* not attached */
1078 rc
= 0; /* success */
1081 jack_shm_unlock_registry ();
1086 jack_attach_shm (jack_shm_info_t
* si
)
1089 jack_shm_registry_t
*registry
= &jack_shm_registry
[si
->index
];
1091 if ((shm_fd
= OpenFileMapping(FILE_MAP_ALL_ACCESS
, FALSE
, registry
->id
)) == NULL
) {
1092 int rc
= GetLastError();
1093 jack_error ("Cannot open shm segment (%ld)",rc
);
1097 if ((si
->ptr
.attached_at
= MapViewOfFile (shm_fd
, FILE_MAP_ALL_ACCESS
, 0, 0, registry
->size
)) == NULL
) {
1098 jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
1099 jack_remove_shm (®istry_id
);
1100 CloseHandle (shm_fd
);
1104 //CloseHandle (shm_fd); // TO CHECK
1109 jack_attach_shm_read (jack_shm_info_t
* si
)
1112 jack_shm_registry_t
*registry
= &jack_shm_registry
[si
->index
];
1114 if ((shm_fd
= OpenFileMapping(FILE_MAP_ALL_ACCESS
, FALSE
, registry
->id
)) == NULL
) {
1115 int rc
= GetLastError();
1116 jack_error ("Cannot open shm segment (%ld)",rc
);
1120 if ((si
->ptr
.attached_at
= MapViewOfFile (shm_fd
, FILE_MAP_READ
, 0, 0, registry
->size
)) == NULL
) {
1121 jack_error("Cannot mmap shm segment (%ld)", GetLastError());
1122 jack_remove_shm(®istry_id
);
1123 CloseHandle(shm_fd
);
1127 //CloseHandle (shm_fd); // TO CHECK
1133 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1134 * System V interface-dependent functions
1135 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1137 /* gain addressability to existing SHM registry segment
1139 * sets up global registry pointers, if successful
1141 * returns: 0 if existing registry accessed successfully
1142 * ENOENT if registry does not exist
1143 * EINVAL if registry exists, but has the wrong size
1144 * other nonzero error code if unable to access registry
1147 jack_access_registry (jack_shm_info_t
*ri
)
1149 /* registry must be locked */
1151 /* try without IPC_CREAT to get existing segment */
1152 if ((registry_id
= shmget (JACK_SHM_REGISTRY_KEY
,
1153 JACK_SHM_REGISTRY_SIZE
, 0666)) < 0) {
1157 case ENOENT
: /* segment does not exist */
1160 case EINVAL
: /* segment exists, but too small */
1161 /* attempt minimum size access */
1162 registry_id
= shmget (JACK_SHM_REGISTRY_KEY
, 1, 0666);
1165 default: /* or other error */
1166 jack_error ("unable to access shm registry (%s)",
1172 if ((ri
->ptr
.attached_at
= shmat (registry_id
, 0, 0)) < 0) {
1173 jack_error ("Cannot attach shm registry segment (%s)",
1178 /* set up global pointers */
1179 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
1180 jack_shm_header
= ri
->ptr
.attached_at
;
1181 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
1185 /* create a new SHM registry segment
1187 * sets up global registry pointers, if successful
1189 * returns: 0 if registry created successfully
1190 * nonzero error code if unable to allocate a new registry
1193 jack_create_registry (jack_shm_info_t
*ri
)
1195 /* registry must be locked */
1196 if ((registry_id
= shmget (JACK_SHM_REGISTRY_KEY
,
1197 JACK_SHM_REGISTRY_SIZE
,
1198 0666|IPC_CREAT
)) < 0) {
1199 jack_error ("Cannot create shm registry segment (%s)",
1204 if ((ri
->ptr
.attached_at
= shmat (registry_id
, 0, 0)) < 0) {
1205 jack_error ("Cannot attach shm registry segment (%s)",
1210 /* set up global pointers */
1211 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
1212 jack_shm_header
= ri
->ptr
.attached_at
;
1213 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
1215 /* initialize registry contents */
1216 jack_shm_init_registry ();
1221 jack_remove_shm (jack_shm_id_t
*id
)
1223 /* registry may or may not be locked */
1224 shmctl (*id
, IPC_RMID
, NULL
);
1228 jack_release_shm (jack_shm_info_t
* si
)
1230 /* registry may or may not be locked */
1231 if (si
->ptr
.attached_at
!= MAP_FAILED
) {
1232 shmdt (si
->ptr
.attached_at
);
1237 jack_release_lib_shm (jack_shm_info_t
* si
)
1239 jack_release_shm(si
);
1243 jack_shmalloc (const char* name_not_used
, jack_shmsize_t size
,
1244 jack_shm_info_t
* si
)
1249 jack_shm_registry_t
* registry
;
1251 if (jack_shm_lock_registry () < 0) {
1252 jack_error ("jack_shm_lock_registry fails...");
1256 if ((registry
= jack_get_free_shm_info ())) {
1258 shmflags
= 0666 | IPC_CREAT
| IPC_EXCL
;
1260 if ((shmid
= shmget (IPC_PRIVATE
, size
, shmflags
)) >= 0) {
1262 registry
->size
= size
;
1263 registry
->id
= shmid
;
1264 registry
->allocator
= getpid();
1265 si
->index
= registry
->index
;
1266 si
->ptr
.attached_at
= MAP_FAILED
; /* not attached */
1270 jack_error ("Cannot create shm segment %s (%s)",
1271 name_not_used
, strerror (errno
));
1275 jack_shm_unlock_registry ();
1280 jack_attach_shm (jack_shm_info_t
* si
)
1282 if ((si
->ptr
.attached_at
= shmat (jack_shm_registry
[si
->index
].id
, 0, 0)) < 0) {
1283 jack_error ("Cannot attach shm segment (%s)",
1285 jack_release_shm_info (si
->index
);
1292 jack_attach_shm_read (jack_shm_info_t
* si
)
1294 if ((si
->ptr
.attached_at
= shmat (jack_shm_registry
[si
->index
].id
, 0, SHM_RDONLY
)) < 0) {
1295 jack_error ("Cannot attach shm segment (%s)",
1297 jack_release_shm_info (si
->index
);
1303 #endif /* !USE_POSIX_SHM */