summaryrefslogtreecommitdiff
path: root/libjack/shm.c
diff options
context:
space:
mode:
authorjoq <joq@0c269be4-1314-0410-8aa9-9f06e86f4224>2004-12-25 18:39:44 +0000
committerjoq <joq@0c269be4-1314-0410-8aa9-9f06e86f4224>2004-12-25 18:39:44 +0000
commit5246f2a1045a452bbd9881fea01b7ccfbf6994de (patch)
tree9de9db4e74d1453c4a27c8aee189b38e0d0c6033 /libjack/shm.c
parentacf0bcecc170b5be057d0eddca1975807e7945c6 (diff)
downloadjack1-5246f2a1045a452bbd9881fea01b7ccfbf6994de.tar.gz
[0.99.39] multiserver POSIX shm fixes
git-svn-id: svn+ssh://jackaudio.org/trunk/jack@852 0c269be4-1314-0410-8aa9-9f06e86f4224
Diffstat (limited to 'libjack/shm.c')
-rw-r--r--libjack/shm.c103
1 files changed, 78 insertions, 25 deletions
diff --git a/libjack/shm.c b/libjack/shm.c
index 6f7a611..a2e6c54 100644
--- a/libjack/shm.c
+++ b/libjack/shm.c
@@ -74,16 +74,17 @@ static void jack_remove_shm (jack_shm_id_t *id);
* cleanup is also done when a new instance of that server starts.
*/
-/* global data for the SHM interfaces */
-static jack_shm_id_t registry_id; /* SHM id for the registry */
+/* per-process global data for the SHM interfaces */
+static jack_shm_id_t registry_id; /* SHM id for the registry */
static jack_shm_info_t registry_info = { /* SHM info for the registry */
.index = JACK_SHM_NULL_INDEX,
.attached_at = MAP_FAILED
};
/* pointers to registry header and array */
-static jack_shm_header_t* jack_shm_header = NULL;
-static jack_shm_registry_t* jack_shm_registry = NULL;
+static jack_shm_header_t *jack_shm_header = NULL;
+static jack_shm_registry_t *jack_shm_registry = NULL;
+static char jack_shm_server_prefix[JACK_SERVER_NAME_SIZE] = "";
/* jack_shm_lock_registry() serializes updates to the shared memory
* segment JACK uses to keep track of the SHM segements allocated to
@@ -215,6 +216,29 @@ jack_shm_validate_registry ()
return -1;
}
+/* set a unique per-user, per-server shm prefix string
+ *
+ * According to the POSIX standard:
+ *
+ * "The name argument conforms to the construction rules for a
+ * pathname. If name begins with the slash character, then processes
+ * calling shm_open() with the same value of name refer to the same
+ * shared memory object, as long as that name has not been
+ * removed. If name does not begin with the slash character, the
+ * effect is implementation-defined. The interpretation of slash
+ * characters other than the leading slash character in name is
+ * implementation-defined."
+ *
+ * Since the Linux implementation does not allow slashes *within* the
+ * name, in the interest of portability we use colons instead.
+ */
+static void
+jack_set_server_prefix (const char *server_name)
+{
+ snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix),
+ "/jack-%d:%s:", getuid (), server_name);
+}
+
/* gain server addressability to shared memory registration segment
*
* returns: 0 if successful
@@ -269,13 +293,15 @@ jack_server_initialize_shm (void)
* returns: 0 if successful
*/
int
-jack_initialize_shm (void)
+jack_initialize_shm (const char *server_name)
{
int rc;
if (jack_shm_header)
return 0; /* already initialized */
+ jack_set_server_prefix (server_name);
+
jack_shm_lock_registry ();
if ((rc = jack_access_registry (&registry_info)) == 0) {
if ((rc = jack_shm_validate_registry ()) != 0) {
@@ -319,14 +345,23 @@ jack_get_free_shm_info ()
return si;
}
+static inline void
+jack_release_shm_entry (jack_shm_registry_index_t index)
+{
+ /* the registry must be locked */
+ jack_shm_registry[index].size = 0;
+ jack_shm_registry[index].allocator = 0;
+ memset (&jack_shm_registry[index].id, 0,
+ sizeof (jack_shm_registry[index].id));
+}
+
void
jack_release_shm_info (jack_shm_registry_index_t index)
{
/* must NOT have the registry locked */
if (jack_shm_registry[index].allocator == getpid()) {
jack_shm_lock_registry ();
- jack_shm_registry[index].size = 0;
- jack_shm_registry[index].allocator = 0;
+ jack_release_shm_entry (index);
jack_shm_unlock_registry ();
}
}
@@ -343,7 +378,8 @@ jack_register_server (const char *server_name)
{
int i;
pid_t my_pid = getpid ();
- char *server_directory = jack_server_dir (server_name);
+
+ jack_set_server_prefix (server_name);
fprintf (stderr, "JACK compiled with %s SHM support.\n", JACK_SHM_TYPE);
@@ -353,12 +389,12 @@ jack_register_server (const char *server_name)
jack_shm_lock_registry ();
/* See if server_name already registered. Since server names
- * are per-user, we register the server directory path name,
- * which must be unique. */
+ * are per-user, we register the unique server prefix string.
+ */
for (i = 0; i < MAX_SERVERS; i++) {
if (strncmp (jack_shm_header->server[i].name,
- server_directory,
+ jack_shm_server_prefix,
JACK_SERVER_NAME_SIZE) != 0)
continue; /* no match */
@@ -387,7 +423,7 @@ jack_register_server (const char *server_name)
/* claim it */
jack_shm_header->server[i].pid = my_pid;
strncpy (jack_shm_header->server[i].name,
- server_directory,
+ jack_shm_server_prefix,
JACK_SERVER_NAME_SIZE);
jack_shm_unlock_registry ();
@@ -406,9 +442,8 @@ jack_unregister_server (const char *server_name /* unused */)
for (i = 0; i < MAX_SERVERS; i++) {
if (jack_shm_header->server[i].pid == my_pid) {
- jack_shm_header->server[i].pid = 0;
- memset (jack_shm_header->server[i].name, 0,
- JACK_SERVER_NAME_SIZE);
+ memset (&jack_shm_header->server[i], 0,
+ sizeof (jack_shm_server_t));
}
}
@@ -430,7 +465,7 @@ jack_cleanup_shm ()
jack_shm_registry_t* r;
r = &jack_shm_registry[i];
- copy.index = r->index;
+ memcpy (&copy, r, sizeof (jack_shm_info_t));
destroy = FALSE;
/* ignore unused entries */
@@ -456,15 +491,14 @@ jack_cleanup_shm ()
}
}
}
-
+
if (destroy) {
int index = copy.index;
if ((index >= 0) && (index < MAX_SHM_ID)) {
jack_remove_shm (&jack_shm_registry[index].id);
- jack_shm_registry[index].size = 0;
- jack_shm_registry[index].allocator = 0;
+ jack_release_shm_entry (index);
}
r->size = 0;
r->allocator = 0;
@@ -618,38 +652,55 @@ jack_create_registry (jack_shm_info_t *ri)
static void
jack_remove_shm (jack_shm_id_t *id)
{
- shm_unlink (*id);
+ /* registry may or may not be locked */
+ shm_unlink ((char *) id);
}
void
jack_release_shm (jack_shm_info_t* si)
{
- //printf("client->jack_release_shm \n");
+ /* registry may or may not be locked */
if (si->attached_at != MAP_FAILED) {
- //printf("client->jack_release_shm 1 \n");
munmap (si->attached_at, jack_shm_registry[si->index].size);
}
}
+/* allocate a POSIX shared memory segment
+ *
+ * The shm_name should not have a leading slash, that will be provided
+ * here along with a prefix making it unique to this server.
+ */
int
jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
{
jack_shm_registry_t* registry;
int shm_fd;
int rc = -1;
+ char name[NAME_MAX+1];
+
+ /* concatenate jack_shm_server_prefix and shm_name to build a
+ * unique name per user and per server */
+ snprintf (name, sizeof (name), "%s%s",
+ jack_shm_server_prefix, shm_name);
+
+ if (strlen (name) >= sizeof (jack_shm_id_t)) {
+ jack_error ("shm segment name too long %s", name);
+ return -1;
+ }
jack_shm_lock_registry ();
if ((registry = jack_get_free_shm_info ())) {
- if ((shm_fd = shm_open (shm_name, O_RDWR|O_CREAT, 0666)) >= 0) {
+ if ((shm_fd = shm_open (name, O_RDWR|O_CREAT, 0666)) >= 0) {
if (ftruncate (shm_fd, size) >= 0) {
close (shm_fd);
registry->size = size;
+ //JOQ: better to use strncpy() here...
snprintf (registry->id, sizeof (registry->id),
- "%s", shm_name);
+ "%s", name);
registry->allocator = getpid();
si->index = registry->index;
si->attached_at = MAP_FAILED; /* not attached */
@@ -663,7 +714,7 @@ jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
} else {
jack_error ("cannot create shm segment %s (%s)",
- shm_name, strerror (errno));
+ name, strerror (errno));
}
}
@@ -792,12 +843,14 @@ jack_create_registry (jack_shm_info_t *ri)
static void
jack_remove_shm (jack_shm_id_t *id)
{
+ /* registry may or may not be locked */
shmctl (*id, IPC_RMID, NULL);
}
void
jack_release_shm (jack_shm_info_t* si)
{
+ /* registry may or may not be locked */
if (si->attached_at != MAP_FAILED) {
shmdt (si->attached_at);
}