Re: How to implement a syscall in Haiku

"Salvatore Benedetto" <[email protected]> Thu, 12 Jun 2008 06:55:45 +0000
Newsgroups gmane.os.openbeos.kernel.devel
Message-ID <[email protected]>
2008/6/11 Ingo Weinhold <[email protected]>:
>
> On 2008-06-11 at 23:19:06 [+0200], Salvatore Benedetto <[email protected]> wrote:
>>
>> as the subject suggest, the question is very simple.
>> What are the steps in order to implement a syscall in Haiku?
>>
>> I had a look at the _user_realtime_sem_open for example and I found
>> that they are declare in syscall_dispatcher.h and syscall_table.h, but
>> both of them are found in the "generated" directory, which reminds me
>> that there is something to do with the build system.
>>
>> The only document I found on the website is from 2002 and I guess
>> it's pretty outdated? Is it?
>> http://www.haiku-os.org/documents/dev/hello_kernel_you_have_a_syscall_from_userland
>>
>> Anyhow, the syscall_info structures, requires that the second field to
>> be the amount
>> of the parameter size. What if one of the parameter it's a union? Is
>> it that allowed?
>
> You don't have to do anything with the syscall_info structure. Unions (at least
> pointers to unions) should be fine as parameters. If not, this is an issue in
> gensyscalls (and helpers) and the build system will politely issue some error
> message.
>
> The steps to add a syscall are:
>
> * Add the syscall prototype to headers/private/system/syscalls.h. Name it
> _kern_<foo>(). Avoid adding unnecessary dependencies to the header. I.e. if your
> syscall has pointers to structs as arguments, there's no need to include the headers
> that define the structs.
>
> * Add a function prototype _user_<foo>() with the same signature as your syscall to
> a fitting kernel header under headers/private/kernel/. Assuming that you want to add
> syscalls for XSI semaphores, add a new kernel header for them.
>
> * Make sure the header with the _user_<foo>() prototype is included by
> src/system/kernel/syscalls.cpp.
>
> * Implement _user_<foo>() in a fitting source file.
>
> That's it. There are some general rules for the implementation of a syscall:
>
> * If your syscall has a 64 bit return value (as opposed to the common 32 bit
> status_t/ssize_t/int etc.), call syscall_64_bit_return_value() at the very beginning.
>
> * Never access user memory directly or IOW, if your syscall has a parameter that is
> a pointer to something, never dereference the pointer. Also don't dereference
> pointers in structures you get from userland. If you have to access user data, first
> check that the pointer actually points to user address space, using the
> IS_USER_ADDRESS() macro (if not, fail with B_BAD_ADDRESS). Allocate kernel memory
> large enough to hold the user data. If it's a small structure or short string, use
> the stack, otherwise allocate on the heap. For variable sized data enforce maximum
> limits. Then copy the user data to your kernel memory using user_memcpy().
> Parameters are the same as for memcpy(), but the return value is a status_t. If it's
> not B_OK, fail with B_BAD_ADDRESS. If you want to return a data structure to
> userland, use the same strategy (just with swapped parameters for user_memcpy(), of
> course).
>
> * If your syscall can block and can be interrupted, make it restartable (there are
> exceptions when that is not necessary/desired, but usually it is). Restartable means
> that if your syscall has be interrupted by a signal, the kernel can just invoke it
> again after the signal has been handled. It will get the exact same parameters,
> which in some cases requires some special handling. E.g. relative timeouts have to
> be converted to absolute ones and stored. There are inline functions in
> <syscall_restart.h> which help with that. If you don't have any problematic
> parameters, just invoke syscall_restart_handle_post() with B_INTERRUPTED before you
> return from the syscall, if the syscall has been interrupted. Most syscalls return
> error codes and the function returns the error code passed to it, so one can use it
> like "return syscall_restart_handle_post(error);". If you have to deal with relative
> timeouts, use the appropriate syscall_restart_handle_timeout_pre() function at the
> beginning and syscall_restart_handle_timeout_post() (instead of
> restart_handle_post()) at the end of the syscall. The latter stores the timeout for
> restart, the former converts the timeout to absolute, respectively restores the
> stored timeout on syscall restart.
>
> CU, Ingo
>

Thanks a lot. That's more than I expected. :-)

Regards,
-- 
Salvatore Benedetto (a.k.a. emitrax)
Student of Computer Engineer
University of Pisa
www.haiku-os.it

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php