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) ;
}