CS452 - Real-Time Programming - Fall 2008
Lecture 11 - Send/Receive/Reply
Questions & Comments
Producer/Consumer
Two ways to do this
- Producer
Send
s, consumer
Receives
Send
means "Here is some data"
Receive
means "I'm ready to receive data"
Reply
means "I got the data"
After Reply
buffers holding data can be overwritten at
will
- Producer
Receive
s and Reply
s
Send
means "I'm ready for data"
Receive
means "I'm ready to transmit data"
Reply
means "Here's the data"
After Reply
buffers can be overwritten at will.
What is the difference?
- If relationship is one-to-one
- If relationship is many-to-one
- the one doing many MUST
Receive
.
- If relationship is many-to-many
- there must be an extra component that Receives from both
int Send( Tid tid, char *arg, int arg-length, char *reply-buffer, int
reply-buffer-size )
These are pretty self explanatory, except
- The return value is the number of characters actually placed in the
reply-buffer
- including the \0 if the contents of the reply buffer is a
string
- If something goes wrong, the return value is negative, coded to
indicate what went wrong
What can go wrong
- Illegal
tid
tid
not an existing task
It's up to Send
to check that the reply-buffer was big
enough by looking at its return value
It's not an error if the task to which we Send
never
Receive
s
- Parsing
argument
and reply-buffer
is
potentially costly and error-prone
- A type system might be nice
- But then you would feel compelled to implement run-time type
checking
- This form of message passing requires user and kernel code to cooperate
to avoid malignancies
- which is just barely okay when one implementer does both
- but is otherwise monumentally insecure
Implementing Send
What's in application space is just stubs.
- checking arguments
- putting arguments in the right place
What the kernel must do
- Check arguments
- Change state of sender to RECEIVE_BLOCKED
- Put sender on receiver's sendQ
- If receiver is SEND_BLOCKED, do 3 in receiver
- Wait for Reply
int Receive( Tid *tid, char *arg-buffer, int arg-buffer-length )
These are pretty self explanatory, except
- How is the task id copied form kernel to receiver?
- That is, where does the pointer point to?
- What if the buffer wasn't big enough?
- If several tasks have
Send
ed, which one gets
Receive
d first?
- return value is number of bytes in message, including \0.
Implementing Receive
What the kernel must do
- Check the sendQ
- If SENDQ_EMPTY
- change state to SEND_BLOCKED
- Wait for Send
- sendQ is not empty
- sender = head( sendQ )
sendQ = next( sendQ )
- copy message from sender to receiver, after checking buffer
sizes
- change sender's state to REPLY_BLOCKED
- put sender's tid into receiver's variable
- put receiver on readyQ
- set up receiver's return value
- change receiver's state to READY
int Reply( Tid tid, char *reply, int reply-length )
These are pretty self explanatory.
Implementing Reply
- Check arguments
- sender (tid) must be REPLY_BLOCKED
- Copy message from replier to sender, checking buffer sizes
- Put sender on readyQ
- Set up sender's return value
- Change sender's state to READY
- Put replier on readyQ
- Set up replier's return value
- replier 's state is already ready
Return to: