€•pŒsphinx.addnodes”Œdocument”“”)�”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)�”}”(hhh]”(hŒ pending_xref”“”)�”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…”�”}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ*/translations/zh_CN/kernel-hacking/hacking”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)�”}”(hhh]”hŒChinese (Traditional)”…”�”}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/zh_TW/kernel-hacking/hacking”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒItalian”…”�”}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/it_IT/kernel-hacking/hacking”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒJapanese”…”�”}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/ja_JP/kernel-hacking/hacking”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒKorean”…”�”}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/ko_KR/kernel-hacking/hacking”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒPortuguese (Brazilian)”…”�”}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/pt_BR/kernel-hacking/hacking”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒSpanish”…”�”}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ*/translations/sp_SP/kernel-hacking/hacking”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒtarget”“”)�”}”(hŒ.. _kernel_hacking_hack:”h]”h}”(h]”h ]”h"]”h$]”h&]”Œrefid”Œkernel-hacking-hack”uh1hµh´Khhh²hh³ŒD/var/lib/git/docbuild/linux/Documentation/kernel-hacking/hacking.rst”ubhŒsection”“”)�”}”(hhh]”(hŒtitle”“”)�”}”(hŒ,Unreliable Guide To Hacking The Linux Kernel”h]”hŒ,Unreliable Guide To Hacking The Linux Kernel”…”�”}”(hhËh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhhÆh²hh³hÃh´KubhŒ field_list”“”)�”}”(hhh]”hŒfield”“”)�”}”(hhh]”(hŒ field_name”“”)�”}”(hŒAuthor”h]”hŒAuthor”…”�”}”(hhåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hãhhàh³hÃh´KubhŒ field_body”“”)�”}”(hŒRusty Russell ”h]”hŒ paragraph”“”)�”}”(hŒ Rusty Russell”h]”hŒ Rusty Russell”…”�”}”(hhûh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Khhõubah}”(h]”h ]”h"]”h$]”h&]”uh1hóhhàubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÞh³hÃh´KhhÛh²hubah}”(h]”h ]”h"]”h$]”h&]”uh1hÙhhÆh²hh³hÃh´KubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ Introduction”h]”hŒ Introduction”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjh²hh³hÃh´K ubhú)�”}”(hXuWelcome, gentle reader, to Rusty's Remarkably Unreliable Guide to Linux Kernel Hacking. This document describes the common routines and general requirements for kernel code: its goal is to serve as a primer for Linux kernel development for experienced C programmers. I avoid implementation details: that's what the code is for, and I ignore whole tracts of useful routines.”h]”hXyWelcome, gentle reader, to Rusty’s Remarkably Unreliable Guide to Linux Kernel Hacking. This document describes the common routines and general requirements for kernel code: its goal is to serve as a primer for Linux kernel development for experienced C programmers. I avoid implementation details: that’s what the code is for, and I ignore whole tracts of useful routines.”…”�”}”(hj,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K hjh²hubhú)�”}”(hXBefore you read this, please understand that I never wanted to write this document, being grossly under-qualified, but I always wanted to read it, and this was the only way. I hope it will grow into a compendium of best practice, common starting points and random information.”h]”hXBefore you read this, please understand that I never wanted to write this document, being grossly under-qualified, but I always wanted to read it, and this was the only way. I hope it will grow into a compendium of best practice, common starting points and random information.”…”�”}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Khjh²hubeh}”(h]”Œ introduction”ah ]”h"]”Œ introduction”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´K ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ The Players”h]”hŒ The Players”…”�”}”(hjSh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjPh²hh³hÃh´Kubhú)�”}”(hŒ0At any time each of the CPUs in a system can be:”h]”hŒ0At any time each of the CPUs in a system can be:”…”�”}”(hjah²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KhjPh²hubhŒ bullet_list”“”)�”}”(hhh]”(hŒ list_item”“”)�”}”(hŒ?not associated with any process, serving a hardware interrupt; ”h]”hú)�”}”(hŒ>not associated with any process, serving a hardware interrupt;”h]”hŒ>not associated with any process, serving a hardware interrupt;”…”�”}”(hjzh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Khjvubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjqh²hh³hÃh´Nubju)�”}”(hŒ?not associated with any process, serving a softirq or tasklet; ”h]”hú)�”}”(hŒ>not associated with any process, serving a softirq or tasklet;”h]”hŒ>not associated with any process, serving a softirq or tasklet;”…”�”}”(hj’h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K hjŽubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjqh²hh³hÃh´Nubju)�”}”(hŒCrunning in kernel space, associated with a process (user context); ”h]”hú)�”}”(hŒBrunning in kernel space, associated with a process (user context);”h]”hŒBrunning in kernel space, associated with a process (user context);”…”�”}”(hjªh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K"hj¦ubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjqh²hh³hÃh´Nubju)�”}”(hŒ!running a process in user space. ”h]”hú)�”}”(hŒ running a process in user space.”h]”hŒ running a process in user space.”…”�”}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K$hj¾ubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjqh²hh³hÃh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1joh³hÃh´KhjPh²hubhú)�”}”(hXPThere is an ordering between these. The bottom two can preempt each other, but above that is a strict hierarchy: each can only be preempted by the ones above it. For example, while a softirq is running on a CPU, no other softirq will preempt it, but a hardware interrupt can. However, any other CPUs in the system execute independently.”h]”hXPThere is an ordering between these. The bottom two can preempt each other, but above that is a strict hierarchy: each can only be preempted by the ones above it. For example, while a softirq is running on a CPU, no other softirq will preempt it, but a hardware interrupt can. However, any other CPUs in the system execute independently.”…”�”}”(hjÞh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K&hjPh²hubhú)�”}”(hŒgWe'll see a number of ways that the user context can block interrupts, to become truly non-preemptable.”h]”hŒiWe’ll see a number of ways that the user context can block interrupts, to become truly non-preemptable.”…”�”}”(hjìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K,hjPh²hubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ User Context”h]”hŒ User Context”…”�”}”(hjýh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjúh²hh³hÃh´K0ubhú)�”}”(hŒ½User context is when you are coming in from a system call or other trap: like userspace, you can be preempted by more important tasks and by interrupts. You can sleep by calling schedule().”h]”hŒ½User context is when you are coming in from a system call or other trap: like userspace, you can be preempted by more important tasks and by interrupts. You can sleep by calling schedule().”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K2hjúh²hubhŒnote”“”)�”}”(hŒfYou are always in user context on module load and unload, and on operations on the block device layer.”h]”hú)�”}”(hŒfYou are always in user context on module load and unload, and on operations on the block device layer.”h]”hŒfYou are always in user context on module load and unload, and on operations on the block device layer.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K8hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjúh²hh³hÃh´Nubhú)�”}”(hŒžIn user context, the ``current`` pointer (indicating the task we are currently executing) is valid, and in_interrupt() (``include/linux/preempt.h``) is false.”h]”(hŒIn user context, the ”…”�”}”(hj3h²hh³Nh´NubhŒliteral”“”)�”}”(hŒ ``current``”h]”hŒcurrent”…”�”}”(hj=h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj3ubhŒX pointer (indicating the task we are currently executing) is valid, and in_interrupt() (”…”�”}”(hj3h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/preempt.h``”h]”hŒinclude/linux/preempt.h”…”�”}”(hjOh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj3ubhŒ ) is false.”…”�”}”(hj3h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K;hjúh²hubhŒwarning”“”)�”}”(hŒqBeware that if you have preemption or softirqs disabled (see below), in_interrupt() will return a false positive.”h]”hú)�”}”(hŒqBeware that if you have preemption or softirqs disabled (see below), in_interrupt() will return a false positive.”h]”hŒqBeware that if you have preemption or softirqs disabled (see below), in_interrupt() will return a false positive.”…”�”}”(hjmh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KAhjiubah}”(h]”h ]”h"]”h$]”h&]”uh1jghjúh²hh³hÃh´Nubeh}”(h]”Œ user-context”ah ]”h"]”Œ user context”ah$]”h&]”uh1hÄhjPh²hh³hÃh´K0ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒHardware Interrupts (Hard IRQs)”h]”hŒHardware Interrupts (Hard IRQs)”…”�”}”(hjŒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj‰h²hh³hÃh´KEubhú)�”}”(hXÇTimer ticks, network cards and keyboard are examples of real hardware which produce interrupts at any time. The kernel runs interrupt handlers, which services the hardware. The kernel guarantees that this handler is never re-entered: if the same interrupt arrives, it is queued (or dropped). Because it disables interrupts, this handler has to be fast: frequently it simply acknowledges the interrupt, marks a 'software interrupt' for execution and exits.”h]”hXËTimer ticks, network cards and keyboard are examples of real hardware which produce interrupts at any time. The kernel runs interrupt handlers, which services the hardware. The kernel guarantees that this handler is never re-entered: if the same interrupt arrives, it is queued (or dropped). Because it disables interrupts, this handler has to be fast: frequently it simply acknowledges the interrupt, marks a ‘software interrupt’ for execution and exits.”…”�”}”(hjšh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KGhj‰h²hubhú)�”}”(hŒPYou can tell you are in a hardware interrupt, because in_hardirq() returns true.”h]”hŒPYou can tell you are in a hardware interrupt, because in_hardirq() returns true.”…”�”}”(hj¨h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KOhj‰h²hubjh)�”}”(hŒUBeware that this will return a false positive if interrupts are disabled (see below).”h]”hú)�”}”(hŒUBeware that this will return a false positive if interrupts are disabled (see below).”h]”hŒUBeware that this will return a false positive if interrupts are disabled (see below).”…”�”}”(hjºh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KThj¶ubah}”(h]”h ]”h"]”h$]”h&]”uh1jghj‰h²hh³hÃh´Nubeh}”(h]”Œhardware-interrupts-hard-irqs”ah ]”h"]”Œhardware interrupts (hard irqs)”ah$]”h&]”uh1hÄhjPh²hh³hÃh´KEubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ1Software Interrupt Context: Softirqs and Tasklets”h]”hŒ1Software Interrupt Context: Softirqs and Tasklets”…”�”}”(hjÙh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjÖh²hh³hÃh´KXubhú)�”}”(hŒÒWhenever a system call is about to return to userspace, or a hardware interrupt handler exits, any 'software interrupts' which are marked pending (usually by hardware interrupts) are run (``kernel/softirq.c``).”h]”(hŒÀWhenever a system call is about to return to userspace, or a hardware interrupt handler exits, any ‘software interrupts’ which are marked pending (usually by hardware interrupts) are run (”…”�”}”(hjçh²hh³Nh´Nubj<)�”}”(hŒ``kernel/softirq.c``”h]”hŒkernel/softirq.c”…”�”}”(hjïh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjçubhŒ).”…”�”}”(hjçh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KZhjÖh²hubhú)�”}”(hX4Much of the real interrupt handling work is done here. Early in the transition to SMP, there were only 'bottom halves' (BHs), which didn't take advantage of multiple CPUs. Shortly after we switched from wind-up computers made of match-sticks and snot, we abandoned this limitation and switched to 'softirqs'.”h]”hX>Much of the real interrupt handling work is done here. Early in the transition to SMP, there were only ‘bottom halves’ (BHs), which didn’t take advantage of multiple CPUs. Shortly after we switched from wind-up computers made of match-sticks and snot, we abandoned this limitation and switched to ‘softirqs’.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K^hjÖh²hubhú)�”}”(hŒÔ``include/linux/interrupt.h`` lists the different softirqs. A very important softirq is the timer softirq (``include/linux/timer.h``): you can register to have it call functions for you in a given length of time.”h]”(j<)�”}”(hŒ``include/linux/interrupt.h``”h]”hŒinclude/linux/interrupt.h”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjubhŒN lists the different softirqs. A very important softirq is the timer softirq (”…”�”}”(hjh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/timer.h``”h]”hŒinclude/linux/timer.h”…”�”}”(hj+h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjubhŒP): you can register to have it call functions for you in a given length of time.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KdhjÖh²hubhú)�”}”(hX‹Softirqs are often a pain to deal with, since the same softirq will run simultaneously on more than one CPU. For this reason, tasklets (``include/linux/interrupt.h``) are more often used: they are dynamically-registrable (meaning you can have as many as you want), and they also guarantee that any tasklet will only run on one CPU at any time, although different tasklets can run simultaneously.”h]”(hŒˆSoftirqs are often a pain to deal with, since the same softirq will run simultaneously on more than one CPU. For this reason, tasklets (”…”�”}”(hjCh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/interrupt.h``”h]”hŒinclude/linux/interrupt.h”…”�”}”(hjKh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjCubhŒæ) are more often used: they are dynamically-registrable (meaning you can have as many as you want), and they also guarantee that any tasklet will only run on one CPU at any time, although different tasklets can run simultaneously.”…”�”}”(hjCh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KihjÖh²hubjh)�”}”(hŒGThe name 'tasklet' is misleading: they have nothing to do with 'tasks'.”h]”hú)�”}”(hŒGThe name 'tasklet' is misleading: they have nothing to do with 'tasks'.”h]”hŒOThe name ‘tasklet’ is misleading: they have nothing to do with ‘tasks’.”…”�”}”(hjgh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Krhjcubah}”(h]”h ]”h"]”h$]”h&]”uh1jghjÖh²hh³hÃh´Nubhú)�”}”(hŒjYou can tell you are in a softirq (or tasklet) using the in_softirq() macro (``include/linux/preempt.h``).”h]”(hŒMYou can tell you are in a softirq (or tasklet) using the in_softirq() macro (”…”�”}”(hj{h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/preempt.h``”h]”hŒinclude/linux/preempt.h”…”�”}”(hjƒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj{ubhŒ).”…”�”}”(hj{h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KuhjÖh²hubjh)�”}”(hŒfBeware that this will return a false positive if a :ref:`bottom half lock ` is held.”h]”hú)�”}”(hŒfBeware that this will return a false positive if a :ref:`bottom half lock ` is held.”h]”(hŒ3Beware that this will return a false positive if a ”…”�”}”(hjŸh²hh³Nh´Nubh)�”}”(hŒ*:ref:`bottom half lock `”h]”hŒinline”“”)�”}”(hj©h]”hŒbottom half lock”…”�”}”(hj­h²hh³Nh´Nubah}”(h]”h ]”(Œxref”Œstd”Œstd-ref”eh"]”h$]”h&]”uh1j«hj§ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”Œkernel-hacking/hacking”Œ refdomain”j¸Œreftype”Œref”Œ refexplicit”ˆŒrefwarn”ˆŒ reftarget”Œlocal_bh_disable”uh1hh³hÃh´KzhjŸubhŒ is held.”…”�”}”(hjŸh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Kzhj›ubah}”(h]”h ]”h"]”h$]”h&]”uh1jghjÖh²hh³hÃh´Nubeh}”(h]”Œ0software-interrupt-context-softirqs-and-tasklets”ah ]”h"]”Œ1software interrupt context: softirqs and tasklets”ah$]”h&]”uh1hÄhjPh²hh³hÃh´KXubeh}”(h]”Œ the-players”ah ]”h"]”Œ the players”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´KubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒSome Basic Rules”h]”hŒSome Basic Rules”…”�”}”(hjïh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjìh²hh³hÃh´K~ubhŒdefinition_list”“”)�”}”(hhh]”(hŒdefinition_list_item”“”)�”}”(hŒ®No memory protection If you corrupt memory, whether in user context or interrupt context, the whole machine will crash. Are you sure you can't do what you want in userspace? ”h]”(hŒterm”“”)�”}”(hŒNo memory protection”h]”hŒNo memory protection”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´KƒhjubhŒ definition”“”)�”}”(hhh]”hú)�”}”(hŒ˜If you corrupt memory, whether in user context or interrupt context, the whole machine will crash. Are you sure you can't do what you want in userspace?”h]”hŒšIf you corrupt memory, whether in user context or interrupt context, the whole machine will crash. Are you sure you can’t do what you want in userspace?”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K�hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´Kƒhjÿubj)�”}”(hXxNo floating point or MMX The FPU context is not saved; even in user context the FPU state probably won't correspond with the current process: you would mess with some user process' FPU state. If you really want to do this, you would have to explicitly save/restore the full FPU state (and avoid context switches). It is generally a bad idea; use fixed point arithmetic first. ”h]”(j )�”}”(hŒNo floating point or MMX”h]”hŒNo floating point or MMX”…”�”}”(hj;h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´K‹hj7ubj)�”}”(hhh]”hú)�”}”(hX^The FPU context is not saved; even in user context the FPU state probably won't correspond with the current process: you would mess with some user process' FPU state. If you really want to do this, you would have to explicitly save/restore the full FPU state (and avoid context switches). It is generally a bad idea; use fixed point arithmetic first.”h]”hXbThe FPU context is not saved; even in user context the FPU state probably won’t correspond with the current process: you would mess with some user process’ FPU state. If you really want to do this, you would have to explicitly save/restore the full FPU state (and avoid context switches). It is generally a bad idea; use fixed point arithmetic first.”…”�”}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K†hjIubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj7ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´K‹hjÿh²hubj)�”}”(hX5A rigid stack limit Depending on configuration options the kernel stack is about 3K to 6K for most 32-bit architectures: it's about 14K on most 64-bit archs, and often shared with interrupts so you can't use it all. Avoid deep recursion and huge local arrays on the stack (allocate them dynamically instead). ”h]”(j )�”}”(hŒA rigid stack limit”h]”hŒA rigid stack limit”…”�”}”(hjjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´K’hjfubj)�”}”(hhh]”hú)�”}”(hX Depending on configuration options the kernel stack is about 3K to 6K for most 32-bit architectures: it's about 14K on most 64-bit archs, and often shared with interrupts so you can't use it all. Avoid deep recursion and huge local arrays on the stack (allocate them dynamically instead).”h]”hX$Depending on configuration options the kernel stack is about 3K to 6K for most 32-bit architectures: it’s about 14K on most 64-bit archs, and often shared with interrupts so you can’t use it all. Avoid deep recursion and huge local arrays on the stack (allocate them dynamically instead).”…”�”}”(hj{h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KŽhjxubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjfubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´K’hjÿh²hubj)�”}”(hXHThe Linux kernel is portable Let's keep it that way. Your code should be 64-bit clean, and endian-independent. You should also minimize CPU specific stuff, e.g. inline assembly should be cleanly encapsulated and minimized to ease porting. Generally it should be restricted to the architecture-dependent part of the kernel tree. ”h]”(j )�”}”(hŒThe Linux kernel is portable”h]”hŒThe Linux kernel is portable”…”�”}”(hj™h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´K™hj•ubj)�”}”(hhh]”hú)�”}”(hX*Let's keep it that way. Your code should be 64-bit clean, and endian-independent. You should also minimize CPU specific stuff, e.g. inline assembly should be cleanly encapsulated and minimized to ease porting. Generally it should be restricted to the architecture-dependent part of the kernel tree.”h]”hX,Let’s keep it that way. Your code should be 64-bit clean, and endian-independent. You should also minimize CPU specific stuff, e.g. inline assembly should be cleanly encapsulated and minimized to ease porting. Generally it should be restricted to the architecture-dependent part of the kernel tree.”…”�”}”(hjªh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K•hj§ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj•ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´K™hjÿh²hubeh}”(h]”h ]”h"]”h$]”h&]”uh1jýhjìh²hh³hÃh´Nubeh}”(h]”Œsome-basic-rules”ah ]”h"]”Œsome basic rules”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´K~ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ%ioctls: Not writing a new system call”h]”hŒ%ioctls: Not writing a new system call”…”�”}”(hjÕh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjÒh²hh³hÃh´Kœubhú)�”}”(hŒ)A system call generally looks like this::”h]”hŒ(A system call generally looks like this:”…”�”}”(hjãh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KžhjÒh²hubhŒ literal_block”“”)�”}”(hŒ9asmlinkage long sys_mycall(int arg) { return 0; }”h]”hŒ9asmlinkage long sys_mycall(int arg) { return 0; }”…”�”}”hjósbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1jñh³hÃh´K hjÒh²hubhú)�”}”(hXVFirst, in most cases you don't want to create a new system call. You create a character device and implement an appropriate ioctl for it. This is much more flexible than system calls, doesn't have to be entered in every architecture's ``include/asm/unistd.h`` and ``arch/kernel/entry.S`` file, and is much more likely to be accepted by Linus.”h]”(hŒñFirst, in most cases you don’t want to create a new system call. You create a character device and implement an appropriate ioctl for it. This is much more flexible than system calls, doesn’t have to be entered in every architecture’s ”…”�”}”(hjh²hh³Nh´Nubj<)�”}”(hŒ``include/asm/unistd.h``”h]”hŒinclude/asm/unistd.h”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjubhŒ and ”…”�”}”(hjh²hh³Nh´Nubj<)�”}”(hŒ``arch/kernel/entry.S``”h]”hŒarch/kernel/entry.S”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjubhŒ7 file, and is much more likely to be accepted by Linus.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K¦hjÒh²hubhú)�”}”(hŒlIf all your routine does is read or write some parameter, consider implementing a sysfs() interface instead.”h]”hŒlIf all your routine does is read or write some parameter, consider implementing a sysfs() interface instead.”…”�”}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K­hjÒh²hubhú)�”}”(hŒñInside the ioctl you're in user context to a process. When a error occurs you return a negated errno (see ``include/uapi/asm-generic/errno-base.h``, ``include/uapi/asm-generic/errno.h`` and ``include/linux/errno.h``), otherwise you return 0.”h]”(hŒlInside the ioctl you’re in user context to a process. When a error occurs you return a negated errno (see ”…”�”}”(hjCh²hh³Nh´Nubj<)�”}”(hŒ)``include/uapi/asm-generic/errno-base.h``”h]”hŒ%include/uapi/asm-generic/errno-base.h”…”�”}”(hjKh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjCubhŒ, ”…”�”}”(hjCh²hh³Nh´Nubj<)�”}”(hŒ$``include/uapi/asm-generic/errno.h``”h]”hŒ include/uapi/asm-generic/errno.h”…”�”}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjCubhŒ and ”…”�”}”(hjCh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/errno.h``”h]”hŒinclude/linux/errno.h”…”�”}”(hjoh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjCubhŒ), otherwise you return 0.”…”�”}”(hjCh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K°hjÒh²hubhú)�”}”(hX¾After you slept you should check if a signal occurred: the Unix/Linux way of handling signals is to temporarily exit the system call with the ``-ERESTARTSYS`` error. The system call entry code will switch back to user context, process the signal handler and then your system call will be restarted (unless the user disabled that). So you should be prepared to process the restart, e.g. if you're in the middle of manipulating some data structure.”h]”(hŒŽAfter you slept you should check if a signal occurred: the Unix/Linux way of handling signals is to temporarily exit the system call with the ”…”�”}”(hj‡h²hh³Nh´Nubj<)�”}”(hŒ``-ERESTARTSYS``”h]”hŒ -ERESTARTSYS”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj‡ubhX" error. The system call entry code will switch back to user context, process the signal handler and then your system call will be restarted (unless the user disabled that). So you should be prepared to process the restart, e.g. if you’re in the middle of manipulating some data structure.”…”�”}”(hj‡h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´K¶hjÒh²hubjò)�”}”(hŒ9if (signal_pending(current)) return -ERESTARTSYS;”h]”hŒ9if (signal_pending(current)) return -ERESTARTSYS;”…”�”}”hj§sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´KÀhjÒh²hubhú)�”}”(hŒÝIf you're doing longer computations: first think userspace. If you **really** want to do it in kernel you should regularly check if you need to give up the CPU (remember there is cooperative multitasking per CPU). Idiom::”h]”(hŒEIf you’re doing longer computations: first think userspace. If you ”…”�”}”(hjµh²hh³Nh´NubhŒstrong”“”)�”}”(hŒ **really**”h]”hŒreally”…”�”}”(hj¿h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hjµubhŒ� want to do it in kernel you should regularly check if you need to give up the CPU (remember there is cooperative multitasking per CPU). Idiom:”…”�”}”(hjµh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KÄhjÒh²hubjò)�”}”(hŒ cond_resched(); /* Will sleep */”h]”hŒ cond_resched(); /* Will sleep */”…”�”}”hj×sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´KÉhjÒh²hubhú)�”}”(hŒ_A short note on interface design: the UNIX system call motto is "Provide mechanism not policy".”h]”hŒcA short note on interface design: the UNIX system call motto is “Provide mechanism not policyâ€�.”…”�”}”(hjåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KÌhjÒh²hubeh}”(h]”Œ$ioctls-not-writing-a-new-system-call”ah ]”h"]”Œ%ioctls: not writing a new system call”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´KœubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒRecipes for Deadlock”h]”hŒRecipes for Deadlock”…”�”}”(hjþh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjûh²hh³hÃh´KÐubhú)�”}”(hŒ5You cannot call any routines which may sleep, unless:”h]”hŒ5You cannot call any routines which may sleep, unless:”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KÒhjûh²hubjp)�”}”(hhh]”(ju)�”}”(hŒYou are in user context. ”h]”hú)�”}”(hŒYou are in user context.”h]”hŒYou are in user context.”…”�”}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KÔhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjh²hh³hÃh´Nubju)�”}”(hŒYou do not own any spinlocks. ”h]”hú)�”}”(hŒYou do not own any spinlocks.”h]”hŒYou do not own any spinlocks.”…”�”}”(hj9h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KÖhj5ubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjh²hh³hÃh´Nubju)�”}”(hŒ”You have interrupts enabled (actually, Andi Kleen says that the scheduling code will enable them for you, but that's probably not what you wanted). ”h]”hú)�”}”(hŒ“You have interrupts enabled (actually, Andi Kleen says that the scheduling code will enable them for you, but that's probably not what you wanted).”h]”hŒ•You have interrupts enabled (actually, Andi Kleen says that the scheduling code will enable them for you, but that’s probably not what you wanted).”…”�”}”(hjQh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KØhjMubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjh²hh³hÃh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jÜjÝuh1joh³hÃh´KÔhjûh²hubhú)�”}”(hŒ Note that some functions may sleep implicitly: common ones are the user space access functions (\*_user) and memory allocation functions without ``GFP_ATOMIC``.”h]”(hŒ‘Note that some functions may sleep implicitly: common ones are the user space access functions (*_user) and memory allocation functions without ”…”�”}”(hjkh²hh³Nh´Nubj<)�”}”(hŒ``GFP_ATOMIC``”h]”hŒ GFP_ATOMIC”…”�”}”(hjsh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjkubhŒ.”…”�”}”(hjkh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´KÜhjûh²hubhú)�”}”(hŒ»You should always compile your kernel ``CONFIG_DEBUG_ATOMIC_SLEEP`` on, and it will warn you if you break these rules. If you **do** break the rules, you will eventually lock up your box.”h]”(hŒ&You should always compile your kernel ”…”�”}”(hj‹h²hh³Nh´Nubj<)�”}”(hŒ``CONFIG_DEBUG_ATOMIC_SLEEP``”h]”hŒCONFIG_DEBUG_ATOMIC_SLEEP”…”�”}”(hj“h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj‹ubhŒ; on, and it will warn you if you break these rules. If you ”…”�”}”(hj‹h²hh³Nh´Nubj¾)�”}”(hŒ**do**”h]”hŒdo”…”�”}”(hj¥h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hj‹ubhŒ7 break the rules, you will eventually lock up your box.”…”�”}”(hj‹h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Kàhjûh²hubhú)�”}”(hŒReally.”h]”hŒReally.”…”�”}”(hj½h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Kähjûh²hubeh}”(h]”Œrecipes-for-deadlock”ah ]”h"]”Œrecipes for deadlock”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´KÐubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒCommon Routines”h]”hŒCommon Routines”…”�”}”(hjÖh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjÓh²hh³hÃh´KçubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒprintk()”h]”hŒprintk()”…”�”}”(hjçh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjäh²hh³hÃh´Kêubhú)�”}”(hŒ%Defined in ``include/linux/printk.h``”h]”(hŒ Defined in ”…”�”}”(hjõh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/printk.h``”h]”hŒinclude/linux/printk.h”…”�”}”(hjýh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjõubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Kìhjäh²hubhú)�”}”(hX‰printk() feeds kernel messages to the console, dmesg, and the syslog daemon. It is useful for debugging and reporting errors, and can be used inside interrupt context, but use with caution: a machine which has its console flooded with printk messages is unusable. It uses a format string mostly compatible with ANSI C printf, and C string concatenation to give it a first "priority" argument::”h]”hXŒprintk() feeds kernel messages to the console, dmesg, and the syslog daemon. It is useful for debugging and reporting errors, and can be used inside interrupt context, but use with caution: a machine which has its console flooded with printk messages is unusable. It uses a format string mostly compatible with ANSI C printf, and C string concatenation to give it a first “priorityâ€� argument:”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Kîhjäh²hubjò)�”}”(hŒ printk(KERN_INFO "i = %u\n", i);”h]”hŒ printk(KERN_INFO "i = %u\n", i);”…”�”}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´Kõhjäh²hubhú)�”}”(hŒ�See ``include/linux/kern_levels.h``; for other ``KERN_`` values; these are interpreted by syslog as the level. Special case: for printing an IP address use::”h]”(hŒSee ”…”�”}”(hj-h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/kern_levels.h``”h]”hŒinclude/linux/kern_levels.h”…”�”}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj-ubhŒ ; for other ”…”�”}”(hj-h²hh³Nh´Nubj<)�”}”(hŒ ``KERN_``”h]”hŒKERN_”…”�”}”(hjGh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj-ubhŒd values; these are interpreted by syslog as the level. Special case: for printing an IP address use:”…”�”}”(hj-h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Køhjäh²hubjò)�”}”(hŒ@__be32 ipaddress; printk(KERN_INFO "my ip: %pI4\n", &ipaddress);”h]”hŒ@__be32 ipaddress; printk(KERN_INFO "my ip: %pI4\n", &ipaddress);”…”�”}”hj_sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´Kühjäh²hubhú)�”}”(hŒ`printk() internally uses a 1K buffer and does not catch overruns. Make sure that will be enough.”h]”hŒ`printk() internally uses a 1K buffer and does not catch overruns. Make sure that will be enough.”…”�”}”(hjmh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhjäh²hubj)�”}”(hŒpYou will know when you are a real kernel hacker when you start typoing printf as printk in your user programs :)”h]”hú)�”}”(hŒpYou will know when you are a real kernel hacker when you start typoing printf as printk in your user programs :)”h]”hŒpYou will know when you are a real kernel hacker when you start typoing printf as printk in your user programs :)”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhj{ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjäh²hh³hÃh´Nubj)�”}”(hŒ¬Another sidenote: the original Unix Version 6 sources had a comment on top of its printf function: "Printf should not be used for chit-chat". You should follow that advice.”h]”hú)�”}”(hŒ¬Another sidenote: the original Unix Version 6 sources had a comment on top of its printf function: "Printf should not be used for chit-chat". You should follow that advice.”h]”hŒ°Another sidenote: the original Unix Version 6 sources had a comment on top of its printf function: “Printf should not be used for chit-chatâ€�. You should follow that advice.”…”�”}”(hj—h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M hj“ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjäh²hh³hÃh´Nubeh}”(h]”Œprintk”ah ]”h"]”Œprintk()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´KêubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ;copy_to_user() / copy_from_user() / get_user() / put_user()”h]”hŒ;copy_to_user() / copy_from_user() / get_user() / put_user()”…”�”}”(hj¶h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj³h²hh³hÃh´Mubhú)�”}”(hŒ:Defined in ``include/linux/uaccess.h`` / ``asm/uaccess.h``”h]”(hŒ Defined in ”…”�”}”(hjÄh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/uaccess.h``”h]”hŒinclude/linux/uaccess.h”…”�”}”(hjÌh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjÄubhŒ / ”…”�”}”(hjÄh²hh³Nh´Nubj<)�”}”(hŒ``asm/uaccess.h``”h]”hŒ asm/uaccess.h”…”�”}”(hjÞh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjÄubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhj³h²hubhú)�”}”(hŒ **[SLEEPS]**”h]”j¾)�”}”(hjôh]”hŒ[SLEEPS]”…”�”}”(hjöh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hjòubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhj³h²hubhú)�”}”(hŒþput_user() and get_user() are used to get and put single values (such as an int, char, or long) from and to userspace. A pointer into userspace should never be simply dereferenced: data should be copied using these routines. Both return ``-EFAULT`` or 0.”h]”(hŒíput_user() and get_user() are used to get and put single values (such as an int, char, or long) from and to userspace. A pointer into userspace should never be simply dereferenced: data should be copied using these routines. Both return ”…”�”}”(hj h²hh³Nh´Nubj<)�”}”(hŒ ``-EFAULT``”h]”hŒ-EFAULT”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj ubhŒ or 0.”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhj³h²hubhú)�”}”(hŒrcopy_to_user() and copy_from_user() are more general: they copy an arbitrary amount of data to and from userspace.”h]”hŒrcopy_to_user() and copy_from_user() are more general: they copy an arbitrary amount of data to and from userspace.”…”�”}”(hj)h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhj³h²hubjh)�”}”(hŒfUnlike put_user() and get_user(), they return the amount of uncopied data (ie. 0 still means success).”h]”hú)�”}”(hŒfUnlike put_user() and get_user(), they return the amount of uncopied data (ie. 0 still means success).”h]”hŒfUnlike put_user() and get_user(), they return the amount of uncopied data (ie. 0 still means success).”…”�”}”(hj;h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M!hj7ubah}”(h]”h ]”h"]”h$]”h&]”uh1jghj³h²hh³hÃh´Nubhú)�”}”(hŒb[Yes, this objectionable interface makes me cringe. The flamewar comes up every year or so. --RR.]”h]”hŒb[Yes, this objectionable interface makes me cringe. The flamewar comes up every year or so. --RR.]”…”�”}”(hjOh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M$hj³h²hubhú)�”}”(hŒ—The functions may sleep implicitly. This should never be called outside user context (it makes no sense), with interrupts disabled, or a spinlock held.”h]”hŒ—The functions may sleep implicitly. This should never be called outside user context (it makes no sense), with interrupts disabled, or a spinlock held.”…”�”}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M'hj³h²hubeh}”(h]”Œ-copy-to-user-copy-from-user-get-user-put-user”ah ]”h"]”Œ;copy_to_user() / copy_from_user() / get_user() / put_user()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´MubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒkmalloc()/kfree()”h]”hŒkmalloc()/kfree()”…”�”}”(hjvh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjsh²hh³hÃh´M,ubhú)�”}”(hŒ#Defined in ``include/linux/slab.h``”h]”(hŒ Defined in ”…”�”}”(hj„h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/slab.h``”h]”hŒinclude/linux/slab.h”…”�”}”(hjŒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj„ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M.hjsh²hubhú)�”}”(hŒ**[MAY SLEEP: SEE BELOW]**”h]”j¾)�”}”(hj¢h]”hŒ[MAY SLEEP: SEE BELOW]”…”�”}”(hj¤h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M0hjsh²hubhú)�”}”(hŒ°These routines are used to dynamically request pointer-aligned chunks of memory, like malloc and free do in userspace, but kmalloc() takes an extra flag word. Important values:”h]”hŒ°These routines are used to dynamically request pointer-aligned chunks of memory, like malloc and free do in userspace, but kmalloc() takes an extra flag word. Important values:”…”�”}”(hj·h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M2hjsh²hubjþ)�”}”(hhh]”(j)�”}”(hŒ�``GFP_KERNEL`` May sleep and swap to free memory. Only allowed in user context, but is the most reliable way to allocate memory. ”h]”(j )�”}”(hŒ``GFP_KERNEL``”h]”j<)�”}”(hjÎh]”hŒ GFP_KERNEL”…”�”}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjÌubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´M8hjÈubj)�”}”(hhh]”hú)�”}”(hŒqMay sleep and swap to free memory. Only allowed in user context, but is the most reliable way to allocate memory.”h]”hŒqMay sleep and swap to free memory. Only allowed in user context, but is the most reliable way to allocate memory.”…”�”}”(hjæh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M7hjãubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjÈubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´M8hjÅubj)�”}”(hŒ²``GFP_ATOMIC`` Don't sleep. Less reliable than ``GFP_KERNEL``, but may be called from interrupt context. You should **really** have a good out-of-memory error-handling strategy. ”h]”(j )�”}”(hŒ``GFP_ATOMIC``”h]”j<)�”}”(hj h]”hŒ GFP_ATOMIC”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´M=hj ubj)�”}”(hhh]”hú)�”}”(hŒ¢Don't sleep. Less reliable than ``GFP_KERNEL``, but may be called from interrupt context. You should **really** have a good out-of-memory error-handling strategy.”h]”(hŒ"Don’t sleep. Less reliable than ”…”�”}”(hj h²hh³Nh´Nubj<)�”}”(hŒ``GFP_KERNEL``”h]”hŒ GFP_KERNEL”…”�”}”(hj& h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj ubhŒ7, but may be called from interrupt context. You should ”…”�”}”(hj h²hh³Nh´Nubj¾)�”}”(hŒ **really**”h]”hŒreally”…”�”}”(hj8 h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hj ubhŒ3 have a good out-of-memory error-handling strategy.”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M;hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´M=hjÅh²hubj)�”}”(hŒq``GFP_DMA`` Allocate ISA DMA lower than 16MB. If you don't know what that is you don't need it. Very unreliable. ”h]”(j )�”}”(hŒ ``GFP_DMA``”h]”j<)�”}”(hjb h]”hŒGFP_DMA”…”�”}”(hjd h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj` ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´MAhj\ ubj)�”}”(hhh]”hú)�”}”(hŒdAllocate ISA DMA lower than 16MB. If you don't know what that is you don't need it. Very unreliable.”h]”hŒhAllocate ISA DMA lower than 16MB. If you don’t know what that is you don’t need it. Very unreliable.”…”�”}”(hjz h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M@hjw ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj\ ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÃh´MAhjÅh²hubeh}”(h]”h ]”h"]”h$]”h&]”uh1jýhjsh²hh³hÃh´Nubhú)�”}”(hŒÜIf you see a sleeping function called from invalid context warning message, then maybe you called a sleeping allocation function from interrupt context without ``GFP_ATOMIC``. You should really fix that. Run, don't walk.”h]”(hŒ If you see a sleeping function called from invalid context warning message, then maybe you called a sleeping allocation function from interrupt context without ”…”�”}”(hjš h²hh³Nh´Nubj<)�”}”(hŒ``GFP_ATOMIC``”h]”hŒ GFP_ATOMIC”…”�”}”(hj¢ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjš ubhŒ0. You should really fix that. Run, don’t walk.”…”�”}”(hjš h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MChjsh²hubhú)�”}”(hX"If you are allocating at least ``PAGE_SIZE`` (``asm/page.h`` or ``asm/page_types.h``) bytes, consider using __get_free_pages() (``include/linux/gfp.h``). It takes an order argument (0 for page sized, 1 for double page, 2 for four pages etc.) and the same memory priority flag word as above.”h]”(hŒIf you are allocating at least ”…”�”}”(hjº h²hh³Nh´Nubj<)�”}”(hŒ ``PAGE_SIZE``”h]”hŒ PAGE_SIZE”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjº ubhŒ (”…”�”}”(hjº h²hh³Nh´Nubj<)�”}”(hŒ``asm/page.h``”h]”hŒ asm/page.h”…”�”}”(hjÔ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjº ubhŒ or ”…”�”}”(hjº h²hh³Nh´Nubj<)�”}”(hŒ``asm/page_types.h``”h]”hŒasm/page_types.h”…”�”}”(hjæ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjº ubhŒ,) bytes, consider using __get_free_pages() (”…”�”}”(hjº h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/gfp.h``”h]”hŒinclude/linux/gfp.h”…”�”}”(hjø h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjº ubhŒ‹). It takes an order argument (0 for page sized, 1 for double page, 2 for four pages etc.) and the same memory priority flag word as above.”…”�”}”(hjº h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MHhjsh²hubhú)�”}”(hXZIf you are allocating more than a page worth of bytes you can use vmalloc(). It'll allocate virtual memory in the kernel map. This block is not contiguous in physical memory, but the MMU makes it look like it is for you (so it'll only look contiguous to the CPUs, not to external device drivers). If you really need large physically contiguous memory for some weird device, you have a problem: it is poorly supported in Linux because after some time memory fragmentation in a running kernel makes it hard. The best way is to allocate the block early in the boot process via the alloc_bootmem() routine.”h]”hX^If you are allocating more than a page worth of bytes you can use vmalloc(). It’ll allocate virtual memory in the kernel map. This block is not contiguous in physical memory, but the MMU makes it look like it is for you (so it’ll only look contiguous to the CPUs, not to external device drivers). If you really need large physically contiguous memory for some weird device, you have a problem: it is poorly supported in Linux because after some time memory fragmentation in a running kernel makes it hard. The best way is to allocate the block early in the boot process via the alloc_bootmem() routine.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MNhjsh²hubhú)�”}”(hŒmBefore inventing your own cache of often-used objects consider using a slab cache in ``include/linux/slab.h``”h]”(hŒUBefore inventing your own cache of often-used objects consider using a slab cache in ”…”�”}”(hj h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/slab.h``”h]”hŒinclude/linux/slab.h”…”�”}”(hj& h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MYhjsh²hubeh}”(h]”Œ kmalloc-kfree”ah ]”h"]”Œkmalloc()/kfree()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´M,ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒcurrent”h]”hŒcurrent”…”�”}”(hjE h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjB h²hh³hÃh´M]ubhú)�”}”(hŒ$Defined in ``include/asm/current.h``”h]”(hŒ Defined in ”…”�”}”(hjS h²hh³Nh´Nubj<)�”}”(hŒ``include/asm/current.h``”h]”hŒinclude/asm/current.h”…”�”}”(hj[ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjS ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M_hjB h²hubhú)�”}”(hXThis global variable (really a macro) contains a pointer to the current task structure, so is only valid in user context. For example, when a process makes a system call, this will point to the task structure of the calling process. It is **not NULL** in interrupt context.”h]”(hŒïThis global variable (really a macro) contains a pointer to the current task structure, so is only valid in user context. For example, when a process makes a system call, this will point to the task structure of the calling process. It is ”…”�”}”(hjo h²hh³Nh´Nubj¾)�”}”(hŒ **not NULL**”h]”hŒnot NULL”…”�”}”(hjw h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hjo ubhŒ in interrupt context.”…”�”}”(hjo h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MahjB h²hubeh}”(h]”Œcurrent”ah ]”h"]”Œcurrent”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´M]ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒmdelay()/udelay()”h]”hŒmdelay()/udelay()”…”�”}”(hjš h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj— h²hh³hÃh´Mgubhú)�”}”(hŒ>Defined in ``include/asm/delay.h`` / ``include/linux/delay.h``”h]”(hŒ Defined in ”…”�”}”(hj¨ h²hh³Nh´Nubj<)�”}”(hŒ``include/asm/delay.h``”h]”hŒinclude/asm/delay.h”…”�”}”(hj° h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj¨ ubhŒ / ”…”�”}”(hj¨ h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/delay.h``”h]”hŒinclude/linux/delay.h”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj¨ ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mihj— h²hubhú)�”}”(hŒ½The udelay() and ndelay() functions can be used for small pauses. Do not use large values with them as you risk overflow - the helper function mdelay() is useful here, or consider msleep().”h]”hŒ½The udelay() and ndelay() functions can be used for small pauses. Do not use large values with them as you risk overflow - the helper function mdelay() is useful here, or consider msleep().”…”�”}”(hjÖ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mkhj— h²hubeh}”(h]”Œ mdelay-udelay”ah ]”h"]”Œmdelay()/udelay()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´MgubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ7cpu_to_be32()/be32_to_cpu()/cpu_to_le32()/le32_to_cpu()”h]”hŒ7cpu_to_be32()/be32_to_cpu()/cpu_to_le32()/le32_to_cpu()”…”�”}”(hjï h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjì h²hh³hÃh´Mqubhú)�”}”(hŒ&Defined in ``include/asm/byteorder.h``”h]”(hŒ Defined in ”…”�”}”(hjý h²hh³Nh´Nubj<)�”}”(hŒ``include/asm/byteorder.h``”h]”hŒinclude/asm/byteorder.h”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjý ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mshjì h²hubhú)�”}”(hXThe cpu_to_be32() family (where the "32" can be replaced by 64 or 16, and the "be" can be replaced by "le") are the general way to do endian conversions in the kernel: they return the converted value. All variations supply the reverse as well: be32_to_cpu(), etc.”h]”hXThe cpu_to_be32() family (where the “32â€� can be replaced by 64 or 16, and the “beâ€� can be replaced by “leâ€�) are the general way to do endian conversions in the kernel: they return the converted value. All variations supply the reverse as well: be32_to_cpu(), etc.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Muhjì h²hubhú)�”}”(hX/There are two major variations of these functions: the pointer variation, such as cpu_to_be32p(), which take a pointer to the given type, and return the converted value. The other variation is the "in-situ" family, such as cpu_to_be32s(), which convert value referred to by the pointer, and return void.”h]”hX3There are two major variations of these functions: the pointer variation, such as cpu_to_be32p(), which take a pointer to the given type, and return the converted value. The other variation is the “in-situâ€� family, such as cpu_to_be32s(), which convert value referred to by the pointer, and return void.”…”�”}”(hj' h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M{hjì h²hubeh}”(h]”Œ/cpu-to-be32-be32-to-cpu-cpu-to-le32-le32-to-cpu”ah ]”h"]”Œ7cpu_to_be32()/be32_to_cpu()/cpu_to_le32()/le32_to_cpu()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´MqubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ$local_irq_save()/local_irq_restore()”h]”hŒ$local_irq_save()/local_irq_restore()”…”�”}”(hj@ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj= h²hh³hÃh´M‚ubhú)�”}”(hŒ'Defined in ``include/linux/irqflags.h``”h]”(hŒ Defined in ”…”�”}”(hjN h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/irqflags.h``”h]”hŒinclude/linux/irqflags.h”…”�”}”(hjV h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjN ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M„hj= h²hubhú)�”}”(hXThese routines disable hard interrupts on the local CPU, and restore them. They are reentrant; saving the previous state in their one ``unsigned long flags`` argument. If you know that interrupts are enabled, you can simply use local_irq_disable() and local_irq_enable().”h]”(hŒ†These routines disable hard interrupts on the local CPU, and restore them. They are reentrant; saving the previous state in their one ”…”�”}”(hjj h²hh³Nh´Nubj<)�”}”(hŒ``unsigned long flags``”h]”hŒunsigned long flags”…”�”}”(hjr h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjj ubhŒr argument. If you know that interrupts are enabled, you can simply use local_irq_disable() and local_irq_enable().”…”�”}”(hjj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M†hj= h²hubh¶)�”}”(hŒ.. _local_bh_disable:”h]”h}”(h]”h ]”h"]”h$]”h&]”hÁŒlocal-bh-disable”uh1hµh´MŒhj= h²hh³hÃubeh}”(h]”Œ local-irq-save-local-irq-restore”ah ]”h"]”Œ$local_irq_save()/local_irq_restore()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´M‚ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ$local_bh_disable()/local_bh_enable()”h]”hŒ$local_bh_disable()/local_bh_enable()”…”�”}”(hj  h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj� h²hh³hÃh´M�ubhú)�”}”(hŒ*Defined in ``include/linux/bottom_half.h``”h]”(hŒ Defined in ”…”�”}”(hj® h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/bottom_half.h``”h]”hŒinclude/linux/bottom_half.h”…”�”}”(hj¶ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj® ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M‘hj� h²hubhú)�”}”(hXThese routines disable soft interrupts on the local CPU, and restore them. They are reentrant; if soft interrupts were disabled before, they will still be disabled after this pair of functions has been called. They prevent softirqs and tasklets from running on the current CPU.”h]”hXThese routines disable soft interrupts on the local CPU, and restore them. They are reentrant; if soft interrupts were disabled before, they will still be disabled after this pair of functions has been called. They prevent softirqs and tasklets from running on the current CPU.”…”�”}”(hjÊ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M”hj� h²hubeh}”(h]”(Œ local-bh-disable-local-bh-enable”j” eh ]”h"]”(Œ$local_bh_disable()/local_bh_enable()”Œlocal_bh_disable”eh$]”h&]”uh1hÄhjÓh²hh³hÃh´M�Œexpect_referenced_by_name”}”jÞ jŠ sŒexpect_referenced_by_id”}”j” jŠ subhÅ)�”}”(hhh]”(hÊ)�”}”(hŒsmp_processor_id()”h]”hŒsmp_processor_id()”…”�”}”(hjè h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjå h²hh³hÃh´Mšubhú)�”}”(hŒ"Defined in ``include/linux/smp.h``”h]”(hŒ Defined in ”…”�”}”(hjö h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/smp.h``”h]”hŒinclude/linux/smp.h”…”�”}”(hjþ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjö ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mœhjå h²hubhú)�”}”(hXget_cpu() disables preemption (so you won't suddenly get moved to another CPU) and returns the current processor number, between 0 and ``NR_CPUS``. Note that the CPU numbers are not necessarily continuous. You return it again with put_cpu() when you are done.”h]”(hŒ‰get_cpu() disables preemption (so you won’t suddenly get moved to another CPU) and returns the current processor number, between 0 and ”…”�”}”(hj h²hh³Nh´Nubj<)�”}”(hŒ ``NR_CPUS``”h]”hŒNR_CPUS”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj ubhŒq. Note that the CPU numbers are not necessarily continuous. You return it again with put_cpu() when you are done.”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mžhjå h²hubhú)�”}”(hŒ“If you know you cannot be preempted by another task (ie. you are in interrupt context, or have preemption disabled) you can use smp_processor_id().”h]”hŒ“If you know you cannot be preempted by another task (ie. you are in interrupt context, or have preemption disabled) you can use smp_processor_id().”…”�”}”(hj2 h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M¤hjå h²hubeh}”(h]”Œsmp-processor-id”ah ]”h"]”Œsmp_processor_id()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´MšubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ$``__init``/``__exit``/``__initdata``”h]”(j<)�”}”(hŒ ``__init``”h]”hŒ__init”…”�”}”(hjO h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjK ubhŒ/”…”�”}”(hjK h²hh³Nh´Nubj<)�”}”(hŒ ``__exit``”h]”hŒ__exit”…”�”}”(hja h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjK ubhŒ/”…”�”}”hjK sbj<)�”}”(hŒ``__initdata``”h]”hŒ __initdata”…”�”}”(hjs h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjK ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjH h²hh³hÃh´M©ubhú)�”}”(hŒ$Defined in ``include/linux/init.h``”h]”(hŒ Defined in ”…”�”}”(hj‡ h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/init.h``”h]”hŒinclude/linux/init.h”…”�”}”(hj� h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj‡ ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M«hjH h²hubhú)�”}”(hX)After boot, the kernel frees up a special section; functions marked with ``__init`` and data structures marked with ``__initdata`` are dropped after boot is complete: similarly modules discard this memory after initialization. ``__exit`` is used to declare a function which is only required on exit: the function will be dropped if this file is not compiled as a module. See the header file for use. Note that it makes no sense for a function marked with ``__init`` to be exported to modules with EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()- this will break.”h]”(hŒIAfter boot, the kernel frees up a special section; functions marked with ”…”�”}”(hj£ h²hh³Nh´Nubj<)�”}”(hŒ ``__init``”h]”hŒ__init”…”�”}”(hj« h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj£ ubhŒ! and data structures marked with ”…”�”}”(hj£ h²hh³Nh´Nubj<)�”}”(hŒ``__initdata``”h]”hŒ __initdata”…”�”}”(hj½ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj£ ubhŒa are dropped after boot is complete: similarly modules discard this memory after initialization. ”…”�”}”(hj£ h²hh³Nh´Nubj<)�”}”(hŒ ``__exit``”h]”hŒ__exit”…”�”}”(hjÏ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj£ ubhŒÚ is used to declare a function which is only required on exit: the function will be dropped if this file is not compiled as a module. See the header file for use. Note that it makes no sense for a function marked with ”…”�”}”(hj£ h²hh³Nh´Nubj<)�”}”(hŒ ``__init``”h]”hŒ__init”…”�”}”(hjá h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj£ ubhŒX to be exported to modules with EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()- this will break.”…”�”}”(hj£ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M­hjH h²hubeh}”(h]”Œinit-exit-initdata”ah ]”h"]”Œ__init/__exit/__initdata”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´M©ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ__initcall()/module_init()”h]”hŒ__initcall()/module_init()”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj h²hh³hÃh´M¸ubhú)�”}”(hŒADefined in ``include/linux/init.h`` / ``include/linux/module.h``”h]”(hŒ Defined in ”…”�”}”(hj h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/init.h``”h]”hŒinclude/linux/init.h”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj ubhŒ / ”…”�”}”(hj h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/module.h``”h]”hŒinclude/linux/module.h”…”�”}”(hj, h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mºhj h²hubhú)�”}”(hŒ÷Many parts of the kernel are well served as a module (dynamically-loadable parts of the kernel). Using the module_init() and module_exit() macros it is easy to write code without #ifdefs which can operate both as a module or built into the kernel.”h]”hŒ÷Many parts of the kernel are well served as a module (dynamically-loadable parts of the kernel). Using the module_init() and module_exit() macros it is easy to write code without #ifdefs which can operate both as a module or built into the kernel.”…”�”}”(hj@ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M¼hj h²hubhú)�”}”(hX;The module_init() macro defines which function is to be called at module insertion time (if the file is compiled as a module), or at boot time: if the file is not compiled as a module the module_init() macro becomes equivalent to __initcall(), which through linker magic ensures that the function is called on boot.”h]”hX;The module_init() macro defines which function is to be called at module insertion time (if the file is compiled as a module), or at boot time: if the file is not compiled as a module the module_init() macro becomes equivalent to __initcall(), which through linker magic ensures that the function is called on boot.”…”�”}”(hjN h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MÂhj h²hubhú)�”}”(hŒðThe function can return a negative error number to cause module loading to fail (unfortunately, this has no effect if the module is compiled into the kernel). This function is called in user context with interrupts enabled, so it can sleep.”h]”hŒðThe function can return a negative error number to cause module loading to fail (unfortunately, this has no effect if the module is compiled into the kernel). This function is called in user context with interrupts enabled, so it can sleep.”…”�”}”(hj\ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MÉhj h²hubeh}”(h]”Œinitcall-module-init”ah ]”h"]”Œ__initcall()/module_init()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´M¸ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ module_exit()”h]”hŒ module_exit()”…”�”}”(hju h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjr h²hh³hÃh´MÏubhú)�”}”(hŒ&Defined in ``include/linux/module.h``”h]”(hŒ Defined in ”…”�”}”(hjƒ h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/module.h``”h]”hŒinclude/linux/module.h”…”�”}”(hj‹ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjƒ ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MÑhjr h²hubhú)�”}”(hX)This macro defines the function to be called at module removal time (or never, in the case of the file compiled into the kernel). It will only be called if the module usage count has reached zero. This function can also sleep, but cannot fail: everything must be cleaned up by the time it returns.”h]”hX)This macro defines the function to be called at module removal time (or never, in the case of the file compiled into the kernel). It will only be called if the module usage count has reached zero. This function can also sleep, but cannot fail: everything must be cleaned up by the time it returns.”…”�”}”(hjŸ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MÓhjr h²hubhú)�”}”(hŒrNote that this macro is optional: if it is not present, your module will not be removable (except for 'rmmod -f').”h]”hŒvNote that this macro is optional: if it is not present, your module will not be removable (except for ‘rmmod -f’).”…”�”}”(hj­ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MÙhjr h²hubeh}”(h]”Œ module-exit”ah ]”h"]”Œ module_exit()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´MÏubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒtry_module_get()/module_put()”h]”hŒtry_module_get()/module_put()”…”�”}”(hjÆ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjà h²hh³hÃh´MÝubhú)�”}”(hŒ%Defined in ``include/linux/module.h``”h]”(hŒ Defined in ”…”�”}”(hjÔ h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/module.h``”h]”hŒinclude/linux/module.h”…”�”}”(hjÜ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjÔ ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mßhjà h²hubhú)�”}”(hX¥These manipulate the module usage count, to protect against removal (a module also can't be removed if another module uses one of its exported symbols: see below). Before calling into module code, you should call try_module_get() on that module: if it fails, then the module is being removed and you should act as if it wasn't there. Otherwise, you can safely enter the module, and call module_put() when you're finished.”h]”hX«These manipulate the module usage count, to protect against removal (a module also can’t be removed if another module uses one of its exported symbols: see below). Before calling into module code, you should call try_module_get() on that module: if it fails, then the module is being removed and you should act as if it wasn’t there. Otherwise, you can safely enter the module, and call module_put() when you’re finished.”…”�”}”(hjð h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Máhjà h²hubhú)�”}”(hŒ«Most registerable structures have an owner field, such as in the :c:type:`struct file_operations ` structure. Set this field to the macro ``THIS_MODULE``.”h]”(hŒAMost registerable structures have an owner field, such as in the ”…”�”}”(hjþ h²hh³Nh´Nubh)�”}”(hŒ2:c:type:`struct file_operations `”h]”j<)�”}”(hjh]”hŒstruct file_operations”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”(j·Œc”Œc-type”eh"]”h$]”h&]”uh1j;hjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jÄŒ refdomain”jŒreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰jÊŒfile_operations”uh1hh³hÃh´Méhjþ ubhŒ( structure. Set this field to the macro ”…”�”}”(hjþ h²hh³Nh´Nubj<)�”}”(hŒ``THIS_MODULE``”h]”hŒ THIS_MODULE”…”�”}”(hj*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjþ ubhŒ.”…”�”}”(hjþ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Méhjà h²hubeh}”(h]”Œtry-module-get-module-put”ah ]”h"]”Œtry_module_get()/module_put()”ah$]”h&]”uh1hÄhjÓh²hh³hÃh´MÝubeh}”(h]”Œcommon-routines”ah ]”h"]”Œcommon routines”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´KçubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ$Wait Queues ``include/linux/wait.h``”h]”(hŒ Wait Queues ”…”�”}”(hjUh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/wait.h``”h]”hŒinclude/linux/wait.h”…”�”}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjUubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjRh²hh³hÃh´Mîubhú)�”}”(hŒ **[SLEEPS]**”h]”j¾)�”}”(hjsh]”hŒ[SLEEPS]”…”�”}”(hjuh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hjqubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MðhjRh²hubhú)�”}”(hX\A wait queue is used to wait for someone to wake you up when a certain condition is true. They must be used carefully to ensure there is no race condition. You declare a :c:type:`wait_queue_head_t`, and then processes which want to wait for that condition declare a :c:type:`wait_queue_entry_t` referring to themselves, and place that in the queue.”•!°h]”(hŒªA wait queue is used to wait for someone to wake you up when a certain condition is true. They must be used carefully to ensure there is no race condition. You declare a ”…”�”}”(hjˆh²hh³Nh´Nubh)�”}”(hŒ:c:type:`wait_queue_head_t`”h]”j<)�”}”(hj’h]”hŒwait_queue_head_t”…”�”}”(hj”h²hh³Nh´Nubah}”(h]”h ]”(j·jŒc-type”eh"]”h$]”h&]”uh1j;hj�ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jÄŒ refdomain”jŒreftype”Œtype”Œ refexplicit”‰Œrefwarn”‰jÊŒwait_queue_head_t”uh1hh³hÃh´MòhjˆubhŒE, and then processes which want to wait for that condition declare a ”…”�”}”(hjˆh²hh³Nh´Nubh)�”}”(hŒ:c:type:`wait_queue_entry_t`”h]”j<)�”}”(hjµh]”hŒwait_queue_entry_t”…”�”}”(hj·h²hh³Nh´Nubah}”(h]”h ]”(j·jŒc-type”eh"]”h$]”h&]”uh1j;hj³ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jÄŒ refdomain”jŒreftype”Œtype”Œ refexplicit”‰Œrefwarn”‰jÊŒwait_queue_entry_t”uh1hh³hÃh´MòhjˆubhŒ6 referring to themselves, and place that in the queue.”…”�”}”(hjˆh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MòhjRh²hubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ Declaring”h]”hŒ Declaring”…”�”}”(hjßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjÜh²hh³hÃh´Mùubhú)�”}”(hŒ–You declare a ``wait_queue_head_t`` using the DECLARE_WAIT_QUEUE_HEAD() macro, or using the init_waitqueue_head() routine in your initialization code.”h]”(hŒYou declare a ”…”�”}”(hjíh²hh³Nh´Nubj<)�”}”(hŒ``wait_queue_head_t``”h]”hŒwait_queue_head_t”…”�”}”(hjõh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjíubhŒs using the DECLARE_WAIT_QUEUE_HEAD() macro, or using the init_waitqueue_head() routine in your initialization code.”…”�”}”(hjíh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MûhjÜh²hubeh}”(h]”Œ declaring”ah ]”h"]”Œ declaring”ah$]”h&]”uh1hÄhjRh²hh³hÃh´MùubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒQueuing”h]”hŒQueuing”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjh²hh³hÃh´Mubhú)�”}”(hX¹Placing yourself in the waitqueue is fairly complex, because you must put yourself in the queue before checking the condition. There is a macro to do this: wait_event_interruptible() (``include/linux/wait.h``) The first argument is the wait queue head, and the second is an expression which is evaluated; the macro returns 0 when this expression is true, or ``-ERESTARTSYS`` if a signal is received. The wait_event() version ignores signals.”h]”(hŒ¸Placing yourself in the waitqueue is fairly complex, because you must put yourself in the queue before checking the condition. There is a macro to do this: wait_event_interruptible() (”…”�”}”(hj&h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/wait.h``”h]”hŒinclude/linux/wait.h”…”�”}”(hj.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj&ubhŒ–) The first argument is the wait queue head, and the second is an expression which is evaluated; the macro returns 0 when this expression is true, or ”…”�”}”(hj&h²hh³Nh´Nubj<)�”}”(hŒ``-ERESTARTSYS``”h]”hŒ -ERESTARTSYS”…”�”}”(hj@h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj&ubhŒC if a signal is received. The wait_event() version ignores signals.”…”�”}”(hj&h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhjh²hubeh}”(h]”Œqueuing”ah ]”h"]”Œqueuing”ah$]”h&]”uh1hÄhjRh²hh³hÃh´MubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒWaking Up Queued Tasks”h]”hŒWaking Up Queued Tasks”…”�”}”(hjch²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj`h²hh³hÃh´M ubhú)�”}”(hXCall wake_up() (``include/linux/wait.h``), which will wake up every process in the queue. The exception is if one has ``TASK_EXCLUSIVE`` set, in which case the remainder of the queue will not be woken. There are other variants of this basic function available in the same header.”h]”(hŒCall wake_up() (”…”�”}”(hjqh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/wait.h``”h]”hŒinclude/linux/wait.h”…”�”}”(hjyh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjqubhŒN), which will wake up every process in the queue. The exception is if one has ”…”�”}”(hjqh²hh³Nh´Nubj<)�”}”(hŒ``TASK_EXCLUSIVE``”h]”hŒTASK_EXCLUSIVE”…”�”}”(hj‹h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjqubhŒ� set, in which case the remainder of the queue will not be woken. There are other variants of this basic function available in the same header.”…”�”}”(hjqh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhj`h²hubeh}”(h]”Œwaking-up-queued-tasks”ah ]”h"]”Œwaking up queued tasks”ah$]”h&]”uh1hÄhjRh²hh³hÃh´M ubeh}”(h]”Œ wait-queues-include-linux-wait-h”ah ]”h"]”Œ wait queues include/linux/wait.h”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´MîubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒAtomic Operations”h]”hŒAtomic Operations”…”�”}”(hj¶h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj³h²hh³hÃh´Mubhú)�”}”(hXÔCertain operations are guaranteed atomic on all platforms. The first class of operations work on :c:type:`atomic_t` (``include/asm/atomic.h``); this contains a signed integer (at least 32 bits long), and you must use these functions to manipulate or read :c:type:`atomic_t` variables. atomic_read() and atomic_set() get and set the counter, atomic_add(), atomic_sub(), atomic_inc(), atomic_dec(), and atomic_dec_and_test() (returns true if it was decremented to zero).”h]”(hŒaCertain operations are guaranteed atomic on all platforms. The first class of operations work on ”…”�”}”(hjÄh²hh³Nh´Nubh)�”}”(hŒ:c:type:`atomic_t`”h]”j<)�”}”(hjÎh]”hŒatomic_t”…”�”}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”(j·jŒc-type”eh"]”h$]”h&]”uh1j;hjÌubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jÄŒ refdomain”jŒreftype”Œtype”Œ refexplicit”‰Œrefwarn”‰jÊŒatomic_t”uh1hh³hÃh´MhjÄubhŒ (”…”�”}”(hjÄh²hh³Nh´Nubj<)�”}”(hŒ``include/asm/atomic.h``”h]”hŒinclude/asm/atomic.h”…”�”}”(hjïh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjÄubhŒr); this contains a signed integer (at least 32 bits long), and you must use these functions to manipulate or read ”…”�”}”(hjÄh²hh³Nh´Nubh)�”}”(hŒ:c:type:`atomic_t`”h]”j<)�”}”(hjh]”hŒatomic_t”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(j·jŒc-type”eh"]”h$]”h&]”uh1j;hjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jÄŒ refdomain”jŒreftype”Œtype”Œ refexplicit”‰Œrefwarn”‰jÊŒatomic_t”uh1hh³hÃh´MhjÄubhŒÃ variables. atomic_read() and atomic_set() get and set the counter, atomic_add(), atomic_sub(), atomic_inc(), atomic_dec(), and atomic_dec_and_test() (returns true if it was decremented to zero).”…”�”}”(hjÄh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhj³h²hubhú)�”}”(hŒ@Yes. It returns true (i.e. != 0) if the atomic variable is zero.”h]”hŒ@Yes. It returns true (i.e. != 0) if the atomic variable is zero.”…”�”}”(hj*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M!hj³h²hubhú)�”}”(hŒeNote that these functions are slower than normal arithmetic, and so should not be used unnecessarily.”h]”hŒeNote that these functions are slower than normal arithmetic, and so should not be used unnecessarily.”…”�”}”(hj8h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M#hj³h²hubhú)�”}”(hXþThe second class of atomic operations is atomic bit operations on an ``unsigned long``, defined in ``include/linux/bitops.h``. These operations generally take a pointer to the bit pattern, and a bit number: 0 is the least significant bit. set_bit(), clear_bit() and change_bit() set, clear, and flip the given bit. test_and_set_bit(), test_and_clear_bit() and test_and_change_bit() do the same thing, except return true if the bit was previously set; these are particularly useful for atomically setting flags.”h]”(hŒEThe second class of atomic operations is atomic bit operations on an ”…”�”}”(hjFh²hh³Nh´Nubj<)�”}”(hŒ``unsigned long``”h]”hŒ unsigned long”…”�”}”(hjNh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjFubhŒ , defined in ”…”�”}”(hjFh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/bitops.h``”h]”hŒinclude/linux/bitops.h”…”�”}”(hj`h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjFubhX�. These operations generally take a pointer to the bit pattern, and a bit number: 0 is the least significant bit. set_bit(), clear_bit() and change_bit() set, clear, and flip the given bit. test_and_set_bit(), test_and_clear_bit() and test_and_change_bit() do the same thing, except return true if the bit was previously set; these are particularly useful for atomically setting flags.”…”�”}”(hjFh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M&hj³h²hubhú)�”}”(hŒ¾It is possible to call these operations with bit indices greater than ``BITS_PER_LONG``. The resulting behavior is strange on big-endian platforms though so it is a good idea not to do this.”h]”(hŒFIt is possible to call these operations with bit indices greater than ”…”�”}”(hjxh²hh³Nh´Nubj<)�”}”(hŒ``BITS_PER_LONG``”h]”hŒ BITS_PER_LONG”…”�”}”(hj€h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjxubhŒg. The resulting behavior is strange on big-endian platforms though so it is a good idea not to do this.”…”�”}”(hjxh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M1hj³h²hubeh}”(h]”Œatomic-operations”ah ]”h"]”Œatomic operations”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´MubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒSymbols”h]”hŒSymbols”…”�”}”(hj£h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj h²hh³hÃh´M6ubhú)�”}”(hXBWithin the kernel proper, the normal linking rules apply (ie. unless a symbol is declared to be file scope with the ``static`` keyword, it can be used anywhere in the kernel). However, for modules, a special exported symbol table is kept which limits the entry points to the kernel proper. Modules can also export symbols.”h]”(hŒtWithin the kernel proper, the normal linking rules apply (ie. unless a symbol is declared to be file scope with the ”…”�”}”(hj±h²hh³Nh´Nubj<)�”}”(hŒ ``static``”h]”hŒstatic”…”�”}”(hj¹h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj±ubhŒÄ keyword, it can be used anywhere in the kernel). However, for modules, a special exported symbol table is kept which limits the entry points to the kernel proper. Modules can also export symbols.”…”�”}”(hj±h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M8hj h²hubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒEXPORT_SYMBOL()”h]”hŒEXPORT_SYMBOL()”…”�”}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjÑh²hh³hÃh´M?ubhú)�”}”(hŒ%Defined in ``include/linux/export.h``”h]”(hŒ Defined in ”…”�”}”(hjâh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/export.h``”h]”hŒinclude/linux/export.h”…”�”}”(hjêh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjâubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MAhjÑh²hubhú)�”}”(hŒvThis is the classic method of exporting a symbol: dynamically loaded modules will be able to use the symbol as normal.”h]”hŒvThis is the classic method of exporting a symbol: dynamically loaded modules will be able to use the symbol as normal.”…”�”}”(hjþh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MChjÑh²hubeh}”(h]”Œ export-symbol”ah ]”h"]”Œexport_symbol()”ah$]”h&]”uh1hÄhj h²hh³hÃh´M?ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒEXPORT_SYMBOL_GPL()”h]”hŒEXPORT_SYMBOL_GPL()”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjh²hh³hÃh´MGubhú)�”}”(hŒ%Defined in ``include/linux/export.h``”h]”(hŒ Defined in ”…”�”}”(hj%h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/export.h``”h]”hŒinclude/linux/export.h”…”�”}”(hj-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj%ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MIhjh²hubhú)�”}”(hXŽSimilar to EXPORT_SYMBOL() except that the symbols exported by EXPORT_SYMBOL_GPL() can only be seen by modules with a MODULE_LICENSE() that specifies a GPLv2 compatible license. It implies that the function is considered an internal implementation issue, and not really an interface. Some maintainers and developers may however require EXPORT_SYMBOL_GPL() when adding any new APIs or functionality.”h]”hXŽSimilar to EXPORT_SYMBOL() except that the symbols exported by EXPORT_SYMBOL_GPL() can only be seen by modules with a MODULE_LICENSE() that specifies a GPLv2 compatible license. It implies that the function is considered an internal implementation issue, and not really an interface. Some maintainers and developers may however require EXPORT_SYMBOL_GPL() when adding any new APIs or functionality.”…”�”}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MKhjh²hubeh}”(h]”Œexport-symbol-gpl”ah ]”h"]”Œexport_symbol_gpl()”ah$]”h&]”uh1hÄhj h²hh³hÃh´MGubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒEXPORT_SYMBOL_NS()”h]”hŒEXPORT_SYMBOL_NS()”…”�”}”(hjZh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjWh²hh³hÃh´MTubhú)�”}”(hŒ%Defined in ``include/linux/export.h``”h]”(hŒ Defined in ”…”�”}”(hjhh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/export.h``”h]”hŒinclude/linux/export.h”…”�”}”(hjph²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjhubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MVhjWh²hubhú)�”}”(hŒ¢This is the variant of EXPORT_SYMBOL() that allows specifying a symbol namespace. Symbol Namespaces are documented in Documentation/core-api/symbol-namespaces.rst”h]”hŒ¢This is the variant of EXPORT_SYMBOL() that allows specifying a symbol namespace. Symbol Namespaces are documented in Documentation/core-api/symbol-namespaces.rst”…”�”}”(hj„h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MXhjWh²hubeh}”(h]”Œexport-symbol-ns”ah ]”h"]”Œexport_symbol_ns()”ah$]”h&]”uh1hÄhj h²hh³hÃh´MTubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒEXPORT_SYMBOL_NS_GPL()”h]”hŒEXPORT_SYMBOL_NS_GPL()”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjšh²hh³hÃh´M]ubhú)�”}”(hŒ%Defined in ``include/linux/export.h``”h]”(hŒ Defined in ”…”�”}”(hj«h²hh³Nh´Nubj<)�”}”(hŒ``include/linux/export.h``”h]”hŒinclude/linux/export.h”…”�”}”(hj³h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj«ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M_hjšh²hubhú)�”}”(hŒ¦This is the variant of EXPORT_SYMBOL_GPL() that allows specifying a symbol namespace. Symbol Namespaces are documented in Documentation/core-api/symbol-namespaces.rst”h]”hŒ¦This is the variant of EXPORT_SYMBOL_GPL() that allows specifying a symbol namespace. Symbol Namespaces are documented in Documentation/core-api/symbol-namespaces.rst”…”�”}”(hjÇh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mahjšh²hubeh}”(h]”Œexport-symbol-ns-gpl”ah ]”h"]”Œexport_symbol_ns_gpl()”ah$]”h&]”uh1hÄhj h²hh³hÃh´M]ubeh}”(h]”Œsymbols”ah ]”h"]”Œsymbols”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´M6ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒRoutines and Conventions”h]”hŒRoutines and Conventions”…”�”}”(hjèh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjåh²hh³hÃh´MfubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ,Double-linked lists ``include/linux/list.h``”h]”(hŒDouble-linked lists ”…”�”}”(hjùh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/list.h``”h]”hŒinclude/linux/list.h”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjùubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjöh²hh³hÃh´Miubhú)�”}”(hŒ½There used to be three sets of linked-list routines in the kernel headers, but this one is the winner. If you don't have some particular pressing need for a single list, it's a good choice.”h]”hŒÁThere used to be three sets of linked-list routines in the kernel headers, but this one is the winner. If you don’t have some particular pressing need for a single list, it’s a good choice.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mkhjöh²hubhú)�”}”(hŒ/In particular, list_for_each_entry() is useful.”h]”hŒ/In particular, list_for_each_entry() is useful.”…”�”}”(hj#h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mohjöh²hubeh}”(h]”Œ(double-linked-lists-include-linux-list-h”ah ]”h"]”Œ(double-linked lists include/linux/list.h”ah$]”h&]”uh1hÄhjåh²hh³hÃh´MiubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒReturn Conventions”h]”hŒReturn Conventions”…”�”}”(hj<h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj9h²hh³hÃh´Mrubhú)�”}”(hŒèFor code called in user context, it's very common to defy C convention, and return 0 for success, and a negative error number (eg. ``-EFAULT``) for failure. This can be unintuitive at first, but it's fairly widespread in the kernel.”h]”(hŒ…For code called in user context, it’s very common to defy C convention, and return 0 for success, and a negative error number (eg. ”…”�”}”(hjJh²hh³Nh´Nubj<)�”}”(hŒ ``-EFAULT``”h]”hŒ-EFAULT”…”�”}”(hjRh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjJubhŒ\) for failure. This can be unintuitive at first, but it’s fairly widespread in the kernel.”…”�”}”(hjJh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mthj9h²hubhú)�”}”(hŒãUsing ERR_PTR() (``include/linux/err.h``) to encode a negative error number into a pointer, and IS_ERR() and PTR_ERR() to get it back out again: avoids a separate pointer parameter for the error number. Icky, but in a good way.”h]”(hŒUsing ERR_PTR() (”…”�”}”(hjjh²hh³Nh´Nubj<)�”}”(hŒ``include/linux/err.h``”h]”hŒinclude/linux/err.h”…”�”}”(hjrh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjjubhŒ») to encode a negative error number into a pointer, and IS_ERR() and PTR_ERR() to get it back out again: avoids a separate pointer parameter for the error number. Icky, but in a good way.”…”�”}”(hjjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Myhj9h²hubeh}”(h]”Œreturn-conventions”ah ]”h"]”Œreturn conventions”ah$]”h&]”uh1hÄhjåh²hh³hÃh´MrubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒBreaking Compilation”h]”hŒBreaking Compilation”…”�”}”(hj•h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj’h²hh³hÃh´Mubhú)�”}”(hXúLinus and the other developers sometimes change function or structure names in development kernels; this is not done just to keep everyone on their toes: it reflects a fundamental change (eg. can no longer be called with interrupts on, or does extra checks, or doesn't do checks which were caught before). Usually this is accompanied by a fairly complete note to the appropriate kernel development mailing list; search the archives. Simply doing a global replace on the file usually makes things **worse**.”h]”(hXòLinus and the other developers sometimes change function or structure names in development kernels; this is not done just to keep everyone on their toes: it reflects a fundamental change (eg. can no longer be called with interrupts on, or does extra checks, or doesn’t do checks which were caught before). Usually this is accompanied by a fairly complete note to the appropriate kernel development mailing list; search the archives. Simply doing a global replace on the file usually makes things ”…”�”}”(hj£h²hh³Nh´Nubj¾)�”}”(hŒ **worse**”h]”hŒworse”…”�”}”(hj«h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hj£ubhŒ.”…”�”}”(hj£h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M�hj’h²hubeh}”(h]”Œbreaking-compilation”ah ]”h"]”Œbreaking compilation”ah$]”h&]”uh1hÄhjåh²hh³hÃh´MubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒInitializing structure members”h]”hŒInitializing structure members”…”�”}”(hjÎh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjËh²hh³hÃh´M‹ubhú)�”}”(hŒnThe preferred method of initializing structures is to use designated initialisers, as defined by ISO C99, eg::”h]”hŒmThe preferred method of initializing structures is to use designated initialisers, as defined by ISO C99, eg:”…”�”}”(hjÜh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M�hjËh²hubjò)�”}”(hŒástatic struct block_device_operations opt_fops = { .open = opt_open, .release = opt_release, .ioctl = opt_ioctl, .check_media_change = opt_media_change, };”h]”hŒástatic struct block_device_operations opt_fops = { .open = opt_open, .release = opt_release, .ioctl = opt_ioctl, .check_media_change = opt_media_change, };”…”�”}”hjêsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´M�hjËh²hubhú)�”}”(hŒ|This makes it easy to grep for, and makes it clear which structure fields are set. You should do this because it looks cool.”h]”hŒ|This makes it easy to grep for, and makes it clear which structure fields are set. You should do this because it looks cool.”…”�”}”(hjøh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M˜hjËh²hubeh}”(h]”Œinitializing-structure-members”ah ]”h"]”Œinitializing structure members”ah$]”h&]”uh1hÄhjåh²hh³hÃh´M‹ubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒGNU Extensions”h]”hŒGNU Extensions”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjh²hh³hÃh´Mœubhú)�”}”(hX]GNU Extensions are explicitly allowed in the Linux kernel. Note that some of the more complex ones are not very well supported, due to lack of general use, but the following are considered standard (see the GCC info page section "C Extensions" for more details - Yes, really the info page, the man page is only a short summary of the stuff in info).”h]”hXaGNU Extensions are explicitly allowed in the Linux kernel. Note that some of the more complex ones are not very well supported, due to lack of general use, but the following are considered standard (see the GCC info page section “C Extensionsâ€� for more details - Yes, really the info page, the man page is only a short summary of the stuff in info).”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mžhjh²hubjp)�”}”(hhh]”(ju)�”}”(hŒInline functions ”h]”hú)�”}”(hŒInline functions”h]”hŒInline functions”…”�”}”(hj4h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M¤hj0ubah}”(h]”h ]”h"]”h$]”h&]”uh1jthj-h²hh³hÃh´Nubju)�”}”(hŒ6Statement expressions (ie. the ({ and }) constructs). ”h]”hú)�”}”(hŒ5Statement expressions (ie. the ({ and }) constructs).”h]”hŒ5Statement expressions (ie. the ({ and }) constructs).”…”�”}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M¦hjHubah}”(h]”h ]”h"]”h$]”h&]”uh1jthj-h²hh³hÃh´Nubju)�”}”(hŒEDeclaring attributes of a function / variable / type (__attribute__) ”h]”hú)�”}”(hŒDDeclaring attributes of a function / variable / type (__attribute__)”h]”hŒDDeclaring attributes of a function / variable / type (__attribute__)”…”�”}”(hjdh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M¨hj`ubah}”(h]”h ]”h"]”h$]”h&]”uh1jthj-h²hh³hÃh´Nubju)�”}”(hŒtypeof ”h]”hú)�”}”(hŒtypeof”h]”hŒtypeof”…”�”}”(hj|h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M«hjxubah}”(h]”h ]”h"]”h$]”h&]”uh1jthj-h²hh³hÃh´Nubju)�”}”(hŒZero length arrays ”h]”hú)�”}”(hŒZero length arrays”h]”hŒZero length arrays”…”�”}”(hj”h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M­hj�ubah}”(h]”h ]”h"]”h$]”h&]”uh1jthj-h²hh³hÃh´Nubju)�”}”(hŒMacro varargs ”h]”hú)�”}”(hŒ Macro varargs”h]”hŒ Macro varargs”…”�”}”(hj¬h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M¯hj¨ubah}”(h]”h ]”h"]”h$]”h&]”uh1jthj-h²hh³hÃh´Nubju)�”}”(hŒArithmetic on void pointers ”h]”hú)�”}”(hŒArithmetic on void pointers”h]”hŒArithmetic on void pointers”…”�”}”(hjÄh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M±hjÀubah}”(h]”h ]”h"]”h$]”h&]”uh1jthj-h²hh³hÃh´Nubju)�”}”(hŒNon-Constant initializers ”h]”hú)�”}”(hŒNon-Constant initializers”h]”hŒNon-Constant initializers”…”�”}”(hjÜh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M³hjØubah}”(h]”h ]”h"]”h$]”h&]”uh1jthj-h²hh³hÃh´Nubju)�”}”(hŒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M»hjh²hubeh}”(h]”Œgnu-extensions”ah ]”h"]”Œgnu extensions”ah$]”h&]”uh1hÄhjåh²hh³hÃh´MœubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒC++”h]”hŒC++”…”�”}”(hjWh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjTh²hh³hÃh´MÁubhú)�”}”(hX Using C++ in the kernel is usually a bad idea, because the kernel does not provide the necessary runtime environment and the include files are not tested for it. It is still possible, but not recommended. If you really want to do this, forget about exceptions at least.”h]”hX Using C++ in the kernel is usually a bad idea, because the kernel does not provide the necessary runtime environment and the include files are not tested for it. It is still possible, but not recommended. If you really want to do this, forget about exceptions at least.”…”�”}”(hjeh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MÃhjTh²hubeh}”(h]”Œc”ah ]”h"]”Œc++”ah$]”h&]”uh1hÄhjåh²hh³hÃh´MÁubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ#if”h]”hŒ#if”…”�”}”(hj~h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj{h²hh³hÃh´MÉubhú)�”}”(hŒÅIt is generally considered cleaner to use macros in header files (or at the top of .c files) to abstract away functions rather than using \`#if' pre-processor statements throughout the source code.”h]”hŒÇIt is generally considered cleaner to use macros in header files (or at the top of .c files) to abstract away functions rather than using `#if’ pre-processor statements throughout the source code.”…”�”}”(hjŒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MËhj{h²hubeh}”(h]”Œif”ah ]”h"]”Œ#if”ah$]”h&]”uh1hÄhjåh²hh³hÃh´MÉubeh}”(h]”Œroutines-and-conventions”ah ]”h"]”Œroutines and conventions”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´MfubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒ Putting Your Stuff in the Kernel”h]”hŒ Putting Your Stuff in the Kernel”…”�”}”(hj­h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjªh²hh³hÃh´MÐubhú)�”}”(hŒƒIn order to get your stuff into shape for official inclusion, or even to make a neat patch, there's administrative work to be done:”h]”hŒ…In order to get your stuff into shape for official inclusion, or even to make a neat patch, there’s administrative work to be done:”…”�”}”(hj»h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MÒhjªh²hubjp)�”}”(hhh]”(ju)�”}”(hXFigure out who are the owners of the code you've been modifying. Look at the top of the source files, inside the ``MAINTAINERS`` file, and last of all in the ``CREDITS`` file. You should coordinate with these people to make sure you're not duplicating effort, or trying something that's already been rejected. Make sure you put your name and email address at the top of any files you create or modify significantly. This is the first place people will look when they find a bug, or when **they** want to make a change. ”h]”(hú)�”}”(hX5Figure out who are the owners of the code you've been modifying. Look at the top of the source files, inside the ``MAINTAINERS`` file, and last of all in the ``CREDITS`` file. You should coordinate with these people to make sure you're not duplicating effort, or trying something that's already been rejected.”h]”(hŒsFigure out who are the owners of the code you’ve been modifying. Look at the top of the source files, inside the ”…”�”}”(hjÐh²hh³Nh´Nubj<)�”}”(hŒ``MAINTAINERS``”h]”hŒ MAINTAINERS”…”�”}”(hjØh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjÐubhŒ file, and last of all in the ”…”�”}”(hjÐh²hh³Nh´Nubj<)�”}”(hŒ ``CREDITS``”h]”hŒCREDITS”…”�”}”(hjêh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjÐubhŒ� file. You should coordinate with these people to make sure you’re not duplicating effort, or trying something that’s already been rejected.”…”�”}”(hjÐh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MÕhjÌubhú)�”}”(hŒÐMake sure you put your name and email address at the top of any files you create or modify significantly. This is the first place people will look when they find a bug, or when **they** want to make a change.”h]”(hŒ±Make sure you put your name and email address at the top of any files you create or modify significantly. This is the first place people will look when they find a bug, or when ”…”�”}”(hjh²hh³Nh´Nubj¾)�”}”(hŒ**they**”h]”hŒthey”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hjubhŒ want to make a change.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MÛhjÌubeh}”(h]”h ]”h"]”h$]”h&]”uh1jthjÉh²hh³hÃh´Nubju)�”}”(hX>Usually you want a configuration option for your kernel hack. Edit ``Kconfig`` in the appropriate directory. The Config language is simple to use by cut and paste, and there's complete documentation in Documentation/kbuild/kconfig-language.rst. In your description of the option, make sure you address both the expert user and the user who knows nothing about your feature. Mention incompatibilities and issues here. **Definitely** end your description with “if in doubt, say Nâ€� (or, occasionally, \`Y'); this is for people who have no idea what you are talking about. ”h]”(hú)�”}”(hŒôUsually you want a configuration option for your kernel hack. Edit ``Kconfig`` in the appropriate directory. The Config language is simple to use by cut and paste, and there's complete documentation in Documentation/kbuild/kconfig-language.rst.”h]”(hŒCUsually you want a configuration option for your kernel hack. Edit ”…”�”}”(hj,h²hh³Nh´Nubj<)�”}”(hŒ ``Kconfig``”h]”hŒKconfig”…”�”}”(hj4h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj,ubhŒ¨ in the appropriate directory. The Config language is simple to use by cut and paste, and there’s complete documentation in Documentation/kbuild/kconfig-language.rst.”…”�”}”(hj,h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mßhj(ubhú)�”}”(hXGIn your description of the option, make sure you address both the expert user and the user who knows nothing about your feature. Mention incompatibilities and issues here. **Definitely** end your description with “if in doubt, say Nâ€� (or, occasionally, \`Y'); this is for people who have no idea what you are talking about.”h]”(hŒ¬In your description of the option, make sure you address both the expert user and the user who knows nothing about your feature. Mention incompatibilities and issues here. ”…”�”}”(hjLh²hh³Nh´Nubj¾)�”}”(hŒ**Definitely**”h]”hŒ Definitely”…”�”}”(hjTh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j½hjLubhŒ� end your description with “if in doubt, say Nâ€� (or, occasionally, `Y’); this is for people who have no idea what you are talking about.”…”�”}”(hjLh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mähj(ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jthjÉh²hh³hÃh´Nubju)�”}”(hŒ¿Edit the ``Makefile``: the CONFIG variables are exported here so you can usually just add a "obj-$(CONFIG_xxx) += xxx.o" line. The syntax is documented in Documentation/kbuild/makefiles.rst. ”h]”hú)�”}”(hŒ¾Edit the ``Makefile``: the CONFIG variables are exported here so you can usually just add a "obj-$(CONFIG_xxx) += xxx.o" line. The syntax is documented in Documentation/kbuild/makefiles.rst.”h]”(hŒ Edit the ”…”�”}”(hjvh²hh³Nh´Nubj<)�”}”(hŒ ``Makefile``”h]”hŒMakefile”…”�”}”(hj~h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjvubhŒ­: the CONFIG variables are exported here so you can usually just add a “obj-$(CONFIG_xxx) += xxx.oâ€� line. The syntax is documented in Documentation/kbuild/makefiles.rst.”…”�”}”(hjvh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mêhjrubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjÉh²hh³hÃh´Nubju)�”}”(hXQPut yourself in ``CREDITS`` if you consider what you've done noteworthy, usually beyond a single file (your name should be at the top of the source files anyway). ``MAINTAINERS`` means you want to be consulted when changes are made to a subsystem, and hear about bugs; it implies a more-than-passing commitment to some part of the code. ”h]”hú)�”}”(hXPPut yourself in ``CREDITS`` if you consider what you've done noteworthy, usually beyond a single file (your name should be at the top of the source files anyway). ``MAINTAINERS`` means you want to be consulted when changes are made to a subsystem, and hear about bugs; it implies a more-than-passing commitment to some part of the code.”h]”(hŒPut yourself in ”…”�”}”(hj h²hh³Nh´Nubj<)�”}”(hŒ ``CREDITS``”h]”hŒCREDITS”…”�”}”(hj¨h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj ubhŒŠ if you consider what you’ve done noteworthy, usually beyond a single file (your name should be at the top of the source files anyway). ”…”�”}”(hj h²hh³Nh´Nubj<)�”}”(hŒ``MAINTAINERS``”h]”hŒ MAINTAINERS”…”�”}”(hjºh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj ubhŒž means you want to be consulted when changes are made to a subsystem, and hear about bugs; it implies a more-than-passing commitment to some part of the code.”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mîhjœubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjÉh²hh³hÃh´Nubju)�”}”(hŒLFinally, don't forget to read Documentation/process/submitting-patches.rst. ”h]”hú)�”}”(hŒKFinally, don't forget to read Documentation/process/submitting-patches.rst.”h]”hŒMFinally, don’t forget to read Documentation/process/submitting-patches.rst.”…”�”}”(hjÜh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´MôhjØubah}”(h]”h ]”h"]”h$]”h&]”uh1jthjÉh²hh³hÃh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jÜjÝuh1joh³hÃh´MÕhjªh²hubeh}”(h]”Œ putting-your-stuff-in-the-kernel”ah ]”h"]”Œ putting your stuff in the kernel”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´MÐubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒKernel Cantrips”h]”hŒKernel Cantrips”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhjþh²hh³hÃh´Møubhú)�”}”(hŒGSome favorites from browsing the source. Feel free to add to this list.”h]”hŒGSome favorites from browsing the source. Feel free to add to this list.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Múhjþh²hubhú)�”}”(hŒ"``arch/x86/include/asm/delay.h``::”h]”(j<)�”}”(hŒ ``arch/x86/include/asm/delay.h``”h]”hŒarch/x86/include/asm/delay.h”…”�”}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjubhŒ:”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mühjþh²hubjò)�”}”(hŒŠ#define ndelay(n) (__builtin_constant_p(n) ? \ ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ __ndelay(n))”h]”hŒŠ#define ndelay(n) (__builtin_constant_p(n) ? \ ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ __ndelay(n))”…”�”}”hj9sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´Mþhjþh²hubhú)�”}”(hŒ``include/linux/fs.h``::”h]”(j<)�”}”(hŒ``include/linux/fs.h``”h]”hŒinclude/linux/fs.h”…”�”}”(hjKh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjGubhŒ:”…”�”}”(hjGh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhjþh²hubjò)�”}”(hX®/* * Kernel pointers have redundant information, so we can use a * scheme where we can return either an error code or a dentry * pointer with the same return value. * * This should be a per-architecture thing, to allow different * error and pointer decisions. */ #define ERR_PTR(err) ((void *)((long)(err))) #define PTR_ERR(ptr) ((long)(ptr)) #define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000))”h]”hX®/* * Kernel pointers have redundant information, so we can use a * scheme where we can return either an error code or a dentry * pointer with the same return value. * * This should be a per-architecture thing, to allow different * error and pointer decisions. */ #define ERR_PTR(err) ((void *)((long)(err))) #define PTR_ERR(ptr) ((long)(ptr)) #define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000))”…”�”}”hjcsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´Mhjþh²hubhú)�”}”(hŒ(``arch/x86/include/asm/uaccess_32.h:``::”h]”(j<)�”}”(hŒ&``arch/x86/include/asm/uaccess_32.h:``”h]”hŒ"arch/x86/include/asm/uaccess_32.h:”…”�”}”(hjuh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjqubhŒ:”…”�”}”(hjqh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhjþh²hubjò)�”}”(hŒß#define copy_to_user(to,from,n) \ (__builtin_constant_p(n) ? \ __constant_copy_to_user((to),(from),(n)) : \ __generic_copy_to_user((to),(from),(n)))”h]”hŒß#define copy_to_user(to,from,n) \ (__builtin_constant_p(n) ? \ __constant_copy_to_user((to),(from),(n)) : \ __generic_copy_to_user((to),(from),(n)))”…”�”}”hj�sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´Mhjþh²hubhú)�”}”(hŒ``arch/sparc/kernel/head.S:``::”h]”(j<)�”}”(hŒ``arch/sparc/kernel/head.S:``”h]”hŒarch/sparc/kernel/head.S:”…”�”}”(hjŸh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hj›ubhŒ:”…”�”}”(hj›h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´Mhjþh²hubjò)�”}”(hX¶/* * Sun people can't spell worth damn. "compatability" indeed. * At least we *know* we can't spell, and use a spell-checker. */ /* Uh, actually Linus it is I who cannot spell. Too much murky * Sparc assembly will do this to ya. */ C_LABEL(cputypvar): .asciz "compatibility" /* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */ .align 4 C_LABEL(cputypvar_sun4m): .asciz "compatible"”h]”hX¶/* * Sun people can't spell worth damn. "compatability" indeed. * At least we *know* we can't spell, and use a spell-checker. */ /* Uh, actually Linus it is I who cannot spell. Too much murky * Sparc assembly will do this to ya. */ C_LABEL(cputypvar): .asciz "compatibility" /* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */ .align 4 C_LABEL(cputypvar_sun4m): .asciz "compatible"”…”�”}”hj·sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´Mhjþh²hubhú)�”}”(hŒ ``arch/sparc/lib/checksum.S:``::”h]”(j<)�”}”(hŒ``arch/sparc/lib/checksum.S:``”h]”hŒarch/sparc/lib/checksum.S:”…”�”}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j;hjÅubhŒ:”…”�”}”(hjÅh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M,hjþh²hubjò)�”}”(hŒ¤/* Sun, you just can't beat me, you just can't. Stop trying, * give up. I'm serious, I am going to kick the living shit * out of you, game over, lights out. */”h]”hŒ¤/* Sun, you just can't beat me, you just can't. Stop trying, * give up. I'm serious, I am going to kick the living shit * out of you, game over, lights out. */”…”�”}”hjásbah}”(h]”h ]”h"]”h$]”h&]”jjuh1jñh³hÃh´M.hjþh²hubeh}”(h]”Œkernel-cantrips”ah ]”h"]”Œkernel cantrips”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´MøubhÅ)�”}”(hhh]”(hÊ)�”}”(hŒThanks”h]”hŒThanks”…”�”}”(hjúh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhj÷h²hh³hÃh´M5ubhú)�”}”(hX©Thanks to Andi Kleen for the idea, answering my questions, fixing my mistakes, filling content, etc. Philipp Rumpf for more spelling and clarity fixes, and some excellent non-obvious points. Werner Almesberger for giving me a great summary of disable_irq(), and Jes Sorensen and Andrea Arcangeli added caveats. Michael Elizabeth Chastain for checking and adding to the Configure section. Telsa Gwynne for teaching me DocBook.”h]”hX©Thanks to Andi Kleen for the idea, answering my questions, fixing my mistakes, filling content, etc. Philipp Rumpf for more spelling and clarity fixes, and some excellent non-obvious points. Werner Almesberger for giving me a great summary of disable_irq(), and Jes Sorensen and Andrea Arcangeli added caveats. Michael Elizabeth Chastain for checking and adding to the Configure section. Telsa Gwynne for teaching me DocBook.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hùh³hÃh´M7hj÷h²hubeh}”(h]”Œthanks”ah ]”h"]”Œthanks”ah$]”h&]”uh1hÄhhÆh²hh³hÃh´M5ubeh}”(h]”(Œ,unreliable-guide-to-hacking-the-linux-kernel”hÂeh ]”h"]”(Œ,unreliable guide to hacking the linux kernel”Œkernel_hacking_hack”eh$]”h&]”uh1hÄhhh²hh³hÃh´Kjá }”j$h·sjã }”hÂh·subeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÃuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)�”}”(hÉNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jLŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÃŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”(hÂ]”h·aj” ]”jŠ auŒnameids”}”(j$hÂj#j jMjJjéjæj†jƒjÓjÐjájÞjÏjÌjøjõjÐjÍjOjLj°j­jpjmj? j< j” j‘ jé jæ j: j7 jš j— jÞ j” jÝ jÚ jE jB jþ jû jo jl jÀ j½ jGjDj°j­jjj]jZj¨j¥j�jšjâjßjjjTjQj—j”jÚj×j§j¤j6j3j�jŒjÈjÅj jjQjNjxjujŸjœjûjøjôjñjjuŒ nametypes”}”(j$ˆj#‰jM‰jé‰j†‰jÓ‰já‰jωjø‰jЉjO‰j°‰jp‰j? ‰j” ‰jé ‰j: ‰jš ‰jÞ ˆjÝ ‰jE ‰jþ ‰jo ‰jÀ ‰jG‰j°‰j‰j]‰j¨‰j�‰jâ‰j‰jT‰j—‰jÚ‰j§‰j6‰j�‰jȉj ‰jQ‰jx‰jŸ‰jû‰jô‰j‰uh}”(hÂhÆj hÆjJjjæjPjƒjújÐj‰jÞjÖjÌjìjõjÒjÍjûjLjÓj­jäjmj³j< jsj‘ jB jæ j— j7 jì j— j= j” j� jÚ j� jB jå jû jH jl j j½ jr jDjà j­jRjjÜjZjj¥j`jšj³jßj jjÑjQjj”jWj×jšj¤jåj3jöjŒj9jÅj’jjËjNjjujTjœj{jøjªjñjþjj÷uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”(hŒsystem_message”“”)�”}”(hhh]”hú)�”}”(hhh]”hŒ9Hyperlink target "kernel-hacking-hack" is not referenced.”…”�”}”hj·sbah}”(h]”h ]”h"]”h$]”h&]”uh1hùhj´ubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”ŒINFO”Œsource”hÃŒline”Kuh1j²ubj³)�”}”(hhh]”hú)�”}”(hhh]”hŒ6Hyperlink target "local-bh-disable" is not referenced.”…”�”}”hjÒsbah}”(h]”h ]”h"]”h$]”h&]”uh1hùhjÏubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”jÌŒsource”hÃŒline”MŒuh1j²ubeŒ transformer”NŒ include_log”]”Œ decoration”Nh²hub.