aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2019-07-31 23:18:40 +0200
committerHanspeter Portner <dev@open-music-kontrollers.ch>2019-07-31 23:25:51 +0200
commit1fb6c85cdcd3fdd35198f85218a479bbe508c650 (patch)
tree78a4cb8fffc7087be20e24a6515b9b91b6536cf0
parent2256b8b61ef993679359b77bdcbe6de46f52f1cd (diff)
downloadsynthpod-1fb6c85cdcd3fdd35198f85218a479bbe508c650.tar.xz
app: spin up all cores after an Xrun.
-rw-r--r--VERSION2
-rw-r--r--app/synthpod_app.c133
-rw-r--r--app/synthpod_app_private.h2
-rw-r--r--bin/pcmi.cpp16
-rw-r--r--bin/pcmi.h6
-rw-r--r--bin/synthpod_alsa.c19
-rw-r--r--bin/synthpod_jack.c4
-rw-r--r--include/synthpod_app.h3
8 files changed, 141 insertions, 44 deletions
diff --git a/VERSION b/VERSION
index f064214c..7bccbd17 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.6069
+0.1.6073
diff --git a/app/synthpod_app.c b/app/synthpod_app.c
index 07c0ce75..2301d790 100644
--- a/app/synthpod_app.c
+++ b/app/synthpod_app.c
@@ -26,6 +26,8 @@
typedef cpuset_t cpu_set_t;
#endif
+#define REWEIGHT_S 4
+
// non-rt
void
sp_app_activate(sp_app_t *app)
@@ -714,7 +716,6 @@ _dsp_master_wait(sp_app_t *app, dsp_master_t *dsp_master, unsigned num)
{
case ETIMEDOUT:
{
- fprintf(stderr, "%s: taking emergency exit\n", __func__);
atomic_store(&dsp_master->emergency_exit, true);
} continue;
case EINTR:
@@ -881,9 +882,10 @@ sp_app_new(const LilvWorld *world, sp_app_driver_t *driver, void *data)
dsp_master_t *dsp_master = &app->dsp_master;
atomic_init(&dsp_master->kill, false);
atomic_init(&dsp_master->emergency_exit, false);
+ atomic_init(&dsp_master->xrun_report, false);
sem_init(&dsp_master->sem, 0, 0);
dsp_master->num_slaves = driver->num_slaves;
- dsp_master->concurrent = dsp_master->num_slaves; // this is a safe fallback
+ dsp_master->concurrent = dsp_master->num_slaves + 1; // this is a safe fallback
for(unsigned i=0; i<dsp_master->num_slaves; i++)
{
dsp_slave_t *dsp_slave = &dsp_master->dsp_slaves[i];
@@ -895,6 +897,8 @@ sp_app_new(const LilvWorld *world, sp_app_driver_t *driver, void *data)
pthread_create(&dsp_slave->thread, &attr, _dsp_slave_thread, dsp_slave);
}
+ app->skip_reweighting = REWEIGHT_S; // this is a safe fallback
+
lv2_osc_urid_init(&app->osc_urid, driver->map);
return app;
@@ -991,14 +995,12 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples)
dsp_master_t *dsp_master = &app->dsp_master;
if( (dsp_master->num_slaves > 0) && (dsp_master->concurrent > 1) ) // parallel processing makes sense here
+ {
_sp_app_process_parallel(app, nsamples, sparse_update_timeout);
+ }
else
- _sp_app_process_serial(app, nsamples, sparse_update_timeout);
-
- if(atomic_exchange(&dsp_master->emergency_exit, false))
{
- app->dsp_master.concurrent = dsp_master->num_slaves; // spin up all cores
- sp_app_log_trace(app, "%s: had to take emergency exit\n", __func__);
+ _sp_app_process_serial(app, nsamples, sparse_update_timeout);
}
// profiling
@@ -1015,64 +1017,105 @@ sp_app_run_post(sp_app_t *app, uint32_t nsamples)
else if(run_time > app->prof.max)
app->prof.max = run_time;
- if(app_t2.tv_sec > app->prof.t0.tv_sec) // a second has passed
+ bool reset_parallelizer = false;
+
+ if(atomic_exchange(&dsp_master->emergency_exit, false))
{
- const unsigned tot_time = (app_t2.tv_sec - app->prof.t0.tv_sec)*1000000000
- + app_t2.tv_nsec - app->prof.t0.tv_nsec;
- const float tot_time_1 = 100.f / tot_time;
+ sp_app_log_trace(app, "%s: had to take emergency exit\n", __func__);
+ reset_parallelizer = true;
+ }
+
+ if(atomic_exchange(&dsp_master->xrun_report, false))
+ {
+ sp_app_log_trace(app, "%s: Xruns reported\n", __func__);
+ reset_parallelizer = true;
+ }
+
+ if(reset_parallelizer)
+ {
+ app->dsp_master.concurrent = dsp_master->num_slaves + 1; // spin up all cores
+ app->skip_reweighting = REWEIGHT_S;
+
+ app->prof.min = 0;
+ app->prof.sum = 0;
+ app->prof.max = 0;
+ app->prof.count = 0;
-#if defined(USE_DYNAMIC_PARALLELIZER)
- // reset DAG weights
for(unsigned m=0; m<app->num_mods; m++)
{
mod_t *mod = app->mods[m];
- dsp_client_t *dsp_client = &mod->dsp_client;
- dsp_client->weight = 0;
+ mod->prof.min = 0;
+ mod->prof.sum= 0;
+ mod->prof.max= 0;
}
+ }
- unsigned T1 = 0;
- unsigned Tinf = 0;
+ if(app_t2.tv_sec > app->prof.t0.tv_sec) // a second has passed
+ {
+ const unsigned tot_time = (app_t2.tv_sec - app->prof.t0.tv_sec)*1000000000
+ + app_t2.tv_nsec - app->prof.t0.tv_nsec;
+ const float tot_time_1 = 100.f / tot_time;
- // calculate DAG weights
- for(unsigned m1=0; m1<app->num_mods; m1++)
+#if defined(USE_DYNAMIC_PARALLELIZER)
+ if(app->skip_reweighting > 0)
{
- mod_t *mod1 = app->mods[m1];
- dsp_client_t *dsp_client1 = &mod1->dsp_client;
+ app->skip_reweighting -= 1;
+ }
+ else
+ {
+ // reset DAG weights
+ for(unsigned m=0; m<app->num_mods; m++)
+ {
+ mod_t *mod = app->mods[m];
+ dsp_client_t *dsp_client = &mod->dsp_client;
+
+ dsp_client->weight = 0;
+ }
- unsigned gsw = 0; // greatest sink weight
+ unsigned T1 = 0;
+ unsigned Tinf = 0;
- for(unsigned m2=0; m2<m1; m2++)
+ // calculate DAG weights
+ for(unsigned m1=0; m1<app->num_mods; m1++)
{
- mod_t *mod2 = app->mods[m2];
- dsp_client_t *dsp_client2 = &mod2->dsp_client;
+ mod_t *mod1 = app->mods[m1];
+ dsp_client_t *dsp_client1 = &mod1->dsp_client;
+
+ unsigned gsw = 0; // greatest sink weight
- for(unsigned s=0; s<dsp_client2->num_sinks; s++)
+ for(unsigned m2=0; m2<m1; m2++)
{
- dsp_client_t *dsp_client3 = dsp_client2->sinks[s];
+ mod_t *mod2 = app->mods[m2];
+ dsp_client_t *dsp_client2 = &mod2->dsp_client;
- if(dsp_client3 == dsp_client1) // mod2 is source of mod1
+ for(unsigned s=0; s<dsp_client2->num_sinks; s++)
{
- if(dsp_client2->weight > gsw)
- gsw = dsp_client2->weight;
+ dsp_client_t *dsp_client3 = dsp_client2->sinks[s];
- break;
+ if(dsp_client3 == dsp_client1) // mod2 is source of mod1
+ {
+ if(dsp_client2->weight > gsw)
+ gsw = dsp_client2->weight;
+
+ break;
+ }
}
}
- }
- const unsigned w1 = mod1->prof.sum;
+ const unsigned w1 = mod1->prof.sum;
- T1 += w1;
- dsp_client1->weight = gsw + w1;
+ T1 += w1;
+ dsp_client1->weight = gsw + w1;
- if(dsp_client1->weight > Tinf)
- Tinf = dsp_client1->weight;
- }
+ if(dsp_client1->weight > Tinf)
+ Tinf = dsp_client1->weight;
+ }
- // derive average parallelism
- const float parallelism = (float)T1 / Tinf; //TODO add some head-room?
- app->dsp_master.concurrent = ceilf(parallelism);
+ // derive average parallelism
+ const float parallelism = (float)T1 / Tinf; //TODO add some head-room?
+ app->dsp_master.concurrent = ceilf(parallelism);
+ }
// to nk
{
@@ -1502,3 +1545,11 @@ sp_app_bundle_reset(sp_app_t *app)
{
_sp_app_reset(app);
}
+
+void
+sp_app_xrun_report(sp_app_t *app)
+{
+ dsp_master_t *dsp_master = &app->dsp_master;
+
+ atomic_store(&dsp_master->xrun_report, true);
+}
diff --git a/app/synthpod_app_private.h b/app/synthpod_app_private.h
index 7cf03592..514b8a2e 100644
--- a/app/synthpod_app_private.h
+++ b/app/synthpod_app_private.h
@@ -166,6 +166,7 @@ struct _dsp_master_t {
dsp_slave_t dsp_slaves [MAX_SLAVES];
atomic_bool kill;
atomic_bool emergency_exit;
+ atomic_bool xrun_report;
sem_t sem;
unsigned concurrent;
unsigned num_slaves;
@@ -445,6 +446,7 @@ struct _sp_app_t {
void *data;
atomic_bool dirty;
+ unsigned skip_reweighting;
blocking_state_t block_state;
silencing_state_t silence_state;
diff --git a/bin/pcmi.cpp b/bin/pcmi.cpp
index 187b9687..ddf6c468 100644
--- a/bin/pcmi.cpp
+++ b/bin/pcmi.cpp
@@ -127,6 +127,14 @@ pcmi_capt_done(pcmi_t *pcmi, uint32_t frsize)
_pcmi->capt_done(frsize);
}
+float
+pcmi_capt_xrun(pcmi_t *pcmi)
+{
+ Alsa_pcmi *_pcmi = (Alsa_pcmi *)pcmi;
+
+ return _pcmi->capt_xrun();
+}
+
void
pcmi_play_init(pcmi_t *pcmi, uint32_t frsize)
{
@@ -158,3 +166,11 @@ pcmi_play_done(pcmi_t *pcmi, uint32_t frsize)
_pcmi->play_done(frsize);
}
+
+float
+pcmi_play_xrun(pcmi_t *pcmi)
+{
+ Alsa_pcmi *_pcmi = (Alsa_pcmi *)pcmi;
+
+ return _pcmi->play_xrun();
+}
diff --git a/bin/pcmi.h b/bin/pcmi.h
index e6bb1801..a330db1f 100644
--- a/bin/pcmi.h
+++ b/bin/pcmi.h
@@ -61,6 +61,9 @@ pcmi_capt_chan(pcmi_t *pcmi, uint32_t channel, float *dst, uint32_t frsize);
void
pcmi_capt_done(pcmi_t *pcmi, uint32_t frsize);
+float
+pcmi_capt_xrun(pcmi_t *pcmi);
+
void
pcmi_play_init(pcmi_t *pcmi, uint32_t frsize);
@@ -73,6 +76,9 @@ pcmi_play_chan(pcmi_t *pcmi, uint32_t channel, const float *src, uint32_t frsize
void
pcmi_play_done(pcmi_t *pcmi, uint32_t frsize);
+float
+pcmi_play_xrun(pcmi_t *pcmi);
+
#ifdef __cplusplus
}
#endif
diff --git a/bin/synthpod_alsa.c b/bin/synthpod_alsa.c
index d8c1cd73..2ef3c569 100644
--- a/bin/synthpod_alsa.c
+++ b/bin/synthpod_alsa.c
@@ -160,11 +160,30 @@ _process(prog_t *handle)
snd_seq_real_time_t ref_time;
snd_seq_queue_status_malloc(&stat);
+ float last_capt_xrun = 0.f;
+ float last_play_xrun = 0.f;
+
pcmi_pcm_start(handle->pcmi);
while(!atomic_load_explicit(&handle->kill, memory_order_relaxed))
{
uint32_t na = pcmi_pcm_wait(pcmi);
+ // detect Xruns
+ const float capt_xrun = pcmi_capt_xrun(pcmi);
+ const float play_xrun = pcmi_play_xrun(pcmi);
+
+ if(capt_xrun != last_capt_xrun)
+ {
+ sp_app_xrun_report(app);
+ last_capt_xrun = capt_xrun;
+ }
+
+ if(play_xrun != last_play_xrun)
+ {
+ sp_app_xrun_report(app);
+ last_play_xrun = play_xrun;
+ }
+
// current time is next time from last cycle
_ntp_clone(&handle->cur_ntp, &handle->nxt_ntp);
diff --git a/bin/synthpod_jack.c b/bin/synthpod_jack.c
index 3d52bca5..7f93a9c5 100644
--- a/bin/synthpod_jack.c
+++ b/bin/synthpod_jack.c
@@ -735,9 +735,9 @@ _xrun(void *data)
{
prog_t *handle = data;
bin_t *bin = &handle->bin;
+ sp_app_t *app = bin->app;
- //TODO do this asynchronously?
- bin_log_warning(bin, "JACK XRun\n");
+ sp_app_xrun_report(app);
return 0;
}
diff --git a/include/synthpod_app.h b/include/synthpod_app.h
index 0de492d1..563d5398 100644
--- a/include/synthpod_app.h
+++ b/include/synthpod_app.h
@@ -206,4 +206,7 @@ sp_app_bundle_load(sp_app_t *app, LV2_URID urn, bool via_app);
void
sp_app_bundle_save(sp_app_t *app, LV2_URID urn, bool via_app);
+void
+sp_app_xrun_report(sp_app_t *app);
+
#endif // _SYNTHPOD_APP_H