Calling system functions from an external task
Calling system functions from an external task
hi, i am beginning to plan/think about writing support for a multitasking environment. my question is this, if i write a program to run externally from my kernel, how does it call system functions like malloc()? i have heard that it is possible to do this through software interrupts but is this the only way to do it? thanks
RE:Calling system functions from an external task
You can also use call gates. Call gates are explained in chapter 4 of the IA32 Manual Volume 3. You could also try using task gates for system calls, but you'd have to do some weird stuff to make it work (how to pass parameters?).
RE:Calling system functions from an external task
You can try to remap the PIC and set up so that some of the Interrupts call functions in your kernel. That's what I did (with a real mode multi-tasking OS).
RE:Calling system functions from an external task
There is a sysenter/sysleave pair of instructions in newwer processors. They are more efficient than interrupts, and on processors that do not support them, you can just catch the invalid opcode exception.
P.S. malloc() itself is usually not a system call. Usually, malloc is a call to a library that calls a more primative memory allocator in the kernel.
P.S. malloc() itself is usually not a system call. Usually, malloc is a call to a library that calls a more primative memory allocator in the kernel.
RE:Calling system functions from an external task
When you load your executable, patch up all the system calls to point to the desired system function.
Your executables will need to have a "patch table" structure embedded in them for storing the offset of the CALL FAR PTR instructions which need to be patched.
The loader then needs to know which shared library/function that each call should point to. To do this, put an index in the CALL instruction which points into an "imports" structure. This structure is a list of "library/function" pairs.
So the executable loader should do this:
1: Enumerate the "patch table" structure.
2: For each call instruction referenced...
3: Read the resource index stored in that instruction.
4: Use that index to read the "library/function" entry in the "imports" structure.
5: Ensure that the library desired is memory resident and increment its "reference count".
6: Use that libraries "exports" structure to locate the desired function.
7: Replace the resource index stored in the call instruction with the address of the function.
8: Repeat for each call instruction referenced by the "patch table" structure.
When you unload the executable make sure it isn't still be referenced by some other library or executable (if it is, just decrement its reference count). This really only applies if shared libraries and executables are treated the same by your OS (that-is: either can reference other libraries and can be referenced by other libraries).
I've created my own executable format "SLEX" which uses this method of dynamic linking. It moves the resolution overhead from the runtime stage to the loadtime stage. Since loadtime only happens once and inner loops execute many times, it is ussually ideal to have pre-resolved external references like this.
It also means that your kernel can actually be an SLX file and export your system interfaces (as long as your OS loader is smart enough to part the patch table, exports table and imports table and initialize the OS's own SLX management structures to be self-aware of its own exports and memory usage.
-Robert
Your executables will need to have a "patch table" structure embedded in them for storing the offset of the CALL FAR PTR instructions which need to be patched.
The loader then needs to know which shared library/function that each call should point to. To do this, put an index in the CALL instruction which points into an "imports" structure. This structure is a list of "library/function" pairs.
So the executable loader should do this:
1: Enumerate the "patch table" structure.
2: For each call instruction referenced...
3: Read the resource index stored in that instruction.
4: Use that index to read the "library/function" entry in the "imports" structure.
5: Ensure that the library desired is memory resident and increment its "reference count".
6: Use that libraries "exports" structure to locate the desired function.
7: Replace the resource index stored in the call instruction with the address of the function.
8: Repeat for each call instruction referenced by the "patch table" structure.
When you unload the executable make sure it isn't still be referenced by some other library or executable (if it is, just decrement its reference count). This really only applies if shared libraries and executables are treated the same by your OS (that-is: either can reference other libraries and can be referenced by other libraries).
I've created my own executable format "SLEX" which uses this method of dynamic linking. It moves the resolution overhead from the runtime stage to the loadtime stage. Since loadtime only happens once and inner loops execute many times, it is ussually ideal to have pre-resolved external references like this.
It also means that your kernel can actually be an SLX file and export your system interfaces (as long as your OS loader is smart enough to part the patch table, exports table and imports table and initialize the OS's own SLX management structures to be self-aware of its own exports and memory usage.
-Robert