From 5eea78a924c4d85751caa98a54cdd2e714d972a7 Mon Sep 17 00:00:00 2001 From: pbd Date: Fri, 7 Dec 2001 18:54:45 +0000 Subject: [PATCH] used segment:offset addressing git-svn-id: svn+ssh://jackaudio.org/trunk/jack@63 0c269be4-1314-0410-8aa9-9f06e86f4224 --- alsa_driver.c | 6 +-- client.c | 107 ++++++++++++++++++++++++++++++++++-------------- configure.in | 4 +- engine.c | 63 +++++++++------------------- jack/internal.h | 1 - jack/port.h | 30 +++++++++----- 6 files changed, 119 insertions(+), 92 deletions(-) diff --git a/alsa_driver.c b/alsa_driver.c index 80202d7..692247a 100644 --- a/alsa_driver.c +++ b/alsa_driver.c @@ -951,7 +951,7 @@ alsa_driver_process (nframes_t nframes, void *arg) continue; } - alsa_driver_read_from_channel (driver, chn, port->shared->buffer, nframes, 0); + alsa_driver_read_from_channel (driver, chn, jack_port_buffer (port), nframes, 0); } return 0; @@ -1002,7 +1002,6 @@ alsa_driver_attach (alsa_driver_t *driver, jack_engine_t *engine) break; } driver->capture_ports = g_slist_append (driver->capture_ports, port); - printf ("registered %s\n", port->shared->name); } for (chn = 0; chn < driver->playback_nchannels; chn++) { @@ -1015,10 +1014,9 @@ alsa_driver_attach (alsa_driver_t *driver, jack_engine_t *engine) break; } driver->playback_ports = g_slist_append (driver->playback_ports, port); - printf ("registered %s\n", port->shared->name); } - printf ("ports registered, starting client\n"); + printf ("ALSA: ports registered, starting driver\n"); jack_activate (driver->client); } diff --git a/client.c b/client.c index 535058e..7470991 100644 --- a/client.c +++ b/client.c @@ -37,6 +37,8 @@ #include #include +static jack_port_t *jack_port_new (jack_client_t *client, jack_port_id_t port_id, jack_control_t *control); + static pthread_mutex_t client_lock; static pthread_cond_t client_ready; static void *jack_zero_filled_buffer = 0; @@ -106,13 +108,6 @@ jack_client_alloc () return client; } -static jack_port_shared_t * -jack_port_shared_by_id (jack_client_t *client, jack_port_id_t id) - -{ - return &client->engine->ports[id]; -} - static jack_port_t * jack_port_by_id (jack_client_t *client, jack_port_id_t id) @@ -165,7 +160,7 @@ jack_client_invalidate_port_buffers (jack_client_t *client) if (port->shared->flags & JackPortIsInput) { /* XXX release buffer */ - port->shared->buffer = NULL; + port->client_segment_base = NULL; } } } @@ -175,28 +170,31 @@ jack_client_handle_port_connection (jack_client_t *client, jack_event_t *event) { jack_port_t *control_port; - jack_port_shared_t *shared; + jack_port_t *other; GSList *node; switch (event->type) { case PortConnected: - shared = jack_port_shared_by_id (client, event->y.other_id); + other = jack_port_new (client, event->y.other_id, client->engine); control_port = jack_port_by_id (client, event->x.self_id); - control_port->connections = g_slist_prepend (control_port->connections, shared); + control_port->connections = g_slist_prepend (control_port->connections, other); break; case PortDisconnected: - shared = jack_port_shared_by_id (client, event->y.other_id); control_port = jack_port_by_id (client, event->x.self_id); for (node = control_port->connections; node; node = g_slist_next (node)) { - if (((jack_port_shared_t *) node->data) == shared) { + + other = (jack_port_t *) node->data; + + if (other->shared->id == event->y.other_id) { + printf ("%s DIS-connecting and %s\n", control_port->shared->name, other->shared->name); control_port->connections = g_slist_remove_link (control_port->connections, node); g_slist_free_1 (node); + free (other); break; } } - printf ("%s DIS-connected and %s\n", control_port->shared->name, shared->name); break; default: @@ -370,19 +368,19 @@ jack_client_new (const char *client_name) */ if ((port_segment_shm_id = shmget (res.port_segment_key, 0, 0)) < 0) { - jack_error ("cannot determine shared memory segment for port segment key 0x%x", res.port_segment_key); + jack_error ("cannot determine shared memory segment for port segment key 0x%x (%s)", res.port_segment_key, strerror (errno)); goto fail; } - if ((addr = shmat (port_segment_shm_id, res.port_segment_address, 0)) == (void *) -1) { - jack_error ("cannot attached port segment shared memory at 0x%", res.port_segment_address); + if ((addr = shmat (port_segment_shm_id, 0, 0)) == (void *) -1) { + jack_error ("cannot attached port segment shared memory (%s)", strerror (errno)); goto fail; } si = (jack_port_segment_info_t *) malloc (sizeof (jack_port_segment_info_t)); si->shm_key = res.port_segment_key; si->address = addr; - + /* the first chunk of the first port segment is always set by the engine to be a conveniently-sized, zero-filled lump of memory. */ @@ -790,13 +788,14 @@ jack_load_client (const char *client_name, const char *path_to_so) jack_client_t * jack_driver_become_client (const char *client_name) - - { int fd; jack_client_connect_request_t req; jack_client_connect_result_t res; jack_client_t *client = 0; + int port_segment_shm_id; + jack_port_segment_info_t *si; + void *addr; if ((fd = server_connect (0)) < 0) { jack_error ("cannot connect to jack server"); @@ -829,6 +828,34 @@ jack_driver_become_client (const char *client_name) client->control = res.client_control; client->engine = res.engine_control; + /* Lookup, attach and register the port/buffer segments in use + right now. + */ + + if ((port_segment_shm_id = shmget (res.port_segment_key, 0, 0)) < 0) { + jack_error ("cannot determine shared memory segment for port segment key 0x%x (%s)", res.port_segment_key, strerror (errno)); + return NULL; + } + + if ((addr = shmat (port_segment_shm_id, 0, 0)) == (void *) -1) { + jack_error ("cannot attached port segment shared memory (%s)", strerror (errno)); + return NULL; + } + + si = (jack_port_segment_info_t *) malloc (sizeof (jack_port_segment_info_t)); + si->shm_key = res.port_segment_key; + si->address = addr; + + /* the first chunk of the first port segment is always set by the engine + to be a conveniently-sized, zero-filled lump of memory. + */ + + if (client->port_segments == NULL) { + jack_zero_filled_buffer = si->address; + } + + client->port_segments = g_slist_prepend (client->port_segments, si); + /* allow the engine to act on the client's behalf when dealing with in-process clients. */ @@ -851,20 +878,41 @@ unsigned long jack_get_sample_rate (jack_client_t *client) } static jack_port_t * -jack_port_new (jack_port_id_t port_id, jack_control_t *control) +jack_port_new (jack_client_t *client, jack_port_id_t port_id, jack_control_t *control) { jack_port_t *port; jack_port_shared_t *shared; + jack_port_segment_info_t *si; + GSList *node; shared = &control->ports[port_id]; port = (jack_port_t *) malloc (sizeof (jack_port_t)); + port->client_segment_base = NULL; port->shared = shared; port->connections = 0; port->tied = NULL; + si = NULL; + + for (node = client->port_segments; node; node = g_slist_next (node)) { + + si = (jack_port_segment_info_t *) node->data; + + if (si->shm_key == port->shared->shm_key) { + break; + } + } + + if (si == NULL) { + jack_error ("cannot find port segment to match newly registered port\n"); + return NULL; + } + + port->client_segment_base = si->address; + return port; } @@ -913,7 +961,8 @@ jack_port_register (jack_client_t *client, return NULL; } - port = jack_port_new (req.x.port_info.port_id, client->engine); + port = jack_port_new (client, req.x.port_info.port_id, client->engine); + client->ports = g_slist_prepend (client->ports, port); return port; @@ -1043,7 +1092,7 @@ jack_port_get_buffer (jack_port_t *port, nframes_t nframes) if (port->tied) { return jack_port_get_buffer (port->tied, nframes); } - return port->shared->buffer; + return jack_port_buffer (port); } /* Input port. @@ -1062,7 +1111,7 @@ jack_port_get_buffer (jack_port_t *port, nframes_t nframes) the buffer of the connected (output) port. */ - return ((jack_port_shared_t *) node->data)->buffer; + return jack_port_buffer (((jack_port_t *) node->data)); } /* multiple connections. use a local buffer and mixdown @@ -1071,14 +1120,14 @@ jack_port_get_buffer (jack_port_t *port, nframes_t nframes) during the connection process. */ - if (port->shared->buffer == NULL) { - port->shared->buffer = jack_pool_alloc - (port->shared->type_info.buffer_scale_factor * sizeof (sample_t) * nframes); + if (port->client_segment_base == NULL) { + port->client_segment_base = 0; + port->shared->offset = (size_t) jack_pool_alloc (port->shared->type_info.buffer_scale_factor * sizeof (sample_t) * nframes); } port->shared->type_info.mixdown (port, nframes); - return port->shared->buffer; + return jack_port_buffer (port); } int @@ -1095,7 +1144,6 @@ jack_port_tie (jack_port_t *dst, jack_port_t *src) return -1; } - dst->own_buffer = dst->shared->buffer; dst->tied = src; return 0; } @@ -1108,7 +1156,6 @@ jack_port_untie (jack_port_t *port) jack_error ("port \"%s\" is not tied", port->shared->name); return -1; } - port->shared->buffer = port->own_buffer; port->tied = NULL; return 0; } diff --git a/configure.in b/configure.in index fbb7484..7fd0a09 100644 --- a/configure.in +++ b/configure.in @@ -4,8 +4,8 @@ AC_INIT(client.c) AC_CONFIG_AUX_DIR(.) JACK_MAJOR_VERSION=0 -JACK_MINOR_VERSION=3 -JACK_MICRO_VERSION=5 +JACK_MINOR_VERSION=4 +JACK_MICRO_VERSION=0 BETA= diff --git a/engine.c b/engine.c index 6c511d2..857c836 100644 --- a/engine.c +++ b/engine.c @@ -95,34 +95,6 @@ static int jack_deliver_event (jack_engine_t *, jack_client_internal_t *, jack_ static void jack_audio_port_mixdown (jack_port_t *port, nframes_t nframes); -/* This is a disgusting kludge to work around issues with shmat. - A more robust solution is needed. -*/ - -static char *top_end_of_unmapped_memory = (char *) (1048576 * 1536); /* 1.5GB */ -static char *low_end_of_unmapped_memory = (char *) (1048576 * 1024); /* 1GB */ - -static char * -fixed_shmat (int shmid, char *shmaddr, int shmflg, size_t size) -{ - char *addr; - char *attempt; - - if (shmaddr != 0) { - return shmat (shmid, shmaddr, shmflg); - } - - attempt = (char *) (top_end_of_unmapped_memory - size); - - while (attempt > low_end_of_unmapped_memory) { - if ((addr = (char *) shmat (shmid, attempt, shmflg|SHM_RND)) != (char *) -1) { - top_end_of_unmapped_memory = addr; - return addr; - } - attempt -= size; - } - return (char *) -1; -} jack_port_type_info_t builtin_port_types[] = { { JACK_DEFAULT_AUDIO_TYPE, jack_audio_port_mixdown, 1 }, @@ -290,7 +262,7 @@ jack_add_port_segment (jack_engine_t *engine, unsigned long nports) return -1; } - if ((addr = fixed_shmat (id, 0, 0, size)) == (char *) -1) { + if ((addr = shmat (id, 0, 0)) == (char *) -1) { jack_error ("cannot attach new port segment (%s)", strerror (errno)); shmctl (id, IPC_RMID, 0); return -1; @@ -557,7 +529,6 @@ handle_new_client (jack_engine_t *engine, int client_fd) res.client_key = client->shm_key; res.control_key = engine->control_key; res.port_segment_key = engine->port_segment_key; - res.port_segment_address = engine->port_segment_address; res.realtime = engine->control->real_time; res.realtime_priority = engine->rtpriority - 1; @@ -1103,7 +1074,7 @@ jack_engine_new (int realtime, int rtpriority) return 0; } - if ((addr = fixed_shmat (engine->control_shm_id, 0, 0, control_size)) == (void *) -1) { + if ((addr = shmat (engine->control_shm_id, 0, 0)) == (void *) -1) { jack_error ("cannot attach control shared memory segment (%s)", strerror (errno)); shmctl (engine->control_shm_id, IPC_RMID, 0); return 0; @@ -1288,7 +1259,7 @@ jack_client_internal_new (jack_engine_t *engine, int fd, jack_client_connect_req return 0; } - if ((addr = fixed_shmat (shm_id, 0, 0, sizeof (jack_client_control_t))) == (void *) -1) { + if ((addr = shmat (shm_id, 0, 0)) == (void *) -1) { jack_error ("cannot attach new client control block"); shmctl (shm_id, IPC_RMID, 0); return 0; @@ -2207,7 +2178,7 @@ jack_port_assign_buffer (jack_engine_t *engine, jack_port_internal_t *port) jack_port_segment_info_t *psi; jack_port_buffer_info_t *bi; - port->shared->buffer = NULL; + port->shared->shm_key = -1; if (port->shared->flags & JackPortIsInput) { return 0; @@ -2227,12 +2198,13 @@ jack_port_assign_buffer (jack_engine_t *engine, jack_port_internal_t *port) psi = (jack_port_segment_info_t *) node->data; if (bi->shm_key == psi->shm_key) { - port->shared->buffer = psi->address + bi->offset; + port->shared->shm_key = psi->shm_key; + port->shared->offset = bi->offset; break; } } - if (port->shared->buffer) { + if (port->shared->shm_key >= 0) { engine->port_buffer_freelist = g_slist_remove (engine->port_buffer_freelist, bi); } else { jack_error ("port segment info for 0x%x:%d not found!", bi->shm_key, bi->offset); @@ -2241,7 +2213,7 @@ jack_port_assign_buffer (jack_engine_t *engine, jack_port_internal_t *port) out: pthread_mutex_unlock (&engine->buffer_lock); - if (port->shared->buffer == NULL) { + if (port->shared->shm_key < 0) { return -1; } else { return 0; @@ -2297,8 +2269,9 @@ static void jack_audio_port_mixdown (jack_port_t *port, nframes_t nframes) { GSList *node; - jack_port_shared_t *input; + jack_port_t *input; nframes_t n; + sample_t *buffer; sample_t *dst, *src; /* by the time we've called this, we've already established @@ -2306,19 +2279,21 @@ jack_audio_port_mixdown (jack_port_t *port, nframes_t nframes) */ node = port->connections; - input = (jack_port_shared_t *) node->data; + input = (jack_port_t *) node->data; + buffer = jack_port_buffer (port); - memcpy (port->shared->buffer, input->buffer, sizeof (sample_t) * nframes); + memcpy (buffer, jack_port_buffer (input), sizeof (sample_t) * nframes); for (node = g_slist_next (node); node; node = g_slist_next (node)) { - input = (jack_port_shared_t *) node->data; + + input = (jack_port_t *) node->data; + n = nframes; - dst = port->shared->buffer; - src = input->buffer; + dst = buffer; + src = jack_port_buffer (input); + while (n--) { *dst++ += *src++; } } } - - diff --git a/jack/internal.h b/jack/internal.h index fb09da0..e404d3d 100644 --- a/jack/internal.h +++ b/jack/internal.h @@ -158,7 +158,6 @@ typedef struct { /* XXX need to be able to use more than one port segment key */ key_t port_segment_key; - void *port_segment_address; } jack_client_connect_result_t; diff --git a/jack/port.h b/jack/port.h index fea9aa2..25984a3 100644 --- a/jack/port.h +++ b/jack/port.h @@ -52,16 +52,18 @@ typedef struct _jack_port_type_info { */ typedef struct _jack_port_shared { - void *buffer; - unsigned long flags; - unsigned long buffer_size; - jack_port_id_t id; - char name[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE+2]; - jack_port_type_info_t type_info; - jack_client_id_t client_id; - - char in_use : 1; - char locked : 1; + int shm_key; + size_t offset; + + unsigned long flags; + unsigned long buffer_size; + jack_port_id_t id; + char name[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE+2]; + jack_port_type_info_t type_info; + jack_client_id_t client_id; + + char in_use : 1; + char locked : 1; } jack_port_shared_t; /* This is the data structure allocated by the client @@ -70,12 +72,18 @@ typedef struct _jack_port_shared { */ struct _jack_port { + char *client_segment_base; struct _jack_port_shared *shared; GSList *connections; struct _jack_port *tied; - void *own_buffer; }; +/* inline would be cleaner, but it needs to be fast even in non-optimized + code. +*/ + +#define jack_port_buffer(p) ((void *) ((p)->client_segment_base + (p)->shared->offset)) + /* this is the structure allocated by the engine in local memory. */