Before we start reading kernel code in earnest, here are some idioms. ==== Functions defined in assembly ==== The ENTRY_* macros create function symbols that the linker will treat as normal C functions (when C functions are compiled into assembly, similar assembly is actually generated for them, too): http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/intel/ia32/sys/asm_linkage.h#210 #define ENTRY_NP(x) \ .text; \ <--- place in .text (code) segment .align ASM_ENTRY_ALIGN; \ <--- align at 4 byte boundary .globl x; \ <--- make macro's arg a global symbol.. .type x, @function; \ <--- of type "function" x: <--- here it starts... You can try compiling functions with "gcc -S somefunc.c" ==== Getting pointer to current thread ==== http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/intel/asm/thread.h -- thread pointer context: extern __inline__ struct _kthread *threadp(void) { void *__value; #if defined(__amd64) __asm__ __volatile__( "movq %%gs:0x18,%0" /* CPU_THREAD */ : "=r" (__value)); #elif defined(__i386) __asm__ __volatile__( "movl %%gs:0x10,%0" /* CPU_THREAD */ : "=r" (__value)); #else #error "port me" #endif return (__value); } For explanations of the __asm__ embedding of Assembly into gcc C code, see http://www.ibm.com/developerworks/library/l-ia.html, or http://www.cs.virginia.edu/~clc5q/gcc-inline-asm.pdf for more details. For explanations of "extern __inline__" see (**). Here is how it is used: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/sys/thread.h#528 extern kthread_t *threadp(void); /* inline, returns thread pointer */ #define curthread (threadp()) /* current thread pointer */ #define curproc (ttoproc(curthread)) /* current process pointer */ #define curproj (ttoproj(curthread)) /* current project pointer */ #define curzone (curproc->p_zone) /* current zone pointer */ cf: in getpid() code: int64_t getpid(void) { rval_t r; proc_t *p; p = ttoproc(curthread); <--- will access local thread storage off %gs r.r_val1 = p->p_pid; if (p->p_flag & SZONETOP) r.r_val2 = curproc->p_zone->zone_zsched->p_pid; else r.r_val2 = p->p_ppid; return (r.r_vals); } extern struct _kthread t0; /* the scheduler thread */ extern kmutex_t pidlock; /* global process lock */ Observe pidlock being taken an released in the process of reading the process table by pr_readdir_procdir, http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/proc/prvnops.c#pr_readdir_procdir ==== Intermission === What on earth is "v"? The answer in http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/sys/var.h#45 Note: vnode operations table, though which /proc -specific worker functions are found, is here: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/sys/vnode.h#vnodeops This is the heart of the VFS design! ==== Mutex Locks ==== Linux spinlocks explained: http://www.cs.fsu.edu/~xyuan/cop5611/spinlock.html Read this carefully! The details on LOCK and the un-LOCKed testb are important. ==== Solaris optimized adaptive/spin locks ===== Read Chapter 17.5, especially 17.5.2 for detailed explanation: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/intel/ia32/ml/lock_prim.s -- x86 implementation in ASM http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/intel/sys/mutex_impl.h -- data structures to implement the spin/adaptive duality http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/os/mutex.c -- theory behind the spin/adaptive locks explained The CMPXCHG x86 instruction explained: http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-2.html#HEADING2-286 -- (arguments here in AT&T order, as in Solaris kernel; the above link uses the Intel order, which is the opposite one, for historical reasons) cmpxchg operand2, operand1 if ({al/ax/eax} = operand1) then zero := 1 ;Set the zero flag operand1 := operand2 else zero := 0 ;Clear the zero flag {al/ax/eax} := operand1 endif ...TO BE CONTINUED... ================================================================ (**) extern __inline__ explained: http://publib.boulder.ibm.com/infocenter/compbgpl/v9v111/index.jsp?topic=/com.ibm.xlcpp9.bg.doc/language_ref/cplr243.htm -- "If you specify the __inline__ keyword, with the trailing underscores, the compiler uses the GNU C semantics for inline functions. In contrast to the C99 semantics, a function defined as __inline__ provides an external definition only; a function defined as static __inline__ provides an inline definition with internal linkage (as in C99); and a function defined as extern __inline__, when compiled with optimization enabled, allows the co-existence of an inline and external definition of the same function. For more information on the GNU C implementation of inline functions, see the GCC documentation, available at http://gcc.gnu.org/onlinedocs/." Why all this? See http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/intel/ia32/ml/i86_subr.s#2381 -- a different definition in another file, and yet no linking problem)