diff options
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | example-clients/bufsize.c | 2 | ||||
-rw-r--r-- | jackd/engine.c | 16 | ||||
-rw-r--r-- | libjack/client.c | 7 | ||||
-rw-r--r-- | libjack/shm.c | 107 |
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 */ |