[comp.sys.amiga.programmer] message ports seeing the future?

Paul Miller <pmiller@vttcf.cc.vt.edu> (05/09/91)

I'm having a bit of difficulty with a project I am working on and am wondering
if anyone can offer some advice.

This deals with a task I've developed which handles playing sequences of
samples strung together to may break-free music - it does it's own port
allocations and such - you just build up a sequence of sections of the total
song (each having it's own sample and number of cycles to play) and tell the
task to GO. Additionally you can WAIT on a particular section of the sequence
to be played, and have YOUR application signalled. This system originally
worked fine, until I added some other features (such as the ability to WAIT a
specific number of seconds after a section has played).

However, now (and this is untested outside of the application I'm using the
module in), when I tell the task to wait on a particular section, my app gets
signalled BEFORE the cycles actually complete. This obviously screws up the
timing in the program, with things happening on-screen before they're supposed
to, and in some cases, where something is supposed to happen within a given
interval, the audio will go into an endless loop, cycling the same sample over
and over, because I've told it to wait on something that's already been played
(I have checks for this - each section has a PLAYED flag which gets set after
it's played, but this doesn't keep it from going into the playback loop).

Any suggestions to this problem would be appreciated!
-- 
****************************************************************************
* Paul Miller                       | DISCLAIMER IS BETTER THAN DATCLAIMER *
* VIDEOWORKS Computer Applications  | ------------------------------------ *
* Certified AMIGA Developer         |  My opinions are mine own, and not   *
* --------------------------------- | those of those who are not me (um?)  *
* INTERNET: pmiller@vttcf.cc.vt.edu |     - Have a JOLT and a smile! -     *
* ------------------------------------------------------------------------ *
*    Origin: MILLIWAYS, The Restaurant at the End of the Universe! (v42)   *
****************************************************************************

jesup@cbmvax.commodore.com (Randell Jesup) (05/20/91)

In article <24436@know.pws.bull.com> pmiller@vttcf.cc.vt.edu (Paul Miller) writes:
>However, now (and this is untested outside of the application I'm using the
>module in), when I tell the task to wait on a particular section, my app gets
>signalled BEFORE the cycles actually complete. This obviously screws up the
>timing in the program, with things happening on-screen before they're supposed
>to, and in some cases, where something is supposed to happen within a given
>interval, the audio will go into an endless loop, cycling the same sample over
>and over, because I've told it to wait on something that's already been played

	Hmmm.  It's hard to have any reasonable ideas without seeing some of
the code, but in general I'd say you should check that you're not relying
on the port signal to always mean that a message is available in the port.
There are several ways (particularily with device IO, but ways exist with
all ports) that signals can be left set after processing messages - you must
handle the no-messages in port case correctly.

	If that isn't it, I advise posting a snippet of code including the
port-handling.

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com  BIX: rjesup  
Disclaimer: Nothing I say is anything other than my personal opinion.
Thus spake the Master Ninjei: "To program a million-line operating system
is easy, to change a man's temperament is more difficult."
(From "The Zen of Programming")  ;-)

laughlin@fornax.UUCP (Bob Laughlin) (05/21/91)

In article <21732@cbmvax.commodore.com> jesup@cbmvax.commodore.com (Randell Jesup) writes:
#In article <24436@know.pws.bull.com> pmiller@vttcf.cc.vt.edu (Paul Miller) writes:
##However, now (and this is untested outside of the application I'm using the
##module in), when I tell the task to wait on a particular section, my app gets
##signalled BEFORE the cycles actually complete. This obviously screws up the

#	Hmmm.  It's hard to have any reasonable ideas without seeing some of
#the code, but in general I'd say you should check that you're not relying
#on the port signal to always mean that a message is available in the port.
#There are several ways (particularily with device IO, but ways exist with
#all ports) that signals can be left set after processing messages - you must
#handle the no-messages in port case correctly.

    This is mentioned in the 1.3 RKM's as well. On page 285 it says
"It is possible to receive a signal for a port without a message being
present yet." Could you elaborate on this? I understand that retrieving
a message from a reply port with WaitIO() does not clear the ports sigbit,
and it should'nt since there may be other messages there. I'm not sure
what WaitPort() does with the sigbit but I suspect it does'nt clear it
either since it only retrieves the first message. I also know that
the Wait() function DOES clear the signal bits it is waiting on and you
are expected to GetMsg() all the messages queued up after it returns.
I can see how you could get into trouble by leaving a reply port's sigbit
set by using WaitIO() or WaitPort() but my concern is what happens when
you know the bit has been cleared with the Wait() function.

    What happens if another message is added to the reply queue while
you're processing the messages there after Wait() returned? Say your
process is swapped out between processing the 2nd and 3rd replied
message.  Does the signal bit get set again but you GetMsg() the
new message on the old Wait()?

    In other words when Wait() returns after waiting for a sigbit is it
possible for a message to NOT be in the reply port queue? I've been
testing the GetMsg()'s in this situation and have yet to have one fail.
I could see this arising if the device driver or Exec sets the signal
bit before queueing up the message at the reply port but I would have
thought these operations would be in the reverse order or Forbid() /
Permit()'ed. The scenerio described in the previous paragraph would
create the problem as well.

   If it is possible for Wait() to return thus waking your process with
no message in the reply queue it seems to me that you are in big trouble
if you need that message to proceed. You can't do another Wait() since
the sigbit has been cleared. I suppose you could do a WaitIO() on a
particular message(?), or---god forbid---a busy wait for the message
to get attached to the reply port? I'm talking about a situation where
you KNOW an IO message has been sent out and NOT previously retrieved
from the reply port.

   This situation has not occurred in several months of testing
for a failed GetMsg() following a Wait(). Is it possible or
am I misunderstanding that cautionary note in the RKMs?
-- 
 Bob Laughlin  laughlin@cs.sfu.ca 

jesup@cbmvax.commodore.com (Randell Jesup) (05/24/91)

In article <2726@fornax.UUCP> laughlin@lccr.UUCP (Bob Laughlin) writes:
>    This is mentioned in the 1.3 RKM's as well. On page 285 it says
>"It is possible to receive a signal for a port without a message being
>present yet." Could you elaborate on this?

	It's situation-dependant in most cases.  For example, you're
processing messages at a port.  A message comes in, you wake up (clearing
the signal bit), and process it.  While processing it another message
comes in, setting the signal bit again.  You loop back to GetMsg(), and
find a second message, and process it.  You then go and wait, and immediately
return since the signal is set already.  However, there are no messages in the
port.

	Another one: there's no guarantee when you allocate a signal that
it starts clear.

>I'm not sure
>what WaitPort() does with the sigbit but I suspect it does'nt clear it
>either since it only retrieves the first message.

	No, it clears it.  (Essentially it's do { Wait(portbit); msg =
first_message_in_list;} while (!msg); return msg;.)  NOTE: WaitPort
returns a pointer to the first message, but doesn't remove it from the
port.

>I can see how you could get into trouble by leaving a reply port's sigbit
>set by using WaitIO() or WaitPort() but my concern is what happens when
>you know the bit has been cleared with the Wait() function.

	Wait is guaranteed to clear it - but if other messages may come back
to the same port, or if it was set for some other reason (such as being set
when allocated), then you must handle the possibility.  It's possible to set
up a port to which only one message ever comes (and where you cleared the
signal bit first) such that the signal is a reliable indicator of a message
being available, but I recommend against doing this.  It's better to code
defensively, since you may one day make a modification that would remove
a required assumption.

>    What happens if another message is added to the reply queue while
>you're processing the messages there after Wait() returned? Say your
>process is swapped out between processing the 2nd and 3rd replied
>message.  Does the signal bit get set again but you GetMsg() the
>new message on the old Wait()?

	Yup.

>    In other words when Wait() returns after waiting for a sigbit is it
>possible for a message to NOT be in the reply port queue?

	Yup.

> I've been
>testing the GetMsg()'s in this situation and have yet to have one fail.

	Timing is everything in multi-process testing.  Code for correctness
and the timing becomes irrelevant.

>   If it is possible for Wait() to return thus waking your process with
>no message in the reply queue it seems to me that you are in big trouble
>if you need that message to proceed. You can't do another Wait() since
>the sigbit has been cleared.

	We most explicitly don't allow the signal to be set before the message
is available.  PutMsg/etc is protected by Enable and/or Forbid.

-- 
Randell Jesup, Jack-of-quite-a-few-trades, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.cbm.commodore.com  BIX: rjesup  
Disclaimer: Nothing I say is anything other than my personal opinion.
"No matter where you go, there you are."  - Buckaroo Banzai

dillon@overload.Berkeley.CA.US (Matthew Dillon) (05/29/91)

In article <21855@cbmvax.commodore.com> jesup@cbmvax.commodore.com (Randell Jesup) writes:
>In article <2726@fornax.UUCP> laughlin@lccr.UUCP (Bob Laughlin) writes:
>...
>>I'm not sure
>>what WaitPort() does with the sigbit but I suspect it does'nt clear it
>>either since it only retrieves the first message.
>
>	No, it clears it.  (Essentially it's do { Wait(portbit); msg =
>first_message_in_list;} while (!msg); return msg;.)  NOTE: WaitPort
>returns a pointer to the first message, but doesn't remove it from the
>port.

    Uh, I don't think you can say that.  WaitPort() does this:

    while (PortMsgListEmpty) {
	Wait(PortSignalMask)
    }
    return(FirstMessageOnPort)

    Thus, WaitPort() is NOT guarenteed to clear the signal bit.  For this
    and other reasons (the one about looping on GetMsg() before going back
    to Wait() -- which you *MUST* do), you cannot depend on the signal
    bit being in any specific state except that it will be set when a
    message is sent to a port.

    Also note that this guarentees that WaitPort() does not *care* about
    the initial signal state when called, meaning you can safely call it
    at any point in your code without worrying about the signal state.

					    -Matt

>--
>Randell Jesup, Jack-of-quite-a-few-trades, Commodore Engineering.
>{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.cbm.commodore.com  BIX: rjesup
>Disclaimer: Nothing I say is anything other than my personal opinion.
>"No matter where you go, there you are."  - Buckaroo Banzai

--

    Matthew Dillon	    dillon@Overload.Berkeley.CA.US
    891 Regal Rd.	    uunet.uu.net!overload!dillon
    Berkeley, Ca. 94708
    USA

jesup@cbmvax.commodore.com (Randell Jesup) (05/30/91)

In article <dillon.8067@overload.Berkeley.CA.US> dillon@overload.Berkeley.CA.US (Matthew Dillon) writes:
>In article <21855@cbmvax.commodore.com> jesup@cbmvax.commodore.com (Randell Jesup) writes:
>>>I'm not sure
>>>what WaitPort() does with the sigbit but I suspect it does'nt clear it
>>>either since it only retrieves the first message.
>>
>>	No, it clears it.  (Essentially it's do { Wait(portbit); msg =
>>first_message_in_list;} while (!msg); return msg;.)  NOTE: WaitPort
>>returns a pointer to the first message, but doesn't remove it from the
>>port.
>
>    Uh, I don't think you can say that.  WaitPort() does this:

>    Thus, WaitPort() is NOT guarenteed to clear the signal bit.

	Quite true.  I may have misread the question - what I should have said
is that WaitPort may clear the signal bit.  Please excuse that code, it
was written late at night off the cuff.

-- 
Randell Jesup, Jack-of-quite-a-few-trades, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.cbm.commodore.com  BIX: rjesup  
Disclaimer: Nothing I say is anything other than my personal opinion.
"No matter where you go, there you are."  - Buckaroo Banzai