Page 1 of 1

Module calls...

Posted: Fri Jan 24, 2003 4:51 am
by DarylD
I am in the process (actually nearly finished) of restructuring my code to resolve some issues, one of which was the excessive use of structs to pass values from my API library to the kernel. Essentially what I was doing was having an API call like:

int FS_Read(handle, bytes needed)

The above is not actual code but you get the idea. Now what happens next is the FS_Read functions will pack all this into a struct that could be called fsread_t and then this is dropped on the stack and an int 0xXX made where the kernel will then pick up this struct and extract the contents again.

Its fairly standard behaviour but I wan't to do things a little different.

I will have some code in the API (user space) that will create a package of parameters. This will be reused for ALL calls that need to pass data to the kernel. The kernel will then call the necessary function and unpackage all the data.

But, for the example above the kernel FSRead call may take several parameters. What I want to know is, how can I extract contents from this "parameter package" and then pass it directly to the kernel function as separate parameters.

Obviously the issue here is different functions take different parameters.

I assume I need to do something using va_args, but this is not an area I have delved into very much.

Any help would be *muchly* appreciated.

Daryl.

Re:Module calls...

Posted: Fri Jan 24, 2003 6:40 am
by Pype.Clicker
can you explain more precisely what you mean with the 'package' ?
and also how you envision its reuse ?

Re:Module calls...

Posted: Fri Jan 24, 2003 7:06 am
by DarylD
I am probably making this sound more complex than it is!

Basically, in the API function, I would have something like this:

Code: Select all

pack_t sPackage;
AddParameter(&sPackage, PARAMETER_INT, 100);
AddParameter(&sPackage, PARAMETER_INT, 50);
AddParameter(&sPackage, PARAMETER_STRING, &string);
Module_Call(moduleid, callid, &sPackage);
pack_t would be something like a fixed structure holding up to say 16 parameters and their type. It would be passed with the Module_Call function.

Inside the kernel it would check that the package parameters match what is specified when the module call was created. This is not necessary but would at least pick up errors in the API library.

The kernel would then call the necessary function (i.e. maybe a function set as an I/O mount call) and would pass the parameters to it. So for example if the prototype for IORead was:

Code: Select all

KStatus IORead(int num1, int num2, char *string);
I would need a way of mapping the package parameters into the call parameters for IORead.

Does that makes sense?

Its just a simple way of handling variant parameters to different modules without creating a million and one struct's.

Daryl.

Re:Module calls...

Posted: Fri Jan 24, 2003 7:38 am
by distantvoices
you could implement messaging.

system calls will be transferred to messages passed to the responsible subsystem(fs,mm,etc). The kernel should this message passing.

the IO subsystem is responsible for all the nitty gritty, neither the kernel nor the user that issues the api call needs to know about, so it knows about what to do with a message passed to it.

if its an absolute weird and impossible idea,let me know this. *g* so i can go another way in the design of my own kernel &mm&fs conglommerate.

Re:Module calls...

Posted: Fri Jan 24, 2003 8:41 am
by DarylD
No, I thought about messaging, but I wanted something a little lighter in weight. I have a message passing system in place which I could add parameters to in about an hour of coding, but I am worried about performance. I would have to have lots of string checking to see if a parameter is called "InputA" for example.

Daryl.

Re:Module calls...

Posted: Fri Jan 24, 2003 12:09 pm
by Lantz
One way would be to start every package with an int or something that specifies whats in the package so the kernel can do some typecasting and stuff to handle it.

Perhaps something like this:

Code: Select all

void kernel_cmd( void* package )
{
    int pkgtype = *( (int*)package );
    switch( pkgtype )
    {
        case PKGTYPE_OPENFILE:
                fs_openfile( (OPENFILE_PKG*)package );
                break;
        case PKGTYPE_WRITEFILE:
                fs_writefile( (WRITEFILE_PKG*)package );
                break;
    }
}

Re:Module calls...

Posted: Fri Jan 24, 2003 12:54 pm
by DarylD
That is essentially what I had before, but I found I had to declare tons of structs everywhere.

What I want is a system without that. I reckon I pretty much have it sorted out now.

Daryl.

Re:Module calls...

Posted: Mon Jan 27, 2003 1:31 am
by Pype.Clicker
DarylD wrote: No, I thought about messaging, but I wanted something a little lighter in weight. I have a message passing system in place which I could add parameters to in about an hour of coding, but I am worried about performance. I would have to have lots of string checking to see if a parameter is called "InputA" for example.
Performing string-checking at run time everytime the service call is done will indeed be a nuisance, imho. Maybe one for the service name or something alike, but one per argument will for sure be unaffordable.

What you could do is resolve those strings at load-time: when your program is loaded, it will invoke the Service Resolver and translate every argument string ("InputA") into a flat unique number (within the numbering space of "MyArgumentsPackage").

Code: Select all

class PutPixelPackage extends Package {
      static const PackageModel model=PackageModel.lookup("gfx.putpixel");
      static const int X=model.getID("x");
      static const int Y=model.getID("y");
      static const int COLOR=model.getID("color");
   }
  
    PutPixelPackage(int x, int y, Color color) {
        new Package(model.ID);
        addArgument(X,INTEGER,x);
        addArgument(Y,INTEGER,y);
        addArgument(COLOR,COLOR_T,color);
    }
}
Now, i must reckon that it only replace a "tons of structures" problem by a "tons of initializ0rs" problem (to fill all those static const integers holding parameters indexes).
But this can be easily done by a smart loader that will recognize the 'long mangled name' __$package$_gfx$putpixel$x as a request to fill in the putpixel.
now just do

Code: Select all

extern void* _X asm("__$package$_gfx$putpixel$x");
#define X (int)_X
and you'll be done with your strings.


BTW, i think that you will not love writing "tons of addArguments" at each function call. Maybe the only way to solve the problem out is to use an intermediate Interface Description Language that will be used to generate all the stubs and structures automagically...

Re:Module calls...

Posted: Mon Jan 27, 2003 4:12 am
by DarylD
I have decided to go with my addParameter system for passing parameters. It will only be done in the API library so it will not be too annoying to code with. The user app will just call FSOpen(...) or something similar, the code for FSOpen will do all the addParameter gubbins.

I have also decided to go with run-time linking of module id's and module call id's as you suggested Pype, should speed things up a little and keep things clean and simple.

Incidentally, I have finished the rewrite of my code, most of it has stayed the same but I changed naming anc calling conventions. For example my I/O system now uses pointers to functions for open/mount etc. rather than going through a module call interface. Should help speed things up a bit in the future.

Daryl.

Re:Module calls...

Posted: Mon Jan 27, 2003 1:33 pm
by Therx
Rather than using interupts I think you should use direct pointers as they are much quicker

eg.

Code: Select all

typedef int (*ptr_t)(int callid, some_t parameters);

ptr_t modulecall;

modulecall = (ptr_t) 0x90000;  //Address of sys call function

modulecall(10, paras);
I don't know any further details as I'm not that far in my OS but this is what I plan to use

Re:Module calls...

Posted: Mon Jan 27, 2003 4:43 pm
by Pype.Clicker
there's a drawback with constant pointers address which is ... that they are constant. So the component that implements FSopen will "have" to be at 0x9000. Interrupts are a first step to get rid of this constraint, but still they force all components to agree that FSOpen is accessed through interrupt 21h, service 3Fh ...

With a quickly developing system, and if you want to avoid the Unix "ioctl" problem of having 90% of your system calls going through a too generic and meaningless interface, i suggest that service addressing should be resolved at load-time rather than compile-time.

This way you can easily set up new services: the service provider will add symbolic informations into the system so that its client can locate and invoke it .