Passing all regs as both input and output regs in gcc inline

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
virusxx

Passing all regs as both input and output regs in gcc inline

Post by virusxx »

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.
User avatar
Pype.Clicker
Member
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

Post by Pype.Clicker »

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...
virusxx

Re:Passing all regs as both input and output regs in gcc inl

Post by virusxx »

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.
User avatar
Pype.Clicker
Member
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

Post by Pype.Clicker »

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 ...
distantvoices
Member
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

Post by distantvoices »

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
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
User avatar
Pype.Clicker
Member
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

Post by Pype.Clicker »

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 ...
distantvoices
Member
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

Post by distantvoices »

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:

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();
}


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.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
User avatar
Pype.Clicker
Member
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

Post by Pype.Clicker »

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 ...
distantvoices
Member
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

Post by distantvoices »

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.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
User avatar
Pype.Clicker
Member
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

Post by Pype.Clicker »

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.
distantvoices
Member
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

Post by distantvoices »

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.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
virusx

Re:Passing all regs as both input and output regs in gcc inl

Post by virusx »

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.
User avatar
Pype.Clicker
Member
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

Post by Pype.Clicker »

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.
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.
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.
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 message ;)
virusx

Re:Passing all regs as both input and output regs in gcc inl

Post by virusx »

Pype.Clicker wrote:
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.
That's fine but that defeats the purpose of using short msg's in registers i,e Speed.
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
Post Reply