[comp.sys.amiga] PutMsg and the ln_Type field

dillon@CORY.BERKELEY.EDU (Matt Dillon) (03/26/88)

	I seem to remember somebody commenting that PutMsg() did not
	always set the ln_Type field in the message to NT_MESSAGE...
	I looked at the ROM code.  The very first thing PutMsg does
	is:

		move.b #5,8(A1)

	Which places NT_MESSAGE on the ln_Type field of the message.
	Therefore, PutMsg() *always* does this.  This means you can
	write an equivalent for WaitIO() for messages, since ReplyMsg()
	will modify the ln_Type to NT_REPLYMSG (NT_FREEMSG if there is not 
	replyport).

	This example works for PA_SIGNAL replyports only.  Note that I
	check the type first.  If the type is NT_MESSAGE, than the
	message has not been replied yet and thus we can use Wait() since
	we are guarenteed a signal.  The Forbid()/Permit() pair is needed
	for the routine to work properly with tasks which use exception
	handlers (so the Wait signal is not prematurely removed in the
	condition loop).  The Disable()/Enable() pair is needed for the
	routine to work in tandem with interrupts (an interrupt decides
	to send a message to that particular port).

	In my dealings with signals, I've always thought they should
	reflect a certain amount of real information.  thus, I restore
	the signal if messages still exist on the port so the rest of the
	program doesn't have to check the port first before going into
	its master Wait() loop.

	WaitMsg(msg)
	MSG *msg;
	{
	    register PORT *port = msg->mn_ReplyPort;
	    register long mask = 1 << port->mp_SigBit;

	    Forbid();
	    while (msg->mn_Node.ln_Type == NT_MESSAGE)
		Wait(mask);
	    Permit();
	    Disable();
	    Remove(msg);
	    Enable();
	    if (port->mp_MsgList.lh_Head != (NODE *)&port->mp_MsgList.lh_Tail)
		SetSignal(mask, mask);
	}

	This is something one would probably want to do in assembly.

					-Matt

rminnich@udel.EDU (Ron Minnich) (03/29/88)

In article <8803260947.AA25241@cory.Berkeley.EDU> dillon@CORY.BERKELEY.EDU (Matt Dillon) writes:
>	I seem to remember somebody commenting that PutMsg() did not
>	always set the ln_Type field in the message to NT_MESSAGE...
>	I looked at the ROM code.  The very first thing PutMsg does
>	is:
>		move.b #5,8(A1)
>	Which places NT_MESSAGE on the ln_Type field of the message.
>	Therefore, PutMsg() *always* does this.  This means you can
   Well, what can i say. That was me who wrote that. And on my
system, SendIO (which i thought called PutMsg) did not set the 
type to NT_MESSAGE. I had to set it by hand in internet.device,
else the type was always NT_REPLYMSG. 
   What is going on here? I don't know. ALl i know is that
on my machine, in the driver, i had to jam the message type
else it never changed back from NT_REPLYMSG.

-- 
ron (rminnich@udel.edu)

dillon@CORY.BERKELEY.EDU (Matt Dillon) (03/29/88)

>   Well, what can i say. That was me who wrote that. And on my
>system, SendIO (which i thought called PutMsg) did not set the 
>type to NT_MESSAGE. I had to set it by hand in internet.device,
>else the type was always NT_REPLYMSG. 
>   What is going on here? I don't know. ALl i know is that
>on my machine, in the driver, i had to jam the message type
>else it never changed back from NT_REPLYMSG.

	Ah Hah!  SendIO() doesn't call PutMsg(), it calls the BeginIO()
entry for the device with IOF_QUICK cleared.  The device then does whatever 
it wants.   Some devices just AddTail() the request to some queue for
processing by an interrupt, or do the request synchronously and then 
ReplyMsg() it.  Thus, you must set the ln_Type field of the request to
NT_MESSAGE yourself before dispatching it with SendIO().  (I.E. don't
trust the device designers to have remembered that little detailed).

	I'll bet a lot of people got caught by that!

						-Matt