Mattise IPC Specification
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
Mattise IPC Specification
I've just drafted up the initial version of the Mattise IPC Specification. It's really basic and hasn't been implemented yet, but I think it's worth putting it up here for you to look at and give constructive criticism about.
It's here.
(the conversion from the Word document into a webpage didn't work quite as nicely as I'd hoped, but it's good enough)
It's here.
(the conversion from the Word document into a webpage didn't work quite as nicely as I'd hoped, but it's good enough)
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Under the assumption that this is indeed a non-blocking call, I miss what would happen if there were no messages? (the buffer isn't filled?), and how to determine that the message received is the same as the one queried by a previous call to message size.SYSCALL_RECVMSG
This system call takes the first message off the message queue and fills a passed buffer with its data. This is a non-blocking call.
Arguments
EAX: 28d
EDI: the address of a local buffer in which to place the new message.
EDX: the maximum count of octets that can be placed into the local buffer.
Return Values
EBX: 0
In either case, I'd return a length of the message (or -1 if none), so that we can pop messages non-blocking and with enough information to allow concurrent receivers.
A second issue is one that has to do when the passed buffer is too small to hold the entire message - will the remainder of the message get discarded, is it kept for subsequent read calls, or will it provide an error code to tell the user that the buffer is too small?
I have to assume that the caller allocated *dat, and that the callee allocates and fills dat->msgbuff.int mattiseRecvMessage( struct RecvMsgData* dat )
Header
#include <mmsg.h>
Parameters
dat: a pointer to a buffer to receive an information structure about the received message
Return Value
The total size of the message data.
To ease the work on the programmer, a set of helpers should be added, a bit like the following:
Code: Select all
int matisseRecvMessage(RecvMsgData * dat);
RecvMsgData * matisseAllocMessage();
void matisseFreeMessage(RecvMsgData * dat);
char * mattisseGetMessageContents(RecvMsgData * dat);
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
The system call does not return a failure code if no messages. I might have to revise that so that I don't try to pop an invalid message off the list.Combuster wrote:Under the assumption that this is indeed a non-blocking call, I miss what would happen if there were no messages? (the buffer isn't filled?), and how to determine that the message received is the same as the one queried by a previous call to message size.
Sounds like a good idea, I was thinking that message receives would be facilitated through the mattiseRecvMessage which performs all this automatically.In either case, I'd return a length of the message (or -1 if none), so that we can pop messages non-blocking and with enough information to allow concurrent receivers.
The system call will put -1 into EBX (this was revised during implementation and I have not updated the spec yet) if the message buffer is too small.A second issue is one that has to do when the passed buffer is too small to hold the entire message - will the remainder of the message get discarded, is it kept for subsequent read calls, or will it provide an error code to tell the user that the buffer is too small?
Again, this is about to be re-implemented (will have to revise the spec) - I probably will have functionality to allocate the message for you.I have to assume that the caller allocated *dat, and that the callee allocates and fills dat->msgbuff.
I'll look into implementing a set of blocking calls. The only reason I haven't used them is because all system calls are via an interrupt (that isn't a trap gate) and doing a while loop with an interrupt call each time doesn't really work too well.Also, a set of blocking calls are useful to have been provided to the software developer rather than needing to be written manually.
The reason I don't use trap gates is to give a rudimentary form of mutual exclusion - for example only one process can write to the console at once.
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
Agreed - I don't see why a system call needs to set errno... You check errno after finding out a function call just failed, if you're coding assembly why would you need to worry about errno?Combuster wrote:You sure you don't need a check on your specifications? That's about the ugliest hack I've heard of in a long time...my crt0 tells the kernel where errno is. So the kernel can set errno itself.
Well, errno needs to be set with the appropriate value when a syscall fails, *somehow*. As far as I can see, there are only 3 ways of doing this.
1. Setting it in the kernel, when the function call fails.
2. Returning the value errno should take (ETOOLONG, etc) as well as the normal function "failed" return value (which differs depending on the function, if you're going by POSIX standards)
3. Returning the new value of errno encoded into the return value (negated or something) and hoping that it doesn't clash with a valid return value.
Many people opt for 2. I couldnt, so I opted for 1.
JamesM
1. Setting it in the kernel, when the function call fails.
2. Returning the value errno should take (ETOOLONG, etc) as well as the normal function "failed" return value (which differs depending on the function, if you're going by POSIX standards)
3. Returning the new value of errno encoded into the return value (negated or something) and hoping that it doesn't clash with a valid return value.
Many people opt for 2. I couldnt, so I opted for 1.
JamesM
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
It shouldn't. As I said before, errno is part of the C library, NOT of the kernel. if you want to report error codes from the kernel, you should use a kernel-specific function.errno needs to be set with the appropriate value when a syscall fails
Even the C99 standard suggests that errno is restricted for use by the C library. Interfering kernel calls might therefore break C99 compliance which is a Bad Thing.
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
A system call is called, for example, like this:
You don't use errno because then assembly language programs (assuming the programmer does not link in system libraries) would not be able to detect reasons for failure...
On the other hand, my libc functionality for message passing can set errno, based on what it reads from the return value of the syscall.
It is your choice how you make it all work though...
Code: Select all
uint32_t ebx;
asm( "int $0x80" : "=b" (ebx) : "a" (27) /*args...*/ );
// ebx = error code on failure, 0 if success
On the other hand, my libc functionality for message passing can set errno, based on what it reads from the return value of the syscall.
It is your choice how you make it all work though...