Subject:
|
Kernel proposal - message passing and signals
|
Newsgroups:
|
lugnet.robotics.rcx.legos
|
Date:
|
Tue, 13 Mar 2001 13:47:28 GMT
|
Viewed:
|
1600 times
|
| |
| |
Hi,
I have been poking around in the legOS kernel and it appears that there
is no formal way to pass messages between tasks - only shared protected
resources through semaphores. I intend to modify the kernel to add the
features descried below. Note that none of this has been tested yet,
and I have probably got some of the wakeup stuff wrong...
- each pdata_t will have three additional fields: waitbits, sigbits
and lockedbits. waitbits contains the "signal bits" the task is
waiting for, sigbits contains the bits it has been sent and
lockedbits contains a record of the signals the task has allocated
(for waiting on messages, signals from other tasks and stuff).
- two functions, alloc_sig() and free_sig() to allocate and free
signal bits in the task structure. These use lockedbits to see
which isgnals are free..
- a function send_sig(pid, signum) which sets the signum bit in
the sigbits field of the specified task.
- a new structure:
struct _message_t {
struct _message_t *next;
struct _message_t *prev;
struct _message_port_t *replyport; // allow for synchronsiation
int message_id; // General purpose id, user controlled
}
#typedef struct _message_t message_t
- a new list, msg_ports, of these structures :
struct _message_port_t {
struct _message_port_t *next;
struct _message_port_t *prev;
struct _message_t *messages;
char *name;
struct _pdata_t *task;
byte signum;
}
#typedef struct _message_port_t message_port_t
- two functions alloc_mp() and free_mp() which create new message
ports, allocate a signal in the parent task and link into the
kernel mp list.
- a functions find_msg_port(char *) which returns a pointer to the
message port with the specified name.
- a new wakeup function:
static wakeup_t tm_waitsig_wakeup(wakeup_t data) {
return cpid -> waitbits & cpid -> sigbits;
}
- and a new sleep:
unsigned int waitsig(byte signals)
{
cpid -> waitbits = signals;
cpid -> sigbits = 0;
return wait_event(&tm_waitsig_wakeup, 0);
}
(note that you can use the return value from this to work
out which signal(s) woke you up..)
- a put_msg(message_port_t, message_t) function which
adds the message to the list of messages in the port and
then uses send_sig() to signal the port owner task.
- a get_msg(message_port_t) which fetches each message
in turn from the port.
- a reply_msg(message_t) which does the same same thing
as put_msg() but the message port used is the one in
message_t -> replyport
How does this work? Well, say that we have two tasks
A and B. They both understand the structure:
struct _exampleData {
message_t exampleMsg;
int dataA;
int dataB;
int result;
}
#typedef struct _exampleData exampleData
task A does:
message_port_t myMP = alloc_mp("PORTA");
if(myMP) {
while(something isn't true) {
sigs = waitsig(1 << myMP -> signum);
if(sigs & (1 << myMP -> signum)) {
while(myMsg = (exampleData *)get_msg(myMP)) {
myMsg -> result = myMsg -> dataA + myMsg -> dataB;
reply_msg((message_t)myMsg);
}
}
}
}
task B can then do something like:
message_port_t waitMP = alloc_mp("PORTB");
if(waitMP) {
if(newMsg = (exampleData *)calloc(1, sizeof(exampleData))) {
newMsg -> dataA = 10;
newMsg -> dataB = 20;
newMsg -> exampleMsg -> replyport = waitMP;
if(aMP = find_msg_port("PORTA")) {
put_msg(aMP, (message_t)newMsg);
waitsig(1 << waitMP -> sigbit);
lcd_int(newMsg -> result);
// now clean up...
Any comments, suggestions? Is this of interest to anyone else?
|
|
1 Message in This Thread:
- Entire Thread on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
|
|
|
|