rjvbertin
2004.09.02, 10:33 AM
I wonder if anyone has encountered the following annoying phenomenon under Mac OS X, and/or has a solution to propose.
In short, to try to get fluid animation, I use the code below to enter realtime priority just before I start drawing a frame. I suppose to be running at FrameRate herz, determined empirically, using SDL in OpenGL, patched to by synched with the VBL. FrameRate typically is somewhat less than 60.
The way I understand the documentation, this code requests realtime priority for the specified duration (enough for a single frame), with a few constraints.
This works (see also below). HOWEVER, if a bug causes a crash and (I suppose) we're still in realtime priority, a deadlock occurs in which the system tries to do something (show the quit dialog?? I don't use the SDL "parachute") but cannot. This FREEZES UP THE WHOLE system. Even if I still have focus on the calling terminal, or if I have a remote terminal running, the only solution is to powercycle. Note that even some events like clicking the window close button can cause a crash inside SDL_GL_SwapBuffers().
Am I doing something wrong? Should I force an exit from realtime after drawing the frame -- but how??
Curiously, when I do not enter realtime mode, my process is not killed when the same programme crash occurs: it remains in a sort of semi-limbo/semi-functional state, and no longer responds to SIGINT (^C). Is this a "known issue" with SDL on/or Mac OS X??
There *are* some benefits to using realtime: my application is a visual psychophysics stimulus programme (for doing fundamental science ;^)), and gives feedback to the user with system beeps (until now, I only know to ring the terminal bell, which causes some overhead that perturbs the animation). There is also a known issue where once every 30-some seconds one looses one or more frames, possibly due to the update(8) process -- this seems somewhat less when using realtime.
Thanks!
RenČ
Here's the code: I start drawing immediately afterwards.
#if defined(__MACH__) /* && !defined(DEBUG) */
static struct thread_time_constraint_policy ttcpolicy;
static unsigned char called= 0;
if( CloudCity_Attempt_RealTime ){
if( !called && CloudCity_Attempt_RealTime ){
int ret, bus_speed, mib[2] = { CTL_HW, HW_BUS_FREQ };
size_t len;
extern double FrameRate;
len = sizeof( bus_speed);
ret = sysctl (mib, 2, &bus_speed, &len, NULL, 0);
if (ret < 0) {
fprintf( stderr, "sysctl query bus speed failed (%s)\n", serror() );
}
else{
fprintf( stderr, "System cpu/bus_speed==%d\n", bus_speed );
ttcpolicy.period= bus_speed / FrameRate;
ttcpolicy.computation= bus_speed / 330;
ttcpolicy.constraint= bus_speed / 220;
ttcpolicy.preemptible= 1;
}
called= 1;
}
if( called ){
errno= 0;
/* Do a sync() to flush all open disk buffers before entering realtime priority. We do
\ this since even if there are no bugs in this routine itself, SDL_GL_SwapBuffers()
\ can crash in some circumstances, and we do not know exactly at what time we get
\ out of realtime mode. Crashing in realtime mode usually means the system ends up
\ in a deadlock situation, requiring a powercycle. Syncing means that at least we minimise
\ the risk of filesystem corruption.
\ There doesn't seem to be a penalty for doing a sync here.
*/
sync();
if( thread_policy_set( mach_thread_self(),
THREAD_TIME_CONSTRAINT_POLICY, (int*) &ttcpolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT
)!= KERN_SUCCESS
){
if( called< 255 ){
fprintf( stderr, "Couldn't set realtime priority: %s\n", serror() );
called+= 1;
}
}
}
}
#endif
In short, to try to get fluid animation, I use the code below to enter realtime priority just before I start drawing a frame. I suppose to be running at FrameRate herz, determined empirically, using SDL in OpenGL, patched to by synched with the VBL. FrameRate typically is somewhat less than 60.
The way I understand the documentation, this code requests realtime priority for the specified duration (enough for a single frame), with a few constraints.
This works (see also below). HOWEVER, if a bug causes a crash and (I suppose) we're still in realtime priority, a deadlock occurs in which the system tries to do something (show the quit dialog?? I don't use the SDL "parachute") but cannot. This FREEZES UP THE WHOLE system. Even if I still have focus on the calling terminal, or if I have a remote terminal running, the only solution is to powercycle. Note that even some events like clicking the window close button can cause a crash inside SDL_GL_SwapBuffers().
Am I doing something wrong? Should I force an exit from realtime after drawing the frame -- but how??
Curiously, when I do not enter realtime mode, my process is not killed when the same programme crash occurs: it remains in a sort of semi-limbo/semi-functional state, and no longer responds to SIGINT (^C). Is this a "known issue" with SDL on/or Mac OS X??
There *are* some benefits to using realtime: my application is a visual psychophysics stimulus programme (for doing fundamental science ;^)), and gives feedback to the user with system beeps (until now, I only know to ring the terminal bell, which causes some overhead that perturbs the animation). There is also a known issue where once every 30-some seconds one looses one or more frames, possibly due to the update(8) process -- this seems somewhat less when using realtime.
Thanks!
RenČ
Here's the code: I start drawing immediately afterwards.
#if defined(__MACH__) /* && !defined(DEBUG) */
static struct thread_time_constraint_policy ttcpolicy;
static unsigned char called= 0;
if( CloudCity_Attempt_RealTime ){
if( !called && CloudCity_Attempt_RealTime ){
int ret, bus_speed, mib[2] = { CTL_HW, HW_BUS_FREQ };
size_t len;
extern double FrameRate;
len = sizeof( bus_speed);
ret = sysctl (mib, 2, &bus_speed, &len, NULL, 0);
if (ret < 0) {
fprintf( stderr, "sysctl query bus speed failed (%s)\n", serror() );
}
else{
fprintf( stderr, "System cpu/bus_speed==%d\n", bus_speed );
ttcpolicy.period= bus_speed / FrameRate;
ttcpolicy.computation= bus_speed / 330;
ttcpolicy.constraint= bus_speed / 220;
ttcpolicy.preemptible= 1;
}
called= 1;
}
if( called ){
errno= 0;
/* Do a sync() to flush all open disk buffers before entering realtime priority. We do
\ this since even if there are no bugs in this routine itself, SDL_GL_SwapBuffers()
\ can crash in some circumstances, and we do not know exactly at what time we get
\ out of realtime mode. Crashing in realtime mode usually means the system ends up
\ in a deadlock situation, requiring a powercycle. Syncing means that at least we minimise
\ the risk of filesystem corruption.
\ There doesn't seem to be a penalty for doing a sync here.
*/
sync();
if( thread_policy_set( mach_thread_self(),
THREAD_TIME_CONSTRAINT_POLICY, (int*) &ttcpolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT
)!= KERN_SUCCESS
){
if( called< 255 ){
fprintf( stderr, "Couldn't set realtime priority: %s\n", serror() );
called+= 1;
}
}
}
}
#endif