Neon IPC and why it was ... replaced.
Posted: Thu Jun 30, 2005 9:48 am
Neon IPC-system used to be a fairly compilicated single-function send/receive synchronous rendezvous thingie.
Anyway, there where four practical difficulties:
- correct, not to mention efficient use of the facility would have been hard. I mean, hard as in "hard even if you designed it".
- implementation of such a system efficiently (and correctly) is tricky, especially if things like realtime concerns and user pagers become part of the mess
- any kind of asynchronous operation whatsoever would require an additional helper process
- the whole mess was almost impossible to use from kernel space
So what happened was that sometime yesterday, I thought: "ok, who cares if I queue messages in kernel space". So what I have now is possibly the most simple message passing system that could possibly work, and still be reasonably flexible and secure:
1. There are "objects" which are really <dispatchFn,userdata> pairs.
2. There are also "handles", which are like remote pointers to objects. You can only use "handles" for sending message to the object. Within a single process, one can use object pointers directly in place of handles.
3. Each message is a 4-tuple <object, op, w1, w2> where op is a hashed operation code (generated with 'nifgen'). W1 and w2 are two paramaters. The first is (currently) always an integer, while the second can hold (currently) either an integer, a pointer to message data structure, or a handle.
4. Each thread has a message queue. Each object is owned by some thread. Any messages to an object are stored in it's owner's message queue.
5. One can either get any kind of message, or filter by specific object, or by specific message code. Messages are received in FIFO order. When filtering is used, non-matching messages are kept in the queue for the future.
The whole system is actually a bit like a cross-breed between Windows PostMessage/GetMessage-stuff, and COM like architecture.
On user level, the main interface looks like this:
The op-code is a combination of a hash, and few bits of type-information, generated by 'nifgen', such that the system automatically knows what type of information w2 contains.
The most interesting part is that lots of stuff in kernel that was previously special cased is now trivially implemented in terms of the message system. For example, the "sleep" function really just installs a timer, and waits for timer completion message.
The system is more or less implemented, and more or less seems to work. From theoretical standing point it is nowhere near as pure as the old one, but at least it's not totally awful either. And it sure makes things quite easy.
Anyway, there where four practical difficulties:
- correct, not to mention efficient use of the facility would have been hard. I mean, hard as in "hard even if you designed it".
- implementation of such a system efficiently (and correctly) is tricky, especially if things like realtime concerns and user pagers become part of the mess
- any kind of asynchronous operation whatsoever would require an additional helper process
- the whole mess was almost impossible to use from kernel space
So what happened was that sometime yesterday, I thought: "ok, who cares if I queue messages in kernel space". So what I have now is possibly the most simple message passing system that could possibly work, and still be reasonably flexible and secure:
1. There are "objects" which are really <dispatchFn,userdata> pairs.
2. There are also "handles", which are like remote pointers to objects. You can only use "handles" for sending message to the object. Within a single process, one can use object pointers directly in place of handles.
3. Each message is a 4-tuple <object, op, w1, w2> where op is a hashed operation code (generated with 'nifgen'). W1 and w2 are two paramaters. The first is (currently) always an integer, while the second can hold (currently) either an integer, a pointer to message data structure, or a handle.
4. Each thread has a message queue. Each object is owned by some thread. Any messages to an object are stored in it's owner's message queue.
5. One can either get any kind of message, or filter by specific object, or by specific message code. Messages are received in FIFO order. When filtering is used, non-matching messages are kept in the queue for the future.
The whole system is actually a bit like a cross-breed between Windows PostMessage/GetMessage-stuff, and COM like architecture.
On user level, the main interface looks like this:
Code: Select all
// Send a message
int SendMessage(HNDL hTarget, MWORD op, MWORD w1, MWORD w2);
// dispatcher function
typedef int (*dispatchFn)(Object *, MWORD, MWORD, MWORD);
The most interesting part is that lots of stuff in kernel that was previously special cased is now trivially implemented in terms of the message system. For example, the "sleep" function really just installs a timer, and waits for timer completion message.
The system is more or less implemented, and more or less seems to work. From theoretical standing point it is nowhere near as pure as the old one, but at least it's not totally awful either. And it sure makes things quite easy.