[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