Skip to content

Instantly share code, notes, and snippets.

Created November 10, 2011 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/1355321 to your computer and use it in GitHub Desktop.
Save anonymous/1355321 to your computer and use it in GitHub Desktop.
Example program for the NP_StartupMsg and NP_TaskMsgPort features
/* procmessages.c - Example program for the NP_StartupMsg and NP_TaskMsgPort
* features
*
***************************************************************************
***************************************************************************
***************************************************************************
***************************************************************************
*
* TASKTAG_STARTUPMSG / NP_StartupMsg / TASKINFOTYPE_STARTUPMSG
*
* Startup message to be passed to task/process, ReplyMsg'd at RemTask().
* ti_Data: struct Message *
*
* TASKTAG_STARTUPMSG is used with AddTask()'s struct TaskInitExtension
* taglist. NP_StartupMsg is used with CreateNewProc() taglist.
*
* You can get pointer to this message with NewGetTaskAttrs()
* TASKINFOTYPE_STARTUPMSG.
*
***************************************************************************
***************************************************************************
***************************************************************************
***************************************************************************
*
* TASKTAG_TASKMSGPORT / NP_TaskMsgPort / TASKINFOTYPE_TASKMSGPORT
*
* Create internal MsgPort for task/process, deleted at RemTask().
* ti_Data: struct MsgPort **, can be NULL, in which case no local pointer
* is saved. Use NULL if you don't need the MsgPort pointer in the parent
* task/process.
*
* TASKTAG_TASKMSGPORT is used with AddTask()'s struct TaskInitExtension
* taglist. NP_TaskMsgPort is used with CreateNewProc() taglist.
*
* You can get pointer to this msgport with NewGetTaskAttrs()
* TASKINFOTYPE_TASKMSGPORT.
*
***************************************************************************
***************************************************************************
***************************************************************************
***************************************************************************
*
* A WORD OF WARNING
*
* These new tags are only available in morphos-20020827.lha and later
* releases.
*
***************************************************************************
***************************************************************************
***************************************************************************
***************************************************************************
*
* Written by Harry Sintonen.
*/
#define USE_INLINE_STDARG
#include <exec/nodes.h>
#include <exec/ports.h>
#include <exec/tasks.h>
#include <exec/libraries.h>
#include <exec/devices.h>
#include <exec/execbase.h>
#include <devices/timer.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <proto/exec.h>
#include <proto/dos.h>
/* exec/tasks.h new stuff
*/
#ifndef TASKTAG_STARTUPMSG
#define TASKTAG_STARTUPMSG (TAG_USER + 0x100000 + 0x18)
#define TASKTAG_TASKMSGPORT (TAG_USER + 0x100000 + 0x19)
#endif /* !TASKTAG_STARTUPMSG */
#ifndef TASKINFOTYPE_STARTUPMSG
#define TASKINFOTYPE_STARTUPMSG (0x13)
#define TASKINFOTYPE_TASKMSGPORT (0x14)
#endif /* !TASKINFOTYPE_STARTUPMSG */
/* dos/dostags.h new stuff
*/
#ifndef NP_StartupMsg
#define NP_StartupMsg (TAG_USER + 1000 + 28)
#define NP_TaskMsgPort (TAG_USER + 1000 + 29)
#endif /* !NP_StartupMsg */
#ifndef NP_CodeType
#define NP_CodeType (TAG_USER + 1000 + 100)
#endif /* !NP_CodeType */
/* Custom startup message
*/
struct startupmsg
{
struct Message msg; /* MUST be the first thing in the message */
/* Could be anything here...
*/
LONG delaysecs;
LONG result;
};
/* Protos
*/
int main(void);
void subproc(void);
/* Custom kprintf, output to sushi/sashimi
*/
#if 1
#ifdef kprintf
#undef kprintf
#endif
static const
UWORD __dputch[5] = {0xCD4B, 0x4EAE, 0xFDFC, 0xCD4B, 0x4E75};
#define kprintf(fmt, tags...) \
({ULONG _tags[] = { 0 , ## tags }; RawDoFmt(fmt, (APTR)&_tags[1], \
(void (*)(void)) __dputch, (APTR) SysBase);})
#endif
int main(void)
{
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
int ret;
SysBase = *((struct ExecBase **) 4);
ret = RETURN_FAIL;
DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 50);
if (DOSBase)
{
struct MsgPort *replyport;
Printf("parent: entry.\n");
replyport = CreateMsgPort();
if (replyport)
{
struct startupmsg *msg;
msg = AllocVec(sizeof(struct startupmsg), MEMF_PUBLIC);
if (msg)
{
struct Process *proc;
struct MsgPort *port;
/* Standard message stuff
*/
msg->msg.mn_Node.ln_Type = NT_MESSAGE;
msg->msg.mn_ReplyPort = replyport;
msg->msg.mn_Length = sizeof(struct startupmsg);
/* Set the parameters passed to subproc
*/
msg->delaysecs = 5;
proc = CreateNewProcTags(NP_CodeType, CODETYPE_PPC,
NP_Entry, (ULONG) subproc,
NP_StartupMsg, (ULONG) msg,
NP_TaskMsgPort, (ULONG) &port,
TAG_DONE);
if (proc)
{
struct startupmsg *reply;
/* The port is not really used for anything here, but it could
* be used to pass custom messages to child. Note that port is
* only valid while the subproc is running. The port will
* disappear as soon as the child exit, so you must be careful
* not to screw up if you use it to pass messages. Leaving
* any messages to this port is illegal and will cause Alert()
* at subproc exit.
*/
Printf("parent: port: 0x%lx\n", (ULONG) port);
/* Here we wait for the child process to exit.
*/
Printf("parent: waiting child 0x%lx to exit...\n", (ULONG) proc);
WaitPort(replyport);
/* Obviously if replyport would be shared with something else,
* it could get some other message here. But since this port
* is exclusive for startup message, it can't be anything else.
*/
reply = (struct startupmsg *) GetMsg(replyport);
Printf("parent: got reply startupmsg 0x%lx...\n", (ULONG) reply);
/* Dump the field to show that things can be passed back in
* the message.
*/
Printf("parent: reply->result: %ld\n", reply->result);
ret = RETURN_OK;
}
else
Printf("parent: failed to start the subproc!\n");
/* Note that the message memory MUST only be released after
* receiving the reply. Releasing it before the subproc exit
* will lead to guaranteed crash (or at least random memory
* trash).
*/
FreeVec(msg);
}
else
Printf("parent: no message memory!\n");
DeleteMsgPort(replyport);
}
else
Printf("parent: no replyport!\n");
Printf("parent: exit.\n");
CloseLibrary((struct Library *) DOSBase);
}
else
kprintf("parent: could not open dos.library V50\n");
return ret;
}
void subproc(void)
{
struct ExecBase *SysBase = *(struct ExecBase **) 4;
struct startupmsg *msg;
kprintf("child: entry.\n");
/* Get the startup message passed with NP_StartupMsg.
*/
if (NewGetTaskAttrs(NULL, &msg, sizeof(struct startupmsg *),
TASKINFOTYPE_STARTUPMSG,
TAG_DONE) && msg)
{
struct MsgPort *port;
kprintf("child: startupmsg: 0x%lx\n", (ULONG) msg);
/* Set default result
*/
msg->result = FALSE;
/* Get the msgport created by NP_TaskMsgPort.
*/
if (NewGetTaskAttrs(NULL, &port, sizeof(struct MsgPort *),
TASKINFOTYPE_TASKMSGPORT,
TAG_DONE) && port)
{
struct timerequest *ioreq;
kprintf("child: msgport: 0x%lx\n", (ULONG) port);
ioreq = (struct timerequest *) CreateIORequest(port,
sizeof(struct timerequest));
if (ioreq)
{
if (!OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *) ioreq,
0))
{
kprintf("child: waiting %ld seconds using timer.device.\n",
msg->delaysecs);
ioreq->tr_node.io_Command = TR_ADDREQUEST;
ioreq->tr_time.tv_secs = msg->delaysecs;
ioreq->tr_time.tv_micro = 0;
DoIO(&ioreq->tr_node);
/* Just do something to demonstrate you can pass values back to
* parent, too.
*/
msg->result = TRUE;
CloseDevice(&ioreq->tr_node);
}
else
kprintf("child: could not open timer.device!\n");
DeleteIORequest(&ioreq->tr_node);
}
else
kprintf("child: could not create timer iorequest!\n");
/* NOTE: Must not delete the port, it is deleted automagically!
*/
}
else
kprintf("child: oops, no msgport!\n");
}
else
kprintf("child: oops, could not get startupmsg!\n");
kprintf("child: all done, exit.\n");
/* The startup message (msg) is replied by exec.library internally,
* you must *NOT* ReplyMsg() it.
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment