Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!sri-unix!ctnews!pyramid!decwrl!labrea!rocky!rokicki From: rokicki@rocky.STANFORD.EDU (Tomas Rokicki) Newsgroups: comp.sys.amiga Subject: Spawning tasks which draw . . . Message-ID: <787@rocky.STANFORD.EDU> Date: Wed, 2-Dec-87 01:51:31 EST Article-I.D.: rocky.787 Posted: Wed Dec 2 01:51:31 1987 Date-Received: Sat, 5-Dec-87 14:24:22 EST Organization: Stanford University Computer Science Department Lines: 106 /* * bug.c * * The interlock demonstrated by this program took me over a day to find, * so I thought I'd pass it on to save someone else some pain. * * Be careful with functions that use the blitter in tasks that you plan * to RemTask() from the parent (or someone else!) If the blitter is * allocated when the RemTask() is executed, it will stay allocated and * the system will lock up tighter than a drum. To fix, simply Forbid()/ * Permit() around all the blitter using sections (like a sequence of * Move/Draws.) * * Compile and run this program (Manx). If you run it with the command: * bug * with no arguments, it locks up the machine. If you run it instead with * bug forbid * it will return correctly. The only difference between the two actions * is the void subroutine it launches; one has the Forbid()/Permit() pair, * the other doesn't, thus showing the problem. */ #include#include #include #include #include #include #include #include #include #include #include #include #include #include "functions.h" struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Task *task ; struct RastPort *rastport ; struct Screen *screen ; char *stackmem ; #define STACKSIZE (1000) static struct NewScreen newscreen = { 0, 0, 640, 400, 1, 0, 1, HIRES | LACE | SCREENQUIET, CUSTOMSCREEN, NULL, NULL, NULL, NULL } ; void task1() { geta4() ; while (1) { Move(rastport, 10L, 10L) ; Draw(rastport, 600L, 390L) ; } } void task2() { geta4() ; while (1) { Forbid() ; Move(rastport, 10L, 10L) ; Draw(rastport, 600L, 390L) ; Permit() ; } } main(argc, argv) int argc ; char *argv[] ; { if ((IntuitionBase= (struct IntuitionBase *)OpenLibrary("intuition.library",0L))==NULL || (GfxBase= (struct GfxBase *)OpenLibrary("graphics.library",0L))==NULL || (screen = OpenScreen(&newscreen))==NULL || (task = (struct Task *)AllocMem((long)sizeof(struct Task), MEMF_CLEAR | MEMF_PUBLIC))==NULL || (stackmem = (char *)AllocMem((long)STACKSIZE, MEMF_CLEAR))==NULL) cleanup() ; rastport = &(screen->RastPort) ; task->tc_Node.ln_Pri = -20 ; task->tc_Node.ln_Type = NT_TASK ; task->tc_Node.ln_Name = "Line" ; task->tc_SPLower = (APTR)stackmem ; task->tc_SPUpper = task->tc_SPReg = (APTR)(stackmem + STACKSIZE - 8) ; AddTask(task, (argc > 1 ? task2 : task1), 0L) ; Delay(50L) ; RemTask(task) ; cleanup() ; } cleanup() { if (task) FreeMem(task, (long)sizeof(struct Task)) ; if (stackmem) FreeMem(stackmem, (long)STACKSIZE) ; if (screen) CloseScreen(screen) ; if (IntuitionBase) CloseLibrary(IntuitionBase) ; if (GfxBase) CloseLibrary(GfxBase) ; exit(0) ; }