Re: How to implement a syscall in Haiku
Ingo Weinhold <[email protected]> Thu, 12 Jun 2008 00:24:37 +0200
| Newsgroups | gmane.os.openbeos.kernel.devel |
|---|---|
| Message-ID | <[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 ------------------------------------------------------------------------- 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