Update of /cvsroot/pure-data/pd/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17121
Modified Files: Tag: devel_0_38 s_inter.c Log Message: watchdog thread instead of process ... should be more efficient
Index: s_inter.c =================================================================== RCS file: /cvsroot/pure-data/pd/src/s_inter.c,v retrieving revision 1.5.4.10 retrieving revision 1.5.4.11 diff -C2 -d -r1.5.4.10 -r1.5.4.11 *** s_inter.c 14 May 2005 17:05:27 -0000 1.5.4.10 --- s_inter.c 16 Jun 2005 12:47:50 -0000 1.5.4.11 *************** *** 6,9 **** --- 6,11 ---- that didn't really belong anywhere. */
+ #define WATCHDOGTHREAD + #include "m_pd.h" #include "s_stuff.h" *************** *** 192,202 **** */
! if (microsec < 1000) ! microsec = 1000; #ifndef MSW ! struct timespec rec, rem; ! rec.tv_sec = 0; ! rec.tv_nsec = 1000 * microsec; ! nanosleep(&rec, &rem); #else Sleep(microsec/1000); --- 194,205 ---- */
! /* if (!sys_callbackscheduler && microsec < 1000) */ ! /* microsec = 1000; */ #ifndef MSW ! struct timeval timeout; ! timeout.tv_sec = 0; ! timeout.tv_usec = microsec; ! select(0,0,0,0,&timeout); ! #else Sleep(microsec/1000); *************** *** 204,208 **** /* a solution for lower timeslices might be a busysleep but this might ! block a low-prority thread and won't work for win9x
#define _WIN32_WINNT 0x0400 --- 207,211 ---- /* a solution for lower timeslices might be a busysleep but this might ! block a low-priority thread and won't work for win9x
#define _WIN32_WINNT 0x0400 *************** *** 215,219 **** SwitchToThread(); #else ! sched_yield() #endif } --- 218,222 ---- SwitchToThread(); #else ! sched_yield(); #endif } *************** *** 299,303 **** p1 = sched_get_priority_min(SCHED_FIFO); p2 = sched_get_priority_max(SCHED_FIFO); ! #ifdef USEAPI_JACK p3 = (higher ? p1 + 7 : p1 + 5); #else --- 302,306 ---- p1 = sched_get_priority_min(SCHED_FIFO); p2 = sched_get_priority_max(SCHED_FIFO); ! #ifdef USEAPI_JACK p3 = (higher ? p1 + 7 : p1 + 5); #else *************** *** 857,860 **** --- 860,864 ---- void glob_watchdog(t_pd *dummy) { + #ifndef WATCHDOGTHREAD if (write(sys_watchfd, "\n", 1) < 1) { *************** *** 862,865 **** --- 866,873 ---- sys_bail(1); } + #else + + #endif + } #endif *************** *** 871,874 **** --- 879,884 ---- 24, 15, 28};
+ static int sys_start_watchdog_thread(); + int sys_startgui(const char *guidir) { *************** *** 1141,1144 **** --- 1151,1155 ---- if (sys_hipriority) { + #ifndef WATCHDOGTHREAD /* To prevent lockup, we fork off a watchdog process with higher real-time priority than ours. The GUI has to send *************** *** 1193,1196 **** --- 1204,1211 ---- this is done later when the socket is open. */ } + #else + sys_start_watchdog_thread(); + sys_set_priority(0); + #endif }
*************** *** 1241,1247 **** --- 1256,1264 ---- /* here is where we start the pinging. */ #if defined(__linux__) || defined(IRIX) + #ifndef WATCHDOGTHREAD if (sys_hipriority) sys_gui("pdtk_watchdog\n"); #endif + #endif sys_get_audio_apis(buf); sys_vgui("pdtk_pd_startup {%s} %s {%s}\n", pd_version, buf, *************** *** 1288,1289 **** --- 1305,1385 ---- }
+ #include "pthread.h" + static pthread_t watchdog_id; + static pthread_t main_pd_thread; + static pthread_mutex_t watchdog_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_cond_t watchdog_cond = PTHREAD_COND_INITIALIZER; + + static void * watchdog_thread(void*); + + /* start a high priority watchdog thread */ + static int sys_start_watchdog_thread() + { + pthread_attr_t w_attr; + int status; + + /* get parent thread ID */ + main_pd_thread = pthread_self(); + + /* set up attributes */ + pthread_attr_init(&w_attr); + + pthread_attr_setschedpolicy(&w_attr, SCHED_FIFO); /* use rt scheduling */ + + status = pthread_create(&watchdog_id, &w_attr, (void*) watchdog_thread, NULL); + } + + + + #ifdef MSW + int gettimeofday (struct timeval *tv, void* tz); + #endif + + + static t_int* watchdog_callback(t_int* dummy) + { + /* signal the condition */ + pthread_cond_signal(&watchdog_cond); + return 0; + } + + /* this watchdog thread registers an idle callback once a minute + if the idle callback isn't excecuted within one minute, we're probably + blocking the system. + kill the whole process! + */ + + static void * watchdog_thread(void* dummy) + { + sys_set_priority(1); + post("watchdog thread started"); + + while (1) + { + /* - register idle callback + - wait for condition variable + - in case of timeout kill the parent thread + - sleep + */ + struct timespec timeout; + struct timeval now; + + int status; + + gettimeofday(&now,0); + timeout.tv_sec = now.tv_sec + 60; /* timeout: 60 seconds */ + timeout.tv_nsec = now.tv_usec * 1000; + + sys_callback((void*)watchdog_callback, 0, 0); + status = pthread_cond_timedwait(&watchdog_cond, &watchdog_mutex, &timeout); + + if (status) + { + /* kill parent thread */ + kill(0,9); + } + + sys_microsleep(6e7); /* and sleep for another 60 seconds */ + } + } +