From: Jake H. <jh...@po...> - 2005-02-16 07:38:46
|
I'm about 90% completed with my C99 typesafe conversion of the kernel sources, and the code now compiles with few warnings (and the remaining ones I know how to fix), and IMHO is a lot easier to read. The only problem is that it doesn't work yet! I'm getting a bunch of error messages that scroll off the screen too quickly for me to read. I'll try to capture the error messages tomorrow using VMware and continue debugging, but in the meantime I wanted to post what I have so far and hopefully get some feedback and suggestions from the kernel hackers on the list. Here's the new source (I didn't try to create diffs: the changes are too extensive). http://anobject.com/jhamby/c99_kernel.tar.bz2 Main highlights: * Compiles in C99 mode with few warnings and almost all warning options enabled. * uint8, uint16, uint32 are gone, replaced with uint8_t, uint16_t, etc., or one of these symbolic types: status_t - most functions return this.. it's a uint_fast32_t count_t - useful for loop counters and count variables flags_t - used for variables holding flags or mode bits handle_t - used to return a handle, when there wasn't already a type for it, e.g. sem_id, area_id, etc. * I've tried to follow a consistent pattern; most functions will have one or more of these: status_t foo( struct Foo_s *psFoo ) { status_t nError = 0; flags_t nFlg = cli(); sched_lock(); for ( count_t i = 0; i < psFoo->ff_nCount; ++i ) { // do something nError = ( -ENOMEM ); } sched_unlock(); put_cpu_flags( nFlg ); return nError; } * One idea I had which helped a lot with function prototyping was to define a macro __SYSCALL(), which expands to the function_name() and also, if __KERNEL__ is defined, to sys_function_name(). See, e.g. <posix/unistd.h> which has a bunch of these: __SYSCALL( int, rmdir(const char *_path) ); This gives a prototype for rmdir() and also sys_rmdir() in the kernel. In the few cases where the system call prototype is different from the user-mode version, for example the get_system_info() wrapper passes a hidden version number to sys_get_system_info(), then you can't use __SYSCALL(), and it's obvious that there's something unusual going on. * There were a few cases where const was used in prototypes unnecessarily, e.g.: foo( const int nFoo, const thread_id nThread ); Since the parameter is an integer passed by value, it's impossible for the kernel to modify the user's copy. Whether or not the kernel modifies its local copy of nFoo is irrelevant to the user, and so it shouldn't be in the method signature. Finally, I removed my ugly "box" style of doxygen comments and replaced them with the more traditional and easier to read: /** * Description of function. * \param nFoo param 1 * \return the answer to life, the universe, and everything (42). * \pre precondition * \post postcondition * \invariant pre- and post- and in-between condition :-) */ I also have a question for Daniel: I would like to use the DLIST_ macros in more places but unfortunately your version doesn't have a pointer to the tail of the list so there's no quick way to append an item to the end of a list or get the last item, operations which are needed by most of the kernel's lists. Do you have any plans for a new version of dlist.h that might address this? If you can add that functionality to DLIST, then I'll take care of patching up the rest of the kernel to use it. -Jake |