[PD-cvs] pd/src m_sched.c,1.5.4.3,1.5.4.4
Tim Blechmann
timblech at users.sourceforge.net
Wed Nov 24 00:07:46 CET 2004
Update of /cvsroot/pure-data/pd/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24481
Modified Files:
Tag: devel_0_38
m_sched.c
Log Message:
callback-based scheduler and generalized idle callbacks
Index: m_sched.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/m_sched.c,v
retrieving revision 1.5.4.3
retrieving revision 1.5.4.4
diff -C2 -d -r1.5.4.3 -r1.5.4.4
*** m_sched.c 11 Nov 2004 22:30:41 -0000 1.5.4.3
--- m_sched.c 23 Nov 2004 23:07:40 -0000 1.5.4.4
***************
*** 23,26 ****
--- 23,33 ----
static double sys_time_per_msec = TIMEUNITPERSEC / 1000.;
+ /* tb: { */
+ int sys_keepsched = 1; /* if 0: change scheduler mode */
+ int sys_callbackscheduler = 0; /* if 1: change scheduler to callback based dsp */
+
+ static t_int run_idle_callbacks();
+ /* tb: }*/
+
int sys_usecsincelastsleep(void);
int sys_sleepgrain;
***************
*** 387,390 ****
--- 394,400 ----
int (*sys_idlehook)(void);
+
+
+
int m_scheduler( void)
{
***************
*** 395,399 ****
#ifdef THREAD_LOCKING
/* T.Grill - lock mutex */
! sys_lock();
#endif
--- 405,409 ----
#ifdef THREAD_LOCKING
/* T.Grill - lock mutex */
! sys_lock();
#endif
***************
*** 408,505 ****
while (!sys_quit)
{
! int didsomething = 0;
! int timeforward;
! sys_addhist(0);
! waitfortick:
! if (sched_usedacs)
! {
#ifdef THREAD_LOCKING
! /* T.Grill - send_dacs may sleep ->
! unlock thread lock make that time available
! - could messaging do any harm while sys_send_dacs is running?
! */
! sys_unlock();
#endif
! timeforward = sys_send_dacs();
#ifdef THREAD_LOCKING
! /* T.Grill - done */
! sys_unlock();
#endif
! /* if dacs remain "idle" for 1 sec, they're hung up. */
! if (timeforward != 0)
! idlecount = 0;
! else
! {
! idlecount++;
! if (!(idlecount & 31))
! {
! static double idletime;
! /* on 32nd idle, start a clock watch; every
! 32 ensuing idles, check it */
! if (idlecount == 32)
! idletime = sys_getrealtime();
! else if (sys_getrealtime() - idletime > 1.)
! {
! post("audio I/O stuck... closing audio\n");
! sys_close_audio();
! sched_set_using_dacs(0);
! goto waitfortick;
! }
! }
! }
! }
! else
! {
! if (1000. * (sys_getrealtime() - sched_referencerealtime)
! > clock_gettimesince(sched_referencelogicaltime))
! timeforward = SENDDACS_YES;
! else timeforward = SENDDACS_NO;
! }
! sys_setmiditimediff(0, 1e-6 * sys_schedadvance);
! sys_addhist(1);
! if (timeforward != SENDDACS_NO)
! sched_tick(sys_time + sys_time_per_dsp_tick);
! if (timeforward == SENDDACS_YES)
! didsomething = 1;
! sys_addhist(2);
! sys_pollmidiqueue();
! if (sys_pollgui())
! {
! if (!didsomething)
! sched_didpoll++;
! didsomething = 1;
! }
! sys_addhist(3);
! /* test for idle; if so, do graphics updates. */
! if (!didsomething)
! {
! sched_pollformeters();
! sys_reportidle();
#ifdef THREAD_LOCKING
! /* T.Grill - enter idle phase -> unlock thread lock */
! sys_unlock();
#endif
! /* call externally installed idle function if any. */
! if (!sys_idlehook || !sys_idlehook())
! {
! /* if even that had nothing to do, sleep. */
! if (timeforward != SENDDACS_SLEPT)
{
! sys_microsleep(sys_sleepgrain);
}
- }
#ifdef THREAD_LOCKING
! /* T.Grill - leave idle phase -> lock thread lock */
! sys_lock();
#endif
! sys_addhist(5);
! sched_didnothing++;
! }
! }
#ifdef THREAD_LOCKING
/* T.Grill - done */
--- 418,568 ----
while (!sys_quit)
{
! if (!sys_callbackscheduler)
! while (sys_keepsched)
! {
! int didsomething = 0;
! int timeforward;
! sys_addhist(0);
! waitfortick:
! if (sched_usedacs)
! {
#ifdef THREAD_LOCKING
! /* T.Grill - send_dacs may sleep ->
! unlock thread lock make that time available
! - could messaging do any harm while sys_send_dacs is running?
! */
! sys_unlock();
#endif
! timeforward = sys_send_dacs();
#ifdef THREAD_LOCKING
! /* T.Grill - done */
! sys_unlock();
#endif
! /* if dacs remain "idle" for 1 sec, they're hung up. */
! if (timeforward != 0)
! idlecount = 0;
! else
! {
! idlecount++;
! if (!(idlecount & 31))
! {
! static double idletime;
! /* on 32nd idle, start a clock watch; every
! 32 ensuing idles, check it */
! if (idlecount == 32)
! idletime = sys_getrealtime();
! else if (sys_getrealtime() - idletime > 1.)
! {
! post("audio I/O stuck... closing audio\n");
! sys_close_audio();
! sched_set_using_dacs(0);
! goto waitfortick;
! }
! }
! }
! }
! else
! {
! if (1000. * (sys_getrealtime() - sched_referencerealtime)
! > clock_gettimesince(sched_referencelogicaltime))
! timeforward = SENDDACS_YES;
! else timeforward = SENDDACS_NO;
! }
! sys_setmiditimediff(0, 1e-6 * sys_schedadvance);
! sys_addhist(1);
! if (timeforward != SENDDACS_NO)
! sched_tick(sys_time + sys_time_per_dsp_tick);
! if (timeforward == SENDDACS_YES)
! didsomething = 1;
! sys_addhist(2);
! sys_pollmidiqueue();
! if (sys_pollgui())
! {
! if (!didsomething)
! sched_didpoll++;
! didsomething = 1;
! }
! sys_addhist(3);
! /* test for idle; if so, do graphics updates. */
! if (!didsomething)
! {
! sched_pollformeters();
! sys_reportidle();
#ifdef THREAD_LOCKING
! /* T.Grill - enter idle phase -> unlock thread lock */
! sys_unlock();
#endif
! /* tb: call idle callbacks */
! if (run_idle_callbacks())
{
! /* if even that had nothing to do, sleep. */
! if (timeforward != SENDDACS_SLEPT)
! {
! sys_microsleep(sys_sleepgrain);
! }
}
#ifdef THREAD_LOCKING
! /* T.Grill - leave idle phase -> lock thread lock */
! sys_lock();
#endif
! sys_addhist(5);
! sched_didnothing++;
! }
! }
! else /* tb: scheduler for callback-based dsp scheduling */
! while(sys_keepsched)
! {
! int didsomething = 0;
! int timeforward;
+ sys_addhist(0);
+
+ sys_setmiditimediff(0, 1e-6 * sys_schedadvance);
+ sys_addhist(1);
+
+ /* run this from the callback
+ */
+
+ sys_addhist(2);
+ sys_pollmidiqueue();
+ if (sys_pollgui())
+ {
+ if (!didsomething)
+ sched_didpoll++;
+ didsomething = 1;
+ }
+ sys_addhist(3);
+
+ /* test for idle; if so, do graphics updates. */
+ if (!didsomething)
+ {
+ sched_pollformeters();
+ sys_reportidle();
+ }
+
+ #ifdef THREAD_LOCKING
+ sys_unlock();
+ #endif
+
+ /* sleep: the callback might run sched_tick during this time */
+ sys_microsleep(sys_sleepgrain / 10);
+
+ /* call externally installed idle function if any. */
+ /* tb: is there a more elegant way to do this? */
+ // sys_idlehook();
+
+ #ifdef THREAD_LOCKING
+ sys_lock();
+ #endif
+ sys_addhist(5);
+ sched_didnothing++;
+ }
+ sys_keepsched = 1;
+ }
+
#ifdef THREAD_LOCKING
/* T.Grill - done */
***************
*** 549,552 ****
void sys_exit(void)
{
! sys_quit = 1;
}
--- 612,691 ----
void sys_exit(void)
{
! sys_keepsched = 0;
! sys_quit = 1;
}
+
+
+ /* tb: place callbacks in scheduler
+ * { */
+
+ #if 1
+ /* linked list of callbacks */
+ typedef struct _sched_callback
+ {
+ void (*function) (t_int** argv);
+ t_int** argv;
+ t_int argc;
+ struct _sched_callback* next;
+ } t_sched_callback;
+
+ /* this is not save ... possibly not atomic */
+ static volatile t_sched_callback * cb_fifo_begin = NULL;
+ static volatile t_sched_callback * cb_fifo_end = NULL;
+
+ void set_callback(void (*callback) (t_int** argv), t_int** argv, t_int argc)
+ {
+ t_sched_callback* new = (t_sched_callback*) getbytes
+ (sizeof(t_sched_callback));
+
+ new->function = callback;
+ new->argv = (t_int**) getbytes (argc * sizeof (t_int*));
+ new->argc = argc;
+ new->next = NULL;
+
+ if (cb_fifo_begin != NULL)
+ {
+ cb_fifo_end->next = new;
+ cb_fifo_end = new;
+ }
+ else
+ {
+ cb_fifo_begin = new;
+ cb_fifo_end = new;
+ }
+
+ }
+
+
+ static t_int run_idle_callbacks()
+ {
+ if (cb_fifo_begin)
+ {
+ double stop = sys_getrealtime() + sys_sleepgrain;
+
+ do
+ {
+ t_sched_callback* next = cb_fifo_begin->next;
+ cb_fifo_begin->function(cb_fifo_begin->argv);
+
+
+ freebytes (cb_fifo_begin->argv, cb_fifo_begin->argc);
+ freebytes ((void*)cb_fifo_begin, sizeof(t_sched_callback));
+
+ cb_fifo_begin = next;
+ }
+ while ( sys_getrealtime() > stop);
+
+ return 0; /* don't sleep */
+ }
+ return 1; /* sleep now */
+ }
+
+
+ #else
+
+ #error to be implemented
+
+ #endif /* LOCK_FREE */
+
+ /* } tb */
More information about the Pd-cvs
mailing list