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>
55 #include "promiscuous.h"
60 #include "JackError.h"
66 //#error "No getuid function available"
82 static jack_shmtype_t jack_shmtype
= shm_POSIX
;
84 static jack_shmtype_t jack_shmtype
= shm_WIN32
;
86 static jack_shmtype_t jack_shmtype
= shm_SYSV
;
89 /* interface-dependent forward declarations */
90 static int jack_access_registry (jack_shm_info_t
*ri
);
91 static int jack_create_registry (jack_shm_info_t
*ri
);
92 static void jack_remove_shm (jack_shm_id_t
*id
);
94 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
95 * common interface-independent section
96 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
98 /* The JACK SHM registry is a chunk of memory for keeping track of the
99 * shared memory used by each active JACK server. This allows the
100 * server to clean up shared memory when it exits. To avoid memory
101 * leakage due to kill -9, crashes or debugger-driven exits, this
102 * cleanup is also done when a new instance of that server starts.
105 /* per-process global data for the SHM interfaces */
106 static jack_shm_id_t registry_id
; /* SHM id for the registry */
109 static jack_shm_info_t registry_info
= {/* SHM info for the registry */
114 static jack_shm_info_t registry_info
= { /* SHM info for the registry */
115 .index
= JACK_SHM_NULL_INDEX
,
116 .ptr
.attached_at
= MAP_FAILED
120 /* pointers to registry header and array */
121 static jack_shm_header_t
*jack_shm_header
= NULL
;
122 static jack_shm_registry_t
*jack_shm_registry
= NULL
;
123 static char jack_shm_server_prefix
[JACK_SERVER_NAME_SIZE
+1] = "";
125 /* jack_shm_lock_registry() serializes updates to the shared memory
126 * segment JACK uses to keep track of the SHM segments allocated to
127 * all its processes, including multiple servers.
129 * This is not a high-contention lock, but it does need to work across
130 * multiple processes. High transaction rates and realtime safety are
131 * not required. Any solution needs to at least be portable to POSIX
132 * and POSIX-like systems.
134 * We must be particularly careful to ensure that the lock be released
135 * if the owning process terminates abnormally. Otherwise, a segfault
136 * or kill -9 at the wrong moment could prevent JACK from ever running
137 * again on that machine until after a reboot.
140 #define JACK_SEMAPHORE_KEY 0x282929
141 #ifndef USE_POSIX_SHM
142 #define JACK_SHM_REGISTRY_KEY JACK_SEMAPHORE_KEY
145 static int semid
= -1;
152 static BOOL
check_process_running(DWORD process_id
)
154 DWORD aProcesses
[2048], cbNeeded
, cProcesses
;
157 // Enumerate all processes
158 if (!EnumProcesses(aProcesses
, sizeof(aProcesses
), &cbNeeded
)) {
162 // Calculate how many process identifiers were returned.
163 cProcesses
= cbNeeded
/ sizeof(DWORD
);
165 for (i
= 0; i
< cProcesses
; i
++) {
166 if (aProcesses
[i
] == process_id
) {
167 // Process process_id is running...
175 semaphore_init () {return 0;}
178 semaphore_add (int value
) {return 0;}
181 /* all semaphore errors are fatal -- issue message, but do not return */
183 semaphore_error (char *msg
)
185 jack_error ("JACK semaphore error: %s (%s)",
186 msg
, strerror (errno
));
192 key_t semkey
= JACK_SEMAPHORE_KEY
;
194 int create_flags
= IPC_CREAT
| IPC_EXCL
195 | S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
;
197 /* Get semaphore ID associated with this key. */
198 if ((semid
= semget(semkey
, 0, 0)) == -1) {
200 /* Semaphore does not exist - Create. */
201 if ((semid
= semget(semkey
, 1, create_flags
)) != -1) {
203 /* Initialize the semaphore, allow one owner. */
207 if (semop(semid
, &sbuf
, 1) == -1) {
208 semaphore_error ("semop");
212 } else if (errno
== EEXIST
) {
213 if ((semid
= semget(semkey
, 0, 0)) == -1) {
214 semaphore_error ("semget");
219 semaphore_error ("semget creation");
228 semaphore_add (int value
)
234 sbuf
.sem_flg
= SEM_UNDO
;
236 if (semop(semid
, &sbuf
, 1) == -1) {
237 semaphore_error ("semop");
247 jack_shm_lock_registry (void)
250 if (semaphore_init () < 0)
254 return semaphore_add (-1);
258 jack_shm_unlock_registry (void)
264 jack_shm_init_registry ()
266 /* registry must be locked */
269 memset (jack_shm_header
, 0, JACK_SHM_REGISTRY_SIZE
);
271 jack_shm_header
->magic
= JACK_SHM_MAGIC
;
272 //jack_shm_header->protocol = JACK_PROTOCOL_VERSION;
273 jack_shm_header
->type
= jack_shmtype
;
274 jack_shm_header
->size
= JACK_SHM_REGISTRY_SIZE
;
275 jack_shm_header
->hdr_len
= sizeof (jack_shm_header_t
);
276 jack_shm_header
->entry_len
= sizeof (jack_shm_registry_t
);
278 for (i
= 0; i
< MAX_SHM_ID
; ++i
) {
279 jack_shm_registry
[i
].index
= i
;
284 jack_shm_validate_registry ()
286 /* registry must be locked */
288 if ((jack_shm_header
->magic
== JACK_SHM_MAGIC
)
289 //&& (jack_shm_header->protocol == JACK_PROTOCOL_VERSION)
290 && (jack_shm_header
->type
== jack_shmtype
)
291 && (jack_shm_header
->size
== JACK_SHM_REGISTRY_SIZE
)
292 && (jack_shm_header
->hdr_len
== sizeof (jack_shm_header_t
))
293 && (jack_shm_header
->entry_len
== sizeof (jack_shm_registry_t
))) {
295 return 0; /* registry OK */
301 /* set a unique per-user, per-server shm prefix string
303 * According to the POSIX standard:
305 * "The name argument conforms to the construction rules for a
306 * pathname. If name begins with the slash character, then processes
307 * calling shm_open() with the same value of name refer to the same
308 * shared memory object, as long as that name has not been
309 * removed. If name does not begin with the slash character, the
310 * effect is implementation-defined. The interpretation of slash
311 * characters other than the leading slash character in name is
312 * implementation-defined."
314 * Since the Linux implementation does not allow slashes *within* the
315 * name, in the interest of portability we use colons instead.
318 jack_set_server_prefix (const char *server_name
)
321 char buffer
[UNLEN
+1]={0};
323 GetUserName(buffer
, &len
);
324 snprintf (jack_shm_server_prefix
, sizeof (jack_shm_server_prefix
),
325 "jack-%s:%s:", buffer
, server_name
);
327 snprintf (jack_shm_server_prefix
, sizeof (jack_shm_server_prefix
),
328 "jack-%d:%s:", GetUID(), server_name
);
332 /* gain server addressability to shared memory registration segment
334 * returns: 0 if successful
337 jack_server_initialize_shm (int new_registry
)
342 return 0; /* already initialized */
344 if (jack_shm_lock_registry () < 0) {
345 jack_error ("jack_shm_lock_registry fails...");
349 rc
= jack_access_registry (®istry_info
);
352 jack_remove_shm (®istry_id
);
357 case ENOENT
: /* registry does not exist */
358 rc
= jack_create_registry (®istry_info
);
360 case 0: /* existing registry */
361 if (jack_shm_validate_registry () == 0)
363 /* else it was invalid, so fall through */
364 case EINVAL
: /* bad registry */
365 /* Apparently, this registry was created by an older
366 * JACK version. Delete it so we can try again. */
367 jack_release_shm (®istry_info
);
368 jack_remove_shm (®istry_id
);
369 if ((rc
= jack_create_registry (®istry_info
)) != 0) {
370 jack_error ("incompatible shm registry (%s)",
372 #ifndef USE_POSIX_SHM
373 jack_error ("to delete, use `ipcrm -M 0x%0.8x'",
374 JACK_SHM_REGISTRY_KEY
);
378 default: /* failure return code */
382 jack_shm_unlock_registry ();
386 /* gain client addressability to shared memory registration segment
388 * NOTE: this function is no longer used for server initialization,
389 * instead it calls jack_register_server().
391 * returns: 0 if successful
394 jack_initialize_shm (const char *server_name
)
399 return 0; /* already initialized */
401 jack_set_server_prefix (server_name
);
403 if (jack_shm_lock_registry () < 0) {
404 jack_error ("jack_shm_lock_registry fails...");
408 if ((rc
= jack_access_registry (®istry_info
)) == 0) {
409 if ((rc
= jack_shm_validate_registry ()) != 0) {
410 jack_error ("Incompatible shm registry, "
411 "are jackd and libjack in sync?");
414 jack_shm_unlock_registry ();
420 char* jack_shm_addr (jack_shm_info_t
* si
)
422 return (char*)si
->ptr
.attached_at
;
426 jack_destroy_shm (jack_shm_info_t
* si
)
428 /* must NOT have the registry locked */
429 if (si
->index
== JACK_SHM_NULL_INDEX
)
430 return; /* segment not allocated */
432 jack_remove_shm (&jack_shm_registry
[si
->index
].id
);
433 jack_release_shm_info (si
->index
);
436 jack_shm_registry_t
*
437 jack_get_free_shm_info ()
439 /* registry must be locked */
440 jack_shm_registry_t
* si
= NULL
;
443 for (i
= 0; i
< MAX_SHM_ID
; ++i
) {
444 if (jack_shm_registry
[i
].size
== 0) {
449 if (i
< MAX_SHM_ID
) {
450 si
= &jack_shm_registry
[i
];
457 jack_release_shm_entry (jack_shm_registry_index_t index
)
459 /* the registry must be locked */
460 jack_shm_registry
[index
].size
= 0;
461 jack_shm_registry
[index
].allocator
= 0;
462 memset (&jack_shm_registry
[index
].id
, 0,
463 sizeof (jack_shm_registry
[index
].id
));
467 jack_release_shm_info (jack_shm_registry_index_t index
)
469 /* must NOT have the registry locked */
470 if (jack_shm_registry
[index
].allocator
== GetPID()) {
471 if (jack_shm_lock_registry () < 0) {
472 jack_error ("jack_shm_lock_registry fails...");
475 jack_release_shm_entry (index
);
476 jack_shm_unlock_registry ();
482 /* Claim server_name for this process.
484 * returns 0 if successful
485 * EEXIST if server_name was already active for this user
486 * ENOSPC if server registration limit reached
487 * ENOMEM if unable to access shared memory registry
490 jack_register_server (const char *server_name
, int new_registry
)
494 jack_set_server_prefix (server_name
);
496 if (jack_server_initialize_shm (new_registry
))
499 if (jack_shm_lock_registry () < 0) {
500 jack_error ("jack_shm_lock_registry fails...");
504 /* See if server_name already registered. Since server names
505 * are per-user, we register the unique server prefix string.
507 for (i
= 0; i
< MAX_SERVERS
; i
++) {
509 if (strncmp (jack_shm_header
->server
[i
].name
,
510 jack_shm_server_prefix
,
511 JACK_SERVER_NAME_SIZE
) != 0)
512 continue; /* no match */
514 if (jack_shm_header
->server
[i
].pid
== GetPID()){
515 res
= 0; /* it's me */
519 /* see if server still exists */
521 if (check_process_running(jack_shm_header
->server
[i
].pid
)) {
522 res
= EEXIST
; /* other server running */
526 if (kill (jack_shm_header
->server
[i
].pid
, 0) == 0) {
527 res
= EEXIST
; /* other server running */
532 /* it's gone, reclaim this entry */
533 memset (&jack_shm_header
->server
[i
], 0,
534 sizeof (jack_shm_server_t
));
537 /* find a free entry */
538 for (i
= 0; i
< MAX_SERVERS
; i
++) {
539 if (jack_shm_header
->server
[i
].pid
== 0)
543 if (i
>= MAX_SERVERS
){
544 res
= ENOSPC
; /* out of space */
549 jack_shm_header
->server
[i
].pid
= GetPID();
550 strncpy (jack_shm_header
->server
[i
].name
,
551 jack_shm_server_prefix
,
552 JACK_SERVER_NAME_SIZE
);
555 jack_shm_unlock_registry ();
559 /* release server_name registration */
561 jack_unregister_server (const char *server_name
/* unused */)
564 if (jack_shm_lock_registry () < 0) {
565 jack_error ("jack_shm_lock_registry fails...");
569 for (i
= 0; i
< MAX_SERVERS
; i
++) {
570 if (jack_shm_header
->server
[i
].pid
== GetPID()) {
571 memset (&jack_shm_header
->server
[i
], 0,
572 sizeof (jack_shm_server_t
));
576 jack_shm_unlock_registry ();
580 /* called for server startup and termination */
586 jack_shm_info_t copy
;
588 if (jack_shm_lock_registry () < 0) {
589 jack_error ("jack_shm_lock_registry fails...");
593 for (i
= 0; i
< MAX_SHM_ID
; i
++) {
594 jack_shm_registry_t
* r
;
596 r
= &jack_shm_registry
[i
];
597 memcpy (©
, r
, sizeof (jack_shm_info_t
));
600 /* ignore unused entries */
601 if (r
->allocator
== 0)
604 /* is this my shm segment? */
605 if (r
->allocator
== GetPID()) {
607 /* allocated by this process, so unattach
609 jack_release_shm (©
);
614 /* see if allocator still exists */
616 //jack_info("TODO: kill API not available !!");
618 if (kill (r
->allocator
, 0)) {
619 if (errno
== ESRCH
) {
620 /* allocator no longer exists,
630 int index
= copy
.index
;
632 if ((index
>= 0) && (index
< MAX_SHM_ID
)) {
633 jack_remove_shm (&jack_shm_registry
[index
].id
);
634 jack_release_shm_entry (index
);
641 jack_shm_unlock_registry ();
645 /* resize a shared memory segment
647 * There is no way to resize a System V shm segment. Resizing is
648 * possible with POSIX shm, but not with the non-conformant Mac OS X
649 * implementation. Since POSIX shm is mainly used on that platform,
650 * it's simpler to treat them both the same.
652 * So, we always resize by deleting and reallocating. This is
653 * tricky, because the old segment will not disappear until
654 * all the clients have released it. We only do what we can
657 * This is not done under a single lock. I don't even want to think
658 * about all the things that could possibly go wrong if multiple
659 * processes tried to resize the same segment concurrently. That
660 * probably doesn't happen.
663 jack_resize_shm (jack_shm_info_t
* si
, jack_shmsize_t size
)
667 /* The underlying type of `id' differs for SYSV and POSIX */
668 memcpy (&id
, &jack_shm_registry
[si
->index
].id
, sizeof (id
));
670 jack_release_shm (si
);
671 jack_destroy_shm (si
);
673 if (jack_shmalloc ((char *) id
, size
, si
)) {
677 return jack_attach_shm (si
);
681 jack_attach_lib_shm (jack_shm_info_t
* si
)
683 int res
= jack_attach_shm(si
);
685 si
->size
= jack_shm_registry
[si
->index
].size
; // Keep size in si struct
690 jack_attach_lib_shm_read (jack_shm_info_t
* si
)
692 int res
= jack_attach_shm_read(si
);
694 si
->size
= jack_shm_registry
[si
->index
].size
; // Keep size in si struct
700 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
701 * POSIX interface-dependent functions
702 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
704 /* gain addressability to existing SHM registry segment
706 * sets up global registry pointers, if successful
708 * returns: 0 if existing registry accessed successfully
709 * ENOENT if registry does not exist
710 * EINVAL if registry exists, but has the wrong size
713 jack_access_registry (jack_shm_info_t
*ri
)
715 /* registry must be locked */
718 strncpy (registry_id
, "/jack-shm-registry", sizeof (registry_id
));
720 /* try to open an existing segment */
721 if ((shm_fd
= shm_open (registry_id
, O_RDWR
, 0666)) < 0) {
723 if (errno
!= ENOENT
) {
724 jack_error ("Cannot open existing shm registry segment"
725 " (%s)", strerror (errno
));
731 if ((ri
->ptr
.attached_at
= mmap (0, JACK_SHM_REGISTRY_SIZE
,
732 PROT_READ
|PROT_WRITE
,
733 MAP_SHARED
, shm_fd
, 0)) == MAP_FAILED
) {
734 jack_error ("Cannot mmap shm registry segment (%s)",
740 /* set up global pointers */
741 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
742 jack_shm_header
= ri
->ptr
.attached_at
;
743 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
749 /* create a new SHM registry segment
751 * sets up global registry pointers, if successful
753 * returns: 0 if registry created successfully
754 * nonzero error code if unable to allocate a new registry
757 jack_create_registry (jack_shm_info_t
*ri
)
759 /* registry must be locked */
762 strncpy (registry_id
, "/jack-shm-registry", sizeof (registry_id
));
764 if ((shm_fd
= shm_open (registry_id
, O_RDWR
|O_CREAT
, 0666)) < 0) {
766 jack_error ("Cannot create shm registry segment (%s)",
771 /* Previous shm_open result depends of the actual value of umask, force correct file permission here */
772 if (fchmod(shm_fd
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
) < 0) {
773 jack_log("Cannot chmod jack-shm-registry (%s) %d %d", strerror (errno
));
776 /* Set the desired segment size. NOTE: the non-conformant Mac
777 * OS X POSIX shm only allows ftruncate() on segment creation.
779 if (ftruncate (shm_fd
, JACK_SHM_REGISTRY_SIZE
) < 0) {
781 jack_error ("Cannot set registry size (%s)", strerror (errno
));
782 jack_remove_shm (®istry_id
);
787 if ((ri
->ptr
.attached_at
= mmap (0, JACK_SHM_REGISTRY_SIZE
,
788 PROT_READ
|PROT_WRITE
,
789 MAP_SHARED
, shm_fd
, 0)) == MAP_FAILED
) {
790 jack_error ("Cannot mmap shm registry segment (%s)",
792 jack_remove_shm (®istry_id
);
797 /* set up global pointers */
798 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
799 jack_shm_header
= ri
->ptr
.attached_at
;
800 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
802 /* initialize registry contents */
803 jack_shm_init_registry ();
809 jack_remove_shm (jack_shm_id_t
*id
)
811 /* registry may or may not be locked */
812 shm_unlink ((char *) id
);
816 jack_release_shm (jack_shm_info_t
* si
)
818 /* registry may or may not be locked */
819 if (si
->ptr
.attached_at
!= MAP_FAILED
) {
820 munmap (si
->ptr
.attached_at
, jack_shm_registry
[si
->index
].size
);
825 jack_release_lib_shm (jack_shm_info_t
* si
)
827 /* registry may or may not be locked */
828 if (si
->ptr
.attached_at
!= MAP_FAILED
) {
829 munmap (si
->ptr
.attached_at
, si
->size
);
833 /* allocate a POSIX shared memory segment */
835 jack_shmalloc (const char *shm_name
, jack_shmsize_t size
, jack_shm_info_t
* si
)
837 jack_shm_registry_t
* registry
;
840 char name
[SHM_NAME_MAX
+1];
841 const char* promiscuous
;
843 if (jack_shm_lock_registry () < 0) {
844 jack_error ("jack_shm_lock_registry fails...");
848 if ((registry
= jack_get_free_shm_info ()) == NULL
) {
849 jack_error ("shm registry full");
853 /* On Mac OS X, the maximum length of a shared memory segment
854 * name is SHM_NAME_MAX (instead of NAME_MAX or PATH_MAX as
855 * defined by the standard). Unfortunately, Apple sets this
856 * value so small (about 31 bytes) that it is useless for
857 * actual names. So, we construct a short name from the
858 * registry index for uniqueness and ignore the shm_name
861 snprintf (name
, sizeof (name
), "/jack-%d-%d", GetUID(), registry
->index
);
863 if (strlen (name
) >= sizeof (registry
->id
)) {
864 jack_error ("shm segment name too long %s", name
);
868 if ((shm_fd
= shm_open (name
, O_RDWR
|O_CREAT
, 0666)) < 0) {
869 jack_error ("Cannot create shm segment %s (%s)",
870 name
, strerror (errno
));
874 if (ftruncate (shm_fd
, size
) < 0) {
875 jack_error ("Cannot set size of engine shm "
882 promiscuous
= getenv("JACK_PROMISCUOUS_SERVER");
883 if ((promiscuous
!= NULL
) && (jack_promiscuous_perms(shm_fd
, name
, jack_group2gid(promiscuous
)) < 0))
887 registry
->size
= size
;
888 strncpy (registry
->id
, name
, sizeof (registry
->id
));
889 registry
->allocator
= GetPID();
890 si
->index
= registry
->index
;
891 si
->ptr
.attached_at
= MAP_FAILED
; /* not attached */
892 rc
= 0; /* success */
895 jack_shm_unlock_registry ();
900 jack_attach_shm (jack_shm_info_t
* si
)
903 jack_shm_registry_t
*registry
= &jack_shm_registry
[si
->index
];
905 if ((shm_fd
= shm_open (registry
->id
,
906 O_RDWR
, 0666)) < 0) {
907 jack_error ("Cannot open shm segment %s (%s)", registry
->id
,
912 if ((si
->ptr
.attached_at
= mmap (0, registry
->size
, PROT_READ
|PROT_WRITE
,
913 MAP_SHARED
, shm_fd
, 0)) == MAP_FAILED
) {
914 jack_error ("Cannot mmap shm segment %s (%s)",
926 jack_attach_shm_read (jack_shm_info_t
* si
)
929 jack_shm_registry_t
*registry
= &jack_shm_registry
[si
->index
];
931 if ((shm_fd
= shm_open (registry
->id
,
932 O_RDONLY
, 0666)) < 0) {
933 jack_error ("Cannot open shm segment %s (%s)", registry
->id
,
938 if ((si
->ptr
.attached_at
= mmap (0, registry
->size
, PROT_READ
,
939 MAP_SHARED
, shm_fd
, 0)) == MAP_FAILED
) {
940 jack_error ("Cannot mmap shm segment %s (%s)",
954 jack_access_registry (jack_shm_info_t
*ri
)
956 /* registry must be locked */
958 strncpy (registry_id
, "jack-shm-registry", sizeof (registry_id
));
960 /* try to open an existing segment */
962 if ((shm_fd
= OpenFileMapping(FILE_MAP_ALL_ACCESS
, FALSE
, registry_id
)) == NULL
) {
963 int rc
= GetLastError();
964 if (rc
!= ERROR_FILE_NOT_FOUND
) {
965 jack_error ("Cannot open existing shm registry segment (%ld)", rc
);
970 if ((ri
->ptr
.attached_at
= MapViewOfFile (shm_fd
, FILE_MAP_ALL_ACCESS
, 0, 0, JACK_SHM_REGISTRY_SIZE
)) == NULL
) {
971 jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
972 jack_remove_shm (®istry_id
);
973 CloseHandle (shm_fd
);
977 /* set up global pointers */
978 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
979 jack_shm_header
= ri
->ptr
.attached_at
;
980 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
982 //CloseHandle(shm_fd); // TO CHECK
987 jack_create_registry (jack_shm_info_t
*ri
)
989 /* registry must be locked */
992 strncpy (registry_id
, "jack-shm-registry", sizeof (registry_id
));
994 if ((shm_fd
= CreateFileMapping(INVALID_HANDLE_VALUE
,
996 0, JACK_SHM_REGISTRY_SIZE
,
997 registry_id
)) == NULL
|| (shm_fd
== INVALID_HANDLE_VALUE
)) {
998 int rc
= GetLastError();
999 jack_error ("Cannot create shm registry segment (%ld)", rc
);
1003 if ((ri
->ptr
.attached_at
= MapViewOfFile (shm_fd
, FILE_MAP_ALL_ACCESS
, 0, 0, JACK_SHM_REGISTRY_SIZE
)) == NULL
) {
1004 jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError());
1005 jack_remove_shm (®istry_id
);
1006 CloseHandle (shm_fd
);
1010 /* set up global pointers */
1011 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
1012 jack_shm_header
= ri
->ptr
.attached_at
;
1013 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
1015 /* initialize registry contents */
1016 jack_shm_init_registry ();
1018 //CloseHandle(shm_fd); // TO CHECK
1023 jack_remove_shm (jack_shm_id_t
*id
)
1029 jack_release_shm (jack_shm_info_t
* si
)
1031 /* registry may or may not be locked */
1032 if (si
->ptr
.attached_at
!= NULL
) {
1033 UnmapViewOfFile (si
->ptr
.attached_at
);
1038 jack_release_lib_shm (jack_shm_info_t
* si
)
1040 jack_release_shm(si
);
1044 jack_shmalloc (const char *shm_name
, jack_shmsize_t size
, jack_shm_info_t
* si
)
1046 jack_shm_registry_t
* registry
;
1049 char name
[SHM_NAME_MAX
+1];
1051 if (jack_shm_lock_registry () < 0) {
1052 jack_error ("jack_shm_lock_registry fails...");
1056 if ((registry
= jack_get_free_shm_info ()) == NULL
) {
1057 jack_error ("shm registry full");
1061 snprintf (name
, sizeof (name
), "jack-%d-%d", GetUID(), registry
->index
);
1063 if (strlen (name
) >= sizeof (registry
->id
)) {
1064 jack_error ("shm segment name too long %s", name
);
1068 if ((shm_fd
= CreateFileMapping(INVALID_HANDLE_VALUE
,
1071 name
)) == NULL
|| (shm_fd
== INVALID_HANDLE_VALUE
)) {
1072 int rc
= GetLastError();
1073 jack_error ("Cannot create shm segment (%ld)",rc
);
1077 //CloseHandle (shm_fd); // TO CHECK
1079 registry
->size
= size
;
1080 strncpy (registry
->id
, name
, sizeof (registry
->id
));
1081 registry
->allocator
= _getpid();
1082 si
->index
= registry
->index
;
1083 si
->ptr
.attached_at
= NULL
; /* not attached */
1084 rc
= 0; /* success */
1087 jack_shm_unlock_registry ();
1092 jack_attach_shm (jack_shm_info_t
* si
)
1095 jack_shm_registry_t
*registry
= &jack_shm_registry
[si
->index
];
1097 if ((shm_fd
= OpenFileMapping(FILE_MAP_ALL_ACCESS
, FALSE
, registry
->id
)) == NULL
) {
1098 int rc
= GetLastError();
1099 jack_error ("Cannot open shm segment (%ld)",rc
);
1103 if ((si
->ptr
.attached_at
= MapViewOfFile (shm_fd
, FILE_MAP_ALL_ACCESS
, 0, 0, registry
->size
)) == NULL
) {
1104 jack_error ("Cannot mmap shm segment (%ld)", GetLastError());
1105 jack_remove_shm (®istry_id
);
1106 CloseHandle (shm_fd
);
1110 //CloseHandle (shm_fd); // TO CHECK
1115 jack_attach_shm_read (jack_shm_info_t
* si
)
1118 jack_shm_registry_t
*registry
= &jack_shm_registry
[si
->index
];
1120 if ((shm_fd
= OpenFileMapping(FILE_MAP_ALL_ACCESS
, FALSE
, registry
->id
)) == NULL
) {
1121 int rc
= GetLastError();
1122 jack_error ("Cannot open shm segment (%ld)",rc
);
1126 if ((si
->ptr
.attached_at
= MapViewOfFile (shm_fd
, FILE_MAP_READ
, 0, 0, registry
->size
)) == NULL
) {
1127 jack_error("Cannot mmap shm segment (%ld)", GetLastError());
1128 jack_remove_shm(®istry_id
);
1129 CloseHandle(shm_fd
);
1133 //CloseHandle (shm_fd); // TO CHECK
1139 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1140 * System V interface-dependent functions
1141 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1143 /* gain addressability to existing SHM registry segment
1145 * sets up global registry pointers, if successful
1147 * returns: 0 if existing registry accessed successfully
1148 * ENOENT if registry does not exist
1149 * EINVAL if registry exists, but has the wrong size
1150 * other nonzero error code if unable to access registry
1153 jack_access_registry (jack_shm_info_t
*ri
)
1155 /* registry must be locked */
1157 /* try without IPC_CREAT to get existing segment */
1158 if ((registry_id
= shmget (JACK_SHM_REGISTRY_KEY
,
1159 JACK_SHM_REGISTRY_SIZE
, 0666)) < 0) {
1163 case ENOENT
: /* segment does not exist */
1166 case EINVAL
: /* segment exists, but too small */
1167 /* attempt minimum size access */
1168 registry_id
= shmget (JACK_SHM_REGISTRY_KEY
, 1, 0666);
1171 default: /* or other error */
1172 jack_error ("unable to access shm registry (%s)",
1178 if ((ri
->ptr
.attached_at
= shmat (registry_id
, 0, 0)) < 0) {
1179 jack_error ("Cannot attach shm registry segment (%s)",
1184 /* set up global pointers */
1185 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
1186 jack_shm_header
= ri
->ptr
.attached_at
;
1187 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
1191 /* create a new SHM registry segment
1193 * sets up global registry pointers, if successful
1195 * returns: 0 if registry created successfully
1196 * nonzero error code if unable to allocate a new registry
1199 jack_create_registry (jack_shm_info_t
*ri
)
1201 /* registry must be locked */
1202 if ((registry_id
= shmget (JACK_SHM_REGISTRY_KEY
,
1203 JACK_SHM_REGISTRY_SIZE
,
1204 0666|IPC_CREAT
)) < 0) {
1205 jack_error ("Cannot create shm registry segment (%s)",
1210 if ((ri
->ptr
.attached_at
= shmat (registry_id
, 0, 0)) < 0) {
1211 jack_error ("Cannot attach shm registry segment (%s)",
1216 /* set up global pointers */
1217 ri
->index
= JACK_SHM_REGISTRY_INDEX
;
1218 jack_shm_header
= ri
->ptr
.attached_at
;
1219 jack_shm_registry
= (jack_shm_registry_t
*) (jack_shm_header
+ 1);
1221 /* initialize registry contents */
1222 jack_shm_init_registry ();
1227 jack_remove_shm (jack_shm_id_t
*id
)
1229 /* registry may or may not be locked */
1230 shmctl (*id
, IPC_RMID
, NULL
);
1234 jack_release_shm (jack_shm_info_t
* si
)
1236 /* registry may or may not be locked */
1237 if (si
->ptr
.attached_at
!= MAP_FAILED
) {
1238 shmdt (si
->ptr
.attached_at
);
1243 jack_release_lib_shm (jack_shm_info_t
* si
)
1245 jack_release_shm(si
);
1249 jack_shmalloc (const char* name_not_used
, jack_shmsize_t size
,
1250 jack_shm_info_t
* si
)
1255 jack_shm_registry_t
* registry
;
1257 if (jack_shm_lock_registry () < 0) {
1258 jack_error ("jack_shm_lock_registry fails...");
1262 if ((registry
= jack_get_free_shm_info ())) {
1264 shmflags
= 0666 | IPC_CREAT
| IPC_EXCL
;
1266 if ((shmid
= shmget (IPC_PRIVATE
, size
, shmflags
)) >= 0) {
1268 registry
->size
= size
;
1269 registry
->id
= shmid
;
1270 registry
->allocator
= getpid();
1271 si
->index
= registry
->index
;
1272 si
->ptr
.attached_at
= MAP_FAILED
; /* not attached */
1276 jack_error ("Cannot create shm segment %s (%s)",
1277 name_not_used
, strerror (errno
));
1281 jack_shm_unlock_registry ();
1286 jack_attach_shm (jack_shm_info_t
* si
)
1288 if ((si
->ptr
.attached_at
= shmat (jack_shm_registry
[si
->index
].id
, 0, 0)) < 0) {
1289 jack_error ("Cannot attach shm segment (%s)",
1291 jack_release_shm_info (si
->index
);
1298 jack_attach_shm_read (jack_shm_info_t
* si
)
1300 if ((si
->ptr
.attached_at
= shmat (jack_shm_registry
[si
->index
].id
, 0, SHM_RDONLY
)) < 0) {
1301 jack_error ("Cannot attach shm segment (%s)",
1303 jack_release_shm_info (si
->index
);
1309 #endif /* !USE_POSIX_SHM */