Browse Source

new thread_wait implementation to better match the specs; add JACK_PROMISCUOUS_SERVER handling (any user can connect to jackd, if umask of starting user was correct)

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@1028 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
paul 18 years ago
parent
commit
9121e36367
3 changed files with 81 additions and 103 deletions
  1. +2
    -27
      jack/jack.h
  2. +9
    -1
      jackd/engine.c
  3. +70
    -75
      libjack/client.c

+ 2
- 27
jack/jack.h View File

@@ -180,36 +180,11 @@ void jack_on_shutdown (jack_client_t *client,
int jack_set_process_callback (jack_client_t *client,
JackProcessCallback process_callback,
void *arg);

/**
* Block until this JACK client should process data.
*
* This is an alternative API for clients whose internal
* architecture doesn't suit a callback model. They should
* instead contain a core loop that looks something like
*
* \code
* jack_nframes_t nframes;
*
* // wait for the first time we should do something
*
* nframes = jack_thread_wait (client, 0);
*
* while (TRUE) {
* nframes = jack_thread_wait (client, do_some_processing (nframes));
* }
* \endcode
*
* The function do_some_processing() should return zero if
* the client should keep interacting with JACK, and non-zero
* if it is finished. Note that passing a non-zero status
* will terminate the calling thread. Therefore, this loop should
* run in its own thread which should probably have
* been created with @function jack_client_create_thread().
*
* Clients using this call should probably not call
* @function jack_set_process_callback although it is not
* an error for them to do so.
* The @a status argument typically indicates the result
* of some recent data processing.
*
* @param client - pointer to a JACK client structure
* @param status - if non-zero, calling thread should exit


+ 9
- 1
jackd/engine.c View File

@@ -174,7 +174,15 @@ make_directory (const char *path)
if (stat (path, &statbuf)) {

if (errno == ENOENT) {
if (mkdir (path, 0700) < 0){
int mode;

if (getenv ("JACK_PROMISCUOUS_SERVER")) {
mode = 0777;
} else {
mode = 0700;
}

if (mkdir (path, mode) < 0){
jack_error ("cannot create %s directory (%s)\n",
path, strerror (errno));
return -1;


+ 70
- 75
libjack/client.c View File

@@ -1158,8 +1158,13 @@ jack_user_dir (void)

/* format the path name on the first call */
if (user_dir[0] == '\0') {
snprintf (user_dir, sizeof (user_dir), "%s/jack-%d",
jack_tmpdir, getuid ());
if (getenv ("JACK_PROMISCUOUS_SERVER")) {
snprintf (user_dir, sizeof (user_dir), "%s/jack",
jack_tmpdir);
} else {
snprintf (user_dir, sizeof (user_dir), "%s/jack-%d",
jack_tmpdir, getuid ());
}
}

return user_dir;
@@ -1378,26 +1383,12 @@ jack_client_process_events (jack_client_t* client)

return 0;
}
jack_nframes_t
jack_thread_wait (jack_client_t* client, int status)
{
/* this function waits for either event notifications from the server
(all platforms) or process notifications from the server (with
non-threaded backends like ALSA and OSS). it will process the
event notifications, and return whenever a process notification
arrives.

if passed a non-zero status code, it will terminate the thread
in which it is called.
*/

static int
jack_client_core_wait (jack_client_t* client)
{
jack_client_control_t *control = client->control;

if (status || client->engine->engine_ok == 0) {
return 0;
}

DEBUG ("client polling on %s", client->pollmax == 2 ?
"event_fd and graph_wait_fd..." :
"event_fd only");
@@ -1409,7 +1400,7 @@ jack_thread_wait (jack_client_t* client, int status)
}
jack_error ("poll failed in client (%s)",
strerror (errno));
return 0;
return -1;
}

pthread_testcancel();
@@ -1476,11 +1467,10 @@ jack_thread_wait (jack_client_t* client, int status)

if (client->control->dead || client->pollfd[EVENT_POLL_INDEX].revents & ~POLLIN) {
DEBUG ("client appears dead or event pollfd has error status\n");
return 0;
return -1;
}

DEBUG("thread wait returns %u\n", control->nframes);
return control->nframes;
return 0;
}

static int
@@ -1513,45 +1503,25 @@ jack_wake_next_client (jack_client_t* client)
return 0;
}

static int
jack_client_run_process_callback (jack_client_t* client)
static jack_nframes_t
jack_thread_first_wait (jack_client_t* client)
{
if (jack_client_core_wait (client)) {
return 0;
}
return client->control->nframes;
}
jack_nframes_t
jack_thread_wait (jack_client_t* client, int status)
{
jack_client_control_t *control = client->control;

#ifdef JACK_USE_MACH_THREADS
/* this is done in a dedicated thread on OS X */
return control->nframes;
#endif
/* SECTION ONE: HOUSEKEEPING/CLEANUP FROM LAST DATA PROCESSING */

DEBUG ("client %d signalled at %" PRIu64
", awake for process at %" PRIu64
" (delay = %" PRIu64
" usecs) (wakeup on graph_wait_fd==%d)",
getpid(),
control->signalled_at,
control->awake_at,
control->awake_at - control->signalled_at,
client->pollfd[WAIT_POLL_INDEX].fd);
control->state = Running;
/* begin preemption checking */
CHECK_PREEMPTION (client->engine, TRUE);
if (control->sync_cb)
jack_call_sync_client (client);
if (control->process) {
if (control->process (control->nframes,
control->process_arg)
== 0) {
control->state = Finished;
}
} else {
control->state = Finished;
}
if (control->timebase_cb) {
/* housekeeping/cleanup after data processing */

if (status == 0 && control->timebase_cb) {
jack_call_timebase_master (client);
}
@@ -1560,26 +1530,39 @@ jack_client_run_process_callback (jack_client_t* client)
control->finished_at = jack_get_microseconds();
DEBUG ("client finished processing at %" PRIu64
" (elapsed = %" PRIu64
" usecs), writing on graph_next_fd==%d",
control->finished_at,
control->finished_at - control->awake_at,
client->graph_next_fd);
/* 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) || client->control->dead) {
if (jack_wake_next_client (client)) {
DEBUG("client cannot wake next, or is dead\n");
return -1;
return 0;
}

DEBUG("process cycle fully complete\n");
if (status || client->control->dead || !client->engine->engine_ok) {
return 0;
}
return 0;
/* 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 */

control->state = Running;
/* begin preemption checking */
CHECK_PREEMPTION (client->engine, TRUE);
if (control->sync_cb)
jack_call_sync_client (client);

return control->nframes;
}

static void *
@@ -1594,20 +1577,32 @@ jack_client_thread (void *arg)
pthread_cond_signal (&client_ready);
pthread_mutex_unlock (&client_lock);

client->control->pid = getpid();
client->control->pgrp = getpgrp();
control->pid = getpid();
control->pgrp = getpgrp();

DEBUG ("client thread is now running");

if (client->control->thread_init) {
if (control->thread_init) {
DEBUG ("calling client thread init callback");
client->control->thread_init (client->control->thread_init_arg);
control->thread_init (control->thread_init_arg);
}

/* wait for first wakeup from server */

if (jack_thread_wait (client, 0) == control->nframes) {
while (jack_thread_wait (client, jack_client_run_process_callback (client)) == control->nframes);
if (jack_thread_first_wait (client) == control->nframes) {
/* now run till we're done */
if (control->process) {
/* run process callback, then wait... ad-infinitum */
while (jack_thread_wait (client,
control->process (control->nframes,
control->process_arg)) ==
control->nframes)
;
} else {
/* no process handling but still need to process events */
while (jack_thread_wait (client, 0) == control->nframes)
;
}
}

jack_client_thread_suicide (client);


Loading…
Cancel
Save