From a89837bbfc35338ae3206f55b03b99e496064bfc Mon Sep 17 00:00:00 2001 From: sletz Date: Wed, 12 Mar 2008 14:36:07 +0000 Subject: [PATCH] Version 0.109.8 : new thread model git-svn-id: svn+ssh://jackaudio.org/trunk/jack@1121 0c269be4-1314-0410-8aa9-9f06e86f4224 --- configure.ac | 2 +- jack/internal.h | 2 + jack/jack.h | 8 ++++ jack/types.h | 2 + jackd/clientengine.c | 2 + libjack/client.c | 112 +++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 124 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 6587d84..c9ff3a1 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl changes are made dnl --- JACK_MAJOR_VERSION=0 JACK_MINOR_VERSION=109 -JACK_MICRO_VERSION=7 +JACK_MICRO_VERSION=8 dnl --- dnl HOWTO: updating the jack protocol version diff --git a/jack/internal.h b/jack/internal.h index 7a809f9..3ea9248 100644 --- a/jack/internal.h +++ b/jack/internal.h @@ -259,6 +259,8 @@ typedef volatile struct { void *freewheel_arg; JackClientRegistrationCallback client_register; void *client_register_arg; + JackThreadCallback thread_cb; + void *thread_cb_arg; /* external clients: set by libjack * internal clients: set by engine */ diff --git a/jack/jack.h b/jack/jack.h index f02ca66..f82bbde 100644 --- a/jack/jack.h +++ b/jack/jack.h @@ -192,6 +192,14 @@ int jack_set_process_callback (jack_client_t *client, */ jack_nframes_t jack_thread_wait (jack_client_t*, int status); +// New experimental alternate threading model +jack_nframes_t jack_cycle_wait (jack_client_t* client); + +void jack_cycle_signal (jack_client_t* client, int status); + +int jack_set_process_thread(jack_client_t* client, JackThreadCallback fun, void *arg); + + /** * Tell JACK to call @a thread_init_callback once just after * the creation of the thread in which all other callbacks diff --git a/jack/types.h b/jack/types.h index a4f2886..020a51b 100644 --- a/jack/types.h +++ b/jack/types.h @@ -193,6 +193,8 @@ typedef void (*JackPortConnectCallback)(jack_port_id_t a, jack_port_id_t b, int */ typedef void (*JackFreewheelCallback)(int starting, void *arg); +typedef void *(*JackThreadCallback)(void* arg); + /** * Used for the type argument of jack_port_register() for default * audio and midi ports. diff --git a/jackd/clientengine.c b/jackd/clientengine.c index 03d076f..2d6b172 100644 --- a/jackd/clientengine.c +++ b/jackd/clientengine.c @@ -481,6 +481,8 @@ jack_setup_client_control (jack_engine_t *engine, int fd, client->control->graph_order_arg = NULL; client->control->client_register = NULL; client->control->client_register_arg = NULL; + client->control->thread_cb = NULL; + client->control->thread_cb_arg = NULL; jack_transport_client_new (client); diff --git a/libjack/client.c b/libjack/client.c index 3482213..20d418f 100644 --- a/libjack/client.c +++ b/libjack/client.c @@ -1420,7 +1420,7 @@ static int jack_client_core_wait (jack_client_t* client) { jack_client_control_t *control = client->control; - + DEBUG ("client polling on %s", client->pollmax == 2 ? "event_fd and graph_wait_fd..." : "event_fd only"); @@ -1599,8 +1599,65 @@ jack_thread_wait (jack_client_t* client, int status) return client->control->nframes; } -static void * -jack_client_thread (void *arg) +jack_nframes_t jack_cycle_wait (jack_client_t* client) +{ + /* SECTION TWO: WAIT FOR NEXT DATA PROCESSING TIME */ + + if (jack_client_core_wait (client)) { + return 0; + } + + /* SECTION THREE: START NEXT DATA PROCESSING TIME */ + + /* Time to do data processing */ + + client->control->state = Running; + + /* begin preemption checking */ + CHECK_PREEMPTION (client->engine, TRUE); + + if (client->control->sync_cb) + jack_call_sync_client (client); + + return client->control->nframes; +} + +void jack_cycle_signal(jack_client_t* client, int status) +{ + client->control->last_status = status; + + /* SECTION ONE: HOUSEKEEPING/CLEANUP FROM LAST DATA PROCESSING */ + + /* housekeeping/cleanup after data processing */ + + if (status == 0 && client->control->timebase_cb) { + jack_call_timebase_master (client); + } + + /* end preemption checking */ + CHECK_PREEMPTION (client->engine, FALSE); + + client->control->finished_at = jack_get_microseconds(); + + /* wake the next client in the chain (could be the server), + and check if we were killed during the process + cycle. + */ + + if (jack_wake_next_client (client)) { + DEBUG("client cannot wake next, or is dead\n"); + jack_client_thread_suicide (client); + /*NOTREACHED*/ + } + + if (status || client->control->dead || !client->engine->engine_ok) { + jack_client_thread_suicide (client); + /*NOTREACHED*/ + } +} + +static void +jack_client_thread_aux (void *arg) { jack_client_t *client = (jack_client_t *) arg; jack_client_control_t *control = client->control; @@ -1640,6 +1697,31 @@ jack_client_thread (void *arg) } jack_client_thread_suicide (client); +} + +static void * +jack_client_thread (void *arg) +{ + jack_client_t *client = (jack_client_t *) arg; + jack_client_control_t *control = client->control; + + if (client->control->thread_cb) { + + pthread_mutex_lock (&client_lock); + client->thread_ok = TRUE; + client->thread_id = pthread_self(); + pthread_cond_signal (&client_ready); + pthread_mutex_unlock (&client_lock); + + control->pid = getpid(); + control->pgrp = getpgrp(); + + client->control->thread_cb(client->control->thread_cb_arg); + jack_client_thread_suicide(client); + } else { + jack_client_thread_aux(arg); + } + /*NOTREACHED*/ return (void *) 0; } @@ -2136,6 +2218,12 @@ jack_set_process_callback (jack_client_t *client, jack_error ("You cannot set callbacks on an active client."); return -1; } + + if (client->control->thread_cb) { + jack_error ("A thread callback has already been setup, both models cannot be used at the same time!"); + return -1; + } + client->control->process_arg = arg; client->control->process = callback; return 0; @@ -2219,6 +2307,24 @@ jack_set_client_registration_callback(jack_client_t *client, return 0; } +int +jack_set_process_thread(jack_client_t* client, JackThreadCallback callback, void *arg) +{ + if (client->control->active) { + jack_error ("You cannot set callbacks on an active client."); + return -1; + } + + if (client->control->process) { + jack_error ("A process callback has already been setup, both models cannot be used at the same time!"); + return -1; + } + + client->control->thread_cb_arg = arg; + client->control->thread_cb = callback; + return 0; +} + int jack_get_process_done_fd (jack_client_t *client) {