Mac graphics

svn path=/trunk/boinc/; revision=544
This commit is contained in:
Eric Heien 2002-10-29 18:51:45 +00:00
parent 366bc6958a
commit 6caf172164
10 changed files with 87 additions and 296 deletions

View File

@ -33,10 +33,6 @@
#include <mmsystem.h> // for timing
#endif
#ifdef __APPLE_CC__
#include <CoreServices/CoreServices.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -52,6 +48,11 @@
#include "error_numbers.h"
#include "graphics_api.h"
#ifdef __APPLE_CC__
#include <CoreServices/CoreServices.h>
#include "mac_app_opengl.h"
#endif
#include "boinc_api.h"
static APP_INIT_DATA aid;
@ -129,6 +130,7 @@ int boinc_init() {
time_until_fraction_done_update = aid.fraction_done_update_period;
time_until_redraw = gi.refresh_period;
this_process_active = true;
set_timer(timer_period);
boinc_install_signal_handlers();
@ -235,7 +237,6 @@ int boinc_resolve_filename(char *virtual_name, char *physical_name, int len) {
return 0;
}
bool boinc_time_to_checkpoint() {
// Tell the graphics thread it's OK to draw now
if (ready_to_redraw) {
@ -244,6 +245,12 @@ bool boinc_time_to_checkpoint() {
#ifdef _WIN32
ResetEvent(hGlobalDrawEvent);
WaitForSingleObject( hGlobalDrawEvent, INFINITE );
#endif
#ifdef __APPLE_CC__
while (ok_to_draw) {
MPWaitOnQueue( drawQueue, NULL, NULL, NULL, kDurationImmediate );
YieldToAnyThread();
}
#endif
// Reset the refresh counter
time_until_redraw = gi.refresh_period;
@ -365,6 +372,10 @@ void on_timer(int a) {
time_until_fraction_done_update = aid.fraction_done_update_period;
}
}
#ifdef __APPLE_CC__
YieldToAnyThread();
#endif
}
@ -390,6 +401,11 @@ int set_timer(double period) {
NULL); // object not named
#endif
#ifdef __APPLE_CC__
// Create notification queue for drawing
MPCreateQueue( &drawQueue );
#endif
#if HAVE_SIGNAL_H
#if HAVE_SYS_TIME_H
struct sigaction sa;

View File

@ -30,7 +30,7 @@ DWORD WINAPI win_graphics_event_loop( LPVOID duff );
#ifdef __APPLE_CC__
#include <Carbon/Carbon.h>
#include <CoreServices/CoreServices.h>
//#include "mac_app_opengl.h"
#include "mac_app_opengl.h"
#endif
extern GRAPHICS_INFO gi;
@ -61,10 +61,8 @@ int boinc_init_opengl() {
entry_proc = NewThreadEntryUPP( mac_graphics_event_loop );
// Create the thread in a suspended state
theErr = NewThread (
kCooperativeThread, entry_proc,
(void *)(&gi), 0, kNewSuspend, NULL, &graphicsThreadID
);
theErr = NewThread ( kCooperativeThread, entry_proc,
(void *)(&gi), 0, kNewSuspend | kCreateIfNeeded, NULL, &graphicsThreadID );
if (theErr != noErr) return ERR_THREAD;
// In theory we could do customized scheduling or install thread disposal routines here

View File

@ -49,8 +49,6 @@
#include "mac_main.h"
void drawGL(WindowPtr pWindow);
static void DisposeGLWindow (WindowPtr pWindow); // Dispose a single window and it's GL context
// statics/globals (internal only) ------------------------------------------
@ -72,12 +70,8 @@ EventHandlerUPP appCommandProcessor;
WindowPtr boincAboutWindow;
AGLContext boincAGLContext;
GLuint monacoFontList;
char boincStrContext [256];
structGLWindowInfo glInfo;
long gFrameWindow=0;
float gRotation=0;
AbsoluteTime gTimeWindow;
MPQueueID drawQueue;
bool user_requested_exit = false;
@ -113,17 +107,18 @@ int InitGLWindow(int xsize, int ysize, int depth)
appCommandProcessor = NewEventHandlerUPP(MainAppEventHandler);
err = InstallApplicationEventHandler(appCommandProcessor, GetEventTypeCount(appEventList),
appEventList, 0, NULL);
// Install application graphics timer
boincTimerUPP = NewEventLoopTimerUPP(GraphicsLoopProcessor);
err = InstallEventLoopTimer(GetMainEventLoop(), 0,
kEventDurationMillisecond*10, // Every 1/60th of a second
boincTimerUPP, NULL, &boincTimer);
// Install preemption
boincYieldUPP = NewEventLoopTimerUPP(YieldProcessor);
err = InstallEventLoopTimer(GetMainEventLoop(), 0,
kEventDurationMillisecond*10, // Every 10 ms
boincYieldUPP, NULL, &boincYieldTimer);
// Install graphics
boincYieldUPP = NewEventLoopTimerUPP(GraphicsLoopProcessor);
err = InstallEventLoopTimer(GetMainEventLoop(), 0,
kEventDurationMillisecond*10, // Every 10 ms
boincYieldUPP, NULL, &boincYieldTimer);
// TODO: add an event handler for the window
ChangeWindowAttributes( appGLWindow, kWindowStandardHandlerAttribute, 0 );
@ -153,7 +148,6 @@ int InitGLWindow(int xsize, int ysize, int depth)
if (!boincAGLContext)
{
DestroyGLFromWindow (&boincAGLContext, &glInfo);
sprintf (boincStrContext, "No context");
}
else
{
@ -181,7 +175,6 @@ int InitGLWindow(int xsize, int ysize, int depth)
aglReportError ();
glViewport (0, 0, rectPort.right - rectPort.left, rectPort.bottom - rectPort.top);
glReportError ();
sprintf (boincStrContext, "%d x %d", rectPort.right - rectPort.left, rectPort.bottom - rectPort.top);
GetFNum("\pMonaco", &fNum); // build font
monacoFontList = BuildFontGL (boincAGLContext, fNum, normal, 9);
@ -207,17 +200,6 @@ pascal void YieldProcessor(EventLoopTimerRef inTimer, void* timeData) {
YieldToAnyThread();
}
/*
if ((pWindowInfo) && (boincAGLContext))
{
GetWindowPortBounds (whichWindow, &rectTemp);
aglSetCurrentContext (boincAGLContext); // ensure the context we are working with is current
aglUpdateContext (boincAGLContext);
glViewport (0, 0, rectTemp.right - rectTemp.left, rectTemp.bottom - rectTemp.top);
sprintf (pWindowInfo->strContext, "%d x %d", rectTemp.right - rectTemp.left, rectTemp.bottom - rectTemp.top);
}
*/
//////////////////////////////////////////////////////////////////////////////////
// MainAppEventHandler //
//////////////////////////////////////////////////////////////////////////////////
@ -313,7 +295,7 @@ void mac_cleanup (void)
RemoveEventLoopTimer(boincTimer);
DisposeEventLoopTimerUPP(boincTimerUPP);
DisposeEventHandlerUPP(appCommandProcessor);
//DisposeGLWindow (appGLWindow);
DisposeGLWindow (appGLWindow);
}
// --------------------------------------------------------------------------
@ -329,81 +311,3 @@ static void DisposeGLWindow (WindowPtr pWindow) // Dispose a single window and i
DisposeWindow (pWindow);
}
}
#pragma mark -
//-----------------------------------------------------------------------------------------------------------------------
// OpenGL Drawing
void drawGL(WindowPtr pWindow)
{
static int first = 1;
static char myStr[256];
if( first ) {
gFrameWindow = 0;
gTimeWindow.hi = 0;
gTimeWindow.lo = 0;
gRotation = 0.0;
first = 0;
}
float f = 0.0;
glClearColor(0.25f, 0.25f, 0.25f, 1.0f); // Clear color buffer to dark grey
glClear(GL_COLOR_BUFFER_BIT);
gRotation += 0.5;
f = gRotation;
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glRotated (f, 0.0, 0.0, 1.0);
glEnable (GL_TEXTURE_2D);
glBegin(GL_QUADS); // Draw textured polygon
glColor3d(1.0, 0.0, 0.0);
glVertex3d(0.7, 0.7, 0.0);
glColor3d(0.0, 1.0, 0.0);
glVertex3d(-0.7, 0.7, 0.0);
glColor3d(0.0, 0.0, 1.0);
glVertex3d(-0.7, -0.7, 0.0);
glColor3d(0.7, 0.7, 0.7);
glVertex3d(0.7, -0.7, 0.0);
glEnd();
glDisable (GL_TEXTURE_2D);
// draw info
Rect rectPort;
GLint matrixMode;
GetWindowPortBounds (pWindow, &rectPort);
glGetIntegerv (GL_MATRIX_MODE, &matrixMode);
glMatrixMode (GL_PROJECTION);
glPushMatrix();
glLoadIdentity ();
glMatrixMode (GL_MODELVIEW);
glPushMatrix();
glLoadIdentity ();
glScalef (2.0 / (rectPort.right - rectPort.left), -2.0 / (rectPort.bottom - rectPort.top), 1.0);
glTranslatef (-(rectPort.right - rectPort.left) / 2.0, -(rectPort.bottom - rectPort.top) / 2.0, 0.0);
glColor3f (1.0, 1.0, 1.0);
glRasterPos3d (10, 12, 0);
MultiWinDrawFrameRate (monacoFontList, myStr, &gFrameWindow, &gTimeWindow);
glRasterPos3d (10, 24, 0);
DrawCStringGL (boincStrContext, monacoFontList);
glRasterPos3d (10, (rectPort.bottom - rectPort.top) - 15, 0);
DrawCStringGL ((char*) glGetString (GL_VENDOR), monacoFontList);
glRasterPos3d (10, (rectPort.bottom - rectPort.top) - 3, 0);
DrawCStringGL ((char*) glGetString (GL_RENDERER), monacoFontList);
glPopMatrix(); // GL_MODELVIEW
glMatrixMode (GL_PROJECTION);
glPopMatrix();
glMatrixMode (matrixMode);
}

View File

@ -28,6 +28,9 @@ pascal void GraphicsLoopProcessor(EventLoopTimerRef inTimer, void* timeData);
pascal void YieldProcessor(EventLoopTimerRef inTimer, void* timeData);
extern int InitGLWindow(int xsize, int ysize, int depth);
extern MPQueueID drawQueue;
extern int ok_to_draw;
#ifdef __cplusplus
}
#endif

View File

@ -54,15 +54,10 @@
Adapted to BOINC by Eric Heien
*/
// Usage notes:
// kUseFades enables gamma fades for activates and deactivates
#define kUseFades
//kUseRAMCheck enables estimated video card RAM checks
#define kUseRAMCheck
// system includes ----------------------------------------------------------
#ifdef __APPLE_CC__
@ -74,8 +69,6 @@
#include <fp.h>
#endif
#include <string.h>
// project includes ---------------------------------------------------------
#include "mac_carbon_dsp.h"
@ -99,11 +92,9 @@ void BuildResolutionList (GDHandle hGD, Point * pResList, SInt32 * pFreqList);
OSStatus DoDeviceRAMCheck (pstructGLInfo pcontextInfo, Point * pResList, SInt32 * pFreqList, GLint depthSizeSupport);
Boolean DoContextStepDown (pstructGLInfo pcontextInfo, DSpContextAttributes * pContextAttributes, Point * pResList, SInt32 * pFreqList);
// functions (internal/private) ---------------------------------------------
// ReserveUnusedDevices
// reserves contexts on unused devices to vprevent their selection by DSp, returns list of these devices
DSpContextReference * ReserveUnusedDevices (GDHandle hGD)
@ -143,9 +134,7 @@ DSpContextReference * ReserveUnusedDevices (GDHandle hGD)
}
// --------------------------------------------------------------------------
// FreeUnusedDevices
// frees screen that were previously reserved to prevent selection
OSStatus FreeUnusedDevices (GDHandle hGD, DSpContextReference ** ppContextRefUnused)
@ -173,9 +162,7 @@ OSStatus FreeUnusedDevices (GDHandle hGD, DSpContextReference ** ppContextRefUnu
}
// --------------------------------------------------------------------------
// BuildResolutionList
// builds a list of supported resolutions and frequencies for GDevice
void BuildResolutionList (GDHandle hGD, Point * pResList, SInt32 * pFreqList)
@ -257,9 +244,7 @@ void BuildResolutionList (GDHandle hGD, Point * pResList, SInt32 * pFreqList)
}
// --------------------------------------------------------------------------
// DoDeviceRAMCheck
// checks requested allocation against device RAM
// Note: may modify pcontextInfo
// this should be equal or less strigent than OpenGL actual allocation to avoid failing on valid drawables
@ -487,7 +472,6 @@ OSStatus DoDeviceRAMCheck (pstructGLInfo pcontextInfo, Point * pResList, SInt32
// --------------------------------------------------------------------------
// DoContextStepDown
// steps down through frequencies, depths and sizes to try to find a valid context
// bounded by flags for SizeMust and DepthMust
// Note: may modify pcontextInfo
@ -552,9 +536,7 @@ Boolean DoContextStepDown (pstructGLInfo pcontextInfo, DSpContextAttributes * pC
#pragma mark -
// functions (public) -------------------------------------------------------
// GetDSpVersion
// Gets the current version of DSp
NumVersion GetDSpVersion (void)
@ -569,9 +551,7 @@ NumVersion GetDSpVersion (void)
}
// --------------------------------------------------------------------------
// StartDSp
// handles starting up DrawSprocket
OSStatus StartDSp (void)
@ -598,9 +578,7 @@ OSStatus StartDSp (void)
}
// --------------------------------------------------------------------------
// ShutdownDSpContext
// shuts down DrawSprocket
void ShutdownDSp (void)
@ -616,14 +594,10 @@ void ShutdownDSp (void)
// --------------------------------------------------------------------------
// GetDSpDrawable
// Just returns the front buffer
// Inputs: *pdspContext
// pcontextInfo: request and requirements for cotext and drawable
// Outputs: returns CGrafPtr thaat is front buffer of context
// if error: will return NULL
CGrafPtr GetDSpDrawable (DSpContextReference dspContext)
@ -638,15 +612,11 @@ CGrafPtr GetDSpDrawable (DSpContextReference dspContext)
// --------------------------------------------------------------------------
// BuildDSpContext
// contextInfo and tries to allocate the corresponding DSp context
// Inputs: hGD: GDHandle to device to look at
// pcontextInfo: request and requirements for cotext and drawable
// Outputs: *pdspContext as allocated
// pcontextInfo: allocated parameters
// if fail to allocate: pdspContext will be NULL
// if error: will return error pdspContext will be NULL
@ -807,9 +777,6 @@ void DestroyDSpContext (DSpContextReference* pdspContext)
OSStatus DSpContext_CustomFadeGammaIn (DSpContextReference inContext, const RGBColor *fadeColor, long fadeTicks)
{
OSStatus err = noErr;
#ifndef kUseFades
#pragma unused (inContext, fadeColor, fadeTicks)
#else
RGBColor inZeroIntensityColor;
UInt32 currTick;
UInt16 step = (UInt16) (800 / fadeTicks);
@ -841,7 +808,6 @@ OSStatus DSpContext_CustomFadeGammaIn (DSpContextReference inContext, const RGBC
if (err == noErr)
err = DSpContext_FadeGamma(inContext, 100, &inZeroIntensityColor);
}
#endif // kUseFades
return err;
}
@ -851,9 +817,6 @@ OSStatus DSpContext_CustomFadeGammaOut (DSpContextReference inContext, const RGB
{
OSStatus err = noErr;
#ifndef kUseFades
#pragma unused (inContext, fadeColor, fadeTicks)
#else
RGBColor inZeroIntensityColor;
UInt32 currTick;
UInt16 step = (UInt16) (800 / fadeTicks);
@ -883,6 +846,5 @@ OSStatus DSpContext_CustomFadeGammaOut (DSpContextReference inContext, const RGB
currTick = TickCount ();
}
}
#endif // kUseFades
return err;
}

View File

@ -76,17 +76,11 @@
Adapted to BOINC by Eric Heien
*/
// Usage notes:
// include control --------------------------------------------------
#ifndef SetupDSp_h
#define SetupDSp_h
// includes ---------------------------------------------------------
#ifdef __APPLE_CC__

View File

@ -84,6 +84,8 @@
#include "mac_carbon_dsp.h"
#include "mac_carbon_gl.h"
#include "graphics_api.h"
#include "mac_app_opengl.h"
extern WindowRef appGLWindow;
@ -107,8 +109,7 @@ static OSStatus BuildGLonDevice (AGLDrawable* paglDraw, AGLContext* paglContext,
GDHandle hGD, pstructGLInfo pcontextInfo, AGLContext aglShareContext);
static OSStatus BuildGLonWindow (WindowPtr pWindow, AGLContext* paglContext, pstructGLWindowInfo pcontextInfo, AGLContext aglShareContext);
extern void drawGL(WindowPtr pWindow);
extern GLuint monacoFontList;
// functions (internal/private) ---------------------------------------------
@ -1027,7 +1028,6 @@ OSStatus PauseGL (AGLContext aglContext)
//-----------------------------------------------------------------------------------------------------------------------
// ResumeGL
// resumes gl to allow gl drawing
OSStatus ResumeGL (AGLContext aglContext)
@ -1043,64 +1043,9 @@ OSStatus ResumeGL (AGLContext aglContext)
// --------------------------------------------------------------------------
// FindGDHandleFromRect
// Inputs: a global Rect
// Outputs: the GDHandle that that Rect is mostly on
// returns the number of devices that the Rect touches
short FindGDHandleFromRect (Rect * pRect, GDHandle * phgdOnThisDevice)
{
Rect rectSect;
long greatestArea, sectArea;
short numDevices = 0;
GDHandle hgdNthDevice;
if (!phgdOnThisDevice)
return NULL;
*phgdOnThisDevice = NULL;
hgdNthDevice = GetDeviceList ();
greatestArea = 0;
// check window against all gdRects in gDevice list and remember
// which gdRect contains largest area of window}
while (hgdNthDevice)
{
if (TestDeviceAttribute (hgdNthDevice, screenDevice)) {
if (TestDeviceAttribute (hgdNthDevice, screenActive))
{
// The SectRect routine calculates the intersection
// of the window rectangle and this gDevice
// rectangle and returns TRUE if the rectangles intersect,
// FALSE if they don't.
SectRect (pRect, &(**hgdNthDevice).gdRect, &rectSect);
// determine which screen holds greatest window area
// first, calculate area of rectangle on current device
sectArea = (long) (rectSect.right - rectSect.left) * (rectSect.bottom - rectSect.top);
if (sectArea > 0)
numDevices++;
if (sectArea > greatestArea)
{
greatestArea = sectArea; // set greatest area so far
*phgdOnThisDevice = hgdNthDevice; // set zoom device
}
hgdNthDevice = GetNextDevice(hgdNthDevice);
}
}
}
return numDevices;
}
// --------------------------------------------------------------------------
// GetWindowDevice
// Inputs: a valid WindowPtr
// Outputs: the GDHandle that that window is mostly on
// returns the number of devices that the windows content touches
short FindGDHandleFromWindow (WindowPtr pWindow, GDHandle * phgdOnThisDevice)
@ -1155,69 +1100,26 @@ short FindGDHandleFromWindow (WindowPtr pWindow, GDHandle * phgdOnThisDevice)
return numDevices;
}
//-----------------------------------------------------------------------------------------------------------------------
// FindDeviceNumFromRect
// returns the number of the device that the point is on (i.e., where it is in the search order)
// just a ultility to find the number of the device from a point
short FindDeviceNumFromRect (Rect * pRect)
{
short displayNum = 0;
GDHandle hgdNthDevice, hgdFoundDevice;
FindGDHandleFromRect (pRect, &hgdFoundDevice);
hgdNthDevice = DMGetFirstScreenDevice (true);
while (hgdNthDevice)
{
if (hgdFoundDevice == hgdNthDevice)
break;
hgdNthDevice = DMGetNextScreenDevice(hgdNthDevice, true);
displayNum++;
} // of WHILE
return displayNum;
}
//-----------------------------------------------------------------------------------------------------------------------
// Draw frame rate in current color at current raster positon with provided font display list
// This version handles multiple windows, thus the calling code must track the values of frames and time from call to call
// The application needs to maintain a cstring (32 characters should be fine), frame counter and time for each window,
// but this routine will take care of all updates.
void MultiWinDrawFrameRate (GLuint fontList, char * cString, long * frames, AbsoluteTime * time)
{
AbsoluteTime currTime = UpTime ();
float deltaTime = (float) AbsoluteDeltaToDuration (currTime, *time);
if (0 > deltaTime) // if negative microseconds
deltaTime /= -1000000.0;
else // else milliseconds
deltaTime /= 1000.0;
(*frames)++;
if (0.5 <= deltaTime) // has update interval passed
{
sprintf (cString, "FPS: %0.1f", (float) *frames / deltaTime);
*time = currTime; // reset for next time interval
*frames = 0;
}
DrawCStringGL (cString, fontList);
}
#pragma mark -
//-----------------------------------------------------------------------------------------------------------------------
void DrawCStringGL (char * cstrOut, GLuint fontList)
GLvoid glPrint(const char *fmt, ...) // Custom GL "Print" Routine
{
GLint i = 0;
while (cstrOut [i])
glCallList (fontList + cstrOut[i++]);
char text[256]; // Holds Our String
va_list ap; // Pointer To List Of Arguments
if (fmt == NULL) // If There's No Text
return; // Do Nothing
va_start(ap, fmt); // Parses The String For Variables
vsprintf(text, fmt, ap); // And Converts Symbols To Actual Numbers
va_end(ap); // Results Are Stored In Text
glPushAttrib(GL_LIST_BIT); // Pushes The Display List Bits
glListBase(monacoFontList); // Sets The Base Character to 32
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Draws The Display List Text
glPopAttrib(); // Pops The Display List Bits
}
//-----------------------------------------------------------------------------------------------------------------------
@ -1366,14 +1268,16 @@ OSStatus glReportError (void)
void DoUpdate (AGLContext aglContext)
{
if (aglContext)
if (aglContext && ok_to_draw)
{
aglSetCurrentContext (aglContext);
aglUpdateContext (aglContext);
drawGL (appGLWindow);
DrawGLScene(); // Here's Where We Do All The Drawing
aglSwapBuffers(aglContext); // send swap command
ok_to_draw = 0;
MPNotifyQueue( drawQueue, NULL, NULL, NULL );
}
}

View File

@ -78,16 +78,11 @@
Adapted to BOINC by Eric Heien
*/
// Usage notes:
// include control --------------------------------------------------
#ifndef SetupGL_h
#define SetupGL_h
// includes ---------------------------------------------------------
#ifdef __APPLE_CC__
@ -203,21 +198,11 @@ OSStatus PauseGL (AGLContext aglContext);
// resumes gl to allow gl drawing
OSStatus ResumeGL (AGLContext aglContext);
short FindGDHandleFromRect (Rect * pRect, GDHandle * phgdOnThisDevice);
short FindGDHandleFromWindow (WindowPtr pWindow, GDHandle * phgdOnThisDevice);
// returns the number of the device that the rect is mostly is on (i.e., where it is numerically in the search order)
short FindDeviceNumFromRect (Rect * rect);
void MultiWinDrawFrameRate (GLuint fontList, char * cString, long * frames, AbsoluteTime * time);
void DrawCStringGL (char * cstrOut, GLuint fontList);
GLuint BuildFontGL (AGLContext ctx, GLint fontID, Style face, GLint size);
void DeleteFontGL (GLuint fontList);
void DeleteFontGL (GLuint fontList);
// Error reporter, can be set to report however the application desires
void ReportError (char * strError);
@ -236,6 +221,10 @@ OSStatus glReportError (void);
void DoUpdate (AGLContext aglContext);
GLvoid glPrint(const char *fmt, ...);
int DrawGLScene(GLvoid); // Here's Where We Do All The Drawing
#ifdef __cplusplus
}
#endif

View File

@ -2239,3 +2239,27 @@ David Oct 21, 2002
validate.C
test/
test_loop.php
Eric October 28, 2002
- added signal handling to API
- removed win_build.zip
api/
boinc_api.C,h
apps/
upper_case.C
concat.C
lib/
error_numbers.h
win_build.zip (removed)
Eric October 29, 2002
- Mac graphics completed (except for screensaver mode)
api/
boinc_api.C
graphics_api.C
mac_app_opengl.c,h
mac_carbon_dsp.c,h
mac_carbon_gl.c,h

3
todo
View File

@ -32,9 +32,6 @@ investigate binary diff mechanism for updating persistent files
use FTP instead of HTTP for file xfer??
measure speed diff
catch signals in applications (API) to return better info
in case of crash (seg fault addr, etc.)
Delete files if needed to honor disk usage constraint
inform user if this happens