/*
** ppc.library emulation
** (c)1998-99 Frank Wille <frank@phoenix.owl.de>
**
** Task objects
**
** V0.7  (11.12.1999) phx
**       Pass a lock to PROGDIR in TaskObject for asynchronous PPC tasks.
**       They will have neither a valid PROGDIR nor a current directory
**       under WarpOS otherwise.
** V0.6g (05.12.1999) phx
**       PPCThread structure for spawning a new PPC task from a running
**       TaskObject.
** V0.5d (04.04.1999) phx
**       Stacksize, syncCreator, PPC-MsgPort and startup message.
**       Added MPSemaphore for multi-processor write access.
** V0.5b (12.02.1999) phx
**       Ext_UserData.
** V0.4c (22.01.1999) phx
**       TaskObject is finally being used. :)
**       The TaskObject will be passed in r2. A pointer to the TaskObject
**       is then stored in tc_UserData of the WarpOS task structure.
** V0.1  (15.11.1998) phx
**       First partially working ppc.library emulation. Synchronous PPC
**       tasks, started by runelf, which only use the basic PowerUp kernel
**       functions for I/O, memory and context-switch seem to work fine.
** V0.0  (10.11.1998) phx
**       created
*/

#ifndef TASKOBJECT_H
#define TASKOBJECT_H

#ifndef ELFOBJECT_H
#include "elfobject.h"
#endif
#ifndef MSGSYSTEM_H
#include "msgsystem.h"
#endif
#ifndef MPSEMA_H
#include "mpsema.h"
#endif

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif
#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif
#ifndef DOS_DOSTAGS_H
#include <dos/dostags.h>
#endif


struct TaskObject {
  struct Node n;                /* contains task name and priority */
  UBYTE flags;
  UBYTE id;                     /* used to check a TaskObject pointer */
  struct MPSemaphore mpSema;    /* cpu/task write-access arbitration */
  struct ElfObject *elf;
  struct Task *m68kParent;      /* parent 68k process, for sync. tasks */
  APTR start_addr;              /* ptr to the task's first instruction */
  ULONG stacksize;
  ULONG args[8];                /* r3 - r10 */
  struct Library *PPCBase;      /* our library base */
  BPTR inputhandle;             /* the standard I/O handles */
  BPTR outputhandle;
  BPTR errorhandle;
  BPTR progdirLock;             /* PROGDIR: lock from parent */
  struct PPCMessage *startup;
  void *msg_data;               /* only relevant, if we really have a */
  ULONG msg_length;             /*  startup msg (PPCTASKTAG_STARTUP_MSG) */
  ULONG msg_id;
  char reserved2[32];
/* PPC-only data below */
  struct TaskPPC *this;
  APTR initialstack;            /* ptr to task's initial V.4 stack frame */
  APTR exit_addr;               /* function to call on PPCFinishTask() */
  struct PPCMsgPort *ppc_port;  /* automatically created MsgPort */
  ULONG Ext_UserData;
  char reserved3[32];
};

#define TskObj_idMagic 0xa5

#define TskObjB_Async     7   /* Asynchronous TaskObject */
#define TskObjF_Async     (1<<7)
#define TskObjB_Enq       6   /* TaskNode is enqueued in TaskObjects list */
#define TskObjF_Enq       (1<<6)
#define TskObjB_MsgPort   5   /* create a MsgPort for the PPC task */
#define TskObjF_MsgPort   (1<<5)
#define TskObjB_breaksigs 3
#define TskObjF_breaksigs (1<<3)
#define TskObjB_closeerr  2
#define TskObjF_closeerr  (1<<2)
#define TskObjB_closeout  1
#define TskObjF_closeout  (1<<1)
#define TskObjB_closeinp  0
#define TskObjF_closeinp  (1<<0)


struct PPCThread {
  ULONG magicID;
  struct TaskObject *parentTask;
  APTR pc;                      /* program counter, where to start exec. */
};

#define THREAD_MAGIC      0x54485244    /* 'THRD' */


#endif /* TASKOBJECT_H */
