summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in2
-rw-r--r--example-clients/bufsize.c2
-rw-r--r--jackd/engine.c16
-rw-r--r--libjack/client.c7
-rw-r--r--libjack/shm.c107
5 files changed, 82 insertions, 52 deletions
diff --git a/configure.in b/configure.in
index c440f53..93b9ec6 100644
--- a/configure.in
+++ b/configure.in
@@ -14,7 +14,7 @@ dnl changes are made
dnl ---
JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=83
-JACK_MICRO_VERSION=2
+JACK_MICRO_VERSION=3
dnl ---
dnl HOWTO: updating the jack protocal version
diff --git a/example-clients/bufsize.c b/example-clients/bufsize.c
index 39e6718..a190a93 100644
--- a/example-clients/bufsize.c
+++ b/example-clients/bufsize.c
@@ -88,7 +88,7 @@ int main(int argc, char *argv[])
rc = jack_set_buffer_size(client, nframes);
if (rc)
- fprintf(stderr, "jack_set_buffer_size() returns %d\n", rc);
+ fprintf(stderr, "jack_set_buffer_size(): %s\n", strerror(rc));
jack_client_close(client);
diff --git a/jackd/engine.c b/jackd/engine.c
index 21954c2..29d7dc2 100644
--- a/jackd/engine.c
+++ b/jackd/engine.c
@@ -298,6 +298,7 @@ jack_cleanup_files ()
closedir (dir);
}
+// JOQ: this should have a return code...
static void
jack_resize_port_segment (jack_engine_t *engine,
jack_port_type_info_t *port_type,
@@ -370,8 +371,8 @@ jack_resize_port_segment (jack_engine_t *engine,
pthread_mutex_unlock (&pti->buffer_lock);
} else {
- /* resize existing buffer segment */
+ /* resize existing buffer segment */
if ((addr = jack_resize_shm (port_type->shm_info.shm_name,
size, perm, 0666,
PROT_READ|PROT_WRITE))
@@ -410,6 +411,14 @@ jack_resize_port_segment (jack_engine_t *engine,
port_type->shm_info.size = size;
engine->port_type[ptid].seg_addr = addr;
+ if (engine->control->real_time) {
+ int rc = mlock (addr, size);
+ if (rc < 0) {
+ jack_error("JACK: unable to mlock() port buffers: "
+ "%s", strerror(errno));
+ }
+ }
+
/* Tell everybody about this segment. */
event.type = AttachPortSegment;
strcpy (event.x.shm_name, port_type->shm_info.shm_name);
@@ -494,7 +503,6 @@ jack_set_buffer_size_request (jack_engine_t *engine, jack_nframes_t nframes)
return EIO;
}
-#if USE_POSIX_SHM
rc = driver->bufsize(driver, nframes);
if (rc == 0)
engine->rolling_interval =
@@ -502,10 +510,6 @@ jack_set_buffer_size_request (jack_engine_t *engine, jack_nframes_t nframes)
else
jack_error("driver does not support %" PRIu32
"-frame buffers", nframes);
-#else
- /* jack_resize_shm() not implemented for SysV shm */
- rc = ENOSYS; /* function not implemented */
-#endif
if (driver->start (driver)) {
jack_error ("cannot restart driver after setting buffer size");
diff --git a/libjack/client.c b/libjack/client.c
index e719a95..bb03481 100644
--- a/libjack/client.c
+++ b/libjack/client.c
@@ -473,6 +473,13 @@ jack_attach_port_segment (jack_client_t *client, shm_name_t shm_name,
abort();
}
+ /* release any previous segment */
+ if (client->port_segment[ptid].size) {
+ jack_release_shm (client->port_segment[ptid].address,
+ client->port_segment[ptid].size);
+ client->port_segment[ptid].size = 0;
+ }
+
if ((addr = jack_get_shm (shm_name, size, O_RDWR, 0,
(PROT_READ|PROT_WRITE),
&shmid)) == MAP_FAILED) {
diff --git a/libjack/shm.c b/libjack/shm.c
index 4a8541a..499caba 100644
--- a/libjack/shm.c
+++ b/libjack/shm.c
@@ -37,11 +37,8 @@
typedef struct {
shm_name_t name;
-#ifdef USE_POSIX_SHM
char *address;
-#else
- int shmid;
-#endif
+ int shmid; /* only needed for SysV shm */
} jack_shm_registry_entry_t;
static jack_shm_registry_entry_t *jack_shm_registry;
@@ -51,16 +48,29 @@ void
jack_register_shm (char *shm_name, char *addr, int id)
{
if (jack_shm_id_cnt < MAX_SHM_ID) {
- snprintf (jack_shm_registry[jack_shm_id_cnt++].name,
- sizeof (shm_name_t), "%s", shm_name);
-#ifdef USE_POSIX_SHM
- jack_shm_registry[jack_shm_id_cnt].address = addr;
-#else
- jack_shm_registry[jack_shm_id_cnt].shmid = id;
-#endif
+ int entry = jack_shm_id_cnt++;
+ strncpy (jack_shm_registry[entry].name, shm_name,
+ sizeof (shm_name_t));
+ jack_shm_registry[entry].address = addr;
+ jack_shm_registry[entry].shmid = id;
}
}
+static inline int
+jack_lookup_shm (const char *shm_name)
+{
+ /***** NOT THREAD SAFE *****/
+
+ int i;
+
+ for (i = 0; i < jack_shm_id_cnt; ++i) {
+ if (strcmp (jack_shm_registry[i].name, shm_name) == 0) {
+ return i;
+ }
+ }
+ return -1; /* not found */
+}
+
int
jack_initialize_shm ()
{
@@ -209,26 +219,17 @@ char *
jack_resize_shm (const char *shm_name, size_t size, int perm, int mode,
int prot)
{
- int i;
+ int entry;
int shm_fd;
char *addr;
struct stat statbuf;
- for (i = 0; i < jack_shm_id_cnt; ++i) {
- if (strcmp (jack_shm_registry[i].name, shm_name) == 0) {
- break;
- }
- }
-
- if (i == jack_shm_id_cnt) {
+ if ((entry = jack_lookup_shm (shm_name)) < 0) {
jack_error ("attempt to resize unknown shm segment \"%s\"",
shm_name);
return MAP_FAILED;
}
- // JOQ: this does not work reliably for me. After a few
- // resize operations, the open starts failing. Maybe my
- // system is running out of some tmpfs resource?
if ((shm_fd = shm_open (shm_name, perm, mode)) < 0) {
jack_error ("cannot create shm segment %s (%s)", shm_name,
strerror (errno));
@@ -237,7 +238,7 @@ jack_resize_shm (const char *shm_name, size_t size, int perm, int mode,
fstat (shm_fd, &statbuf);
- munmap (jack_shm_registry[i].address, statbuf.st_size);
+ munmap (jack_shm_registry[entry].address, statbuf.st_size);
if (perm & O_CREAT) {
if (ftruncate (shm_fd, size) < 0) {
@@ -262,29 +263,30 @@ jack_resize_shm (const char *shm_name, size_t size, int perm, int mode,
#else /* USE_POSIX_SHM */
-int
-jack_get_shmid (const char *name)
+char
+jack_hash_shm (jack_shmsize_t size)
{
- int i;
+ char log2size = 0; /* log2 of size */
- /* **** NOT THREAD SAFE *****/
+ if (size == 0)
+ return log2size; /* don't loop forever */
- for (i = 0; i < jack_shm_id_cnt; ++i) {
- if (strcmp (jack_shm_registry[i].name, name) == 0) {
- return jack_shm_registry[i].shmid;
- }
+ /* remove low-order zeroes, counting them */
+ while ((size & 1) == 0) {
+ ++log2size;
+ size >>= 1;
}
- return -1;
+
+ return (char) ((size + log2size) & 0x7f);
}
void
jack_destroy_shm (const char *shm_name)
{
- int shmid = jack_get_shmid (shm_name);
+ int i = jack_lookup_shm (shm_name);
- if (shmid >= 0) {
- shmctl (IPC_RMID, shmid, NULL);
- }
+ if (i >= 0)
+ shmctl (IPC_RMID, jack_shm_registry[i].shmid, NULL);
}
void
@@ -305,10 +307,7 @@ jack_get_shm (const char *shm_name, size_t size, int perm, int mode,
int status;
/* note: no trailing '/' on basic path because we expect shm_name to
- begin with one (as per POSIX shm API).
- */
-
-
+ begin with one (as per POSIX shm API). */
snprintf (path, sizeof(path), "%s/jack", jack_server_dir);
if (mkdir (path, 0775)) {
if (errno != EEXIST) {
@@ -340,7 +339,11 @@ jack_get_shm (const char *shm_name, size_t size, int perm, int mode,
close (fd);
}
- if ((key = ftok (path, 'j')) < 0) {
+ /* Hash the shm size to distinguish differently-sized segments
+ * with the same path name. This allows jack_resize_shm() to
+ * allocate a new segment when the size changes with the same
+ * name but a different shmid. */
+ if ((key = ftok (path, jack_hash_shm(size))) < 0) {
jack_error ("cannot generate IPC key for shm segment %s (%s)",
path, strerror (errno));
unlink (path);
@@ -397,9 +400,25 @@ char *
jack_resize_shm (const char *shm_name, size_t size, int perm, int mode,
int prot)
{
- jack_error ("jack_resize_shm() is not implemented for the System V "
- "shared memory API");
- return 0;
+ int entry = jack_lookup_shm (shm_name);
+
+ if (entry < 0) {
+ jack_error ("attempt to resize unknown shm segment \"%s\"",
+ shm_name);
+ return MAP_FAILED;
+ }
+
+ /* There is no way to resize a System V shm segment. So, we
+ * delete it and allocate a new one. This is tricky, because
+ * the old segment will not disappear until all the clients
+ * have released it. */
+ jack_destroy_shm (shm_name);
+ jack_release_shm (jack_shm_registry[entry].address, size);
+ jack_shm_registry[entry].address =
+ jack_get_shm (shm_name, size, perm, mode, prot,
+ &jack_shm_registry[entry].shmid);
+
+ return jack_shm_registry[entry].address;
}
#endif /* USE_POSIX_SHM */