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