Browse Source

[0.83.3] resize with SysV shm

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@514 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
joq 22 years ago
parent
commit
1c3df32369
5 changed files with 82 additions and 52 deletions
  1. +1
    -1
      configure.in
  2. +1
    -1
      example-clients/bufsize.c
  3. +10
    -6
      jackd/engine.c
  4. +7
    -0
      libjack/client.c
  5. +63
    -44
      libjack/shm.c

+ 1
- 1
configure.in View File

@@ -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


+ 1
- 1
example-clients/bufsize.c View File

@@ -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);



+ 10
- 6
jackd/engine.c View File

@@ -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");


+ 7
- 0
libjack/client.c View File

@@ -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) {


+ 63
- 44
libjack/shm.c View File

@@ -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 */

Loading…
Cancel
Save