How to pass variable number of arguments to new processes?

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
rrd
Posts: 6
Joined: Wed Mar 14, 2018 8:07 am

How to pass variable number of arguments to new processes?

Post by rrd »

I'm working on the process management features of a little embedded operating system and I'm stuck on the design of a function that can create processes that run a function with a variable number of parameters. Here's a simplified version of how I want my API to looks like:

Code: Select all

// create a new process
// * function is a pointer to the routine the process will run
// * nargs is the number of arguments the routine takes
void create(void* function, uint8_t nargs, ...);

void f1();
void f2(int i);
void f3(float f, int i, const char* str);

int main()
{
    create(f1, 0);
    create(f2, 1, 9);
    create(f3, 3, 3.14f, 9, "string");

    return 0;
}
And here is a pseudocode for the relevant part of the implementation of system call create:

Code: Select all

void create(void* function, uint8_t nargs, ...)
{
    process_stack = create_stack();
    first_arg = &nargs + 1;
    copy_args_list_to_process_stack(process_stack, first_arg);
}
Of course I'll need to know the calling convention in order to be able to copy from create's activation record to the new process stack, but that's not the problem. The problem is how many bytes do I need to copy. Even though I know how many arguments I need to copy, I don't know how much space each of those arguments occupy. So I don't know when to stop copying.

The Xinu Operating System does something very similar to what I want to do, but I tried hard to understand the code and didn't succeed. I'll transcript a very simplified version of the Xinu's create function here. Maybe someone understand and help me.

Code: Select all

pid32 create(void* procaddr, uint32 ssize, pri16 priority, char *name, int32 nargs, ...)
{
    int32        i;
    uint32      *a;     /* points to list of args   */
    uint32  *saddr;     /* stack address        */

    saddr = (uint32 *)getstk(ssize); // return a pointer to the new process's stack

    *saddr = STACKMAGIC; // STACKMAGIC is just a marker to detect stack overflow

    // this is the cryptic part
    /* push arguments */
    a = (uint32 *)(&nargs + 1);     /* start of args        */
    a += nargs -1;                  /* last argument        */
    for ( ; nargs > 4 ; nargs--)    /* machine dependent; copy args */
        *--saddr = *a--;            /* onto created process's stack */
    *--saddr = (long)procaddr;
    for(i = 11; i >= 4; i--)
        *--saddr = 0;
    for(i = 4; i > 0; i--) {
        if(i <= nargs)
            *--saddr = *a--;
        else
            *--saddr = 0;
    }

    *--saddr = (long)INITRET;	/* push on return address	*/
    
    // prptr->prstkptr is the stack pointer in the PCB
    prptr->prstkptr = (char *)saddr;
}
I got stuck on this line:

Code: Select all

a += nargs -1;
This should move the pointer a 4*(nargs - 1) ahead in memory, right? What if an argument's size is not 4 bytes? But that is just the first question. I also didn't understand the next lines of the code.
thomasloven
Member
Member
Posts: 89
Joined: Tue Feb 26, 2008 10:47 am
Location: Sweden

Re: How to pass variable number of arguments to new processe

Post by thomasloven »

A common way of passing arguments to new processes is in string form.
Otherwise you'll have to revise your API to somehow specify the type of each argument as well. A printf-like format string, perhaps?
rrd
Posts: 6
Joined: Wed Mar 14, 2018 8:07 am

Re: How to pass variable number of arguments to new processe

Post by rrd »

thomasloven wrote:Otherwise you'll have to revise your API to somehow specify the type of each argument as well.
How could I do that? Any ideas? I guess I could replace nargs with a parameter that receives the sum of the sizes of all the arguments together. But maybe that is a little hard to use and error prone.
thomasloven wrote:A printf-like format string, perhaps?
A little ugly, but it's an option. The drawback is its inability to handle user defined data types.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: How to pass variable number of arguments to new processe

Post by iansjack »

Concatenate the arguments into a string, whose address you pass on the stack. The startup code for the new process parses this string into the familiar argc, argv parameters,
thomasloven
Member
Member
Posts: 89
Joined: Tue Feb 26, 2008 10:47 am
Location: Sweden

Re: How to pass variable number of arguments to new processe

Post by thomasloven »

rrd wrote:
How could I do that? Any ideas? [...]
thomasloven wrote:A printf-like format string, perhaps?
That... was my idea...
rrd
Posts: 6
Joined: Wed Mar 14, 2018 8:07 am

Re: How to pass variable number of arguments to new processe

Post by rrd »

thomasloven wrote: That... was my idea...
OK! Thanks!
rrd
Posts: 6
Joined: Wed Mar 14, 2018 8:07 am

Re: How to pass variable number of arguments to new processe

Post by rrd »

iansjack wrote:Concatenate the arguments into a string, whose address you pass on the stack. The startup code for the new process parses this string into the familiar argc, argv parameters,
I liked your idea. I'll try!
Post Reply