Support for Real-Time Graphics Applications On SGI Linux Visual Workstations 230,330,550. By Jaya Kanajan, SGI H1. Introduction: The Real Time extension to IRIX, REACT offers hard real time and IRIX 6.5 has long supported soft real time in accordance to the POSIX 1003.1c specification. SGI customers have been proud of IRIX being able to gurantee the performance of their application and the ability to tweak the scheduler with very fine granularity. As such, SGI is eager to help guide the Linux community in the same direction in order to achieve similar performance in the future. Currently, the 2.2.15 and 2.2.14 Linux kernels that SGI offers and supports on the SGI Visual Workstations with ProPack 1.3-VW can offer a portion of that functionality. This is through the mlock,mlockall, and sched_setscheduler functions. The level of functionality available with these functions is similar to the soft real time support offered by IRIX (POSIX 1003.1c). H1. Details With regards to graphics, the primary concern is the ability to gurantee a particular frame rate. In order to achieve this, the application has to be able to control how the kernel allocates certain resources. For example, the application could be willing to lock it's data, stack, and possibly text pages into physical memory in order to gurantee that it is never swapped out. And similarly, the application would desire that only a specific set of tasks be allowed to use the CPU(s) available (not completely feasible on linux currently) on the system and also define how the kernel would choose which task ought to be run first. In the example application, the intent would be to get maximum frame rate by locking data that is being used in physical memory, and setting a non-degrading process priority for the process. The control of process priority allows the application to suggest to the kernel that it is an important user task. H1. Things to Think About The Linux kernel is a general purpose kernel. As such, there are many things that will affect the determinism of your real time application. For example, disk I/O is gathered together before being written to disk using standard elevator algorithms. As such, a little bit of IO by your application could trigger a long delay while the kernel gathers and writes blocks of data (some from lower priority applications) to disk. So one should be concerned about any blocking system call within a real time application. Other things to think about are which processes are important to give processor time to. For example, on a real time flight simulator, setting the application's threads for FIFO scheduling would result in the X server getting no time to handle input and this would thus hurt the usability of the simulator. H1. Example Application In this example application (tested on a 550 running 1.3-VW), I set the application for SCHED_FIFO with a priority of 99 and locks the two data buffers into physical memory. Since the 550 is a dual CPU box, the X server gets to run primarily on the other CPU. Thus, I didn't notice any loss of interactivity. /* * jaya@sgi.com * locking a process's memory ranges * controling the scheduler */ #include #include #include #include struct sched_param schedattr; Window makewindow(Display* dpy, int w, int h, int x, int y) { XSetWindowAttributes winattribs; Colormap cmap; XVisualInfo* vis; Window win; GLXContext ctxt; int attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None }; vis = glXChooseVisual( dpy, DefaultScreen( dpy ), attribs ); cmap = XCreateColormap( dpy, RootWindow(dpy, vis->screen), vis->visual, AllocNone ); winattribs.colormap = cmap; winattribs.border_pixel = 0; winattribs.background_pixel = 0; win = XCreateWindow( dpy, RootWindow(dpy, vis->screen), x, y, w, h, 0, vis->depth, InputOutput, vis->visual, CWColormap|CWBorderPixel|CWBackPixel, &winattribs ); XStoreName(dpy, win, "drawpixels test"); XSelectInput(dpy, win, ExposureMask | StructureNotifyMask | KeyReleaseMask ); XMapWindow( dpy, win ); XFlush( dpy ); ctxt = glXCreateContext( dpy, vis, 0, GL_TRUE ); glXMakeCurrent(dpy, win, ctxt); glViewport(0, 0, (GLint)w, (GLint)h); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho(0, w, 0, h, -1, +1); glRasterPos2f(0.0, 0.0); return win; } int main(int argc, char **argv) { Display *dpy = XOpenDisplay(NULL); Window win; GLenum gltype = GL_RGBA; GLenum glformat = GL_UNSIGNED_BYTE; int i,j; int w = 300; int h = 300; int x = 0; int y = 0; char *buf,*ptrbuf,*buf2,*ptrbuf2; win = makewindow(dpy,w,h,x,y); buf = (char*) malloc(w*h*4*sizeof(char)); ptrbuf = buf; for (i=0;i