Passing all regs as both input and output regs in gcc inline
Passing all regs as both input and output regs in gcc inline
hi,
How can i pass all the regs (eax, ebx, ecx edx esi edi and ebp) both as input and output constrant.
In My os I need to pass a message in registers only for short transfers.
int send_message(tid_t tid, message_t msg)
{
register int ret;
__asm__ __volatile__(
"int $0x30\n\t"
// "pushl %%eax\n\t"
"movl %%ebp, %%eax\n\t"
"movl %%eax, %5\n\t"
// "popl %%eax"
:"=a"(ret), "=c"(msg->w1),"=d"(msg->w2), "=D"(msg->w4), "=S"(msg->w3),"=g"(msg->w5)
:"0"(SYS_RECEIVE_MESSAGE | (msg->flags << 16)), "3"(msg->w4), "b"(tid), "1"(msg->w1),"2"(msg->w2), "4"(msg->w3),"5"(msg->w5)
);
if(ret < 0)
{
errno = -ret;
return -1;
}
return ret;
}
The results are unexpected.
Can anybody help???
BTW: I have heard gcc 3.x produces invalid codes. I am using gcc 3.3.
Thanks in Advance.
How can i pass all the regs (eax, ebx, ecx edx esi edi and ebp) both as input and output constrant.
In My os I need to pass a message in registers only for short transfers.
int send_message(tid_t tid, message_t msg)
{
register int ret;
__asm__ __volatile__(
"int $0x30\n\t"
// "pushl %%eax\n\t"
"movl %%ebp, %%eax\n\t"
"movl %%eax, %5\n\t"
// "popl %%eax"
:"=a"(ret), "=c"(msg->w1),"=d"(msg->w2), "=D"(msg->w4), "=S"(msg->w3),"=g"(msg->w5)
:"0"(SYS_RECEIVE_MESSAGE | (msg->flags << 16)), "3"(msg->w4), "b"(tid), "1"(msg->w1),"2"(msg->w2), "4"(msg->w3),"5"(msg->w5)
);
if(ret < 0)
{
errno = -ret;
return -1;
}
return ret;
}
The results are unexpected.
Can anybody help???
BTW: I have heard gcc 3.x produces invalid codes. I am using gcc 3.3.
Thanks in Advance.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
first troulbesome thing is the "=g" for the 5th message argument ... You'll let the compiler chose the register freely (if any degree of freedom is left), and it may chose a different register everytime.
Moreover, i fail to see why you toy with %eax and %ebp in your code...
In addition, i don't see a good reason for storing back things in the message ... Maybe you should try to send an asynchronous (with no reply) message before you try to perform a synchronous send-then-receive-response...
Moreover, i fail to see why you toy with %eax and %ebp in your code...
In addition, i don't see a good reason for storing back things in the message ... Maybe you should try to send an asynchronous (with no reply) message before you try to perform a synchronous send-then-receive-response...
Re:Passing all regs as both input and output regs in gcc inl
yes,
The code is too bad. Because i did not know how to do it properly.
I am working now for synchronous message.
I will think about asynchronous.... thanks for suggestion.
Is there any way to do it???
Thanks in Advance.
The code is too bad. Because i did not know how to do it properly.
I am working now for synchronous message.
I will think about asynchronous.... thanks for suggestion.
Is there any way to do it???
Thanks in Advance.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
well, for asynchronous messages, you simply send the message and pray. That means no response is expected and the caller has no guarantee the message was ever delivered.
that means, for your code, that you can simply have the "set arguments in registers" part, and not the "get back response in arguments" aswell ...
that means, for your code, that you can simply have the "set arguments in registers" part, and not the "get back response in arguments" aswell ...
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
the stuff with passing args in registers is fine as long as you only intend to send very short messages away.
You can have it the following way:
a. store the values away internally in a queue dedicated to the receiving thread and let the sending thread stroll away.
b. have the message passing mechanism check, if the receiving thread is receiving:
if yes - copy the message over to the receivers adress space without storing it anywhere
if no - block the sender and attach it to the fifo queue of senders of the receiving thread. when the receiving thread is receiving, the message passing system picks one sender for each receive, transfers the message data from sender to receiver and - if receiver is blocked - sets it running. If no senders are waiting for dispatch of their message, block the receiver and give it state RECEIVING
you can do this with registers or keep somewhere in process memory a structure message_t and pass a pointer to it to the message passing subsystem - and have it copy the data along. - well, minix is doing it this way.
HtH & ccw
You can have it the following way:
a. store the values away internally in a queue dedicated to the receiving thread and let the sending thread stroll away.
b. have the message passing mechanism check, if the receiving thread is receiving:
if yes - copy the message over to the receivers adress space without storing it anywhere
if no - block the sender and attach it to the fifo queue of senders of the receiving thread. when the receiving thread is receiving, the message passing system picks one sender for each receive, transfers the message data from sender to receiver and - if receiver is blocked - sets it running. If no senders are waiting for dispatch of their message, block the receiver and give it state RECEIVING
you can do this with registers or keep somewhere in process memory a structure message_t and pass a pointer to it to the message passing subsystem - and have it copy the data along. - well, minix is doing it this way.
HtH & ccw
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
just in case you're interested, i've updated http://www.osdev.org/osfaq2/index.php/Message%20Passing on the FAQ.
One thing i'm not comfortable with considering register-contained message passing is how one can efficiently design the process switch if up to 4 registers are clobbered with message data ...
One thing i'm not comfortable with considering register-contained message passing is how one can efficiently design the process switch if up to 4 registers are clobbered with message data ...
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
Hm ... the content of the registers is saved into the task control block anyway, so I'd pick eax,ebx,ecx,edx from there and transfer 'em over to the receiving process like this:
that's an out of the head code piece of how one *could* implement receive() with syncronous message passing. Error checking not included. Pls have care of the queue manipulations! Maybe I give it a try. My own implementation is ... a bit heap intensive.
I wouldn't care so much about the state of the registers - me sdoes software taskswitching, so I might sound reckless: important is, that they are not to be overwritten/popped back by gcc. I reckon that's what the clobber list tells: don't push/pop those registers, I'm overwriting them on purpose.
But I strongly recommend to have the sending and receiving in two functions of their own. and eventually have a wrapper function carry out the send_receive() functionality.
Code: Select all
void receive(void){
task_t *receiving;
task_t *sender;
receiving=p; //our global process pointer. Just save it awy for the heck of it.
if(receiving->sending.head!=NULL){
sender=receiving->sending.head;
receiving->sending.head=receiving->sending.head->snd_next;//advance.
receiving->context.eax=sender->context.eax;
receiving->context.ebx=sender->context.ebx;
receiving->context.ecx=sender->context.ecx;
receiving->context.edx=sender->context.edx;
if(sender->state==BLOCKED_SENDING){
unblock(sender);
}
get_running_task();
}
void send(void){
task_t *receiving;
task_t *sender;
sender=p; //our global process pointer. Just save it awy for the heck of it.
if(receiving->sending.msg_from==sender->pid||
receiving->state==RECEIVING_BLOCKED){ //either messege from desired sender or blocked due to empty queue: we dispatch immediately and stroll off.
receiving->context.eax=sender->context.eax;
receiving->context.ebx=sender->context.ebx;
receiving->context.ecx=sender->context.ecx;
receiving->context.edx=sender->context.edx;
unblock(receiver);
}else{
block(sender);
sender->state=SENDING_BLOCKED;
//attach it to the queue of sending task
sender->snd_next=NULL;
receiver->sending.tail->snd_next=sender;
receiver->sending.tail=sender;
}
get_running_task();
}
I wouldn't care so much about the state of the registers - me sdoes software taskswitching, so I might sound reckless: important is, that they are not to be overwritten/popped back by gcc. I reckon that's what the clobber list tells: don't push/pop those registers, I'm overwriting them on purpose.
But I strongly recommend to have the sending and receiving in two functions of their own. and eventually have a wrapper function carry out the send_receive() functionality.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
Yeap. I'll have to do some refactoring too... I have barely used the "events" subsystem of Clicker so far and it's quite a pain to deal with (not mentionning the two AVL lookup for message dispatching :-/)
I feel like the "ports" abstraction is the key solution to my problem ...
I feel like the "ports" abstraction is the key solution to my problem ...
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
Events ... I use them as a quick solution to the problem of having to dispatch GUI events to GUI loopers or single threaded applications.
Basically one sends an event and sets off with other stuff. If the event is fetched is not of our interest.
Currently, I have someone doing event handling stuff install an event handler - which acts like a signal handler so that the current stream of operation is interrupted and the event handler s active - as long as there are events in the queue. Don't know if it's a good approach. It works, thats all.
so I could change over to sync message passing for the other stuff.
Basically one sends an event and sets off with other stuff. If the event is fetched is not of our interest.
Currently, I have someone doing event handling stuff install an event handler - which acts like a signal handler so that the current stream of operation is interrupted and the event handler s active - as long as there are events in the queue. Don't know if it's a good approach. It works, thats all.
so I could change over to sync message passing for the other stuff.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
initially, i had functions to install events handlers, and so on. The event processing engine was using the event code to retrieve the handler description and then called the handler code with the event data (which were 3 or 4 words, iirc)
Unfortunately, as soon as i wished to use events for timeouts, IRQ reporting, etc. i came to the situation where a handler could be called *between* the time where it is registered and the time where we listen for the event reception, etc. requiring additionnal code for blocking events reception until a collection of operations are issued.
Thus the idea would be to revert to a messages-and-port approach. Threads receive message when they wish to do so (and not when the system decides so), and they could select among "peers" or "message types" by assigning different ports to those different peers.
The "ports" thing also allows to avoid "message codes" clash: if you have a dedicated port for GUI events messages, you don't care if the same message code is used by the FS service on the FS-replies port.
Unfortunately, as soon as i wished to use events for timeouts, IRQ reporting, etc. i came to the situation where a handler could be called *between* the time where it is registered and the time where we listen for the event reception, etc. requiring additionnal code for blocking events reception until a collection of operations are issued.
Thus the idea would be to revert to a messages-and-port approach. Threads receive message when they wish to do so (and not when the system decides so), and they could select among "peers" or "message types" by assigning different ports to those different peers.
The "ports" thing also allows to avoid "message codes" clash: if you have a dedicated port for GUI events messages, you don't care if the same message code is used by the FS service on the FS-replies port.
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
If using dedicated memory areas for message passing - and you are using paging and virtual adress space - you gonna have some trouble bringing the message from one location to the other one. That's why I 've implemented this heap intensive thing of storing the messages in kernel heap space.
There comes an idea:
1. we copy the message from user land to a small region of the senders tcb - if the receiver isn't yet receiving - and enqueue it.
2. if the receiver is receiving, we copy the message to the dedicated message region of the receivers tcb and make it ready - the sender strolls away doing else or is receiving himself. as soon as it's the receivers turn, the message is copied to its adress space in the get_running_task() -like function before we iret to the task.
3. upon receive - we are in the receivers adress space - we copy the message into the receivers user space - et voila, here we go.
We could also set up shared memory regions for the message passing. Maybe that's more performant.
There comes an idea:
1. we copy the message from user land to a small region of the senders tcb - if the receiver isn't yet receiving - and enqueue it.
2. if the receiver is receiving, we copy the message to the dedicated message region of the receivers tcb and make it ready - the sender strolls away doing else or is receiving himself. as soon as it's the receivers turn, the message is copied to its adress space in the get_running_task() -like function before we iret to the task.
3. upon receive - we are in the receivers adress space - we copy the message into the receivers user space - et voila, here we go.
We could also set up shared memory regions for the message passing. Maybe that's more performant.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:Passing all regs as both input and output regs in gcc inl
hello all,
Thanks for the wonderful responses.
First for the synchronous messaes.
I know it has few pitfalls.
In my design the mesages can be short (in regs only), long (memory transfer up to 256 bytes) and MAP (page table mapping).
I rewrote the c code to assembly and now it is working fine.
But can anybody tell which regs MUST be saved here. (i am not using base pointers because i need ebp and eax(0-15) syscall no. and (16-31) flags).
#define MSG_CONST \
pushl %ebp; \
pushl %esi; \
pushl %edi; \
pushl %ebx; \
pushl %eax; \
pushl %ecx; \
movl 28(%esp), %ebx; \
pushl %ebx; \
movl 36(%esp), %ebx; \
movl 0(%ebx), %edi; \
movl 4(%ebx), %esi; \
movl 8(%ebx), %ebp; \
movl 20(%ebx), %edx; \
movl 24(%ebx), %ecx; \
xorl %eax, %eax; \
movw 30(%ebx), %ax; \
popl %ebx; \
shl $16, %eax; \
#define MSG_DEST \
int $0x30; \
movl 32(%esp), %ebx; \
movl %edi, (%ebx); \
movl %esi, 4(%ebx); \
movl %ebp, 8(%ebx); \
movl %edx, 20(%ebx); \
movl %ecx, 24(%ebx); \
popl %ecx; \
popl %eax; \
popl %ebx; \
popl %edi; \
popl %esi; \
popl %ebp; \
ret
syscall_send_message:
MSG_CONST
orl $(SYS_SEND_MESSAGE), %eax
MSG_DEST
syscall_receive_message:
MSG_CONST
orl $(SYS_RECEIVE_MESSAGE), %eax
MSG_DEST
syscall_reply_message:
MSG_CONST
orl $(SYS_REPLY_MESSAGE), %eax
int $0x30
ret
Now, on asynchronous Message Transfer,
How can i make sender receive the messages (short messages). Long and Mapped messages can be done easily but how to implement short messages.
Again, What will the sender do when it sends. for eg in open call. The program cannot continue until it gets reply (fd) from file server.
Thanks in advance.
Thanks for the wonderful responses.
First for the synchronous messaes.
I know it has few pitfalls.
In my design the mesages can be short (in regs only), long (memory transfer up to 256 bytes) and MAP (page table mapping).
I rewrote the c code to assembly and now it is working fine.
But can anybody tell which regs MUST be saved here. (i am not using base pointers because i need ebp and eax(0-15) syscall no. and (16-31) flags).
#define MSG_CONST \
pushl %ebp; \
pushl %esi; \
pushl %edi; \
pushl %ebx; \
pushl %eax; \
pushl %ecx; \
movl 28(%esp), %ebx; \
pushl %ebx; \
movl 36(%esp), %ebx; \
movl 0(%ebx), %edi; \
movl 4(%ebx), %esi; \
movl 8(%ebx), %ebp; \
movl 20(%ebx), %edx; \
movl 24(%ebx), %ecx; \
xorl %eax, %eax; \
movw 30(%ebx), %ax; \
popl %ebx; \
shl $16, %eax; \
#define MSG_DEST \
int $0x30; \
movl 32(%esp), %ebx; \
movl %edi, (%ebx); \
movl %esi, 4(%ebx); \
movl %ebp, 8(%ebx); \
movl %edx, 20(%ebx); \
movl %ecx, 24(%ebx); \
popl %ecx; \
popl %eax; \
popl %ebx; \
popl %edi; \
popl %esi; \
popl %ebp; \
ret
syscall_send_message:
MSG_CONST
orl $(SYS_SEND_MESSAGE), %eax
MSG_DEST
syscall_receive_message:
MSG_CONST
orl $(SYS_RECEIVE_MESSAGE), %eax
MSG_DEST
syscall_reply_message:
MSG_CONST
orl $(SYS_REPLY_MESSAGE), %eax
int $0x30
ret
Now, on asynchronous Message Transfer,
How can i make sender receive the messages (short messages). Long and Mapped messages can be done easily but how to implement short messages.
Again, What will the sender do when it sends. for eg in open call. The program cannot continue until it gets reply (fd) from file server.
Thanks in advance.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Passing all regs as both input and output regs in gcc inl
If you cannot immediately switch to the message's target thread and use thread switch that keeps values in the registers, you'll have to catch those register-passed values, store them in some queue in memory and then later move the content of the queue in registers when the target thread is ready to receive.virusx wrote: How can i make sender receive the messages (short messages). Long and Mapped messages can be done easily but how to implement short messages.
Open is usually a synchronous call. There are reasons where you wish to make it asynchronous (e.g. you're trying to open several remote files at the same time and wish to operate on the first one which is ready), in which case you usually wish to have something like "select" system call which will wait until *one* of the FDs is ready (e.g. until you received a "ready" acknowledgment messageAgain, What will the sender do when it sends. for eg in open call. The program cannot continue until it gets reply (fd) from file server.
Re:Passing all regs as both input and output regs in gcc inl
Pype.Clicker wrote:That's fine but that defeats the purpose of using short msg's in registers i,e Speed.virusx wrote:
If you cannot immediately switch to the message's target thread and use thread switch that keeps values in the registers, you'll have to catch those register-passed values, store them in some queue in memory and then later move the content of the queue in registers when the target thread is ready to receive.
But i think i will stick to the Synchronous message for now and now put efforts on other parts of the Project.
Thank You very much for your Help.
Regards