/*
** compiles with inline only in large data! AddTask() uses too many
** nonscratch registers :( use of assembler version is recommended
*/
#include <exec/tasks.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <clib/alib_protos.h>
#include <proto/exec.h>

struct ExecBase *SysBase;

struct newMemList
{
  struct Node nml_Node;
  UWORD nme_NumEntries;
  struct MemEntry nml_ME[2];
};

const struct newMemList MemTemplate =
{ {0,},
  2,
  { {MEMF_CLEAR|MEMF_PUBLIC, sizeof(struct Task)},
    {MEMF_CLEAR, 0} }
};

struct Task *CreateTask(STRPTR name, LONG pri, APTR initpc, ULONG stacksize)
{
  struct Task *newtask,*task2;
  struct newMemList nml;
  struct MemList *ml;

  stacksize=(stacksize+3)&~3;
  {
    long *p1,*p2;
    int i;

    for (p1=(long *)&nml,p2=(long*)&MemTemplate,i=7; i; *p1++=*p2++,i--) ;
    *p1=stacksize;
  }
/*  if (!(((unsigned int)ml=AllocEntry((struct MemList *)&nml)) & (1<<31)))*/
/*  was dieser gcc alles als lvalue durchgehen laesst...    */
  ml=AllocEntry((struct MemList *)&nml);
  if(!((unsigned int)ml&(1<<31)))
  {
    newtask=ml->ml_ME[0].me_Addr;
    newtask->tc_Node.ln_Type=NT_TASK;
    newtask->tc_Node.ln_Pri=pri;
    newtask->tc_Node.ln_Name=name;
    newtask->tc_SPReg=(APTR)((ULONG)ml->ml_ME[1].me_Addr+stacksize);
    newtask->tc_SPLower=ml->ml_ME[1].me_Addr;
    newtask->tc_SPUpper=newtask->tc_SPReg;
    NewList(&newtask->tc_MemEntry);
    AddHead(&newtask->tc_MemEntry,(struct Node *)ml);
    task2=(struct Task *)AddTask(newtask,initpc,0);
    if (SysBase->LibNode.lib_Version>36 && !task2)
    {
      FreeEntry(ml); newtask=NULL;
    }
  }
  else
    newtask=NULL;

  return newtask;
}

