Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'docs-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/docs/linux

Pull documentation updates from Jonathan Corbet:
"A slightly calmer cycle for docs this time around, though there is
still a fair amount going on, including:

- Some signs of life on the long-moribund Japanese translation

- Documentation on policies around the use of generative tools for
patch submissions, and a separate document intended for consumption
by generative tools

- The completion of the move of the documentation tools to
tools/docs. For now we're leaving a /scripts/kernel-doc symlink
behind to avoid breaking scripts

- Ongoing build-system work includes the incorporation of
documentation in Python code, better support for documenting
variables, and lots of improvements and fixes

- Automatic linking of man-page references -- cat(1), for example --
to the online pages in the HTML build

...and the usual array of typo fixes and such"

* tag 'docs-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/docs/linux: (107 commits)
doc: development-process: add notice on testing
tools: sphinx-build-wrapper: improve its help message
docs: sphinx-build-wrapper: allow -v override -q
docs: kdoc: Fix pdfdocs build for tools
docs: ja_JP: process: translate 'Obtain a current source tree'
docs: fix 're-use' -> 'reuse' in documentation
docs: ioctl-number: fix a typo in ioctl-number.rst
docs: filesystems: ensure proc pid substitutable is complete
docs: automarkup.py: Skip common English words as C identifiers
Documentation: use a source-read extension for the index link boilerplate
docs: parse_features: make documentation more consistent
docs: add parse_features module documentation
docs: jobserver: do some documentation improvements
docs: add jobserver module documentation
docs: kabi: helpers: add documentation for each "enum" value
docs: kabi: helpers: add helper for debug bits 7 and 8
docs: kabi: system_symbols: end docstring phrases with a dot
docs: python: abi_regex: do some improvements at documentation
docs: python: abi_parser: do some improvements at documentation
docs: add kabi modules documentation
...

+1811 -4383
+4 -4
CREDITS
··· 695 695 N: Chih-Jen Chang 696 696 E: chihjenc@scf.usc.edu 697 697 E: chihjen@iis.sinica.edu.tw 698 - D: IGMP(Internet Group Management Protocol) version 2 698 + D: IGMP (Internet Group Management Protocol) version 2 699 699 S: 3F, 65 Tajen street 700 700 S: Tamsui town, Taipei county, 701 701 S: Taiwan 251 ··· 1997 1997 E: edv@bartelt.via.at 1998 1998 D: Author of a menu based configuration tool, kmenu, which 1999 1999 D: is the predecessor of 'make menuconfig' and 'make xconfig'. 2000 - D: digiboard driver update(modularisation work and 2.1.x upd) 2000 + D: digiboard driver update (modularisation work and 2.1.x upd) 2001 2001 S: Tallak 95 2002 2002 S: 8103 Rein 2003 2003 S: Austria ··· 3613 3613 N: Deepak Saxena 3614 3614 E: dsaxena@plexity.net 3615 3615 D: I2O kernel layer (config, block, core, pci, net). I2O disk support for LILO 3616 - D: XScale(IOP, IXP) porting and other random ARM bits 3616 + D: XScale (IOP, IXP) porting and other random ARM bits 3617 3617 S: Portland, OR 3618 3618 3619 3619 N: Eric Schenk ··· 3990 3990 3991 3991 N: Tsu-Sheng Tsao 3992 3992 E: tsusheng@scf.usc.edu 3993 - D: IGMP(Internet Group Management Protocol) version 2 3993 + D: IGMP (Internet Group Management Protocol) version 2 3994 3994 S: 2F 14 ALY 31 LN 166 SEC 1 SHIH-PEI RD 3995 3995 S: Taipei 3996 3996 S: Taiwan 112
+1 -1
Documentation/ABI/testing/pstore
··· 26 26 27 27 Once the information in a file has been read, removing 28 28 the file will signal to the underlying persistent storage 29 - device that it can reclaim the space for later re-use:: 29 + device that it can reclaim the space for later reuse:: 30 30 31 31 $ rm /sys/fs/pstore/dmesg-erst-1 32 32
+2 -1
Documentation/Makefile
··· 98 98 @echo ' cleandocs - clean all generated files' 99 99 @echo 100 100 @echo ' make SPHINXDIRS="s1 s2" [target] Generate only docs of folder s1, s2' 101 - @echo ' top level values for SPHINXDIRS are: $(_SPHINXDIRS)' 101 + @echo ' top level values for SPHINXDIRS are:' 102 + @echo '$(_SPHINXDIRS)' | fmt -s -w 75 -g 75 | sed 's/^/ /' 102 103 @echo ' you may also use a subdirectory like SPHINXDIRS=userspace-api/media,' 103 104 @echo ' provided that there is an index.rst file at the subdirectory.' 104 105 @echo
-7
Documentation/RCU/index.rst
··· 28 28 Design/Expedited-Grace-Periods/Expedited-Grace-Periods 29 29 Design/Requirements/Requirements 30 30 Design/Data-Structures/Data-Structures 31 - 32 - .. only:: subproject and html 33 - 34 - Indices 35 - ======= 36 - 37 - * :ref:`genindex`
-7
Documentation/accel/index.rst
··· 11 11 amdxdna/index 12 12 qaic/index 13 13 rocket/index 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
+1 -1
Documentation/admin-guide/README.rst
··· 53 53 these typically contain kernel-specific installation notes for some 54 54 drivers for example. Please read the 55 55 :ref:`Documentation/process/changes.rst <changes>` file, as it 56 - contains information about the problems, which may result by upgrading 56 + contains information about the problems which may result from upgrading 57 57 your kernel. 58 58 59 59 Installing the kernel source
-7
Documentation/admin-guide/aoe/index.rst
··· 8 8 aoe 9 9 todo 10 10 examples 11 - 12 - .. only:: subproject and html 13 - 14 - Indices 15 - ======= 16 - 17 - * :ref:`genindex`
-7
Documentation/admin-guide/auxdisplay/index.rst
··· 7 7 8 8 ks0108.rst 9 9 cfag12864b.rst 10 - 11 - .. only:: subproject and html 12 - 13 - Indices 14 - ======= 15 - 16 - * :ref:`genindex`
+3 -3
Documentation/admin-guide/bug-hunting.rst
··· 52 52 we'll refer to "Oops" for all kinds of stack traces that need to be analyzed. 53 53 54 54 If the kernel is compiled with ``CONFIG_DEBUG_INFO``, you can enhance the 55 - quality of the stack trace by using file:`scripts/decode_stacktrace.sh`. 55 + quality of the stack trace by using ``scripts/decode_stacktrace.sh``. 56 56 57 57 Modules linked in 58 58 ----------------- 59 59 60 60 Modules that are tainted or are being loaded or unloaded are marked with 61 61 "(...)", where the taint flags are described in 62 - file:`Documentation/admin-guide/tainted-kernels.rst`, "being loaded" is 62 + Documentation/admin-guide/tainted-kernels.rst, "being loaded" is 63 63 annotated with "+", and "being unloaded" is annotated with "-". 64 64 65 65 ··· 235 235 mov 0x8(%ebp), %ebx ! %ebx = skb->sk 236 236 mov 0x13c(%ebx), %eax ! %eax = inet_sk(sk)->opt 237 237 238 - file:`scripts/decodecode` can be used to automate most of this, depending 238 + ``scripts/decodecode`` can be used to automate most of this, depending 239 239 on what CPU architecture is being debugged. 240 240 241 241 Reporting the bug
+9 -9
Documentation/admin-guide/cgroup-v1/hugetlb.rst
··· 77 77 doesn't support page reclaim, enforcing the limit at page fault time implies 78 78 that, the application will get SIGBUS signal if it tries to fault in HugeTLB 79 79 pages beyond its limit. Therefore the application needs to know exactly how many 80 - HugeTLB pages it uses before hand, and the sysadmin needs to make sure that 80 + HugeTLB pages it uses beforehand, and the sysadmin needs to make sure that 81 81 there are enough available on the machine for all the users to avoid processes 82 82 getting SIGBUS. 83 83 ··· 91 91 hugetlb.<hugepagesize>.rsvd.usage_in_bytes 92 92 hugetlb.<hugepagesize>.rsvd.failcnt 93 93 94 - The HugeTLB controller allows to limit the HugeTLB reservations per control 94 + The HugeTLB controller allows limiting the HugeTLB reservations per control 95 95 group and enforces the controller limit at reservation time and at the fault of 96 96 HugeTLB memory for which no reservation exists. Since reservation limits are 97 - enforced at reservation time (on mmap or shget), reservation limits never causes 98 - the application to get SIGBUS signal if the memory was reserved before hand. For 97 + enforced at reservation time (on mmap or shget), reservation limits never cause 98 + the application to get SIGBUS signal if the memory was reserved beforehand. For 99 99 MAP_NORESERVE allocations, the reservation limit behaves the same as the fault 100 100 limit, enforcing memory usage at fault time and causing the application to 101 101 receive a SIGBUS if it's crossing its limit. 102 102 103 103 Reservation limits are superior to page fault limits described above, since 104 104 reservation limits are enforced at reservation time (on mmap or shget), and 105 - never causes the application to get SIGBUS signal if the memory was reserved 106 - before hand. This allows for easier fallback to alternatives such as 105 + never cause the application to get SIGBUS signal if the memory was reserved 106 + beforehand. This allows for easier fallback to alternatives such as 107 107 non-HugeTLB memory for example. In the case of page fault accounting, it's very 108 - hard to avoid processes getting SIGBUS since the sysadmin needs precisely know 109 - the HugeTLB usage of all the tasks in the system and make sure there is enough 110 - pages to satisfy all requests. Avoiding tasks getting SIGBUS on overcommited 108 + hard to avoid processes getting SIGBUS since the sysadmin needs to precisely know 109 + the HugeTLB usage of all the tasks in the system and make sure there are enough 110 + pages to satisfy all requests. Avoiding tasks getting SIGBUS on overcommitted 111 111 systems is practically impossible with page fault accounting. 112 112 113 113
-7
Documentation/admin-guide/cgroup-v1/index.rst
··· 22 22 net_prio 23 23 pids 24 24 rdma 25 - 26 - .. only:: subproject and html 27 - 28 - Indices 29 - ======= 30 - 31 - * :ref:`genindex`
+1 -1
Documentation/admin-guide/cgroup-v2.rst
··· 2816 2816 HugeTLB 2817 2817 ------- 2818 2818 2819 - The HugeTLB controller allows to limit the HugeTLB usage per control group and 2819 + The HugeTLB controller allows limiting the HugeTLB usage per control group and 2820 2820 enforces the controller limit during page fault. 2821 2821 2822 2822 HugeTLB Interface Files
-7
Documentation/admin-guide/cifs/index.rst
··· 12 12 todo 13 13 changes 14 14 authors 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex`
-7
Documentation/admin-guide/device-mapper/index.rst
··· 40 40 verity 41 41 writecache 42 42 zero 43 - 44 - .. only:: subproject and html 45 - 46 - Indices 47 - ======= 48 - 49 - * :ref:`genindex`
+6 -4
Documentation/admin-guide/devices.rst
··· 97 97 /dev/bttv0 video0 symbolic Backward compatibility 98 98 /dev/radio radio0 symbolic Backward compatibility 99 99 /dev/i2o* /dev/i2o/* symbolic Backward compatibility 100 - /dev/scd? sr? hard Alternate SCSI CD-ROM name 101 100 =============== =============== =============== =============================== 101 + 102 + Suggested earlier ``/dev/scd?`` alternative names for ``/dev/sr?`` 103 + CD-ROM and other optical drives (using SCSI commands) were removed 104 + in ``udev`` version 174 that was released in 2011. 102 105 103 106 Locally defined links 104 107 +++++++++++++++++++++ ··· 115 112 /dev/mouse mouse port symbolic Current mouse device 116 113 /dev/tape tape device symbolic Current tape device 117 114 /dev/cdrom CD-ROM device symbolic Current CD-ROM device 118 - /dev/cdwriter CD-writer symbolic Current CD-writer device 119 115 /dev/scanner scanner symbolic Current scanner device 120 116 /dev/modem modem port symbolic Current dialout device 121 117 /dev/root root device symbolic Current root filesystem ··· 128 126 129 127 For SCSI devices, ``/dev/tape`` and ``/dev/cdrom`` should point to the 130 128 *cooked* devices (``/dev/st*`` and ``/dev/sr*``, respectively), whereas 131 - ``/dev/cdwriter`` and /dev/scanner should point to the appropriate generic 132 - SCSI devices (/dev/sg*). 129 + ``/dev/scanner`` should point to the appropriate generic 130 + SCSI device (``/dev/sg*``). 133 131 134 132 ``/dev/mouse`` may point to a primary serial TTY device, a hardware mouse 135 133 device, or a socket for a mouse driver program (e.g. ``/dev/gpmdata``).
+3 -3
Documentation/admin-guide/devices.txt
··· 389 389 ... 390 390 391 391 11 block SCSI CD-ROM devices 392 - 0 = /dev/scd0 First SCSI CD-ROM 393 - 1 = /dev/scd1 Second SCSI CD-ROM 392 + 0 = /dev/sr0 First SCSI CD-ROM 393 + 1 = /dev/sr1 Second SCSI CD-ROM 394 394 ... 395 395 396 - The prefix /dev/sr (instead of /dev/scd) has been deprecated. 396 + In the past the prefix /dev/scd (instead of /dev/sr) was used and even recommended. 397 397 398 398 12 char QIC-02 tape 399 399 2 = /dev/ntpqic11 QIC-11, no rewind-on-close
-7
Documentation/admin-guide/gpio/index.rst
··· 12 12 gpio-sim 13 13 gpio-virtuser 14 14 Obsolete APIs <obsolete> 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex`
-7
Documentation/admin-guide/index.rst
··· 189 189 190 190 ldm 191 191 unicode 192 - 193 - .. only:: subproject and html 194 - 195 - Indices 196 - ======= 197 - 198 - * :ref:`genindex`
+1 -1
Documentation/admin-guide/initrd.rst
··· 297 297 8) now the system is bootable and additional installation tasks can be 298 298 performed 299 299 300 - The key role of initrd here is to re-use the configuration data during 300 + The key role of initrd here is to reuse the configuration data during 301 301 normal system operation without requiring the use of a bloated "generic" 302 302 kernel or re-compiling or re-linking the kernel. 303 303
-7
Documentation/admin-guide/kdump/index.rst
··· 11 11 12 12 kdump 13 13 vmcoreinfo 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
+1 -1
Documentation/admin-guide/kdump/kdump.rst
··· 591 591 cat /sys/kernel/config/crash_dm_crypt_keys/count 592 592 2 593 593 594 - # To support CPU/memory hot-plugging, re-use keys already saved to reserved 594 + # To support CPU/memory hot-plugging, reuse keys already saved to reserved 595 595 # memory 596 596 echo true > /sys/kernel/config/crash_dm_crypt_key/reuse 597 597
+4
Documentation/admin-guide/kernel-parameters.txt
··· 1969 1969 param "no_hash_pointers" is an alias for 1970 1970 this mode. 1971 1971 1972 + For controlling hashing dynamically at runtime, 1973 + use the "kernel.kptr_restrict" sysctl instead. 1974 + 1972 1975 hashdist= [KNL,NUMA] Large hashes allocated during boot 1973 1976 are distributed across NUMA nodes. Defaults on 1974 1977 for 64-bit NUMA, off otherwise. ··· 4039 4036 spectre_v2_user=off [X86] 4040 4037 srbds=off [X86,INTEL] 4041 4038 ssbd=force-off [ARM64] 4039 + tsa=off [X86,AMD] 4042 4040 tsx_async_abort=off [X86] 4043 4041 vmscape=off [X86] 4044 4042
+1 -1
Documentation/admin-guide/mm/nommu-mmap.rst
··· 38 38 39 39 In the no-MMU case: 40 40 41 - - If one exists, the kernel will re-use an existing mapping to the 41 + - If one exists, the kernel will reuse an existing mapping to the 42 42 same segment of the same file if that has compatible permissions, 43 43 even if this was created by another process. 44 44
+3
Documentation/admin-guide/sysctl/kernel.rst
··· 591 591 When ``kptr_restrict`` is set to 2, kernel pointers printed using 592 592 %pK will be replaced with 0s regardless of privileges. 593 593 594 + For disabling these security restrictions early at boot time (and once 595 + for all), use the ``hash_pointers`` boot parameter instead. 596 + 594 597 softlockup_sys_info & hardlockup_sys_info 595 598 ========================================= 596 599 A comma separated list of extra system information to be dumped when
-7
Documentation/arch/arc/index.rst
··· 8 8 arc 9 9 10 10 features 11 - 12 - .. only:: subproject and html 13 - 14 - Indices 15 - ======= 16 - 17 - * :ref:`genindex`
-8
Documentation/arch/arm/index.rst
··· 75 75 sti/overview 76 76 77 77 vfp/release-notes 78 - 79 - 80 - .. only:: subproject and html 81 - 82 - Indices 83 - ======= 84 - 85 - * :ref:`genindex`
+1 -1
Documentation/arch/arm/keystone/knav-qmss.rst
··· 39 39 40 40 git://git.ti.com/keystone-rtos/qmss-lld.git 41 41 42 - k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin firmware supports upto 48 accumulator 42 + k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin firmware supports up to 48 accumulator 43 43 channels. This firmware is available under ti-keystone folder of 44 44 firmware.git at 45 45
+1 -1
Documentation/arch/arm/keystone/overview.rst
··· 65 65 66 66 The device tree documentation for the keystone machines are located at 67 67 68 - Documentation/devicetree/bindings/arm/keystone/keystone.txt 68 + Documentation/devicetree/bindings/arm/ti/ti,keystone.yaml 69 69 70 70 Document Author 71 71 ---------------
+2 -2
Documentation/arch/arm64/arm-acpi.rst
··· 306 306 then retrieve the value of the property by evaluating the KEY0 object. 307 307 However, using Name() this way has multiple problems: (1) ACPI limits 308 308 names ("KEY0") to four characters unlike DT; (2) there is no industry 309 - wide registry that maintains a list of names, minimizing re-use; (3) 309 + wide registry that maintains a list of names, minimizing reuse; (3) 310 310 there is also no registry for the definition of property values ("value0"), 311 - again making re-use difficult; and (4) how does one maintain backward 311 + again making reuse difficult; and (4) how does one maintain backward 312 312 compatibility as new hardware comes out? The _DSD method was created 313 313 to solve precisely these sorts of problems; Linux drivers should ALWAYS 314 314 use the _DSD method for device properties and nothing else.
-7
Documentation/arch/arm64/index.rst
··· 33 33 tagged-pointers 34 34 35 35 features 36 - 37 - .. only:: subproject and html 38 - 39 - Indices 40 - ======= 41 - 42 - * :ref:`genindex`
-7
Documentation/arch/loongarch/index.rst
··· 13 13 irq-chip-model 14 14 15 15 features 16 - 17 - .. only:: subproject and html 18 - 19 - Indices 20 - ======= 21 - 22 - * :ref:`genindex`
-7
Documentation/arch/m68k/index.rst
··· 11 11 buddha-driver 12 12 13 13 features 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-7
Documentation/arch/mips/index.rst
··· 12 12 ingenic-tcu 13 13 14 14 features 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex`
-7
Documentation/arch/openrisc/index.rst
··· 11 11 todo 12 12 13 13 features 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-7
Documentation/arch/parisc/index.rst
··· 11 11 registers 12 12 13 13 features 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-7
Documentation/arch/powerpc/index.rst
··· 40 40 vpa-dtl 41 41 42 42 features 43 - 44 - .. only:: subproject and html 45 - 46 - Indices 47 - ======= 48 - 49 - * :ref:`genindex`
-7
Documentation/arch/riscv/index.rst
··· 16 16 cmodx 17 17 18 18 features 19 - 20 - .. only:: subproject and html 21 - 22 - Indices 23 - ======= 24 - 25 - * :ref:`genindex`
+1 -1
Documentation/arch/s390/driver-model.rst
··· 279 279 - Can be 'online' or 'offline'. 280 280 Piping 'on' or 'off' sets the chpid logically online/offline. 281 281 Piping 'on' to an online chpid triggers path reprobing for all devices 282 - the chpid connects to. This can be used to force the kernel to re-use 282 + the chpid connects to. This can be used to force the kernel to reuse 283 283 a channel path the user knows to be online, but the machine hasn't 284 284 created a machine check for. 285 285
-7
Documentation/arch/s390/index.rst
··· 22 22 text_files 23 23 24 24 features 25 - 26 - .. only:: subproject and html 27 - 28 - Indices 29 - ======= 30 - 31 - * :ref:`genindex`
+1 -1
Documentation/arch/x86/shstk.rst
··· 165 165 When a task forks a child, its shadow stack PTEs are copied and both the 166 166 parent's and the child's shadow stack PTEs are cleared of the dirty bit. 167 167 Upon the next shadow stack access, the resulting shadow stack page fault 168 - is handled by page copy/re-use. 168 + is handled by page copy/reuse. 169 169 170 170 When a pthread child is created, the kernel allocates a new shadow stack 171 171 for the new thread. New shadow stack creation behaves like mmap() with respect
-7
Documentation/bpf/index.rst
··· 34 34 other 35 35 redirect 36 36 37 - .. only:: subproject and html 38 - 39 - Indices 40 - ======= 41 - 42 - * :ref:`genindex` 43 - 44 37 .. Links: 45 38 .. _BPF and XDP Reference Guide: https://docs.cilium.io/en/latest/bpf/
-7
Documentation/cdrom/index.rst
··· 8 8 :maxdepth: 1 9 9 10 10 cdrom-standard 11 - 12 - .. only:: subproject and html 13 - 14 - Indices 15 - ======= 16 - 17 - * :ref:`genindex`
+40 -15
Documentation/conf.py
··· 13 13 14 14 import sphinx 15 15 16 - # If extensions (or modules to document with autodoc) are in another directory, 17 - # add these directories to sys.path here. If the directory is relative to the 18 - # documentation root, use os.path.abspath to make it absolute, like shown here. 19 - sys.path.insert(0, os.path.abspath("sphinx")) 16 + # Location of Documentation/ directory 17 + kern_doc_dir = os.path.dirname(os.path.abspath(__file__)) 18 + 19 + # Add location of Sphinx extensions 20 + sys.path.insert(0, os.path.join(kern_doc_dir, "sphinx")) 21 + 22 + # Allow sphinx.ext.autodoc to document files at tools and scripts 23 + sys.path.append(os.path.join(kern_doc_dir, "..", "tools")) 24 + sys.path.append(os.path.join(kern_doc_dir, "..", "scripts")) 20 25 21 26 # Minimal supported version 22 27 needs_sphinx = "3.4.3" ··· 37 32 # Include patterns that don't contain directory names, in glob format 38 33 include_patterns = ["**.rst"] 39 34 40 - # Location of Documentation/ directory 41 - doctree = os.path.abspath(".") 42 - 43 35 # Exclude of patterns that don't contain directory names, in glob format. 44 36 exclude_patterns = [] 45 37 46 38 # List of patterns that contain directory names in glob format. 47 39 dyn_include_patterns = [] 48 - dyn_exclude_patterns = ["output"] 40 + dyn_exclude_patterns = ["output", "sphinx-includes"] 49 41 50 42 # Currently, only netlink/specs has a parser for yaml. 51 43 # Prefer using include patterns if available, as it is faster ··· 52 50 dyn_exclude_patterns.append("netlink/*.yaml") 53 51 dyn_exclude_patterns.append("devicetree/bindings/**.yaml") 54 52 dyn_exclude_patterns.append("core-api/kho/bindings/**.yaml") 53 + 54 + # Link to man pages 55 + manpages_url = 'https://man7.org/linux/man-pages/man{section}/{page}.{section}.html' 55 56 56 57 # Properly handle directory patterns and LaTeX docs 57 58 # ------------------------------------------------- ··· 75 70 # setup include_patterns dynamically 76 71 if has_include_patterns: 77 72 for p in dyn_include_patterns: 78 - full = os.path.join(doctree, p) 73 + full = os.path.join(kern_doc_dir, p) 79 74 80 75 rel_path = os.path.relpath(full, start=app.srcdir) 81 76 if rel_path.startswith("../"): ··· 85 80 86 81 # setup exclude_patterns dynamically 87 82 for p in dyn_exclude_patterns: 88 - full = os.path.join(doctree, p) 83 + full = os.path.join(kern_doc_dir, p) 89 84 90 85 rel_path = os.path.relpath(full, start=app.srcdir) 91 86 if rel_path.startswith("../"): ··· 97 92 # of the app.srcdir. Add them here 98 93 99 94 # Handle the case where SPHINXDIRS is used 100 - if not os.path.samefile(doctree, app.srcdir): 95 + if not os.path.samefile(kern_doc_dir, app.srcdir): 101 96 # Add a tag to mark that the build is actually a subproject 102 97 tags.add("subproject") 103 98 ··· 156 151 "maintainers_include", 157 152 "parser_yaml", 158 153 "rstFlatTable", 154 + "sphinx.ext.autodoc", 159 155 "sphinx.ext.autosectionlabel", 160 156 "sphinx.ext.ifconfig", 161 157 "translations", ··· 585 579 ("kernel-documentation", "Kernel", "Kernel", "J. Random Bozo"), 586 580 ] 587 581 588 - # kernel-doc extension configuration for running Sphinx directly (e.g. by Read 589 - # the Docs). In a normal build, these are supplied from the Makefile via command 590 - # line arguments. 591 - kerneldoc_bin = "../scripts/kernel-doc.py" 592 582 kerneldoc_srctree = ".." 583 + 584 + # Add index link at the end of the root document for SPHINXDIRS builds. 585 + def add_subproject_index(app, docname, content): 586 + # Only care about root documents 587 + if docname != master_doc: 588 + return 589 + 590 + # Add the index link at the root of translations, but not at the root of 591 + # individual translations. They have their own language specific links. 592 + rel = os.path.relpath(app.srcdir, start=kern_doc_dir).split('/') 593 + if rel[0] == 'translations' and len(rel) > 1: 594 + return 595 + 596 + # Only add the link for SPHINXDIRS HTML builds 597 + if not app.builder.tags.has('subproject') or not app.builder.tags.has('html'): 598 + return 599 + 600 + # The include directive needs a relative path from the srcdir 601 + rel = os.path.relpath(os.path.join(kern_doc_dir, 'sphinx-includes/subproject-index.rst'), 602 + start=app.srcdir) 603 + 604 + content[0] += f'\n.. include:: {rel}\n\n' 593 605 594 606 def setup(app): 595 607 """Patterns need to be updated at init time on older Sphinx versions""" 596 608 597 609 app.connect('config-inited', config_init) 610 + app.connect('source-read', add_subproject_index)
-7
Documentation/core-api/index.rst
··· 141 141 librs 142 142 liveupdate 143 143 netlink 144 - 145 - .. only:: subproject and html 146 - 147 - Indices 148 - ======= 149 - 150 - * :ref:`genindex`
-2
Documentation/core-api/kho/index.rst
··· 9 9 10 10 concepts 11 11 fdt 12 - 13 - .. only:: subproject and html
+1 -1
Documentation/core-api/kobject.rst
··· 78 78 often have the opposite problem, however: given a struct kobject pointer, 79 79 what is the pointer to the containing structure? You must avoid tricks 80 80 (such as assuming that the kobject is at the beginning of the structure) 81 - and, instead, use the container_of() macro, found in ``<linux/kernel.h>``:: 81 + and, instead, use the container_of() macro, found in ``<linux/container_of.h>``:: 82 82 83 83 container_of(ptr, type, member) 84 84
+2 -1
Documentation/core-api/real-time/architecture-porting.rst
··· 35 35 POSIX CPU timers must expire from thread context rather than directly within 36 36 the timer interrupt. This behavior is enabled by setting the configuration 37 37 option CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK. 38 - When KVM is enabled, CONFIG_KVM_XFER_TO_GUEST_WORK must also be set to ensure 38 + When virtualization support, such as KVM, is enabled, 39 + CONFIG_VIRT_XFER_TO_GUEST_WORK must also be set to ensure 39 40 that any pending work, such as POSIX timer expiration, is handled before 40 41 transitioning into guest mode. 41 42
+132
Documentation/core-api/real-time/hardware.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ==================== 4 + Considering hardware 5 + ==================== 6 + 7 + :Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de> 8 + 9 + The way a workload is handled can be influenced by the hardware it runs on. 10 + Key components include the CPU, memory, and the buses that connect them. 11 + These resources are shared among all applications on the system. 12 + As a result, heavy utilization of one resource by a single application 13 + can affect the deterministic handling of workloads in other applications. 14 + 15 + Below is a brief overview. 16 + 17 + System memory and cache 18 + ----------------------- 19 + 20 + Main memory and the associated caches are the most common shared resources among 21 + tasks in a system. One task can dominate the available caches, forcing another 22 + task to wait until a cache line is written back to main memory before it can 23 + proceed. The impact of this contention varies based on write patterns and the 24 + size of the caches available. Larger caches may reduce stalls because more lines 25 + can be buffered before being written back. Conversely, certain write patterns 26 + may trigger the cache controller to flush many lines at once, causing 27 + applications to stall until the operation completes. 28 + 29 + This issue can be partly mitigated if applications do not share the same CPU 30 + cache. The kernel is aware of the cache topology and exports this information to 31 + user space. Tools such as **lstopo** from the Portable Hardware Locality (hwloc) 32 + project (https://www.open-mpi.org/projects/hwloc/) can visualize the hierarchy. 33 + 34 + Avoiding shared L2 or L3 caches is not always possible. Even when cache sharing 35 + is minimized, bottlenecks can still occur when accessing system memory. Memory 36 + is used not only by the CPU but also by peripheral devices via DMA, such as 37 + graphics cards or network adapters. 38 + 39 + In some cases, cache and memory bottlenecks can be controlled if the hardware 40 + provides the necessary support. On x86 systems, Intel offers Cache Allocation 41 + Technology (CAT), which enables cache partitioning among applications and 42 + provides control over the interconnect. AMD provides similar functionality under 43 + Platform Quality of Service (PQoS). On Arm64, the equivalent is Memory 44 + System Resource Partitioning and Monitoring (MPAM). 45 + 46 + These features can be configured through the Linux Resource Control interface. 47 + For details, see Documentation/filesystems/resctrl.rst. 48 + 49 + The perf tool can be used to monitor cache behavior. It can analyze 50 + cache misses of an application and compare how they change under 51 + different workloads on a neighboring CPU. Even more powerful, the perf 52 + c2c tool can help identify cache-to-cache issues, where multiple CPU 53 + cores repeatedly access and modify data on the same cache line. 54 + 55 + Hardware buses 56 + -------------- 57 + 58 + Real-time systems often need to access hardware directly to perform their work. 59 + Any latency in this process is undesirable, as it can affect the outcome of the 60 + task. For example, on an I/O bus, a changed output may not become immediately 61 + visible but instead appear with variable delay depending on the latency of the 62 + bus used for communication. 63 + 64 + A bus such as PCI is relatively simple because register accesses are routed 65 + directly to the connected device. In the worst case, a read operation stalls the 66 + CPU until the device responds. 67 + 68 + A bus such as USB is more complex, involving multiple layers. A register read 69 + or write is wrapped in a USB Request Block (URB), which is then sent by the 70 + USB host controller to the device. Timing and latency are influenced by the 71 + underlying USB bus. Requests cannot be sent immediately; they must align with 72 + the next frame boundary according to the endpoint type and the host controller's 73 + scheduling rules. This can introduce delays and additional latency. For example, 74 + a network device connected via USB may still deliver sufficient throughput, but 75 + the added latency when sending or receiving packets may fail to meet the 76 + requirements of certain real-time use cases. 77 + 78 + Additional restrictions on bus latency can arise from power management. For 79 + instance, PCIe with Active State Power Management (ASPM) enabled can suspend 80 + the link between the device and the host. While this behavior is beneficial for 81 + power savings, it delays device access and adds latency to responses. This issue 82 + is not limited to PCIe; internal buses within a System-on-Chip (SoC) can also be 83 + affected by power management mechanisms. 84 + 85 + Virtualization 86 + -------------- 87 + 88 + In a virtualized environment such as KVM, each guest CPU is represented as a 89 + thread on the host. If such a thread runs with real-time priority, the system 90 + should be tested to confirm it can sustain this behavior over extended periods. 91 + Because of its priority, the thread will not be preempted by lower-priority 92 + threads (such as SCHED_OTHER), which may then receive no CPU time. This can 93 + cause problems if a lower-priority thread is pinned to a CPU already occupied by 94 + a real-time task and unable to make progress. Even if a CPU has been isolated, 95 + the system may still (accidentally) start a per‑CPU thread on that CPU. 96 + Ensuring that a guest CPU goes idle is difficult, as it requires avoiding both 97 + task scheduling and interrupt handling. Furthermore, if the guest CPU does go 98 + idle but the guest system is booted with the option **idle=poll**, the guest 99 + CPU will never enter an idle state and will instead spin until an event 100 + arrives. 101 + 102 + Device handling introduces additional considerations. Emulated PCI devices or 103 + VirtIO devices require a counterpart on the host to complete requests. This 104 + adds latency because the host must intercept and either process the request 105 + directly or schedule a thread for its completion. These delays can be avoided if 106 + the required PCI device is passed directly through to the guest. Some devices, 107 + such as networking or storage controllers, support the PCIe SR-IOV feature. 108 + SR-IOV allows a single PCIe device to be divided into multiple virtual functions, 109 + which can then be assigned to different guests. 110 + 111 + Networking 112 + ---------- 113 + 114 + For low-latency networking, the full networking stack may be undesirable, as it 115 + can introduce additional sources of delay. In this context, XDP can be used 116 + as a shortcut to bypass much of the stack while still relying on the kernel's 117 + network driver. 118 + 119 + The requirements are that the network driver must support XDP- preferably using 120 + an "skb pool" and that the application must use an XDP socket. Additional 121 + configuration may involve BPF filters, tuning networking queues, or configuring 122 + qdiscs for time-based transmission. These techniques are often 123 + applied in Time-Sensitive Networking (TSN) environments. 124 + 125 + Documenting all required steps exceeds the scope of this text. For detailed 126 + guidance, see the TSN documentation at https://tsn.readthedocs.io. 127 + 128 + Another useful resource is the Linux Real-Time Communication Testbench 129 + https://github.com/Linutronix/RTC-Testbench. 130 + The goal of this project is to validate real-time network communication. It can 131 + be thought of as a "cyclictest" for networking and also serves as a starting 132 + point for application development.
+1
Documentation/core-api/real-time/index.rst
··· 13 13 14 14 theory 15 15 differences 16 + hardware 16 17 architecture-porting
+1 -1
Documentation/dev-tools/checkpatch.rst
··· 753 753 sizeof(foo)/sizeof(foo[0]) for finding number of elements in an 754 754 array. 755 755 756 - The macro is defined in include/linux/kernel.h:: 756 + The macro is defined in include/linux/array_size.h:: 757 757 758 758 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 759 759
+1 -1
Documentation/dev-tools/clang-format.rst
··· 88 88 89 89 By using an integration with your text editor, you can reformat arbitrary 90 90 blocks (selections) of code with a single keystroke. This is specially 91 - useful when moving code around, for complex code that is deeply intended, 91 + useful when moving code around, for complex code that is deeply indented, 92 92 for multi-line macros (and aligning their backslashes), etc. 93 93 94 94 Remember that you can always tweak the changes afterwards in those cases
-8
Documentation/dev-tools/index.rst
··· 38 38 gpio-sloppy-logic-analyzer 39 39 autofdo 40 40 propeller 41 - 42 - 43 - .. only:: subproject and html 44 - 45 - Indices 46 - ======= 47 - 48 - * :ref:`genindex`
-7
Documentation/doc-guide/index.rst
··· 13 13 contributing 14 14 maintainer-profile 15 15 checktransupdate 16 - 17 - .. only:: subproject and html 18 - 19 - Indices 20 - ======= 21 - 22 - * :ref:`genindex`
+42 -21
Documentation/doc-guide/kernel-doc.rst
··· 54 54 output generation may be used to verify proper formatting of the 55 55 documentation comments. For example:: 56 56 57 - scripts/kernel-doc -v -none drivers/foo/bar.c 57 + tools/docs/kernel-doc -v -none drivers/foo/bar.c 58 58 59 - The documentation format is verified by the kernel build when it is 60 - requested to perform extra gcc checks:: 59 + The documentation format of ``.c`` files is also verified by the kernel build 60 + when it is requested to perform extra gcc checks:: 61 61 62 62 make W=n 63 + 64 + However, the above command does not verify header files. These should be checked 65 + separately using ``kernel-doc``. 63 66 64 67 Function documentation 65 68 ---------------------- ··· 177 174 Structure, union, and enumeration documentation 178 175 ----------------------------------------------- 179 176 180 - The general format of a struct, union, and enum kernel-doc comment is:: 177 + The general format of a ``struct``, ``union``, and ``enum`` kernel-doc 178 + comment is:: 181 179 182 180 /** 183 181 * struct struct_name - Brief description. ··· 191 187 */ 192 188 193 189 You can replace the ``struct`` in the above example with ``union`` or 194 - ``enum`` to describe unions or enums. ``member`` is used to mean struct 195 - and union member names as well as enumerations in an enum. 190 + ``enum`` to describe unions or enums. ``member`` is used to mean ``struct`` 191 + and ``union`` member names as well as enumerations in an ``enum``. 196 192 197 193 The brief description following the structure name may span multiple 198 194 lines, and ends with a member description, a blank comment line, or the ··· 205 201 as function parameters; they immediately succeed the short description 206 202 and may be multi-line. 207 203 208 - Inside a struct or union description, you can use the ``private:`` and 204 + Inside a ``struct`` or ``union`` description, you can use the ``private:`` and 209 205 ``public:`` comment tags. Structure fields that are inside a ``private:`` 210 206 area are not listed in the generated output documentation. 211 207 ··· 277 273 278 274 .. note:: 279 275 280 - #) When documenting nested structs or unions, if the struct/union ``foo`` 281 - is named, the member ``bar`` inside it should be documented as 276 + #) When documenting nested structs or unions, if the ``struct``/``union`` 277 + ``foo`` is named, the member ``bar`` inside it should be documented as 282 278 ``@foo.bar:`` 283 - #) When the nested struct/union is anonymous, the member ``bar`` in it 284 - should be documented as ``@bar:`` 279 + #) When the nested ``struct``/``union`` is anonymous, the member ``bar`` in 280 + it should be documented as ``@bar:`` 285 281 286 282 In-line member documentation comments 287 283 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ··· 323 319 Typedef documentation 324 320 --------------------- 325 321 326 - The general format of a typedef kernel-doc comment is:: 322 + The general format of a ``typedef`` kernel-doc comment is:: 327 323 328 324 /** 329 325 * typedef type_name - Brief description. ··· 345 341 */ 346 342 typedef void (*type_name)(struct v4l2_ctrl *arg1, void *arg2); 347 343 344 + Variables documentation 345 + ----------------------- 346 + 347 + The general format of a kernel-doc variable comment is:: 348 + 349 + /** 350 + * var var_name - Brief description. 351 + * 352 + * Description of the var_name variable. 353 + */ 354 + extern int var_name; 355 + 348 356 Object-like macro documentation 349 357 ------------------------------- 350 358 ··· 365 349 left parenthesis ('(') for function-like macros or not followed by one 366 350 for object-like macros. 367 351 368 - Function-like macros are handled like functions by ``scripts/kernel-doc``. 352 + Function-like macros are handled like functions by ``tools/docs/kernel-doc``. 369 353 They may have a parameter list. Object-like macros have do not have a 370 354 parameter list. 371 355 ··· 448 432 Typedef reference. 449 433 450 434 ``&struct_name->member`` or ``&struct_name.member`` 451 - Structure or union member reference. The cross-reference will be to the struct 452 - or union definition, not the member directly. 435 + ``struct`` or ``union`` member reference. The cross-reference will be to the 436 + ``struct`` or ``union`` definition, not the member directly. 453 437 454 438 ``&name`` 455 439 A generic type reference. Prefer using the full reference described above ··· 478 462 479 463 For further details, please refer to the `Sphinx C Domain`_ documentation. 480 464 465 + .. note:: 466 + Variables aren't automatically cross referenced. For those, you need to 467 + explicitly add a C domain cross-reference. 468 + 481 469 Overview documentation comments 482 470 ------------------------------- 483 471 484 472 To facilitate having source code and comments close together, you can include 485 473 kernel-doc documentation blocks that are free-form comments instead of being 486 - kernel-doc for functions, structures, unions, enums, or typedefs. This could be 487 - used for something like a theory of operation for a driver or library code, for 488 - example. 474 + kernel-doc for functions, structures, unions, enums, typedefs or variables. 475 + This could be used for something like a theory of operation for a driver or 476 + library code, for example. 489 477 490 478 This is done by using a ``DOC:`` section keyword with a section title. 491 479 ··· 557 537 Include documentation for each *function* and *type* in *source*. 558 538 If no *function* is specified, the documentation for all functions 559 539 and types in the *source* will be included. 560 - *type* can be a struct, union, enum, or typedef identifier. 540 + *type* can be a ``struct``, ``union``, ``enum``, ``typedef`` or ``var`` 541 + identifier. 561 542 562 543 Examples:: 563 544 ··· 596 575 597 576 The kernel-doc extension is included in the kernel source tree, at 598 577 ``Documentation/sphinx/kerneldoc.py``. Internally, it uses the 599 - ``scripts/kernel-doc`` script to extract the documentation comments from the 600 - source. 578 + ``tools/docs/kernel-doc`` script to extract the documentation comments from 579 + the source. 601 580 602 581 .. _kernel_doc: 603 582
-7
Documentation/driver-api/80211/index.rst
··· 8 8 cfg80211 9 9 mac80211 10 10 mac80211-advanced 11 - 12 - .. only:: subproject and html 13 - 14 - Indices 15 - ======= 16 - 17 - * :ref:`genindex`
+16 -1
Documentation/driver-api/basics.rst
··· 114 114 Kernel utility functions 115 115 ------------------------ 116 116 117 - .. kernel-doc:: include/linux/kernel.h 117 + .. kernel-doc:: include/linux/array_size.h 118 + :internal: 119 + 120 + .. kernel-doc:: include/linux/container_of.h 121 + :internal: 122 + 123 + .. kernel-doc:: include/linux/kstrtox.h 118 124 :internal: 119 125 :no-identifiers: kstrtol kstrtoul 126 + 127 + .. kernel-doc:: include/linux/stddef.h 128 + :internal: 129 + 130 + .. kernel-doc:: include/linux/util_macros.h 131 + :internal: 132 + 133 + .. kernel-doc:: include/linux/wordpart.h 134 + :internal: 120 135 121 136 .. kernel-doc:: kernel/printk/printk.c 122 137 :export:
-2
Documentation/driver-api/coco/index.rst
··· 8 8 :maxdepth: 1 9 9 10 10 measurement-registers 11 - 12 - .. only:: subproject and html
-7
Documentation/driver-api/crypto/iaa/index.rst
··· 11 11 :maxdepth: 1 12 12 13 13 iaa-crypto 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-7
Documentation/driver-api/crypto/index.rst
··· 11 11 :maxdepth: 1 12 12 13 13 iaa/index 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-2
Documentation/driver-api/cxl/index.rst
··· 50 50 allocation/page-allocator 51 51 allocation/reclaim 52 52 allocation/hugepages.rst 53 - 54 - .. only:: subproject and html
-7
Documentation/driver-api/dmaengine/index.rst
··· 46 46 :maxdepth: 1 47 47 48 48 pxa_dma 49 - 50 - .. only:: subproject and html 51 - 52 - Indices 53 - ======= 54 - 55 - * :ref:`genindex`
+6 -3
Documentation/driver-api/driver-model/binding.rst
··· 53 53 Driver 54 54 ~~~~~~ 55 55 56 - When a driver is attached to a device, the device is inserted into the 57 - driver's list of devices. 58 - 56 + When a driver is attached to a device, the driver's probe() function is 57 + called. Within probe(), the driver initializes the device and allocates 58 + and initializes per-device data structures. This per-device state is 59 + associated with the device object for as long as the driver remains bound 60 + to it. Conceptually, this per-device data together with the binding to 61 + the device can be thought of as an instance of the driver. 59 62 60 63 sysfs 61 64 ~~~~~
+1 -1
Documentation/driver-api/driver-model/design-patterns.rst
··· 103 103 return a single argument which is a pointer to a struct member in the 104 104 callback. 105 105 106 - container_of() is a macro defined in <linux/kernel.h> 106 + container_of() is a macro defined in <linux/container_of.h> 107 107 108 108 What container_of() does is to obtain a pointer to the containing struct from 109 109 a pointer to a member by a simple subtraction using the offsetof() macro from
-7
Documentation/driver-api/driver-model/index.rst
··· 14 14 overview 15 15 platform 16 16 porting 17 - 18 - .. only:: subproject and html 19 - 20 - Indices 21 - ======= 22 - 23 - * :ref:`genindex`
-7
Documentation/driver-api/early-userspace/index.rst
··· 9 9 10 10 early_userspace_support 11 11 buffer-format 12 - 13 - .. only:: subproject and html 14 - 15 - Indices 16 - ======= 17 - 18 - * :ref:`genindex`
-7
Documentation/driver-api/firmware/index.rst
··· 10 10 request_firmware 11 11 fw_upload 12 12 other_interfaces 13 - 14 - .. only:: subproject and html 15 - 16 - Indices 17 - ======= 18 - 19 - * :ref:`genindex`
-7
Documentation/driver-api/index.rst
··· 149 149 wmi 150 150 xilinx/index 151 151 zorro 152 - 153 - .. only:: subproject and html 154 - 155 - Indices 156 - ======= 157 - 158 - * :ref:`genindex`
+1 -1
Documentation/driver-api/mailbox.rst
··· 27 27 28 28 29 29 Allocate mbox_controller and the array of mbox_chan. 30 - Populate mbox_chan_ops, except peek_data() all are mandatory. 30 + Populate mbox_chan_ops, except flush() and peek_data() all are mandatory. 31 31 The controller driver might know a message has been consumed 32 32 by the remote by getting an IRQ or polling some hardware flag 33 33 or it can never know (the client knows by way of the protocol).
-7
Documentation/driver-api/memory-devices/index.rst
··· 9 9 10 10 ti-emif 11 11 ti-gpmc 12 - 13 - .. only:: subproject and html 14 - 15 - Indices 16 - ======= 17 - 18 - * :ref:`genindex`
-7
Documentation/driver-api/pci/index.rst
··· 11 11 pci 12 12 p2pdma 13 13 tsm 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-8
Documentation/driver-api/phy/index.rst
··· 8 8 9 9 phy 10 10 samsung-usb2 11 - 12 - .. only:: subproject and html 13 - 14 - Indices 15 - ======= 16 - 17 - * :ref:`genindex` 18 -
+1 -1
Documentation/driver-api/phy/phy.rst
··· 19 19 SATA etc. 20 20 21 21 The intention of creating this framework is to bring the PHY drivers spread 22 - all over the Linux kernel to drivers/phy to increase code re-use and for 22 + all over the Linux kernel to drivers/phy to increase code reuse and for 23 23 better code maintainability. 24 24 25 25 This framework will be of use only to devices that use external PHY (PHY
-7
Documentation/driver-api/pm/index.rst
··· 10 10 devices 11 11 notifiers 12 12 types 13 - 14 - .. only:: subproject and html 15 - 16 - Indices 17 - ======= 18 - 19 - * :ref:`genindex`
-7
Documentation/driver-api/serial/index.rst
··· 18 18 19 19 serial-iso7816 20 20 serial-rs485 21 - 22 - .. only:: subproject and html 23 - 24 - Indices 25 - ======= 26 - 27 - * :ref:`genindex`
-7
Documentation/driver-api/soundwire/index.rst
··· 11 11 locking 12 12 bra 13 13 bra_cadence 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-7
Documentation/driver-api/surface_aggregator/clients/index.rst
··· 14 14 cdev 15 15 dtx 16 16 san 17 - 18 - .. only:: subproject and html 19 - 20 - Indices 21 - ======= 22 - 23 - * :ref:`genindex`
-7
Documentation/driver-api/surface_aggregator/index.rst
··· 12 12 clients/index 13 13 ssh 14 14 internal 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex`
+1 -1
Documentation/driver-api/tty/tty_ldisc.rst
··· 18 18 Line disciplines are registered with tty_register_ldisc() passing the ldisc 19 19 structure. At the point of registration the discipline must be ready to use and 20 20 it is possible it will get used before the call returns success. If the call 21 - returns an error then it won’t get called. Do not re-use ldisc numbers as they 21 + returns an error then it won’t get called. Do not reuse ldisc numbers as they 22 22 are part of the userspace ABI and writing over an existing ldisc will cause 23 23 demons to eat your computer. You must not re-register over the top of the line 24 24 discipline even with the same data or your computer again will be eaten by
+1 -1
Documentation/driver-api/usb/gadget.rst
··· 459 459 ``gadget`` framework. To do that, the system software relies on small 460 460 additions to those programming interfaces, and on a new internal 461 461 component (here called an "OTG Controller") affecting which driver stack 462 - connects to the OTG port. In each role, the system can re-use the 462 + connects to the OTG port. In each role, the system can reuse the 463 463 existing pool of hardware-neutral drivers, layered on top of the 464 464 controller driver interfaces (:c:type:`usb_bus` or :c:type:`usb_gadget`). 465 465 Such drivers need at most minor changes, and most of the calls added to
-7
Documentation/driver-api/usb/index.rst
··· 22 22 typec 23 23 typec_bus 24 24 usb3-debug-port 25 - 26 - .. only:: subproject and html 27 - 28 - Indices 29 - ======= 30 - 31 - * :ref:`genindex`
-7
Documentation/driver-api/xilinx/index.rst
··· 7 7 :maxdepth: 1 8 8 9 9 eemi 10 - 11 - .. only:: subproject and html 12 - 13 - Indices 14 - ======= 15 - 16 - * :ref:`genindex`
-7
Documentation/fault-injection/index.rst
··· 11 11 notifier-error-inject 12 12 nvme-fault-injection 13 13 provoke-crashes 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-7
Documentation/fb/index.rst
··· 50 50 vesafb 51 51 viafb 52 52 vt8623fb 53 - 54 - .. only:: subproject and html 55 - 56 - Indices 57 - ======= 58 - 59 - * :ref:`genindex`
+3
Documentation/filesystems/api-summary.rst
··· 56 56 .. kernel-doc:: fs/namei.c 57 57 :export: 58 58 59 + .. kernel-doc:: fs/open.c 60 + :export: 61 + 59 62 .. kernel-doc:: block/bio.c 60 63 :export: 61 64
+1 -1
Documentation/filesystems/erofs.rst
··· 162 162 0 +1K 163 163 164 164 All data areas should be aligned with the block size, but metadata areas 165 - may not. All metadatas can be now observed in two different spaces (views): 165 + may not. All metadata can be now observed in two different spaces (views): 166 166 167 167 1. Inode metadata space 168 168
+3 -3
Documentation/filesystems/proc.rst
··· 48 48 3.11 /proc/<pid>/patch_state - Livepatch patch operation state 49 49 3.12 /proc/<pid>/arch_status - Task architecture specific information 50 50 3.13 /proc/<pid>/fd - List of symlinks to open files 51 - 3.14 /proc/<pid/ksm_stat - Information about the process's ksm status. 51 + 3.14 /proc/<pid>/ksm_stat - Information about the process's ksm status. 52 52 53 53 4 Configuring procfs 54 54 4.1 Mount options ··· 2289 2289 of stat() output for /proc/<pid>/fd for fast access. 2290 2290 ------------------------------------------------------- 2291 2291 2292 - 3.14 /proc/<pid/ksm_stat - Information about the process's ksm status 2293 - --------------------------------------------------------------------- 2292 + 3.14 /proc/<pid>/ksm_stat - Information about the process's ksm status 2293 + ---------------------------------------------------------------------- 2294 2294 When CONFIG_KSM is enabled, each process has this file which displays 2295 2295 the information of ksm merging status. 2296 2296
+1 -1
Documentation/filesystems/relay.rst
··· 452 452 Misc 453 453 ---- 454 454 455 - Some applications may want to keep a channel around and re-use it 455 + Some applications may want to keep a channel around and reuse it 456 456 rather than open and close a new channel for each use. relay_reset() 457 457 can be used for this purpose - it resets a channel to its initial 458 458 state without reallocating channel buffer memory or destroying
+1 -1
Documentation/filesystems/resctrl.rst
··· 482 482 "max_threshold_occupancy": 483 483 Read/write file provides the largest value (in 484 484 bytes) at which a previously used LLC_occupancy 485 - counter can be considered for re-use. 485 + counter can be considered for reuse. 486 486 487 487 Finally, in the top level of the "info" directory there is a file 488 488 named "last_cmd_status". This is reset with every "command" issued
+2 -2
Documentation/filesystems/spufs/spu_create.rst
··· 113 113 114 114 Conforming to 115 115 ============= 116 - This call is Linux specific and only implemented by the ppc64 architec- 117 - ture. Programs using this system call are not portable. 116 + This call is Linux specific and only implemented by the ppc64 117 + architecture. Programs using this system call are not portable. 118 118 119 119 120 120 Bugs
+2 -2
Documentation/filesystems/spufs/spu_run.rst
··· 120 120 121 121 Conforming to 122 122 ============= 123 - This call is Linux specific and only implemented by the ppc64 architec- 124 - ture. Programs using this system call are not portable. 123 + This call is Linux specific and only implemented by the ppc64 124 + architecture. Programs using this system call are not portable. 125 125 126 126 127 127 Bugs
+1 -1
Documentation/firmware-guide/acpi/DSD-properties-rules.rst
··· 89 89 account in the first place and returning invalid property sets from _DSD must be 90 90 avoided. For this reason, it may not be possible to make _DSD return a property 91 91 set following the given DT binding literally and completely. Still, for the 92 - sake of code re-use, it may make sense to provide as much of the configuration 92 + sake of code reuse, it may make sense to provide as much of the configuration 93 93 data as possible in the form of device properties and complement that with an 94 94 ACPI-specific mechanism suitable for the use case at hand. 95 95
+1 -1
Documentation/firmware-guide/acpi/enumeration.rst
··· 12 12 SoC/Chipset to appear only in ACPI namespace. These are typically devices 13 13 that are accessed through memory-mapped registers. 14 14 15 - In order to support this and re-use the existing drivers as much as 15 + In order to support this and reuse the existing drivers as much as 16 16 possible we decided to do following: 17 17 18 18 - Devices that have no bus connector resource are represented as
-7
Documentation/fpga/index.rst
··· 8 8 :maxdepth: 1 9 9 10 10 dfl 11 - 12 - .. only:: subproject and html 13 - 14 - Indices 15 - ======= 16 - 17 - * :ref:`genindex`
-7
Documentation/gpu/drivers.rst
··· 26 26 panthor 27 27 zynqmp 28 28 nova/index 29 - 30 - .. only:: subproject and html 31 - 32 - Indices 33 - ======= 34 - 35 - * :ref:`genindex`
-7
Documentation/gpu/index.rst
··· 22 22 implementation_guidelines 23 23 todo 24 24 rfc/index 25 - 26 - .. only:: subproject and html 27 - 28 - Indices 29 - ======= 30 - 31 - * :ref:`genindex`
-7
Documentation/hwmon/index.rst
··· 281 281 xdpe12284 282 282 xdpe152c4 283 283 zl6100 284 - 285 - .. only:: subproject and html 286 - 287 - Indices 288 - ======= 289 - 290 - * :ref:`genindex`
-7
Documentation/i2c/index.rst
··· 66 66 :maxdepth: 1 67 67 68 68 old-module-parameters 69 - 70 - .. only:: subproject and html 71 - 72 - Indices 73 - ======= 74 - 75 - * :ref:`genindex`
-7
Documentation/infiniband/index.rst
··· 15 15 ucaps 16 16 user_mad 17 17 user_verbs 18 - 19 - .. only:: subproject and html 20 - 21 - Indices 22 - ======= 23 - 24 - * :ref:`genindex`
-7
Documentation/input/devices/index.rst
··· 10 10 :glob: 11 11 12 12 * 13 - 14 - .. only:: subproject and html 15 - 16 - Indices 17 - ======= 18 - 19 - * :ref:`genindex`
+1 -1
Documentation/input/gamepad.rst
··· 79 79 All new gamepads are supposed to comply with this mapping. Please report any 80 80 bugs, if they don't. 81 81 82 - There are a lot of less-featured/less-powerful devices out there, which re-use 82 + There are a lot of less-featured/less-powerful devices out there, which reuse 83 83 the buttons from this protocol. However, they try to do this in a compatible 84 84 fashion. For example, the "Nintendo Wii Nunchuk" provides two trigger buttons 85 85 and one analog stick. It reports them as if it were a gamepad with only one
-7
Documentation/input/index.rst
··· 10 10 input_uapi 11 11 input_kapi 12 12 devices/index 13 - 14 - .. only:: subproject and html 15 - 16 - Indices 17 - ======= 18 - 19 - * :ref:`genindex`
+1 -1
Documentation/input/input.rst
··· 278 278 EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for 279 279 release, 1 for keypress and 2 for autorepeat. 280 280 281 - See :ref:`input-event-codes` for more information about various even codes. 281 + See :ref:`input-event-codes` for more information about various event codes.
-7
Documentation/isdn/index.rst
··· 12 12 m_isdn 13 13 14 14 credits 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex`
-7
Documentation/kbuild/index.rst
··· 24 24 gendwarfksyms 25 25 26 26 bash-completion 27 - 28 - .. only:: subproject and html 29 - 30 - Indices 31 - ======= 32 - 33 - * :ref:`genindex`
+1 -1
Documentation/kbuild/kbuild.rst
··· 180 180 KDOCFLAGS 181 181 --------- 182 182 Specify extra (warning/error) flags for kernel-doc checks during the build, 183 - see scripts/kernel-doc for which flags are supported. Note that this doesn't 183 + see tools/docs/kernel-doc for which flags are supported. Note that this doesn't 184 184 (currently) apply to documentation builds. 185 185 186 186 ARCH
+1 -1
Documentation/kbuild/kconfig-language.rst
··· 216 216 217 217 - numerical ranges: "range" <symbol> <symbol> ["if" <expr>] 218 218 219 - This allows to limit the range of possible input values for int 219 + This allows limiting the range of possible input values for int 220 220 and hex symbols. The user can only input a value which is larger than 221 221 or equal to the first symbol and smaller than or equal to the second 222 222 symbol.
+1 -1
Documentation/kbuild/makefiles.rst
··· 1264 1264 -------------------------------- 1265 1265 1266 1266 The archheaders: rule is used to generate header files that 1267 - may be installed into user space by ``make header_install``. 1267 + may be installed into user space by ``make headers_install``. 1268 1268 1269 1269 It is run before ``make archprepare`` when run on the 1270 1270 architecture itself.
+91 -92
Documentation/kernel-hacking/hacking.rst
··· 49 49 50 50 User context is when you are coming in from a system call or other trap: 51 51 like userspace, you can be preempted by more important tasks and by 52 - interrupts. You can sleep, by calling :c:func:`schedule()`. 52 + interrupts. You can sleep by calling schedule(). 53 53 54 54 .. note:: 55 55 ··· 57 57 operations on the block device layer. 58 58 59 59 In user context, the ``current`` pointer (indicating the task we are 60 - currently executing) is valid, and :c:func:`in_interrupt()` 60 + currently executing) is valid, and in_interrupt() 61 61 (``include/linux/preempt.h``) is false. 62 62 63 63 .. warning:: 64 64 65 65 Beware that if you have preemption or softirqs disabled (see below), 66 - :c:func:`in_interrupt()` will return a false positive. 66 + in_interrupt() will return a false positive. 67 67 68 68 Hardware Interrupts (Hard IRQs) 69 69 ------------------------------- ··· 115 115 'tasks'. 116 116 117 117 You can tell you are in a softirq (or tasklet) using the 118 - :c:func:`in_softirq()` macro (``include/linux/preempt.h``). 118 + in_softirq() macro (``include/linux/preempt.h``). 119 119 120 120 .. warning:: 121 121 ··· 171 171 Linus. 172 172 173 173 If all your routine does is read or write some parameter, consider 174 - implementing a :c:func:`sysfs()` interface instead. 174 + implementing a sysfs() interface instead. 175 175 176 176 Inside the ioctl you're in user context to a process. When a error 177 177 occurs you return a negated errno (see ··· 230 230 Common Routines 231 231 =============== 232 232 233 - :c:func:`printk()` 234 - ------------------ 233 + printk() 234 + -------- 235 235 236 236 Defined in ``include/linux/printk.h`` 237 237 238 - :c:func:`printk()` feeds kernel messages to the console, dmesg, and 238 + printk() feeds kernel messages to the console, dmesg, and 239 239 the syslog daemon. It is useful for debugging and reporting errors, and 240 240 can be used inside interrupt context, but use with caution: a machine 241 241 which has its console flooded with printk messages is unusable. It uses ··· 253 253 printk(KERN_INFO "my ip: %pI4\n", &ipaddress); 254 254 255 255 256 - :c:func:`printk()` internally uses a 1K buffer and does not catch 256 + printk() internally uses a 1K buffer and does not catch 257 257 overruns. Make sure that will be enough. 258 258 259 259 .. note:: ··· 267 267 on top of its printf function: "Printf should not be used for 268 268 chit-chat". You should follow that advice. 269 269 270 - :c:func:`copy_to_user()` / :c:func:`copy_from_user()` / :c:func:`get_user()` / :c:func:`put_user()` 271 - --------------------------------------------------------------------------------------------------- 270 + copy_to_user() / copy_from_user() / get_user() / put_user() 271 + ----------------------------------------------------------- 272 272 273 273 Defined in ``include/linux/uaccess.h`` / ``asm/uaccess.h`` 274 274 275 275 **[SLEEPS]** 276 276 277 - :c:func:`put_user()` and :c:func:`get_user()` are used to get 277 + put_user() and get_user() are used to get 278 278 and put single values (such as an int, char, or long) from and to 279 279 userspace. A pointer into userspace should never be simply dereferenced: 280 280 data should be copied using these routines. Both return ``-EFAULT`` or 281 281 0. 282 282 283 - :c:func:`copy_to_user()` and :c:func:`copy_from_user()` are 283 + copy_to_user() and copy_from_user() are 284 284 more general: they copy an arbitrary amount of data to and from 285 285 userspace. 286 286 287 287 .. warning:: 288 288 289 - Unlike :c:func:`put_user()` and :c:func:`get_user()`, they 289 + Unlike put_user() and get_user(), they 290 290 return the amount of uncopied data (ie. 0 still means success). 291 291 292 292 [Yes, this objectionable interface makes me cringe. The flamewar comes ··· 296 296 user context (it makes no sense), with interrupts disabled, or a 297 297 spinlock held. 298 298 299 - :c:func:`kmalloc()`/:c:func:`kfree()` 300 - ------------------------------------- 299 + kmalloc()/kfree() 300 + ----------------- 301 301 302 302 Defined in ``include/linux/slab.h`` 303 303 ··· 305 305 306 306 These routines are used to dynamically request pointer-aligned chunks of 307 307 memory, like malloc and free do in userspace, but 308 - :c:func:`kmalloc()` takes an extra flag word. Important values: 308 + kmalloc() takes an extra flag word. Important values: 309 309 310 310 ``GFP_KERNEL`` 311 311 May sleep and swap to free memory. Only allowed in user context, but ··· 326 326 Run, don't walk. 327 327 328 328 If you are allocating at least ``PAGE_SIZE`` (``asm/page.h`` or 329 - ``asm/page_types.h``) bytes, consider using :c:func:`__get_free_pages()` 329 + ``asm/page_types.h``) bytes, consider using __get_free_pages() 330 330 (``include/linux/gfp.h``). It takes an order argument (0 for page sized, 331 331 1 for double page, 2 for four pages etc.) and the same memory priority 332 332 flag word as above. 333 333 334 334 If you are allocating more than a page worth of bytes you can use 335 - :c:func:`vmalloc()`. It'll allocate virtual memory in the kernel 335 + vmalloc(). It'll allocate virtual memory in the kernel 336 336 map. This block is not contiguous in physical memory, but the MMU makes 337 337 it look like it is for you (so it'll only look contiguous to the CPUs, 338 338 not to external device drivers). If you really need large physically 339 339 contiguous memory for some weird device, you have a problem: it is 340 340 poorly supported in Linux because after some time memory fragmentation 341 341 in a running kernel makes it hard. The best way is to allocate the block 342 - early in the boot process via the :c:func:`alloc_bootmem()` 342 + early in the boot process via the alloc_bootmem() 343 343 routine. 344 344 345 345 Before inventing your own cache of often-used objects consider using a 346 346 slab cache in ``include/linux/slab.h`` 347 347 348 - :c:macro:`current` 349 - ------------------ 348 + current 349 + ------- 350 350 351 351 Defined in ``include/asm/current.h`` 352 352 ··· 355 355 process makes a system call, this will point to the task structure of 356 356 the calling process. It is **not NULL** in interrupt context. 357 357 358 - :c:func:`mdelay()`/:c:func:`udelay()` 359 - ------------------------------------- 358 + mdelay()/udelay() 359 + ----------------- 360 360 361 361 Defined in ``include/asm/delay.h`` / ``include/linux/delay.h`` 362 362 363 - The :c:func:`udelay()` and :c:func:`ndelay()` functions can be 363 + The udelay() and ndelay() functions can be 364 364 used for small pauses. Do not use large values with them as you risk 365 - overflow - the helper function :c:func:`mdelay()` is useful here, or 366 - consider :c:func:`msleep()`. 365 + overflow - the helper function mdelay() is useful here, or 366 + consider msleep(). 367 367 368 - :c:func:`cpu_to_be32()`/:c:func:`be32_to_cpu()`/:c:func:`cpu_to_le32()`/:c:func:`le32_to_cpu()` 369 - ----------------------------------------------------------------------------------------------- 368 + cpu_to_be32()/be32_to_cpu()/cpu_to_le32()/le32_to_cpu() 369 + ------------------------------------------------------- 370 370 371 371 Defined in ``include/asm/byteorder.h`` 372 372 373 - The :c:func:`cpu_to_be32()` family (where the "32" can be replaced 373 + The cpu_to_be32() family (where the "32" can be replaced 374 374 by 64 or 16, and the "be" can be replaced by "le") are the general way 375 375 to do endian conversions in the kernel: they return the converted value. 376 376 All variations supply the reverse as well: 377 - :c:func:`be32_to_cpu()`, etc. 377 + be32_to_cpu(), etc. 378 378 379 379 There are two major variations of these functions: the pointer 380 - variation, such as :c:func:`cpu_to_be32p()`, which take a pointer 380 + variation, such as cpu_to_be32p(), which take a pointer 381 381 to the given type, and return the converted value. The other variation 382 - is the "in-situ" family, such as :c:func:`cpu_to_be32s()`, which 382 + is the "in-situ" family, such as cpu_to_be32s(), which 383 383 convert value referred to by the pointer, and return void. 384 384 385 - :c:func:`local_irq_save()`/:c:func:`local_irq_restore()` 386 - -------------------------------------------------------- 385 + local_irq_save()/local_irq_restore() 386 + ------------------------------------ 387 387 388 388 Defined in ``include/linux/irqflags.h`` 389 389 390 390 These routines disable hard interrupts on the local CPU, and restore 391 391 them. They are reentrant; saving the previous state in their one 392 392 ``unsigned long flags`` argument. If you know that interrupts are 393 - enabled, you can simply use :c:func:`local_irq_disable()` and 394 - :c:func:`local_irq_enable()`. 393 + enabled, you can simply use local_irq_disable() and 394 + local_irq_enable(). 395 395 396 396 .. _local_bh_disable: 397 397 398 - :c:func:`local_bh_disable()`/:c:func:`local_bh_enable()` 399 - -------------------------------------------------------- 398 + local_bh_disable()/local_bh_enable() 399 + ------------------------------------ 400 400 401 401 Defined in ``include/linux/bottom_half.h`` 402 402 ··· 406 406 will still be disabled after this pair of functions has been called. 407 407 They prevent softirqs and tasklets from running on the current CPU. 408 408 409 - :c:func:`smp_processor_id()` 410 - ---------------------------- 409 + smp_processor_id() 410 + ------------------ 411 411 412 412 Defined in ``include/linux/smp.h`` 413 413 414 - :c:func:`get_cpu()` disables preemption (so you won't suddenly get 414 + get_cpu() disables preemption (so you won't suddenly get 415 415 moved to another CPU) and returns the current processor number, between 416 416 0 and ``NR_CPUS``. Note that the CPU numbers are not necessarily 417 - continuous. You return it again with :c:func:`put_cpu()` when you 417 + continuous. You return it again with put_cpu() when you 418 418 are done. 419 419 420 420 If you know you cannot be preempted by another task (ie. you are in ··· 433 433 required on exit: the function will be dropped if this file is not 434 434 compiled as a module. See the header file for use. Note that it makes no 435 435 sense for a function marked with ``__init`` to be exported to modules 436 - with :c:func:`EXPORT_SYMBOL()` or :c:func:`EXPORT_SYMBOL_GPL()`- this 436 + with EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()- this 437 437 will break. 438 438 439 - :c:func:`__initcall()`/:c:func:`module_init()` 440 - ---------------------------------------------- 439 + __initcall()/module_init() 440 + -------------------------- 441 441 442 442 Defined in ``include/linux/init.h`` / ``include/linux/module.h`` 443 443 444 444 Many parts of the kernel are well served as a module 445 445 (dynamically-loadable parts of the kernel). Using the 446 - :c:func:`module_init()` and :c:func:`module_exit()` macros it 446 + module_init() and module_exit() macros it 447 447 is easy to write code without #ifdefs which can operate both as a module 448 448 or built into the kernel. 449 449 450 - The :c:func:`module_init()` macro defines which function is to be 450 + The module_init() macro defines which function is to be 451 451 called at module insertion time (if the file is compiled as a module), 452 452 or at boot time: if the file is not compiled as a module the 453 - :c:func:`module_init()` macro becomes equivalent to 454 - :c:func:`__initcall()`, which through linker magic ensures that 453 + module_init() macro becomes equivalent to 454 + __initcall(), which through linker magic ensures that 455 455 the function is called on boot. 456 456 457 457 The function can return a negative error number to cause module loading ··· 459 459 into the kernel). This function is called in user context with 460 460 interrupts enabled, so it can sleep. 461 461 462 - :c:func:`module_exit()` 463 - ----------------------- 464 - 462 + module_exit() 463 + ------------- 465 464 466 465 Defined in ``include/linux/module.h`` 467 466 ··· 473 474 Note that this macro is optional: if it is not present, your module will 474 475 not be removable (except for 'rmmod -f'). 475 476 476 - :c:func:`try_module_get()`/:c:func:`module_put()` 477 - ------------------------------------------------- 477 + try_module_get()/module_put() 478 + ----------------------------- 478 479 479 480 Defined in ``include/linux/module.h`` 480 481 481 482 These manipulate the module usage count, to protect against removal (a 482 483 module also can't be removed if another module uses one of its exported 483 484 symbols: see below). Before calling into module code, you should call 484 - :c:func:`try_module_get()` on that module: if it fails, then the 485 + try_module_get() on that module: if it fails, then the 485 486 module is being removed and you should act as if it wasn't there. 486 487 Otherwise, you can safely enter the module, and call 487 - :c:func:`module_put()` when you're finished. 488 + module_put() when you're finished. 488 489 489 490 Most registerable structures have an owner field, such as in the 490 491 :c:type:`struct file_operations <file_operations>` structure. ··· 505 506 --------- 506 507 507 508 You declare a ``wait_queue_head_t`` using the 508 - :c:func:`DECLARE_WAIT_QUEUE_HEAD()` macro, or using the 509 - :c:func:`init_waitqueue_head()` routine in your initialization 509 + DECLARE_WAIT_QUEUE_HEAD() macro, or using the 510 + init_waitqueue_head() routine in your initialization 510 511 code. 511 512 512 513 Queuing ··· 514 515 515 516 Placing yourself in the waitqueue is fairly complex, because you must 516 517 put yourself in the queue before checking the condition. There is a 517 - macro to do this: :c:func:`wait_event_interruptible()` 518 + macro to do this: wait_event_interruptible() 518 519 (``include/linux/wait.h``) The first argument is the wait queue head, and 519 520 the second is an expression which is evaluated; the macro returns 0 when 520 521 this expression is true, or ``-ERESTARTSYS`` if a signal is received. The 521 - :c:func:`wait_event()` version ignores signals. 522 + wait_event() version ignores signals. 522 523 523 524 Waking Up Queued Tasks 524 525 ---------------------- 525 526 526 - Call :c:func:`wake_up()` (``include/linux/wait.h``), which will wake 527 + Call wake_up() (``include/linux/wait.h``), which will wake 527 528 up every process in the queue. The exception is if one has 528 529 ``TASK_EXCLUSIVE`` set, in which case the remainder of the queue will 529 530 not be woken. There are other variants of this basic function available ··· 536 537 class of operations work on :c:type:`atomic_t` (``include/asm/atomic.h``); 537 538 this contains a signed integer (at least 32 bits long), and you must use 538 539 these functions to manipulate or read :c:type:`atomic_t` variables. 539 - :c:func:`atomic_read()` and :c:func:`atomic_set()` get and set 540 - the counter, :c:func:`atomic_add()`, :c:func:`atomic_sub()`, 541 - :c:func:`atomic_inc()`, :c:func:`atomic_dec()`, and 542 - :c:func:`atomic_dec_and_test()` (returns true if it was 540 + atomic_read() and atomic_set() get and set 541 + the counter, atomic_add(), atomic_sub(), 542 + atomic_inc(), atomic_dec(), and 543 + atomic_dec_and_test() (returns true if it was 543 544 decremented to zero). 544 545 545 546 Yes. It returns true (i.e. != 0) if the atomic variable is zero. ··· 550 551 The second class of atomic operations is atomic bit operations on an 551 552 ``unsigned long``, defined in ``include/linux/bitops.h``. These 552 553 operations generally take a pointer to the bit pattern, and a bit 553 - number: 0 is the least significant bit. :c:func:`set_bit()`, 554 - :c:func:`clear_bit()` and :c:func:`change_bit()` set, clear, 555 - and flip the given bit. :c:func:`test_and_set_bit()`, 556 - :c:func:`test_and_clear_bit()` and 557 - :c:func:`test_and_change_bit()` do the same thing, except return 554 + number: 0 is the least significant bit. set_bit(), 555 + clear_bit() and change_bit() set, clear, 556 + and flip the given bit. test_and_set_bit(), 557 + test_and_clear_bit() and 558 + test_and_change_bit() do the same thing, except return 558 559 true if the bit was previously set; these are particularly useful for 559 560 atomically setting flags. 560 561 ··· 571 572 exported symbol table is kept which limits the entry points to the 572 573 kernel proper. Modules can also export symbols. 573 574 574 - :c:func:`EXPORT_SYMBOL()` 575 - ------------------------- 575 + EXPORT_SYMBOL() 576 + --------------- 576 577 577 578 Defined in ``include/linux/export.h`` 578 579 579 580 This is the classic method of exporting a symbol: dynamically loaded 580 581 modules will be able to use the symbol as normal. 581 582 582 - :c:func:`EXPORT_SYMBOL_GPL()` 583 - ----------------------------- 583 + EXPORT_SYMBOL_GPL() 584 + ------------------- 584 585 585 586 Defined in ``include/linux/export.h`` 586 587 587 - Similar to :c:func:`EXPORT_SYMBOL()` except that the symbols 588 - exported by :c:func:`EXPORT_SYMBOL_GPL()` can only be seen by 589 - modules with a :c:func:`MODULE_LICENSE()` that specifies a GPLv2 588 + Similar to EXPORT_SYMBOL() except that the symbols 589 + exported by EXPORT_SYMBOL_GPL() can only be seen by 590 + modules with a MODULE_LICENSE() that specifies a GPLv2 590 591 compatible license. It implies that the function is considered an 591 592 internal implementation issue, and not really an interface. Some 592 593 maintainers and developers may however require EXPORT_SYMBOL_GPL() 593 594 when adding any new APIs or functionality. 594 595 595 - :c:func:`EXPORT_SYMBOL_NS()` 596 - ---------------------------- 596 + EXPORT_SYMBOL_NS() 597 + ------------------ 597 598 598 599 Defined in ``include/linux/export.h`` 599 600 600 - This is the variant of `EXPORT_SYMBOL()` that allows specifying a symbol 601 + This is the variant of EXPORT_SYMBOL() that allows specifying a symbol 601 602 namespace. Symbol Namespaces are documented in 602 603 Documentation/core-api/symbol-namespaces.rst 603 604 604 - :c:func:`EXPORT_SYMBOL_NS_GPL()` 605 - -------------------------------- 605 + EXPORT_SYMBOL_NS_GPL() 606 + ---------------------- 606 607 607 608 Defined in ``include/linux/export.h`` 608 609 609 - This is the variant of `EXPORT_SYMBOL_GPL()` that allows specifying a symbol 610 + This is the variant of EXPORT_SYMBOL_GPL() that allows specifying a symbol 610 611 namespace. Symbol Namespaces are documented in 611 612 Documentation/core-api/symbol-namespaces.rst 612 613 ··· 620 621 headers, but this one is the winner. If you don't have some particular 621 622 pressing need for a single list, it's a good choice. 622 623 623 - In particular, :c:func:`list_for_each_entry()` is useful. 624 + In particular, list_for_each_entry() is useful. 624 625 625 626 Return Conventions 626 627 ------------------ ··· 630 631 failure. This can be unintuitive at first, but it's fairly widespread in 631 632 the kernel. 632 633 633 - Using :c:func:`ERR_PTR()` (``include/linux/err.h``) to encode a 634 - negative error number into a pointer, and :c:func:`IS_ERR()` and 635 - :c:func:`PTR_ERR()` to get it back out again: avoids a separate 634 + Using ERR_PTR() (``include/linux/err.h``) to encode a 635 + negative error number into a pointer, and IS_ERR() and 636 + PTR_ERR() to get it back out again: avoids a separate 636 637 pointer parameter for the error number. Icky, but in a good way. 637 638 638 639 Breaking Compilation ··· 735 736 - Usually you want a configuration option for your kernel hack. Edit 736 737 ``Kconfig`` in the appropriate directory. The Config language is 737 738 simple to use by cut and paste, and there's complete documentation in 738 - ``Documentation/kbuild/kconfig-language.rst``. 739 + Documentation/kbuild/kconfig-language.rst. 739 740 740 741 In your description of the option, make sure you address both the 741 742 expert user and the user who knows nothing about your feature. ··· 745 746 746 747 - Edit the ``Makefile``: the CONFIG variables are exported here so you 747 748 can usually just add a "obj-$(CONFIG_xxx) += xxx.o" line. The syntax 748 - is documented in ``Documentation/kbuild/makefiles.rst``. 749 + is documented in Documentation/kbuild/makefiles.rst. 749 750 750 751 - Put yourself in ``CREDITS`` if you consider what you've done 751 752 noteworthy, usually beyond a single file (your name should be at the ··· 754 755 it implies a more-than-passing commitment to some part of the code. 755 756 756 757 - Finally, don't forget to read 757 - ``Documentation/process/submitting-patches.rst`` 758 + Documentation/process/submitting-patches.rst. 758 759 759 760 Kernel Cantrips 760 761 =============== ··· 823 824 Thanks to Andi Kleen for the idea, answering my questions, fixing my 824 825 mistakes, filling content, etc. Philipp Rumpf for more spelling and 825 826 clarity fixes, and some excellent non-obvious points. Werner Almesberger 826 - for giving me a great summary of :c:func:`disable_irq()`, and Jes 827 + for giving me a great summary of disable_irq(), and Jes 827 828 Sorensen and Andrea Arcangeli added caveats. Michael Elizabeth Chastain 828 829 for checking and adding to the Configure section. Telsa Gwynne for 829 830 teaching me DocBook.
-7
Documentation/livepatch/index.rst
··· 15 15 system-state 16 16 reliable-stacktrace 17 17 api 18 - 19 - .. only:: subproject and html 20 - 21 - Indices 22 - ======= 23 - 24 - * :ref:`genindex`
-7
Documentation/locking/index.rst
··· 24 24 percpu-rw-semaphore 25 25 robust-futexes 26 26 robust-futex-ABI 27 - 28 - .. only:: subproject and html 29 - 30 - Indices 31 - ======= 32 - 33 - * :ref:`genindex`
-7
Documentation/mhi/index.rst
··· 9 9 10 10 mhi 11 11 topology 12 - 13 - .. only:: subproject and html 14 - 15 - Indices 16 - ======= 17 - 18 - * :ref:`genindex`
-7
Documentation/netlabel/index.rst
··· 12 12 lsm_interface 13 13 14 14 draft_ietf 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/atm/index.rst
··· 11 11 cxacru 12 12 fore200e 13 13 iphase 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/can/index.rst
··· 13 13 can327 14 14 ctu/ctucanfd-driver 15 15 freescale/flexcan 16 - 17 - .. only:: subproject and html 18 - 19 - Indices 20 - ======= 21 - 22 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/cellular/index.rst
··· 9 9 :maxdepth: 2 10 10 11 11 qualcomm/rmnet 12 - 13 - .. only:: subproject and html 14 - 15 - Indices 16 - ======= 17 - 18 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/ethernet/index.rst
··· 64 64 wangxun/txgbevf 65 65 wangxun/ngbe 66 66 wangxun/ngbevf 67 - 68 - .. only:: subproject and html 69 - 70 - Indices 71 - ======= 72 - 73 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/ethernet/mellanox/mlx5/index.rst
··· 16 16 switchdev 17 17 tracepoints 18 18 counters 19 - 20 - .. only:: subproject and html 21 - 22 - Indices 23 - ======= 24 - 25 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/fddi/index.rst
··· 10 10 11 11 defza 12 12 skfp 13 - 14 - .. only:: subproject and html 15 - 16 - Indices 17 - ======= 18 - 19 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/hamradio/index.rst
··· 10 10 11 11 baycom 12 12 z8530drv 13 - 14 - .. only:: subproject and html 15 - 16 - Indices 17 - ======= 18 - 19 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/index.rst
··· 16 16 hamradio/index 17 17 wifi/index 18 18 wwan/index 19 - 20 - .. only:: subproject and html 21 - 22 - Indices 23 - ======= 24 - 25 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/wifi/index.rst
··· 10 10 11 11 intel/ipw2100 12 12 intel/ipw2200 13 - 14 - .. only:: subproject and html 15 - 16 - Indices 17 - ======= 18 - 19 - * :ref:`genindex`
-7
Documentation/networking/device_drivers/wwan/index.rst
··· 10 10 11 11 iosm 12 12 t7xx 13 - 14 - .. only:: subproject and html 15 - 16 - Indices 17 - ======= 18 - 19 - * :ref:`genindex`
-7
Documentation/networking/diagnostic/index.rst
··· 8 8 :maxdepth: 2 9 9 10 10 twisted_pair_layer1_diagnostics.rst 11 - 12 - .. only:: subproject and html 13 - 14 - Indices 15 - ======= 16 - 17 - * :ref:`genindex`
-7
Documentation/networking/index.rst
··· 134 134 xfrm/index 135 135 xdp-rx-metadata 136 136 xsk-tx-metadata 137 - 138 - .. only:: subproject and html 139 - 140 - Indices 141 - ======= 142 - 143 - * :ref:`genindex`
-7
Documentation/pcmcia/index.rst
··· 11 11 devicetable 12 12 locking 13 13 driver-changes 14 - 15 - .. only:: subproject and html 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
-7
Documentation/peci/index.rst
··· 7 7 .. toctree:: 8 8 9 9 peci 10 - 11 - .. only:: subproject and html 12 - 13 - Indices 14 - ======= 15 - 16 - * :ref:`genindex`
-7
Documentation/power/index.rst
··· 38 38 regulator/machine 39 39 regulator/overview 40 40 regulator/regulator 41 - 42 - .. only:: subproject and html 43 - 44 - Indices 45 - ======= 46 - 47 - * :ref:`genindex`
+1 -1
Documentation/process/1.Intro.rst
··· 194 194 are cloudy at best; quite a few kernel copyright holders believe that 195 195 most binary-only modules are derived products of the kernel and that, as 196 196 a result, their distribution is a violation of the GNU General Public 197 - license (about which more will be said below). Your author is not a 197 + License (about which more will be said below). Your author is not a 198 198 lawyer, and nothing in this document can possibly be considered to be 199 199 legal advice. The true legal status of closed-source modules can only be 200 200 determined by the courts. But the uncertainty which haunts those modules
+1 -1
Documentation/process/2.Process.rst
··· 3 3 How the development process works 4 4 ================================= 5 5 6 - Linux kernel development in the early 1990's was a pretty loose affair, 6 + Linux kernel development in the early 1990s was a pretty loose affair, 7 7 with relatively small numbers of users and developers involved. With a 8 8 user base in the millions and with some 2,000 developers involved over the 9 9 course of one year, the kernel has since had to evolve a number of
+3 -3
Documentation/process/4.Coding.rst
··· 160 160 Locking 161 161 ******* 162 162 163 - In May, 2006, the "Devicescape" networking stack was, with great 163 + In May 2006, the "Devicescape" networking stack was, with great 164 164 fanfare, released under the GPL and made available for inclusion in the 165 165 mainline kernel. This donation was welcome news; support for wireless 166 166 networking in Linux was considered substandard at best, and the Devicescape 167 167 stack offered the promise of fixing that situation. Yet, this code did not 168 - actually make it into the mainline until June, 2007 (2.6.22). What 168 + actually make it into the mainline until June 2007 (2.6.22). What 169 169 happened? 170 170 171 171 This code showed a number of signs of having been developed behind ··· 204 204 It is often argued that a regression can be justified if it causes things 205 205 to work for more people than it creates problems for. Why not make a 206 206 change if it brings new functionality to ten systems for each one it 207 - breaks? The best answer to this question was expressed by Linus in July, 207 + breaks? The best answer to this question was expressed by Linus in July 208 208 2007: 209 209 210 210 ::
+6 -1
Documentation/process/5.Posting.rst
··· 40 40 - Test the code to the extent that you can. Make use of the kernel's 41 41 debugging tools, ensure that the kernel will build with all reasonable 42 42 combinations of configuration options, use cross-compilers to build for 43 - different architectures, etc. 43 + different architectures, etc. Add tests, likely using an existing 44 + testing framework like KUnit, and include them as a separate member 45 + of your series (see the next section for more about patch series). 46 + Note that this may be mandatory when affecting some subsystems. For 47 + example, library functions (resides under lib/) are extensively used 48 + almost everywhere and expected to be tested appropriately. 44 49 45 50 - Make sure your code is compliant with the kernel coding style 46 51 guidelines.
+1 -1
Documentation/process/7.AdvancedTopics.rst
··· 53 53 will, of course, need a server that can be pulled from. Setting up such a 54 54 server with git-daemon is relatively straightforward if you have a system 55 55 which is accessible to the Internet. Otherwise, free, public hosting sites 56 - (Github, for example) are starting to appear on the net. Established 56 + (GitHub, for example) are starting to appear on the net. Established 57 57 developers can get an account on kernel.org, but those are not easy to come 58 58 by; see https://kernel.org/faq/ for more information. 59 59
+10 -10
Documentation/process/adding-syscalls.rst
··· 111 111 new type of userspace object handle when the kernel already has mechanisms and 112 112 well-defined semantics for using file descriptors. 113 113 114 - If your new :manpage:`xyzzy(2)` system call does return a new file descriptor, 114 + If your new xyzzy(2) system call does return a new file descriptor, 115 115 then the flags argument should include a value that is equivalent to setting 116 116 ``O_CLOEXEC`` on the new FD. This makes it possible for userspace to close 117 117 the timing window between ``xyzzy()`` and calling 118 118 ``fcntl(fd, F_SETFD, FD_CLOEXEC)``, where an unexpected ``fork()`` and 119 119 ``execve()`` in another thread could leak a descriptor to 120 - the exec'ed program. (However, resist the temptation to re-use the actual value 120 + the exec'ed program. (However, resist the temptation to reuse the actual value 121 121 of the ``O_CLOEXEC`` constant, as it is architecture-specific and is part of a 122 122 numbering space of ``O_*`` flags that is fairly full.) 123 123 ··· 127 127 normal way for the kernel to indicate to userspace that an event has 128 128 occurred on the corresponding kernel object. 129 129 130 - If your new :manpage:`xyzzy(2)` system call involves a filename argument:: 130 + If your new xyzzy(2) system call involves a filename argument:: 131 131 132 132 int sys_xyzzy(const char __user *path, ..., unsigned int flags); 133 133 134 - you should also consider whether an :manpage:`xyzzyat(2)` version is more appropriate:: 134 + you should also consider whether an xyzzyat(2) version is more appropriate:: 135 135 136 136 int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags); 137 137 138 138 This allows more flexibility for how userspace specifies the file in question; 139 139 in particular it allows userspace to request the functionality for an 140 140 already-opened file descriptor using the ``AT_EMPTY_PATH`` flag, effectively 141 - giving an :manpage:`fxyzzy(3)` operation for free:: 141 + giving an fxyzzy(3) operation for free:: 142 142 143 143 - xyzzyat(AT_FDCWD, path, ..., 0) is equivalent to xyzzy(path,...) 144 144 - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...) ··· 147 147 :manpage:`openat(2)` man page; for an example of AT_EMPTY_PATH, see the 148 148 :manpage:`fstatat(2)` man page.) 149 149 150 - If your new :manpage:`xyzzy(2)` system call involves a parameter describing an 150 + If your new xyzzy(2) system call involves a parameter describing an 151 151 offset within a file, make its type ``loff_t`` so that 64-bit offsets can be 152 152 supported even on 32-bit architectures. 153 153 154 - If your new :manpage:`xyzzy(2)` system call involves privileged functionality, 154 + If your new xyzzy(2) system call involves privileged functionality, 155 155 it needs to be governed by the appropriate Linux capability bit (checked with 156 156 a call to ``capable()``), as described in the :manpage:`capabilities(7)` man 157 157 page. Choose an existing capability bit that governs related functionality, ··· 160 160 the power of root. In particular, avoid adding new uses of the already 161 161 overly-general ``CAP_SYS_ADMIN`` capability. 162 162 163 - If your new :manpage:`xyzzy(2)` system call manipulates a process other than 163 + If your new xyzzy(2) system call manipulates a process other than 164 164 the calling process, it should be restricted (using a call to 165 165 ``ptrace_may_access()``) so that only a calling process with the same 166 166 permissions as the target process, or with the necessary capabilities, can ··· 196 196 Generic System Call Implementation 197 197 ---------------------------------- 198 198 199 - The main entry point for your new :manpage:`xyzzy(2)` system call will be called 199 + The main entry point for your new xyzzy(2) system call will be called 200 200 ``sys_xyzzy()``, but you add this entry point with the appropriate 201 201 ``SYSCALL_DEFINEn()`` macro rather than explicitly. The 'n' indicates the 202 202 number of arguments to the system call, and the macro takes the system call name ··· 459 459 ... 460 460 555 x32 xyzzy __x32_compat_sys_xyzzy 461 461 462 - If no pointers are involved, then it is preferable to re-use the 64-bit system 462 + If no pointers are involved, then it is preferable to reuse the 64-bit system 463 463 call for the x32 ABI (and consequently the entry in 464 464 arch/x86/entry/syscalls/syscall_64.tbl is unchanged). 465 465
+1 -1
Documentation/process/changes.rst
··· 218 218 Linux documentation for functions is transitioning to inline 219 219 documentation via specially-formatted comments near their 220 220 definitions in the source. These comments can be combined with ReST 221 - files the Documentation/ directory to make enriched documentation, which can 221 + files in the Documentation/ directory to make enriched documentation, which can 222 222 then be converted to PostScript, HTML, LaTex, ePUB and PDF files. 223 223 In order to convert from ReST format to a format of your choice, you'll need 224 224 Sphinx.
+59
Documentation/process/coding-assistants.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + .. _coding_assistants: 4 + 5 + AI Coding Assistants 6 + ++++++++++++++++++++ 7 + 8 + This document provides guidance for AI tools and developers using AI 9 + assistance when contributing to the Linux kernel. 10 + 11 + AI tools helping with Linux kernel development should follow the standard 12 + kernel development process: 13 + 14 + * Documentation/process/development-process.rst 15 + * Documentation/process/coding-style.rst 16 + * Documentation/process/submitting-patches.rst 17 + 18 + Licensing and Legal Requirements 19 + ================================ 20 + 21 + All contributions must comply with the kernel's licensing requirements: 22 + 23 + * All code must be compatible with GPL-2.0-only 24 + * Use appropriate SPDX license identifiers 25 + * See Documentation/process/license-rules.rst for details 26 + 27 + Signed-off-by and Developer Certificate of Origin 28 + ================================================= 29 + 30 + AI agents MUST NOT add Signed-off-by tags. Only humans can legally 31 + certify the Developer Certificate of Origin (DCO). The human submitter 32 + is responsible for: 33 + 34 + * Reviewing all AI-generated code 35 + * Ensuring compliance with licensing requirements 36 + * Adding their own Signed-off-by tag to certify the DCO 37 + * Taking full responsibility for the contribution 38 + 39 + Attribution 40 + =========== 41 + 42 + When AI tools contribute to kernel development, proper attribution 43 + helps track the evolving role of AI in the development process. 44 + Contributions should include an Assisted-by tag in the following format:: 45 + 46 + Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2] 47 + 48 + Where: 49 + 50 + * ``AGENT_NAME`` is the name of the AI tool or framework 51 + * ``MODEL_VERSION`` is the specific model version used 52 + * ``[TOOL1] [TOOL2]`` are optional specialized analysis tools used 53 + (e.g., coccinelle, sparse, smatch, clang-tidy) 54 + 55 + Basic development tools (git, gcc, make, editors) should not be listed. 56 + 57 + Example:: 58 + 59 + Assisted-by: Claude:claude-3-opus coccinelle sparse
+8 -4
Documentation/process/coding-style.rst
··· 614 614 615 615 When commenting the kernel API functions, please use the kernel-doc format. 616 616 See the files at :ref:`Documentation/doc-guide/ <doc_guide>` and 617 - ``scripts/kernel-doc`` for details. Note that the danger of over-commenting 617 + ``tools/docs/kernel-doc`` for details. Note that the danger of over-commenting 618 618 applies to kernel-doc comments all the same. Do not add boilerplate 619 619 kernel-doc which simply reiterates what's obvious from the signature 620 620 of the function. ··· 1070 1070 18) Don't re-invent the kernel macros 1071 1071 ------------------------------------- 1072 1072 1073 - The header file include/linux/kernel.h contains a number of macros that 1073 + There are many header files in include/linux/ that contain a number of macros that 1074 1074 you should use, rather than explicitly coding some variant of them yourself. 1075 1075 For example, if you need to calculate the length of an array, take advantage 1076 1076 of the macro ··· 1079 1079 1080 1080 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 1081 1081 1082 + which is defined in array_size.h. 1083 + 1082 1084 Similarly, if you need to calculate the size of some structure member, use 1083 1085 1084 1086 .. code-block:: c 1085 1087 1086 1088 #define sizeof_field(t, f) (sizeof(((t*)0)->f)) 1087 1089 1088 - There are also min() and max() macros that do strict type checking if you 1089 - need them. Feel free to peruse that header file to see what else is already 1090 + which is defined in stddef.h. 1091 + 1092 + There are also min() and max() macros defined in minmax.h that do strict type checking 1093 + if you need them. Feel free to peruse the header files to see what else is already 1090 1094 defined that you shouldn't reproduce in your code. 1091 1095 1092 1096
-9
Documentation/process/debugging/index.rst
··· 15 15 kgdb 16 16 userspace_debugging_guide 17 17 18 - .. only:: subproject and html 19 - 20 18 subsystem specific guides 21 19 ------------------------- 22 20 ··· 22 24 :maxdepth: 1 23 25 24 26 media_specific_debugging_guide 25 - 26 - .. only:: subproject and html 27 - 28 - Indices 29 - ======= 30 - 31 - * :ref:`genindex` 32 27 33 28 General debugging advice 34 29 ========================
+7
Documentation/process/debugging/kgdb.rst
··· 380 380 gdb which resolves addresses of kernel symbols from the symbol table 381 381 of vmlinux. 382 382 383 + Kernel parameter: ``rodata`` 384 + ---------------------------- 385 + 386 + ``CONFIG_STRICT_KERNEL_RWX`` is turned on by default and is not 387 + visible to menuconfig on some architectures (arm64 for example), 388 + you can pass ``rodata=off`` to the kernel in this case. 389 + 383 390 Using kdb 384 391 ========= 385 392
+8 -1
Documentation/process/email-clients.rst
··· 324 324 325 325 - Set ``mailnews.send_plaintext_flowed`` to ``false`` 326 326 327 - - Set ``mailnews.wraplength`` from ``72`` to ``0`` 327 + - Set ``mailnews.wraplength`` from ``72`` to ``0`` **or** install the 328 + "Toggle Line Wrap" extension 329 + 330 + https://github.com/jan-kiszka/togglelinewrap 331 + 332 + https://addons.thunderbird.net/thunderbird/addon/toggle-line-wrap 333 + 334 + to control this registry on the fly. 328 335 329 336 - Don't write HTML messages! Go to the main window 330 337 :menuselection:`Main Menu-->Account Settings-->youracc@server.something-->Composition & Addressing`!
+109
Documentation/process/generated-content.rst
··· 1 + ============================================ 2 + Kernel Guidelines for Tool-Generated Content 3 + ============================================ 4 + 5 + Purpose 6 + ======= 7 + 8 + Kernel contributors have been using tooling to generate contributions 9 + for a long time. These tools can increase the volume of contributions. 10 + At the same time, reviewer and maintainer bandwidth is a scarce 11 + resource. Understanding which portions of a contribution come from 12 + humans versus tools is helpful to maintain those resources and keep 13 + kernel development healthy. 14 + 15 + The goal here is to clarify community expectations around tools. This 16 + lets everyone become more productive while also maintaining high 17 + degrees of trust between submitters and reviewers. 18 + 19 + Out of Scope 20 + ============ 21 + 22 + These guidelines do not apply to tools that make trivial tweaks to 23 + preexisting content. Nor do they pertain to tooling that helps with 24 + menial tasks. Some examples: 25 + 26 + - Spelling and grammar fix ups, like rephrasing to imperative voice 27 + - Typing aids like identifier completion, common boilerplate or 28 + trivial pattern completion 29 + - Purely mechanical transformations like variable renaming 30 + - Reformatting, like running Lindent, ``clang-format`` or 31 + ``rust-fmt`` 32 + 33 + Even whenever your tool use is out of scope, you should still always 34 + consider if it would help reviewing your contribution if the reviewer 35 + knows about the tool that you used. 36 + 37 + In Scope 38 + ======== 39 + 40 + These guidelines apply when a meaningful amount of content in a kernel 41 + contribution was not written by a person in the Signed-off-by chain, 42 + but was instead created by a tool. 43 + 44 + Detection of a problem and testing the fix for it is also part of the 45 + development process; if a tool was used to find a problem addressed by 46 + a change, that should be noted in the changelog. This not only gives 47 + credit where it is due, it also helps fellow developers find out about 48 + these tools. 49 + 50 + Some examples: 51 + - Any tool-suggested fix such as ``checkpatch.pl --fix`` 52 + - Coccinelle scripts 53 + - A chatbot generated a new function in your patch to sort list entries. 54 + - A .c file in the patch was originally generated by a coding 55 + assistant but cleaned up by hand. 56 + - The changelog was generated by handing the patch to a generative AI 57 + tool and asking it to write the changelog. 58 + - The changelog was translated from another language. 59 + 60 + If in doubt, choose transparency and assume these guidelines apply to 61 + your contribution. 62 + 63 + Guidelines 64 + ========== 65 + 66 + First, read the Developer's Certificate of Origin: 67 + Documentation/process/submitting-patches.rst. Its rules are simple 68 + and have been in place for a long time. They have covered many 69 + tool-generated contributions. Ensure that you understand your entire 70 + submission and are prepared to respond to review comments. 71 + 72 + Second, when making a contribution, be transparent about the origin of 73 + content in cover letters and changelogs. You can be more transparent 74 + by adding information like this: 75 + 76 + - What tools were used? 77 + - The input to the tools you used, like the Coccinelle source script. 78 + - If code was largely generated from a single or short set of 79 + prompts, include those prompts. For longer sessions, include a 80 + summary of the prompts and the nature of resulting assistance. 81 + - Which portions of the content were affected by that tool? 82 + - How is the submission tested and what tools were used to test the 83 + fix? 84 + 85 + As with all contributions, individual maintainers have discretion to 86 + choose how they handle the contribution. For example, they might: 87 + 88 + - Treat it just like any other contribution. 89 + - Reject it outright. 90 + - Treat the contribution specially, for example, asking for extra 91 + testing, reviewing with extra scrutiny, or reviewing at a lower 92 + priority than human-generated content. 93 + - Ask for some other special steps, like asking the contributor to 94 + elaborate on how the tool or model was trained. 95 + - Ask the submitter to explain in more detail about the contribution 96 + so that the maintainer can be assured that the submitter fully 97 + understands how the code works. 98 + - Suggest a better prompt instead of suggesting specific code changes. 99 + 100 + If tools permit you to generate a contribution automatically, expect 101 + additional scrutiny in proportion to how much of it was generated. 102 + 103 + As with the output of any tooling, the result may be incorrect or 104 + inappropriate. You are expected to understand and to be able to defend 105 + everything you submit. If you are unable to do so, then do not submit 106 + the resulting changes. 107 + 108 + If you do so anyway, maintainers are entitled to reject your series 109 + without detailed review.
+2 -7
Documentation/process/index.rst
··· 68 68 stable-kernel-rules 69 69 management-style 70 70 researcher-guidelines 71 + generated-content 72 + coding-assistants 71 73 conclave 72 74 73 75 Dealing with bugs ··· 111 109 112 110 kernel-docs 113 111 deprecated 114 - 115 - .. only:: subproject and html 116 - 117 - Indices 118 - ======= 119 - 120 - * :ref:`genindex`
+2 -2
Documentation/process/maintainer-pgp-guide.rst
··· 405 405 406 406 .. note:: 407 407 408 - If you are listed in MAINTAINERS or have an account at kernel.org, 409 - you `qualify for a free Nitrokey Start`_ courtesy of The Linux 408 + If you are listed in an `M:` entry in MAINTAINERS or have an account at 409 + kernel.org, you `qualify for a free Nitrokey Start`_ courtesy of The Linux 410 410 Foundation. 411 411 412 412 .. _`Nitrokey Start`: https://www.nitrokey.com/products/nitrokeys
+5 -1
Documentation/process/security-bugs.rst
··· 33 33 security team will bring in extra help from area maintainers to 34 34 understand and fix the security vulnerability. 35 35 36 - Please send plain text emails without attachments where possible. 36 + Please send **plain text** emails without attachments where possible. 37 37 It is much harder to have a context-quoted discussion about a complex 38 38 issue if all the details are hidden away in attachments. Think of it like a 39 39 :doc:`regular patch submission <../process/submitting-patches>` 40 40 (even if you don't have a patch yet): describe the problem and impact, list 41 41 reproduction steps, and follow it with a proposed fix, all in plain text. 42 + Markdown, HTML and RST formatted reports are particularly frowned upon since 43 + they're quite hard to read for humans and encourage to use dedicated viewers, 44 + sometimes online, which by definition is not acceptable for a confidential 45 + security report. 42 46 43 47 Disclosure and embargoed information 44 48 ------------------------------------
+5 -1
Documentation/process/submitting-patches.rst
··· 805 805 additional information for the reviewers. If it's placed above the 806 806 commit tags, it needs manual interaction to remove it. If it is below 807 807 the separator line, it gets automatically stripped off when applying the 808 - patch:: 808 + patch. If available, adding links to previous versions of the patch (e.g., 809 + lore.kernel.org archive link) is recommended to help reviewers:: 809 810 810 811 <commit message> 811 812 ... ··· 814 813 --- 815 814 V2 -> V3: Removed redundant helper function 816 815 V1 -> V2: Cleaned up coding style and addressed review comments 816 + 817 + v2: https://lore.kernel.org/bar 818 + v1: https://lore.kernel.org/foo 817 819 818 820 path/to/file | 5+++-- 819 821 ...
-7
Documentation/rust/index.rst
··· 58 58 59 59 You can also find learning materials for Rust in its section in 60 60 :doc:`../process/kernel-docs`. 61 - 62 - .. only:: subproject and html 63 - 64 - Indices 65 - ======= 66 - 67 - * :ref:`genindex`
-7
Documentation/scheduler/index.rst
··· 25 25 sched-debug 26 26 27 27 text_files 28 - 29 - .. only:: subproject and html 30 - 31 - Indices 32 - ======= 33 - 34 - * :ref:`genindex`
+3 -3
Documentation/scsi/ChangeLog.sym53c8xx
··· 2 2 * version sym53c8xx-1.7.3c 3 3 - Ensure LEDC bit in GPCNTL is cleared when reading the NVRAM. 4 4 Fix sent by Stig Telfer <stig@api-networks.com>. 5 - - Backport from SYM-2 the work-around that allows to support 6 - hardwares that fail PCI parity checking. 7 - - Check that we received at least 8 bytes of INQUIRY response 5 + - Backport from SYM-2 the work-around that allows to support 6 + hardware that fails PCI parity checking. 7 + - Check that we received at least 8 bytes of INQUIRY response 8 8 for byte 7, that contains device capabilities, to be valid. 9 9 - Define scsi_set_pci_device() as nil for kernel < 2.4.4. 10 10 - + A couple of minor changes.
+1 -1
Documentation/sound/hd-audio/notes.rst
··· 191 191 configuration of that preset with the correct pin setup, etc. 192 192 Thus, if you have a newer machine with a slightly different PCI SSID 193 193 (or codec SSID) from the existing one, you may have a good chance to 194 - re-use the same model. You can pass the ``model`` option to specify the 194 + reuse the same model. You can pass the ``model`` option to specify the 195 195 preset model instead of PCI (and codec-) SSID look-up. 196 196 197 197 What ``model`` option values are available depends on the codec chip.
-7
Documentation/sound/index.rst
··· 15 15 cards/index 16 16 codecs/index 17 17 utimers 18 - 19 - .. only:: subproject and html 20 - 21 - Indices 22 - ======= 23 - 24 - * :ref:`genindex`
+7
Documentation/sphinx-includes/subproject-index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. This file is included in subproject root documents in conf.py 3 + 4 + Indices 5 + ======= 6 + 7 + * :ref:`genindex`
+19 -1
Documentation/sphinx-static/custom.css
··· 20 20 overflow-y: auto; } 21 21 /* Tweak document margins and don't force width */ 22 22 div.document { 23 - margin: 20px 10px 0 10px; 23 + margin: 20px 10px 0 10px; 24 24 width: auto; 25 25 } 26 26 ··· 29 29 width: 104px; 30 30 margin-bottom: 20px; 31 31 } 32 + 33 + /* The default is to use -1em, wich makes it override text */ 34 + li { text-indent: 0em; } 32 35 33 36 /* 34 37 * Parameters for the display of function prototypes and such included ··· 42 39 dl.function dt { margin-left: 10em; text-indent: -10em; } 43 40 dt.sig-object { font-size: larger; } 44 41 div.kernelindent { margin-left: 2em; margin-right: 4em; } 42 + 43 + /* 44 + * Parameters for the display of function prototypes and such included 45 + * from Python source files. 46 + */ 47 + dl.py { margin-top: 2em; background-color: #ecf0f3; } 48 + dl.py.class { margin-left: 2em; text-indent: -2em; padding-left: 2em; } 49 + dl.py.method, dl.py.attribute { margin-left: 2em; text-indent: -2em; } 50 + dl.py li, pre { text-indent: 0em; padding-left: 0 !important; } 45 51 46 52 /* 47 53 * Tweaks for our local TOC ··· 162 150 border-bottom: none; 163 151 text-decoration: underline; 164 152 text-underline-offset: 0.3em; 153 + } 154 + 155 + a.manpage { 156 + font-style: normal; 157 + font-weight: bold; 158 + font-family: "Courier New", Courier, monospace; 165 159 }
+10
Documentation/sphinx/automarkup.py
··· 46 46 # 47 47 Skipnames = [ 'for', 'if', 'register', 'sizeof', 'struct', 'unsigned' ] 48 48 49 + # 50 + # Common English words that should not be recognized as C identifiers 51 + # when following struct/union/enum/typedef keywords. 52 + # Example: "a simple struct that" in workqueue.rst should not be marked as code. 53 + # 54 + Skipidentifiers = [ 'that', 'which', 'where', 'whose' ] 49 55 50 56 # 51 57 # Many places in the docs refer to common system calls. It is ··· 168 162 # cross-referencing inside it first. 169 163 if c_namespace: 170 164 possible_targets.insert(0, c_namespace + "." + base_target) 165 + 166 + # Skip common English words that match identifier pattern but are not C code. 167 + if base_target in Skipidentifiers: 168 + return target_text 171 169 172 170 if base_target not in Skipnames: 173 171 for target in possible_targets:
+11 -49
Documentation/sphinx/kerneldoc.py
··· 47 47 from kdoc.kdoc_files import KernelFiles 48 48 from kdoc.kdoc_output import RestFormat 49 49 50 + # Used when verbose is active to show how to reproduce kernel-doc 51 + # issues via command line 52 + kerneldoc_bin = "tools/docs/kernel-doc" 53 + 50 54 __version__ = '1.0' 51 55 kfiles = None 52 56 logger = logging.getLogger(__name__) ··· 99 95 def handle_args(self): 100 96 101 97 env = self.state.document.settings.env 102 - cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno'] 98 + cmd = [kerneldoc_bin, '-rst', '-enable-lineno'] 103 99 104 100 filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] 105 101 ··· 194 190 195 191 return cmd 196 192 197 - def run_cmd(self, cmd): 198 - """ 199 - Execute an external kernel-doc command. 200 - """ 201 - 202 - env = self.state.document.settings.env 203 - node = nodes.section() 204 - 205 - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 206 - out, err = p.communicate() 207 - 208 - out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8') 209 - 210 - if p.returncode != 0: 211 - sys.stderr.write(err) 212 - 213 - logger.warning("kernel-doc '%s' failed with return code %d" 214 - % (" ".join(cmd), p.returncode)) 215 - return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] 216 - elif env.config.kerneldoc_verbosity > 0: 217 - sys.stderr.write(err) 218 - 219 - filenames = self.parse_args["file_list"] 220 - for filename in filenames: 221 - self.parse_msg(filename, node, out, cmd) 222 - 223 - return node.children 224 - 225 - def parse_msg(self, filename, node, out, cmd): 193 + def parse_msg(self, filename, node, out): 226 194 """ 227 195 Handles a kernel-doc output for a given file 228 196 """ ··· 220 244 221 245 self.do_parse(result, node) 222 246 223 - def run_kdoc(self, cmd, kfiles): 247 + def run_kdoc(self, kfiles): 224 248 """ 225 249 Execute kernel-doc classes directly instead of running as a separate 226 250 command. ··· 234 258 filenames = self.parse_args["file_list"] 235 259 236 260 for filename, out in kfiles.msg(**self.msg_args, filenames=filenames): 237 - self.parse_msg(filename, node, out, cmd) 261 + self.parse_msg(filename, node, out) 238 262 239 263 return node.children 240 264 241 265 def run(self): 242 - global kfiles 243 - 244 266 cmd = self.handle_args() 245 267 if self.verbose >= 1: 246 268 logger.info(cmd_str(cmd)) 247 269 248 270 try: 249 - if kfiles: 250 - return self.run_kdoc(cmd, kfiles) 251 - else: 252 - return self.run_cmd(cmd) 253 - 271 + return self.run_kdoc(kfiles) 254 272 except Exception as e: # pylint: disable=W0703 255 273 logger.warning("kernel-doc '%s' processing failed with: %s" % 256 274 (cmd_str(cmd), pformat(e))) ··· 256 286 257 287 def setup_kfiles(app): 258 288 global kfiles 259 - 260 - kerneldoc_bin = app.env.config.kerneldoc_bin 261 - 262 - if kerneldoc_bin and kerneldoc_bin.endswith("kernel-doc.py"): 263 - print("Using Python kernel-doc") 264 - out_style = RestFormat() 265 - kfiles = KernelFiles(out_style=out_style, logger=logger) 266 - else: 267 - print(f"Using {kerneldoc_bin}") 289 + out_style = RestFormat() 290 + kfiles = KernelFiles(out_style=out_style, logger=logger) 268 291 269 292 270 293 def setup(app): 271 - app.add_config_value('kerneldoc_bin', None, 'env') 272 294 app.add_config_value('kerneldoc_srctree', None, 'env') 273 295 app.add_config_value('kerneldoc_verbosity', 1, 'env') 274 296
-7
Documentation/spi/index.rst
··· 12 12 butterfly 13 13 spi-lm70llp 14 14 spi-sc18is602 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex`
+5 -2
Documentation/staging/rpmsg.rst
··· 224 224 225 225 :: 226 226 227 - #include <linux/kernel.h> 227 + #include <linux/dev_printk.h> 228 + #include <linux/mod_devicetable.h> 228 229 #include <linux/module.h> 230 + #include <linux/printk.h> 229 231 #include <linux/rpmsg.h> 232 + #include <linux/types.h> 230 233 231 234 static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len, 232 235 void *priv, u32 src) ··· 247 244 /* send a message on our channel */ 248 245 err = rpmsg_send(rpdev->ept, "hello!", 6); 249 246 if (err) { 250 - pr_err("rpmsg_send failed: %d\n", err); 247 + dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", err); 251 248 return err; 252 249 } 253 250
-7
Documentation/target/index.rst
··· 10 10 tcmu-design 11 11 tcm_mod_builder 12 12 scripts 13 - 14 - .. only:: subproject and html 15 - 16 - Indices 17 - ======= 18 - 19 - * :ref:`genindex`
-7
Documentation/tee/index.rst
··· 12 12 amd-tee 13 13 ts-tee 14 14 qtee 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex`
-7
Documentation/timers/index.rst
··· 13 13 no_hz 14 14 timekeeping 15 15 delay_sleep_functions 16 - 17 - .. only:: subproject and html 18 - 19 - Indices 20 - ======= 21 - 22 - * :ref:`genindex`
+10
Documentation/tools/feat.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ==================================== 4 + Documentation features parser module 5 + ==================================== 6 + 7 + .. automodule:: lib.python.feat.parse_features 8 + :members: 9 + :show-inheritance: 10 + :undoc-members:
+1 -7
Documentation/tools/index.rst
··· 12 12 13 13 rtla/index 14 14 rv/index 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex` 15 + python
+10
Documentation/tools/jobserver.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ================= 4 + Job server module 5 + ================= 6 + 7 + .. automodule:: lib.python.jobserver 8 + :members: 9 + :show-inheritance: 10 + :undoc-members:
+13
Documentation/tools/kabi.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ===================================== 4 + Kernel ABI documentation tool modules 5 + ===================================== 6 + 7 + .. toctree:: 8 + :maxdepth: 2 9 + 10 + kabi_parser 11 + kabi_regex 12 + kabi_symbols 13 + kabi_helpers
+11
Documentation/tools/kabi_helpers.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ================= 4 + Ancillary classes 5 + ================= 6 + 7 + .. automodule:: lib.python.abi.helpers 8 + :members: 9 + :member-order: bysource 10 + :show-inheritance: 11 + :undoc-members:
+10
Documentation/tools/kabi_parser.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ===================================== 4 + Kernel ABI documentation parser class 5 + ===================================== 6 + 7 + .. automodule:: lib.python.abi.abi_parser 8 + :members: 9 + :show-inheritance: 10 + :undoc-members:
+10
Documentation/tools/kabi_regex.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ============================= 4 + ABI regex search symbol class 5 + ============================= 6 + 7 + .. automodule:: lib.python.abi.abi_regex 8 + :members: 9 + :show-inheritance: 10 + :undoc-members:
+10
Documentation/tools/kabi_symbols.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ========================================= 4 + System ABI documentation validation class 5 + ========================================= 6 + 7 + .. automodule:: lib.python.abi.system_symbols 8 + :members: 9 + :show-inheritance: 10 + :undoc-members:
+12
Documentation/tools/kdoc.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ================== 4 + Kernel-doc modules 5 + ================== 6 + 7 + .. toctree:: 8 + :maxdepth: 2 9 + 10 + kdoc_parser 11 + kdoc_output 12 + kdoc_ancillary
+46
Documentation/tools/kdoc_ancillary.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ================= 4 + Ancillary classes 5 + ================= 6 + 7 + Argparse formatter class 8 + ======================== 9 + 10 + .. automodule:: lib.python.kdoc.enrich_formatter 11 + :members: 12 + :show-inheritance: 13 + :undoc-members: 14 + 15 + Regular expression class handler 16 + ================================ 17 + 18 + .. automodule:: lib.python.kdoc.kdoc_re 19 + :members: 20 + :show-inheritance: 21 + :undoc-members: 22 + 23 + 24 + Chinese, Japanese and Korean variable fonts handler 25 + =================================================== 26 + 27 + .. automodule:: lib.python.kdoc.latex_fonts 28 + :members: 29 + :show-inheritance: 30 + :undoc-members: 31 + 32 + Kernel C file include logic 33 + =========================== 34 + 35 + .. automodule:: lib.python.kdoc.parse_data_structs 36 + :members: 37 + :show-inheritance: 38 + :undoc-members: 39 + 40 + Python version ancillary methods 41 + ================================ 42 + 43 + .. automodule:: lib.python.kdoc.python_version 44 + :members: 45 + :show-inheritance: 46 + :undoc-members:
+14
Documentation/tools/kdoc_output.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ======================= 4 + Kernel-doc output stage 5 + ======================= 6 + 7 + Output handler for man pages and ReST 8 + ===================================== 9 + 10 + .. automodule:: lib.python.kdoc.kdoc_output 11 + :members: 12 + :show-inheritance: 13 + :undoc-members: 14 +
+29
Documentation/tools/kdoc_parser.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ======================= 4 + Kernel-doc parser stage 5 + ======================= 6 + 7 + File handler classes 8 + ==================== 9 + 10 + .. automodule:: lib.python.kdoc.kdoc_files 11 + :members: 12 + :show-inheritance: 13 + :undoc-members: 14 + 15 + Parsed item data class 16 + ====================== 17 + 18 + .. automodule:: lib.python.kdoc.kdoc_item 19 + :members: 20 + :show-inheritance: 21 + :undoc-members: 22 + 23 + Parser classes and methods 24 + ========================== 25 + 26 + .. automodule:: lib.python.kdoc.kdoc_parser 27 + :members: 28 + :show-inheritance: 29 + :undoc-members:
+13
Documentation/tools/python.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ================ 4 + Python libraries 5 + ================ 6 + 7 + .. toctree:: 8 + :maxdepth: 4 9 + 10 + jobserver 11 + feat 12 + kdoc 13 + kabi
-7
Documentation/tools/rtla/index.rst
··· 18 18 rtla-timerlat-hist 19 19 rtla-timerlat-top 20 20 rtla-hwnoise 21 - 22 - .. only:: subproject and html 23 - 24 - Indices 25 - ======= 26 - 27 - * :ref:`genindex`
-7
Documentation/tools/rv/index.rst
··· 16 16 rv-mon-wip 17 17 rv-mon-wwnr 18 18 rv-mon-sched 19 - 20 - .. only:: subproject and html 21 - 22 - Indices 23 - ======= 24 - 25 - * :ref:`genindex`
+1 -1
Documentation/trace/fprobe.rst
··· 79 79 80 80 Same as ftrace, the registered callbacks will start being called some time 81 81 after the register_fprobe() is called and before it returns. See 82 - :file:`Documentation/trace/ftrace.rst`. 82 + Documentation/trace/ftrace.rst. 83 83 84 84 Also, the unregister_fprobe() will guarantee that both enter and exit 85 85 handlers are no longer being called by functions after unregister_fprobe()
+1 -1
Documentation/trace/ftrace-uses.rst
··· 253 253 The @buf can also be a glob expression to enable all functions that 254 254 match a specific pattern. 255 255 256 - See Filter Commands in :file:`Documentation/trace/ftrace.rst`. 256 + See Filter Commands in Documentation/trace/ftrace.rst. 257 257 258 258 To just trace the schedule function: 259 259
-7
Documentation/trace/index.rst
··· 95 95 96 96 For more details, refer to the respective documentation of each 97 97 tracing tool and framework. 98 - 99 - .. only:: subproject and html 100 - 101 - Indices 102 - ======= 103 - 104 - * :ref:`genindex`
+3 -3
Documentation/trace/rv/da_monitor_instrumentation.rst
··· 162 162 163 163 The probes then need to be detached at the disable phase. 164 164 165 - [1] The wip model is presented in:: 165 + [1] The wip model is presented in: 166 166 167 167 Documentation/trace/rv/deterministic_automata.rst 168 168 169 - The wip monitor is presented in:: 169 + The wip monitor is presented in: 170 170 171 - Documentation/trace/rv/da_monitor_synthesis.rst 171 + Documentation/trace/rv/monitor_synthesis.rst
+4 -4
Documentation/translations/it_IT/doc-guide/kernel-doc.rst
··· 80 80 eseguire il programma ``kernel-doc`` con un livello di verbosità alto e senza 81 81 che questo produca alcuna documentazione. Per esempio:: 82 82 83 - scripts/kernel-doc -v -none drivers/foo/bar.c 83 + tools/docs/kernel-doc -v -none drivers/foo/bar.c 84 84 85 85 Il formato della documentazione è verificato della procedura di generazione 86 86 del kernel quando viene richiesto di effettuare dei controlli extra con GCC:: ··· 378 378 immediatamente seguito da una parentesi sinistra ('(') mentre in quelle simili a 379 379 oggetti no. 380 380 381 - Le macro simili a funzioni sono gestite come funzioni da ``scripts/kernel-doc``. 381 + Le macro simili a funzioni sono gestite come funzioni da ``tools/docs/kernel-doc``. 382 382 Possono avere un elenco di parametri. Le macro simili a oggetti non hanno un 383 383 elenco di parametri. 384 384 ··· 595 595 596 596 L'estensione kernel-doc fa parte dei sorgenti del kernel, la si può trovare 597 597 in ``Documentation/sphinx/kerneldoc.py``. Internamente, viene utilizzato 598 - lo script ``scripts/kernel-doc`` per estrarre i commenti di documentazione 598 + lo script ``tools/docs/kernel-doc`` per estrarre i commenti di documentazione 599 599 dai file sorgenti. 600 600 601 601 Come utilizzare kernel-doc per generare pagine man ··· 604 604 Se volete utilizzare kernel-doc solo per generare delle pagine man, potete 605 605 farlo direttamente dai sorgenti del kernel:: 606 606 607 - $ scripts/kernel-doc -man $(git grep -l '/\*\*' -- :^Documentation :^tools) | scripts/split-man.pl /tmp/man 607 + $ tools/docs/kernel-doc -man $(git grep -l '/\*\*' -- :^Documentation :^tools) | scripts/split-man.pl /tmp/man
+8 -8
Documentation/translations/it_IT/process/adding-syscalls.rst
··· 124 124 accesso da spazio utente quando il kernel ha già dei meccanismi e una semantica 125 125 ben definita per utilizzare i descrittori di file. 126 126 127 - Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` ritorna un nuovo 127 + Se la vostra nuova chiamata di sistema xyzzy(2) ritorna un nuovo 128 128 descrittore di file, allora l'argomento *flags* dovrebbe includere un valore 129 129 equivalente a ``O_CLOEXEC`` per i nuovi descrittori. Questo rende possibile, 130 130 nello spazio utente, la chiusura della finestra temporale fra le chiamate a ··· 140 140 per la lettura o la scrittura è il tipico modo del kernel per notificare lo 141 141 spazio utente circa un evento associato all'oggetto del kernel. 142 142 143 - Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` ha un argomento 143 + Se la vostra nuova chiamata di sistema xyzzy(2) ha un argomento 144 144 che è il percorso ad un file:: 145 145 146 146 int sys_xyzzy(const char __user *path, ..., unsigned int flags); 147 147 148 148 dovreste anche considerare se non sia più appropriata una versione 149 - :manpage:`xyzzyat(2)`:: 149 + `xyzzyat(2)`:: 150 150 151 151 int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags); 152 152 ··· 154 154 in questione; in particolare, permette allo spazio utente di richiedere la 155 155 funzionalità su un descrittore di file già aperto utilizzando il *flag* 156 156 ``AT_EMPTY_PATH``, in pratica otterremmo gratuitamente l'operazione 157 - :manpage:`fxyzzy(3)`:: 157 + fxyzzy(3):: 158 158 159 159 - xyzzyat(AT_FDCWD, path, ..., 0) is equivalent to xyzzy(path,...) 160 160 - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...) ··· 163 163 man :manpage:`openat(2)`; per un esempio di AT_EMPTY_PATH, leggere la pagina 164 164 man :manpage:`fstatat(2)`). 165 165 166 - Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` prevede un parametro 166 + Se la vostra nuova chiamata di sistema xyzzy(2) prevede un parametro 167 167 per descrivere uno scostamento all'interno di un file, usate ``loff_t`` come 168 168 tipo cosicché scostamenti a 64-bit potranno essere supportati anche su 169 169 architetture a 32-bit. 170 170 171 - Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` prevede l'uso di 171 + Se la vostra nuova chiamata di sistema xyzzy(2) prevede l'uso di 172 172 funzioni riservate, allora dev'essere gestita da un opportuno bit di privilegio 173 173 (verificato con una chiamata a ``capable()``), come descritto nella pagina man 174 174 :manpage:`capabilities(7)`. Scegliete un bit di privilegio già esistente per ··· 178 178 evitate di aggiungere nuovi usi al fin-troppo-generico privilegio 179 179 ``CAP_SYS_ADMIN``. 180 180 181 - Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` manipola altri 181 + Se la vostra nuova chiamata di sistema xyzzy(2) manipola altri 182 182 processi oltre a quello chiamato, allora dovrebbe essere limitata (usando 183 183 la chiamata ``ptrace_may_access()``) di modo che solo un processo chiamante 184 184 con gli stessi permessi del processo in oggetto, o con i necessari privilegi, ··· 219 219 ------------------------------------------------ 220 220 221 221 Il principale punto d'accesso alla vostra nuova chiamata di sistema 222 - :manpage:`xyzzy(2)` verrà chiamato ``sys_xyzzy()``; ma, piuttosto che in modo 222 + `xyzzy(2)` verrà chiamato ``sys_xyzzy()``; ma, piuttosto che in modo 223 223 esplicito, lo aggiungerete tramite la macro ``SYSCALL_DEFINEn``. La 'n' 224 224 indica il numero di argomenti della chiamata di sistema; la macro ha come 225 225 argomento il nome della chiamata di sistema, seguito dalle coppie (tipo, nome)
+1
Documentation/translations/ja_JP/index.rst
··· 13 13 14 14 disclaimer-ja_JP 15 15 process/howto 16 + process/submitting-patches 16 17 process/submit-checklist 17 18 18 19 .. raw:: latex
+3 -3
Documentation/translations/ja_JP/process/howto.rst
··· 49 49 50 50 カーネルは GNU C と GNU ツールチェインを使って書かれています。カーネル 51 51 は ISO C11 仕様に準拠して書く一方で、標準には無い言語拡張を多く使って 52 - います。カーネルは標準 C ライブラリに依存しない、C 言語非依存環境です。 52 + います。カーネルは標準 C ライブラリに依存しない、自立した C 環境です。 53 53 そのため、C の標準の中で使えないものもあります。特に任意の long long 54 54 の除算や浮動小数点は使えません。カーネルがツールチェインや C 言語拡張 55 55 に置いている前提がどうなっているのかわかりにくいことが時々あり、また、 ··· 61 61 発手順について高度な標準を持つ、多様な人の集まりです。地理的に分散した 62 62 大規模なチームに対してもっともうまくいくとわかったことをベースにしなが 63 63 ら、これらの標準は長い時間をかけて築かれてきました。これらはきちんと文 64 - 書化されていますから、事前にこれらの標準について事前にできるだけたくさ 64 + 書化されていますから、これらの標準について事前にできるだけたくさ 65 65 ん学んでください。また皆があなたやあなたの会社のやり方に合わせてくれる 66 66 と思わないでください。 67 67 ··· 363 363 364 364 あなたのハッキングのスキルを訓練する最高の方法のひとつに、他人がレポー 365 365 トしたバグを修正することがあります。あなたがカーネルをより安定化させる 366 - こに寄与するということだけでなく、あなたは 現実の問題を修正することを 366 + ことに寄与するということだけでなく、あなたは 現実の問題を修正することを 367 367 学び、自分のスキルも強化でき、また他の開発者があなたの存在に気がつきま 368 368 す。バグを修正することは、多くの開発者の中から自分が功績をあげる最善の 369 369 道です、なぜなら多くの人は他人のバグの修正に時間を浪費することを好まな
+2 -2
Documentation/translations/ja_JP/process/submit-checklist.rst
··· 52 52 1) 新規の、もしくは変更された ``CONFIG`` オプションについて、それが関係する 53 53 コンフィグメニューへの悪影響がない。また、 54 54 Documentation/kbuild/kconfig-language.rst の 55 - "Menu attibutes: default value" に記載の例外条件を満たす場合を除き、 55 + "Menu attributes: default value" に記載の例外条件を満たす場合を除き、 56 56 そのデフォルトが無効になっている。 57 57 58 58 2) 新規の ``Kconfig`` オプションにヘルプテキストがある。 ··· 75 75 4) 新規モジュール・パラメータが、すべて ``MODULE_PARM_DESC()`` によって記述 76 76 されている。 77 77 78 - 5) 新規ユーザースペース・インターフェースが、すべて ``Documentaion/ABI/`` 78 + 5) 新規ユーザースペース・インターフェースが、すべて ``Documentation/ABI/`` 79 79 以下に記載されている。詳しくは、 Documentation/admin-guide/abi.rst 80 80 (もしくは ``Documentation/ABI/README``) を参照。 81 81 ユーザースペース・インターフェースを変更するパッチは、
+56
Documentation/translations/ja_JP/process/submitting-patches.rst
··· 1 + .. _jp_process_submitting_patches: 2 + 3 + パッチの投稿: カーネルにコードを入れるための必須ガイド 4 + ====================================================== 5 + 6 + .. note:: 7 + 8 + このドキュメントは :ref:`Documentation/process/submitting-patches.rst <submittingpatches>` の日本語訳です。 9 + 10 + 免責事項: :ref:`translations_ja_JP_disclaimer` 11 + 12 + .. warning:: 13 + 14 + **UNDER CONSTRUCTION!!** 15 + 16 + この文書は翻訳更新の作業中です。最新の内容は原文を参照してください。 17 + 18 + Linux カーネルへ変更を投稿したい個人や企業にとって、もし「仕組み」に 19 + 慣れていなければ、そのプロセスは時に気後れするものでしょう。 20 + このテキストは、あなたの変更が受け入れられる可能性を大きく高めるための 21 + 提案を集めたものです。 22 + 23 + この文書には、比較的簡潔な形式で多数の提案が含まれています。 24 + カーネル開発プロセスの仕組みに関する詳細は 25 + Documentation/process/development-process.rst を参照してください。 26 + また、コードを投稿する前に確認すべき項目の一覧として 27 + Documentation/process/submit-checklist.rst を読んでください。 28 + デバイスツリーバインディングのパッチについては、 29 + Documentation/devicetree/bindings/submitting-patches.rst を読んでください。 30 + 31 + この文書は、パッチ作成に ``git`` を使う前提で書かれています。 32 + もし ``git`` に不慣れであれば、使い方を学ぶことを強く勧めます。 33 + それにより、カーネル開発者として、また一般的にも、あなたの作業は 34 + ずっと楽になるでしょう。 35 + 36 + いくつかのサブシステムやメンテナツリーには、各々のワークフローや 37 + 期待事項に関する追加情報があります。次を参照してください: 38 + :ref:`Documentation/process/maintainer-handbooks.rst <maintainer_handbooks_main>`. 39 + 40 + 現在のソースツリーを入手する 41 + ---------------------------- 42 + 43 + もし手元に最新のカーネルソースのリポジトリがなければ、``git`` を使って取得して 44 + ください。まずは mainline のリポジトリから始めるのがよいでしょう。これは 45 + 次のようにして取得できます:: 46 + 47 + git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 48 + 49 + ただし、直接 mainline のツリーを対象に作業すればよいとは限らないことに注意 50 + してください。多くのサブシステムのメンテナはそれぞれ独自のツリーを運用しており、 51 + そのツリーに対して作成されたパッチを見たいと考えています。該当サブシステムの 52 + ツリーは MAINTAINERS ファイル内の **T:** エントリを参照して見つけてください。 53 + そこに掲載されていない場合は、メンテナに問い合わせてください。 54 + 55 + 変更内容を説明する 56 + ------------------
-18
Documentation/translations/ko_KR/core-api/wrappers/memory-barriers.rst
··· 1 - .. SPDX-License-Identifier: GPL-2.0 2 - This is a simple wrapper to bring memory-barriers.txt into the RST world 3 - until such a time as that file can be converted directly. 4 - 5 - ========================= 6 - 리눅스 커널 메모리 배리어 7 - ========================= 8 - 9 - .. raw:: latex 10 - 11 - \footnotesize 12 - 13 - .. include:: ../../memory-barriers.txt 14 - :literal: 15 - 16 - .. raw:: latex 17 - 18 - \normalsize
-1
Documentation/translations/ko_KR/index.rst
··· 12 12 :maxdepth: 1 13 13 14 14 process/howto 15 - core-api/wrappers/memory-barriers.rst 16 15 17 16 .. raw:: latex 18 17
-2952
Documentation/translations/ko_KR/memory-barriers.txt
··· 1 - NOTE: 2 - This is a version of Documentation/memory-barriers.txt translated into Korean. 3 - This document is maintained by SeongJae Park <sj@kernel.org>. 4 - If you find any difference between this document and the original file or 5 - a problem with the translation, please contact the maintainer of this file. 6 - 7 - Please also note that the purpose of this file is to be easier to 8 - read for non English (read: Korean) speakers and is not intended as 9 - a fork. So if you have any comments or updates for this file please 10 - update the original English file first. The English version is 11 - definitive, and readers should look there if they have any doubt. 12 - 13 - ================================= 14 - 이 문서는 15 - Documentation/memory-barriers.txt 16 - 의 한글 번역입니다. 17 - 18 - 역자: 박성재 <sj@kernel.org> 19 - ================================= 20 - 21 - 22 - ========================= 23 - 리눅스 커널 메모리 배리어 24 - ========================= 25 - 26 - 저자: David Howells <dhowells@redhat.com> 27 - Paul E. McKenney <paulmck@linux.ibm.com> 28 - Will Deacon <will.deacon@arm.com> 29 - Peter Zijlstra <peterz@infradead.org> 30 - 31 - ======== 32 - 면책조항 33 - ======== 34 - 35 - 이 문서는 명세서가 아닙니다; 이 문서는 완벽하지 않은데, 간결성을 위해 의도된 36 - 부분도 있고, 의도하진 않았지만 사람에 의해 쓰였다보니 불완전한 부분도 있습니다. 37 - 이 문서는 리눅스에서 제공하는 다양한 메모리 배리어들을 사용하기 위한 38 - 안내서입니다만, 뭔가 이상하다 싶으면 (그런게 많을 겁니다) 질문을 부탁드립니다. 39 - 일부 이상한 점들은 공식적인 메모리 일관성 모델과 tools/memory-model/ 에 있는 40 - 관련 문서를 참고해서 해결될 수 있을 겁니다. 그러나, 이 메모리 모델조차도 그 41 - 관리자들의 의견의 집합으로 봐야지, 절대 옳은 예언자로 신봉해선 안될 겁니다. 42 - 43 - 다시 말하지만, 이 문서는 리눅스가 하드웨어에 기대하는 사항에 대한 명세서가 44 - 아닙니다. 45 - 46 - 이 문서의 목적은 두가지입니다: 47 - 48 - (1) 어떤 특정 배리어에 대해 기대할 수 있는 최소한의 기능을 명세하기 위해서, 49 - 그리고 50 - 51 - (2) 사용 가능한 배리어들에 대해 어떻게 사용해야 하는지에 대한 안내를 제공하기 52 - 위해서. 53 - 54 - 어떤 아키텍쳐는 특정한 배리어들에 대해서는 여기서 이야기하는 최소한의 55 - 요구사항들보다 많은 기능을 제공할 수도 있습니다만, 여기서 이야기하는 56 - 요구사항들을 충족하지 않는 아키텍쳐가 있다면 그 아키텍쳐가 잘못된 것이란 점을 57 - 알아두시기 바랍니다. 58 - 59 - 또한, 특정 아키텍쳐에서 일부 배리어는 해당 아키텍쳐의 특수한 동작 방식으로 인해 60 - 해당 배리어의 명시적 사용이 불필요해서 no-op 이 될수도 있음을 알아두시기 61 - 바랍니다. 62 - 63 - 역자: 본 번역 역시 완벽하지 않은데, 이 역시 부분적으로는 의도된 것이기도 64 - 합니다. 여타 기술 문서들이 그렇듯 완벽한 이해를 위해서는 번역문과 원문을 함께 65 - 읽으시되 번역문을 하나의 가이드로 활용하시길 추천드리며, 발견되는 오역 등에 66 - 대해서는 언제든 의견을 부탁드립니다. 과한 번역으로 인한 오해를 최소화하기 위해 67 - 애매한 부분이 있을 경우에는 어색함이 있더라도 원래의 용어를 차용합니다. 68 - 69 - 70 - ===== 71 - 목차: 72 - ===== 73 - 74 - (*) 추상 메모리 액세스 모델. 75 - 76 - - 디바이스 오퍼레이션. 77 - - 보장사항. 78 - 79 - (*) 메모리 배리어란 무엇인가? 80 - 81 - - 메모리 배리어의 종류. 82 - - 메모리 배리어에 대해 가정해선 안될 것. 83 - - 주소 데이터 의존성 배리어 (역사적). 84 - - 컨트롤 의존성. 85 - - SMP 배리어 짝맞추기. 86 - - 메모리 배리어 시퀀스의 예. 87 - - 읽기 메모리 배리어 vs 로드 예측. 88 - - Multicopy 원자성. 89 - 90 - (*) 명시적 커널 배리어. 91 - 92 - - 컴파일러 배리어. 93 - - CPU 메모리 배리어. 94 - 95 - (*) 암묵적 커널 메모리 배리어. 96 - 97 - - 락 Acquisition 함수. 98 - - 인터럽트 비활성화 함수. 99 - - 슬립과 웨이크업 함수. 100 - - 그외의 함수들. 101 - 102 - (*) CPU 간 ACQUIRING 배리어의 효과. 103 - 104 - - Acquire vs 메모리 액세스. 105 - 106 - (*) 메모리 배리어가 필요한 곳 107 - 108 - - 프로세서간 상호 작용. 109 - - 어토믹 오퍼레이션. 110 - - 디바이스 액세스. 111 - - 인터럽트. 112 - 113 - (*) 커널 I/O 배리어의 효과. 114 - 115 - (*) 가정되는 가장 완화된 실행 순서 모델. 116 - 117 - (*) CPU 캐시의 영향. 118 - 119 - - 캐시 일관성. 120 - - 캐시 일관성 vs DMA. 121 - - 캐시 일관성 vs MMIO. 122 - 123 - (*) CPU 들이 저지르는 일들. 124 - 125 - - 그리고, Alpha 가 있다. 126 - - 가상 머신 게스트. 127 - 128 - (*) 사용 예. 129 - 130 - - 순환식 버퍼. 131 - 132 - (*) 참고 문헌. 133 - 134 - 135 - ======================= 136 - 추상 메모리 액세스 모델 137 - ======================= 138 - 139 - 다음과 같이 추상화된 시스템 모델을 생각해 봅시다: 140 - 141 - : : 142 - : : 143 - : : 144 - +-------+ : +--------+ : +-------+ 145 - | | : | | : | | 146 - | | : | | : | | 147 - | CPU 1 |<----->| Memory |<----->| CPU 2 | 148 - | | : | | : | | 149 - | | : | | : | | 150 - +-------+ : +--------+ : +-------+ 151 - ^ : ^ : ^ 152 - | : | : | 153 - | : | : | 154 - | : v : | 155 - | : +--------+ : | 156 - | : | | : | 157 - | : | | : | 158 - +---------->| Device |<----------+ 159 - : | | : 160 - : | | : 161 - : +--------+ : 162 - : : 163 - 164 - 프로그램은 여러 메모리 액세스 오퍼레이션을 발생시키고, 각각의 CPU 는 그런 165 - 프로그램들을 실행합니다. 추상화된 CPU 모델에서 메모리 오퍼레이션들의 순서는 166 - 매우 완화되어 있고, CPU 는 프로그램이 인과관계를 어기지 않는 상태로 관리된다고 167 - 보일 수만 있다면 메모리 오퍼레이션을 자신이 원하는 어떤 순서대로든 재배치해 168 - 동작시킬 수 있습니다. 비슷하게, 컴파일러 또한 프로그램의 정상적 동작을 해치지 169 - 않는 한도 내에서는 어떤 순서로든 자신이 원하는 대로 인스트럭션을 재배치 할 수 170 - 있습니다. 171 - 172 - 따라서 위의 다이어그램에서 한 CPU가 동작시키는 메모리 오퍼레이션이 만들어내는 173 - 변화는 해당 오퍼레이션이 CPU 와 시스템의 다른 부분들 사이의 인터페이스(점선)를 174 - 지나가면서 시스템의 나머지 부분들에 인지됩니다. 175 - 176 - 177 - 예를 들어, 다음의 일련의 이벤트들을 생각해 봅시다: 178 - 179 - CPU 1 CPU 2 180 - =============== =============== 181 - { A == 1; B == 2 } 182 - A = 3; x = B; 183 - B = 4; y = A; 184 - 185 - 다이어그램의 가운데에 위치한 메모리 시스템에 보여지게 되는 액세스들은 다음의 총 186 - 24개의 조합으로 재구성될 수 있습니다: 187 - 188 - STORE A=3, STORE B=4, y=LOAD A->3, x=LOAD B->4 189 - STORE A=3, STORE B=4, x=LOAD B->4, y=LOAD A->3 190 - STORE A=3, y=LOAD A->3, STORE B=4, x=LOAD B->4 191 - STORE A=3, y=LOAD A->3, x=LOAD B->2, STORE B=4 192 - STORE A=3, x=LOAD B->2, STORE B=4, y=LOAD A->3 193 - STORE A=3, x=LOAD B->2, y=LOAD A->3, STORE B=4 194 - STORE B=4, STORE A=3, y=LOAD A->3, x=LOAD B->4 195 - STORE B=4, ... 196 - ... 197 - 198 - 따라서 다음의 네가지 조합의 값들이 나올 수 있습니다: 199 - 200 - x == 2, y == 1 201 - x == 2, y == 3 202 - x == 4, y == 1 203 - x == 4, y == 3 204 - 205 - 206 - 한발 더 나아가서, 한 CPU 가 메모리 시스템에 반영한 스토어 오퍼레이션들의 결과는 207 - 다른 CPU 에서의 로드 오퍼레이션을 통해 인지되는데, 이 때 스토어가 반영된 순서와 208 - 다른 순서로 인지될 수도 있습니다. 209 - 210 - 211 - 예로, 아래의 일련의 이벤트들을 생각해 봅시다: 212 - 213 - CPU 1 CPU 2 214 - =============== =============== 215 - { A == 1, B == 2, C == 3, P == &A, Q == &C } 216 - B = 4; Q = P; 217 - P = &B D = *Q; 218 - 219 - D 로 읽혀지는 값은 CPU 2 에서 P 로부터 읽혀진 주소값에 의존적이기 때문에 여기엔 220 - 분명한 주소 의존성이 있습니다. 하지만 이 이벤트들의 실행 결과로는 아래의 221 - 결과들이 모두 나타날 수 있습니다: 222 - 223 - (Q == &A) and (D == 1) 224 - (Q == &B) and (D == 2) 225 - (Q == &B) and (D == 4) 226 - 227 - CPU 2 는 *Q 의 로드를 요청하기 전에 P 를 Q 에 넣기 때문에 D 에 C 를 집어넣는 228 - 일은 없음을 알아두세요. 229 - 230 - 231 - 디바이스 오퍼레이션 232 - ------------------- 233 - 234 - 일부 디바이스는 자신의 컨트롤 인터페이스를 메모리의 특정 영역으로 매핑해서 235 - 제공하는데(Memory mapped I/O), 해당 컨트롤 레지스터에 접근하는 순서는 매우 236 - 중요합니다. 예를 들어, 어드레스 포트 레지스터 (A) 와 데이터 포트 레지스터 (D) 237 - 를 통해 접근되는 내부 레지스터 집합을 갖는 이더넷 카드를 생각해 봅시다. 내부의 238 - 5번 레지스터를 읽기 위해 다음의 코드가 사용될 수 있습니다: 239 - 240 - *A = 5; 241 - x = *D; 242 - 243 - 하지만, 이건 다음의 두 조합 중 하나로 만들어질 수 있습니다: 244 - 245 - STORE *A = 5, x = LOAD *D 246 - x = LOAD *D, STORE *A = 5 247 - 248 - 두번째 조합은 데이터를 읽어온 _후에_ 주소를 설정하므로, 오동작을 일으킬 겁니다. 249 - 250 - 251 - 보장사항 252 - -------- 253 - 254 - CPU 에게 기대할 수 있는 최소한의 보장사항 몇가지가 있습니다: 255 - 256 - (*) 어떤 CPU 든, 의존성이 존재하는 메모리 액세스들은 해당 CPU 자신에게 257 - 있어서는 순서대로 메모리 시스템에 수행 요청됩니다. 즉, 다음에 대해서: 258 - 259 - Q = READ_ONCE(P); D = READ_ONCE(*Q); 260 - 261 - CPU 는 다음과 같은 메모리 오퍼레이션 시퀀스를 수행 요청합니다: 262 - 263 - Q = LOAD P, D = LOAD *Q 264 - 265 - 그리고 그 시퀀스 내에서의 순서는 항상 지켜집니다. 하지만, DEC Alpha 에서 266 - READ_ONCE() 는 메모리 배리어 명령도 내게 되어 있어서, DEC Alpha CPU 는 267 - 다음과 같은 메모리 오퍼레이션들을 내놓게 됩니다: 268 - 269 - Q = LOAD P, MEMORY_BARRIER, D = LOAD *Q, MEMORY_BARRIER 270 - 271 - DEC Alpha 에서 수행되든 아니든, READ_ONCE() 는 컴파일러로부터의 악영향 272 - 또한 제거합니다. 273 - 274 - (*) 특정 CPU 내에서 겹치는 영역의 메모리에 행해지는 로드와 스토어 들은 해당 275 - CPU 안에서는 순서가 바뀌지 않은 것으로 보여집니다. 즉, 다음에 대해서: 276 - 277 - a = READ_ONCE(*X); WRITE_ONCE(*X, b); 278 - 279 - CPU 는 다음의 메모리 오퍼레이션 시퀀스만을 메모리에 요청할 겁니다: 280 - 281 - a = LOAD *X, STORE *X = b 282 - 283 - 그리고 다음에 대해서는: 284 - 285 - WRITE_ONCE(*X, c); d = READ_ONCE(*X); 286 - 287 - CPU 는 다음의 수행 요청만을 만들어 냅니다: 288 - 289 - STORE *X = c, d = LOAD *X 290 - 291 - (로드 오퍼레이션과 스토어 오퍼레이션이 겹치는 메모리 영역에 대해 292 - 수행된다면 해당 오퍼레이션들은 겹친다고 표현됩니다). 293 - 294 - 그리고 _반드시_ 또는 _절대로_ 가정하거나 가정하지 말아야 하는 것들이 있습니다: 295 - 296 - (*) 컴파일러가 READ_ONCE() 나 WRITE_ONCE() 로 보호되지 않은 메모리 액세스를 297 - 당신이 원하는 대로 할 것이라는 가정은 _절대로_ 해선 안됩니다. 그것들이 298 - 없다면, 컴파일러는 컴파일러 배리어 섹션에서 다루게 될, 모든 "창의적인" 299 - 변경들을 만들어낼 권한을 갖게 됩니다. 300 - 301 - (*) 개별적인 로드와 스토어들이 주어진 순서대로 요청될 것이라는 가정은 _절대로_ 302 - 하지 말아야 합니다. 이 말은 곧: 303 - 304 - X = *A; Y = *B; *D = Z; 305 - 306 - 는 다음의 것들 중 어느 것으로든 만들어질 수 있다는 의미입니다: 307 - 308 - X = LOAD *A, Y = LOAD *B, STORE *D = Z 309 - X = LOAD *A, STORE *D = Z, Y = LOAD *B 310 - Y = LOAD *B, X = LOAD *A, STORE *D = Z 311 - Y = LOAD *B, STORE *D = Z, X = LOAD *A 312 - STORE *D = Z, X = LOAD *A, Y = LOAD *B 313 - STORE *D = Z, Y = LOAD *B, X = LOAD *A 314 - 315 - (*) 겹치는 메모리 액세스들은 합쳐지거나 버려질 수 있음을 _반드시_ 가정해야 316 - 합니다. 다음의 코드는: 317 - 318 - X = *A; Y = *(A + 4); 319 - 320 - 다음의 것들 중 뭐든 될 수 있습니다: 321 - 322 - X = LOAD *A; Y = LOAD *(A + 4); 323 - Y = LOAD *(A + 4); X = LOAD *A; 324 - {X, Y} = LOAD {*A, *(A + 4) }; 325 - 326 - 그리고: 327 - 328 - *A = X; *(A + 4) = Y; 329 - 330 - 는 다음 중 뭐든 될 수 있습니다: 331 - 332 - STORE *A = X; STORE *(A + 4) = Y; 333 - STORE *(A + 4) = Y; STORE *A = X; 334 - STORE {*A, *(A + 4) } = {X, Y}; 335 - 336 - 그리고 보장사항에 반대되는 것들(anti-guarantees)이 있습니다: 337 - 338 - (*) 이 보장사항들은 bitfield 에는 적용되지 않는데, 컴파일러들은 bitfield 를 339 - 수정하는 코드를 생성할 때 원자성 없는(non-atomic) 읽고-수정하고-쓰는 340 - 인스트럭션들의 조합을 만드는 경우가 많기 때문입니다. 병렬 알고리즘의 341 - 동기화에 bitfield 를 사용하려 하지 마십시오. 342 - 343 - (*) bitfield 들이 여러 락으로 보호되는 경우라 하더라도, 하나의 bitfield 의 344 - 모든 필드들은 하나의 락으로 보호되어야 합니다. 만약 한 bitfield 의 두 345 - 필드가 서로 다른 락으로 보호된다면, 컴파일러의 원자성 없는 346 - 읽고-수정하고-쓰는 인스트럭션 조합은 한 필드에의 업데이트가 근처의 347 - 필드에도 영향을 끼치게 할 수 있습니다. 348 - 349 - (*) 이 보장사항들은 적절하게 정렬되고 크기가 잡힌 스칼라 변수들에 대해서만 350 - 적용됩니다. "적절하게 크기가 잡힌" 이라함은 현재로써는 "char", "short", 351 - "int" 그리고 "long" 과 같은 크기의 변수들을 의미합니다. "적절하게 정렬된" 352 - 은 자연스런 정렬을 의미하는데, 따라서 "char" 에 대해서는 아무 제약이 없고, 353 - "short" 에 대해서는 2바이트 정렬을, "int" 에는 4바이트 정렬을, 그리고 354 - "long" 에 대해서는 32-bit 시스템인지 64-bit 시스템인지에 따라 4바이트 또는 355 - 8바이트 정렬을 의미합니다. 이 보장사항들은 C11 표준에서 소개되었으므로, 356 - C11 전의 오래된 컴파일러(예를 들어, gcc 4.6) 를 사용할 때엔 주의하시기 357 - 바랍니다. 표준에 이 보장사항들은 "memory location" 을 정의하는 3.14 358 - 섹션에 다음과 같이 설명되어 있습니다: 359 - (역자: 인용문이므로 번역하지 않습니다) 360 - 361 - memory location 362 - either an object of scalar type, or a maximal sequence 363 - of adjacent bit-fields all having nonzero width 364 - 365 - NOTE 1: Two threads of execution can update and access 366 - separate memory locations without interfering with 367 - each other. 368 - 369 - NOTE 2: A bit-field and an adjacent non-bit-field member 370 - are in separate memory locations. The same applies 371 - to two bit-fields, if one is declared inside a nested 372 - structure declaration and the other is not, or if the two 373 - are separated by a zero-length bit-field declaration, 374 - or if they are separated by a non-bit-field member 375 - declaration. It is not safe to concurrently update two 376 - bit-fields in the same structure if all members declared 377 - between them are also bit-fields, no matter what the 378 - sizes of those intervening bit-fields happen to be. 379 - 380 - 381 - ========================= 382 - 메모리 배리어란 무엇인가? 383 - ========================= 384 - 385 - 앞에서 봤듯이, 상호간 의존성이 없는 메모리 오퍼레이션들은 실제로는 무작위적 386 - 순서로 수행될 수 있으며, 이는 CPU 와 CPU 간의 상호작용이나 I/O 에 문제가 될 수 387 - 있습니다. 따라서 컴파일러와 CPU 가 순서를 바꾸는데 제약을 걸 수 있도록 개입할 388 - 수 있는 어떤 방법이 필요합니다. 389 - 390 - 메모리 배리어는 그런 개입 수단입니다. 메모리 배리어는 배리어를 사이에 둔 앞과 391 - 뒤 양측의 메모리 오퍼레이션들 간에 부분적 순서가 존재하도록 하는 효과를 줍니다. 392 - 393 - 시스템의 CPU 들과 여러 디바이스들은 성능을 올리기 위해 명령어 재배치, 실행 394 - 유예, 메모리 오퍼레이션들의 조합, 예측적 로드(speculative load), 브랜치 395 - 예측(speculative branch prediction), 다양한 종류의 캐싱(caching) 등의 다양한 396 - 트릭을 사용할 수 있기 때문에 이런 강제력은 중요합니다. 메모리 배리어들은 이런 397 - 트릭들을 무효로 하거나 억제하는 목적으로 사용되어져서 코드가 여러 CPU 와 398 - 디바이스들 간의 상호작용을 정상적으로 제어할 수 있게 해줍니다. 399 - 400 - 401 - 메모리 배리어의 종류 402 - -------------------- 403 - 404 - 메모리 배리어는 네개의 기본 타입으로 분류됩니다: 405 - 406 - (1) 쓰기 (또는 스토어) 메모리 배리어. 407 - 408 - 쓰기 메모리 배리어는 시스템의 다른 컴포넌트들에 해당 배리어보다 앞서 409 - 명시된 모든 STORE 오퍼레이션들이 해당 배리어 뒤에 명시된 모든 STORE 410 - 오퍼레이션들보다 먼저 수행된 것으로 보일 것을 보장합니다. 411 - 412 - 쓰기 배리어는 스토어 오퍼레이션들에 대한 부분적 순서 세우기입니다; 로드 413 - 오퍼레이션들에 대해서는 어떤 영향도 끼치지 않습니다. 414 - 415 - CPU 는 시간의 흐름에 따라 메모리 시스템에 일련의 스토어 오퍼레이션들을 416 - 하나씩 요청해 집어넣습니다. 쓰기 배리어 앞의 모든 스토어 오퍼레이션들은 417 - 쓰기 배리어 뒤의 모든 스토어 오퍼레이션들보다 _앞서_ 수행될 겁니다. 418 - 419 - [!] 쓰기 배리어들은 읽기 또는 주소 의존성 배리어와 함께 짝을 맞춰 420 - 사용되어야만 함을 알아두세요; "SMP 배리어 짝맞추기" 서브섹션을 참고하세요. 421 - 422 - 423 - (2) 주소 의존성 배리어 (역사적). 424 - 425 - 주소 의존성 배리어는 읽기 배리어의 보다 완화된 형태입니다. 두개의 로드 426 - 오퍼레이션이 있고 두번째 것이 첫번째 것의 결과에 의존하고 있을 때(예: 427 - 두번째 로드가 참조할 주소를 첫번째 로드가 읽는 경우), 두번째 로드가 읽어올 428 - 데이터는 첫번째 로드에 의해 그 주소가 얻어진 뒤에 업데이트 됨을 보장하기 429 - 위해서 주소 의존성 배리어가 필요할 수 있습니다. 430 - 431 - 주소 의존성 배리어는 상호 의존적인 로드 오퍼레이션들 사이의 부분적 순서 432 - 세우기입니다; 스토어 오퍼레이션들이나 독립적인 로드들, 또는 중복되는 433 - 로드들에 대해서는 어떤 영향도 끼치지 않습니다. 434 - 435 - (1) 에서 언급했듯이, 시스템의 CPU 들은 메모리 시스템에 일련의 스토어 436 - 오퍼레이션들을 던져 넣고 있으며, 거기에 관심이 있는 다른 CPU 는 그 437 - 오퍼레이션들을 메모리 시스템이 실행한 결과를 인지할 수 있습니다. 이처럼 438 - 다른 CPU 의 스토어 오퍼레이션의 결과에 관심을 두고 있는 CPU 가 수행 요청한 439 - 주소 의존성 배리어는, 배리어 앞의 어떤 로드 오퍼레이션이 다른 CPU 에서 440 - 던져 넣은 스토어 오퍼레이션과 같은 영역을 향했다면, 그런 스토어 441 - 오퍼레이션들이 만들어내는 결과가 주소 의존성 배리어 뒤의 로드 442 - 오퍼레이션들에게는 보일 것을 보장합니다. 443 - 444 - 이 순서 세우기 제약에 대한 그림을 보기 위해선 "메모리 배리어 시퀀스의 예" 445 - 서브섹션을 참고하시기 바랍니다. 446 - 447 - [!] 첫번째 로드는 반드시 _주소_ 의존성을 가져야지 컨트롤 의존성을 가져야 448 - 하는게 아님을 알아두십시오. 만약 두번째 로드를 위한 주소가 첫번째 로드에 449 - 의존적이지만 그 의존성은 조건적이지 그 주소 자체를 가져오는게 아니라면, 450 - 그것은 _컨트롤_ 의존성이고, 이 경우에는 읽기 배리어나 그보다 강력한 451 - 무언가가 필요합니다. 더 자세한 내용을 위해서는 "컨트롤 의존성" 서브섹션을 452 - 참고하시기 바랍니다. 453 - 454 - [!] 주소 의존성 배리어는 보통 쓰기 배리어들과 함께 짝을 맞춰 사용되어야 455 - 합니다; "SMP 배리어 짝맞추기" 서브섹션을 참고하세요. 456 - 457 - [!] 커널 v5.9 릴리즈에서 명시적 주소 의존성 배리어를 위한 커널 API 들이 458 - 삭제되었습니다. 오늘날에는 공유된 변수들의 로드를 표시하는 READ_ONCE() 나 459 - rcu_dereference() 와 같은 API 들은 묵시적으로 주소 의존성 배리어를 제공합니다. 460 - 461 - 462 - (3) 읽기 (또는 로드) 메모리 배리어. 463 - 464 - 읽기 배리어는 주소 의존성 배리어 기능의 보장사항에 더해서 배리어보다 앞서 465 - 명시된 모든 LOAD 오퍼레이션들이 배리어 뒤에 명시되는 모든 LOAD 466 - 오퍼레이션들보다 먼저 행해진 것으로 시스템의 다른 컴포넌트들에 보여질 것을 467 - 보장합니다. 468 - 469 - 읽기 배리어는 로드 오퍼레이션에 행해지는 부분적 순서 세우기입니다; 스토어 470 - 오퍼레이션에 대해서는 어떤 영향도 끼치지 않습니다. 471 - 472 - 읽기 메모리 배리어는 주소 의존성 배리어를 내장하므로 주소 의존성 배리어를 473 - 대신할 수 있습니다. 474 - 475 - [!] 읽기 배리어는 일반적으로 쓰기 배리어들과 함께 짝을 맞춰 사용되어야 476 - 합니다; "SMP 배리어 짝맞추기" 서브섹션을 참고하세요. 477 - 478 - 479 - (4) 범용 메모리 배리어. 480 - 481 - 범용(general) 메모리 배리어는 배리어보다 앞서 명시된 모든 LOAD 와 STORE 482 - 오퍼레이션들이 배리어 뒤에 명시된 모든 LOAD 와 STORE 오퍼레이션들보다 483 - 먼저 수행된 것으로 시스템의 나머지 컴포넌트들에 보이게 됨을 보장합니다. 484 - 485 - 범용 메모리 배리어는 로드와 스토어 모두에 대한 부분적 순서 세우기입니다. 486 - 487 - 범용 메모리 배리어는 읽기 메모리 배리어, 쓰기 메모리 배리어 모두를 488 - 내장하므로, 두 배리어를 모두 대신할 수 있습니다. 489 - 490 - 491 - 그리고 두개의 명시적이지 않은 타입이 있습니다: 492 - 493 - (5) ACQUIRE 오퍼레이션. 494 - 495 - 이 타입의 오퍼레이션은 단방향의 투과성 배리어처럼 동작합니다. ACQUIRE 496 - 오퍼레이션 뒤의 모든 메모리 오퍼레이션들이 ACQUIRE 오퍼레이션 후에 497 - 일어난 것으로 시스템의 나머지 컴포넌트들에 보이게 될 것이 보장됩니다. 498 - LOCK 오퍼레이션과 smp_load_acquire(), smp_cond_load_acquire() 오퍼레이션도 499 - ACQUIRE 오퍼레이션에 포함됩니다. 500 - 501 - ACQUIRE 오퍼레이션 앞의 메모리 오퍼레이션들은 ACQUIRE 오퍼레이션 완료 후에 502 - 수행된 것처럼 보일 수 있습니다. 503 - 504 - ACQUIRE 오퍼레이션은 거의 항상 RELEASE 오퍼레이션과 짝을 지어 사용되어야 505 - 합니다. 506 - 507 - 508 - (6) RELEASE 오퍼레이션. 509 - 510 - 이 타입의 오퍼레이션들도 단방향 투과성 배리어처럼 동작합니다. RELEASE 511 - 오퍼레이션 앞의 모든 메모리 오퍼레이션들은 RELEASE 오퍼레이션 전에 완료된 512 - 것으로 시스템의 다른 컴포넌트들에 보여질 것이 보장됩니다. UNLOCK 류의 513 - 오퍼레이션들과 smp_store_release() 오퍼레이션도 RELEASE 오퍼레이션의 514 - 일종입니다. 515 - 516 - RELEASE 오퍼레이션 뒤의 메모리 오퍼레이션들은 RELEASE 오퍼레이션이 517 - 완료되기 전에 행해진 것처럼 보일 수 있습니다. 518 - 519 - ACQUIRE 와 RELEASE 오퍼레이션의 사용은 일반적으로 다른 메모리 배리어의 520 - 필요성을 없앱니다. 또한, RELEASE+ACQUIRE 조합은 범용 메모리 배리어처럼 521 - 동작할 것을 보장하지 -않습니다-. 하지만, 어떤 변수에 대한 RELEASE 522 - 오퍼레이션을 앞서는 메모리 액세스들의 수행 결과는 이 RELEASE 오퍼레이션을 523 - 뒤이어 같은 변수에 대해 수행된 ACQUIRE 오퍼레이션을 뒤따르는 메모리 524 - 액세스에는 보여질 것이 보장됩니다. 다르게 말하자면, 주어진 변수의 525 - 크리티컬 섹션에서는, 해당 변수에 대한 앞의 크리티컬 섹션에서의 모든 526 - 액세스들이 완료되었을 것을 보장합니다. 527 - 528 - 즉, ACQUIRE 는 최소한의 "취득" 동작처럼, 그리고 RELEASE 는 최소한의 "공개" 529 - 처럼 동작한다는 의미입니다. 530 - 531 - atomic_t.txt 에 설명된 어토믹 오퍼레이션들 중 일부는 완전히 순서잡힌 것들과 532 - (배리어를 사용하지 않는) 완화된 순서의 것들 외에 ACQUIRE 와 RELEASE 부류의 533 - 것들도 존재합니다. 로드와 스토어를 모두 수행하는 조합된 어토믹 오퍼레이션에서, 534 - ACQUIRE 는 해당 오퍼레이션의 로드 부분에만 적용되고 RELEASE 는 해당 535 - 오퍼레이션의 스토어 부분에만 적용됩니다. 536 - 537 - 메모리 배리어들은 두 CPU 간, 또는 CPU 와 디바이스 간에 상호작용의 가능성이 있을 538 - 때에만 필요합니다. 만약 어떤 코드에 그런 상호작용이 없을 것이 보장된다면, 해당 539 - 코드에서는 메모리 배리어를 사용할 필요가 없습니다. 540 - 541 - 542 - 이것들은 _최소한의_ 보장사항들임을 알아두세요. 다른 아키텍쳐에서는 더 강력한 543 - 보장사항을 제공할 수도 있습니다만, 그런 보장사항은 아키텍쳐 종속적 코드 이외의 544 - 부분에서는 신뢰되지 _않을_ 겁니다. 545 - 546 - 547 - 메모리 배리어에 대해 가정해선 안될 것 548 - ------------------------------------- 549 - 550 - 리눅스 커널 메모리 배리어들이 보장하지 않는 것들이 있습니다: 551 - 552 - (*) 메모리 배리어 앞에서 명시된 어떤 메모리 액세스도 메모리 배리어 명령의 수행 553 - 완료 시점까지 _완료_ 될 것이란 보장은 없습니다; 배리어가 하는 일은 CPU 의 554 - 액세스 큐에 특정 타입의 액세스들은 넘을 수 없는 선을 긋는 것으로 생각될 수 555 - 있습니다. 556 - 557 - (*) 한 CPU 에서 메모리 배리어를 수행하는게 시스템의 다른 CPU 나 하드웨어에 558 - 어떤 직접적인 영향을 끼친다는 보장은 존재하지 않습니다. 배리어 수행이 559 - 만드는 간접적 영향은 두번째 CPU 가 첫번째 CPU 의 액세스들의 결과를 560 - 바라보는 순서가 됩니다만, 다음 항목을 보세요: 561 - 562 - (*) 첫번째 CPU 가 두번째 CPU 의 메모리 액세스들의 결과를 바라볼 때, _설령_ 563 - 두번째 CPU 가 메모리 배리어를 사용한다 해도, 첫번째 CPU _또한_ 그에 맞는 564 - 메모리 배리어를 사용하지 않는다면 ("SMP 배리어 짝맞추기" 서브섹션을 565 - 참고하세요) 그 결과가 올바른 순서로 보여진다는 보장은 없습니다. 566 - 567 - (*) CPU 바깥의 하드웨어[*] 가 메모리 액세스들의 순서를 바꾸지 않는다는 보장은 568 - 존재하지 않습니다. CPU 캐시 일관성 메커니즘은 메모리 배리어의 간접적 569 - 영향을 CPU 사이에 전파하긴 하지만, 순서대로 전파하지는 않을 수 있습니다. 570 - 571 - [*] 버스 마스터링 DMA 와 일관성에 대해서는 다음을 참고하시기 바랍니다: 572 - 573 - Documentation/driver-api/pci/pci.rst 574 - Documentation/core-api/dma-api-howto.rst 575 - Documentation/core-api/dma-api.rst 576 - 577 - 578 - 주소 의존성 배리어 (역사적) 579 - --------------------------- 580 - 581 - 리눅스 커널 v4.15 기준으로, smp_mb() 가 DEC Alpha 용 READ_ONCE() 코드에 582 - 추가되었는데, 이는 이 섹션에 주의를 기울여야 하는 사람들은 DEC Alpha 아키텍쳐 583 - 전용 코드를 만드는 사람들과 READ_ONCE() 자체를 만드는 사람들 뿐임을 의미합니다. 584 - 그런 분들을 위해, 그리고 역사에 관심 있는 분들을 위해, 여기 주소 의존성 585 - 배리어에 대한 이야기를 적습니다. 586 - 587 - [!] 주소 의존성은 로드에서 로드로와 로드에서 스토어로의 관계들 모두에서 588 - 나타나지만, 주소 의존성 배리어는 로드에서 스토어로의 상황에서는 필요하지 589 - 않습니다. 590 - 591 - 주소 의존성 배리어의 사용에 있어 지켜야 하는 사항들은 약간 미묘하고, 데이터 592 - 의존성 배리어가 사용되어야 하는 상황도 항상 명백하지는 않습니다. 설명을 위해 593 - 다음의 이벤트 시퀀스를 생각해 봅시다: 594 - 595 - CPU 1 CPU 2 596 - =============== =============== 597 - { A == 1, B == 2, C == 3, P == &A, Q == &C } 598 - B = 4; 599 - <쓰기 배리어> 600 - WRITE_ONCE(P, &B) 601 - Q = READ_ONCE_OLD(P); 602 - D = *Q; 603 - 604 - [!] READ_ONCE_OLD() 는 4.15 커널 전의 버전에서의, 주소 의존성 배리어를 내포하지 605 - 않는 READ_ONCE() 에 해당합니다. 606 - 607 - 여기엔 분명한 주소 의존성이 존재하므로, 이 시퀀스가 끝났을 때 Q 는 &A 또는 &B 608 - 일 것이고, 따라서: 609 - 610 - (Q == &A) 는 (D == 1) 를, 611 - (Q == &B) 는 (D == 4) 를 의미합니다. 612 - 613 - 하지만! CPU 2 는 B 의 업데이트를 인식하기 전에 P 의 업데이트를 인식할 수 있고, 614 - 따라서 다음의 결과가 가능합니다: 615 - 616 - (Q == &B) and (D == 2) ???? 617 - 618 - 이런 결과는 일관성이나 인과 관계 유지가 실패한 것처럼 보일 수도 있겠지만, 619 - 그렇지 않습니다, 그리고 이 현상은 (DEC Alpha 와 같은) 여러 CPU 에서 실제로 620 - 발견될 수 있습니다. 621 - 622 - 이 문제 상황을 제대로 해결하기 위해, READ_ONCE() 는 커널 v4.15 릴리즈 부터 623 - 묵시적 주소 의존성 배리어를 제공합니다: 624 - 625 - CPU 1 CPU 2 626 - =============== =============== 627 - { A == 1, B == 2, C == 3, P == &A, Q == &C } 628 - B = 4; 629 - <쓰기 배리어> 630 - WRITE_ONCE(P, &B); 631 - Q = READ_ONCE(P); 632 - <묵시적 주소 의존성 배리어> 633 - D = *Q; 634 - 635 - 이 변경은 앞의 처음 두가지 결과 중 하나만이 발생할 수 있고, 세번째의 결과는 636 - 발생할 수 없도록 합니다. 637 - 638 - 639 - [!] 이 상당히 반직관적인 상황은 분리된 캐시를 가지는 기계들에서 가장 잘 640 - 발생하는데, 예를 들면 한 캐시 뱅크는 짝수 번호의 캐시 라인들을 처리하고, 다른 641 - 뱅크는 홀수 번호의 캐시 라인들을 처리하는 경우임을 알아두시기 바랍니다. 포인터 642 - P 는 짝수 번호 캐시 라인에 저장되어 있고, 변수 B 는 홀수 번호 캐시 라인에 643 - 저장되어 있을 수 있습니다. 여기서 값을 읽어오는 CPU 의 캐시의 홀수 번호 처리 644 - 뱅크는 열심히 일감을 처리중인 반면 홀수 번호 처리 뱅크는 할 일 없이 한가한 645 - 중이라면 포인터 P (&B) 의 새로운 값과 변수 B 의 기존 값 (2) 를 볼 수 있습니다. 646 - 647 - 648 - 의존적 쓰기들의 순서를 맞추는데에는 주소 의존성 배리어가 필요치 않은데, 이는 649 - 리눅스 커널이 지원하는 CPU 들은 (1) 쓰기가 정말로 일어날지, (2) 쓰기가 어디에 650 - 이루어질지, 그리고 (3) 쓰여질 값을 확실히 알기 전까지는 쓰기를 수행하지 않기 651 - 때문입니다. 하지만 "컨트롤 의존성" 섹션과 652 - Documentation/RCU/rcu_dereference.rst 파일을 주의 깊게 읽어 주시기 바랍니다: 653 - 컴파일러는 매우 창의적인 많은 방법으로 종속성을 깰 수 있습니다. 654 - 655 - CPU 1 CPU 2 656 - =============== =============== 657 - { A == 1, B == 2, C = 3, P == &A, Q == &C } 658 - B = 4; 659 - <쓰기 배리어> 660 - WRITE_ONCE(P, &B); 661 - Q = READ_ONCE_OLD(P); 662 - WRITE_ONCE(*Q, 5); 663 - 664 - 따라서, Q 로의 읽기와 *Q 로의 쓰기 사이에는 주소 의존성 배리어가 필요치 665 - 않습니다. 달리 말하면, 오늘날의 READ_ONCE() 의 묵시적 주소 의존성 배리어가 666 - 없더라도 다음 결과는 생기지 않습니다: 667 - 668 - (Q == &B) && (B == 4) 669 - 670 - 이런 패턴은 드물게 사용되어야 함을 알아 두시기 바랍니다. 무엇보다도, 의존성 671 - 순서 규칙의 의도는 쓰기 작업을 -예방- 해서 그로 인해 발생하는 비싼 캐시 미스도 672 - 없애려는 것입니다. 이 패턴은 드물게 발생하는 에러 조건 같은것들을 기록하는데 673 - 사용될 수 있으며, CPU의 자연적인 순서 보장이 그런 기록들을 사라지지 않게 674 - 해줍니다. 675 - 676 - 677 - 주소 의존성에 의해 제공되는 이 순서규칙은 이를 포함하고 있는 CPU 에 678 - 지역적임을 알아두시기 바랍니다. 더 많은 정보를 위해선 "Multicopy 원자성" 679 - 섹션을 참고하세요. 680 - 681 - 682 - 주소 의존성 배리어는 매우 중요한데, 예를 들어 RCU 시스템에서 그렇습니다. 683 - include/linux/rcupdate.h 의 rcu_assign_pointer() 와 rcu_dereference() 를 684 - 참고하세요. 이것들은 RCU 로 관리되는 포인터의 타겟을 현재 타겟에서 수정된 685 - 새로운 타겟으로 바꾸는 작업에서 새로 수정된 타겟이 초기화가 완료되지 않은 채로 686 - 보여지는 일이 일어나지 않게 해줍니다. 687 - 688 - 더 많은 예를 위해선 "캐시 일관성" 서브섹션을 참고하세요. 689 - 690 - 691 - 컨트롤 의존성 692 - ------------- 693 - 694 - 현재의 컴파일러들은 컨트롤 의존성을 이해하고 있지 않기 때문에 컨트롤 의존성은 695 - 약간 다루기 어려울 수 있습니다. 이 섹션의 목적은 여러분이 컴파일러의 무시로 696 - 인해 여러분의 코드가 망가지는 걸 막을 수 있도록 돕는겁니다. 697 - 698 - 로드-로드 컨트롤 의존성은 (묵시적인) 주소 의존성 배리어만으로는 정확히 동작할 699 - 수가 없어서 읽기 메모리 배리어를 필요로 합니다. 아래의 코드를 봅시다: 700 - 701 - q = READ_ONCE(a); 702 - <묵시적 주소 의존성 배리어> 703 - if (q) { 704 - /* BUG: No address dependency!!! */ 705 - p = READ_ONCE(b); 706 - } 707 - 708 - 이 코드는 원하는 대로의 효과를 내지 못할 수 있는데, 이 코드에는 주소 의존성이 709 - 아니라 컨트롤 의존성이 존재하기 때문으로, 이런 상황에서 CPU 는 실행 속도를 더 710 - 빠르게 하기 위해 분기 조건의 결과를 예측하고 코드를 재배치 할 수 있어서 다른 711 - CPU 는 b 로부터의 로드 오퍼레이션이 a 로부터의 로드 오퍼레이션보다 먼저 발생한 712 - 걸로 인식할 수 있습니다. 여기에 정말로 필요했던 건 다음과 같습니다: 713 - 714 - q = READ_ONCE(a); 715 - if (q) { 716 - <읽기 배리어> 717 - p = READ_ONCE(b); 718 - } 719 - 720 - 하지만, 스토어 오퍼레이션은 예측적으로 수행되지 않습니다. 즉, 다음 예에서와 721 - 같이 로드-스토어 컨트롤 의존성이 존재하는 경우에는 순서가 -지켜진다-는 722 - 의미입니다. 723 - 724 - q = READ_ONCE(a); 725 - if (q) { 726 - WRITE_ONCE(b, 1); 727 - } 728 - 729 - 컨트롤 의존성은 보통 다른 타입의 배리어들과 짝을 맞춰 사용됩니다. 그렇다곤 730 - 하나, READ_ONCE() 도 WRITE_ONCE() 도 선택사항이 아니라 필수사항임을 부디 731 - 명심하세요! READ_ONCE() 가 없다면, 컴파일러는 'a' 로부터의 로드를 'a' 로부터의 732 - 또다른 로드와 조합할 수 있습니다. WRITE_ONCE() 가 없다면, 컴파일러는 'b' 로의 733 - 스토어를 'b' 로의 또라느 스토어들과 조합할 수 있습니다. 두 경우 모두 순서에 734 - 있어 상당히 비직관적인 결과를 초래할 수 있습니다. 735 - 736 - 이걸로 끝이 아닌게, 컴파일러가 변수 'a' 의 값이 항상 0이 아니라고 증명할 수 737 - 있다면, 앞의 예에서 "if" 문을 없애서 다음과 같이 최적화 할 수도 있습니다: 738 - 739 - q = a; 740 - b = 1; /* BUG: Compiler and CPU can both reorder!!! */ 741 - 742 - 그러니 READ_ONCE() 를 반드시 사용하세요. 743 - 744 - 다음과 같이 "if" 문의 양갈래 브랜치에 모두 존재하는 동일한 스토어에 대해 순서를 745 - 강제하고 싶은 경우가 있을 수 있습니다: 746 - 747 - q = READ_ONCE(a); 748 - if (q) { 749 - barrier(); 750 - WRITE_ONCE(b, 1); 751 - do_something(); 752 - } else { 753 - barrier(); 754 - WRITE_ONCE(b, 1); 755 - do_something_else(); 756 - } 757 - 758 - 안타깝게도, 현재의 컴파일러들은 높은 최적화 레벨에서는 이걸 다음과 같이 759 - 바꿔버립니다: 760 - 761 - q = READ_ONCE(a); 762 - barrier(); 763 - WRITE_ONCE(b, 1); /* BUG: No ordering vs. load from a!!! */ 764 - if (q) { 765 - /* WRITE_ONCE(b, 1); -- moved up, BUG!!! */ 766 - do_something(); 767 - } else { 768 - /* WRITE_ONCE(b, 1); -- moved up, BUG!!! */ 769 - do_something_else(); 770 - } 771 - 772 - 이제 'a' 에서의 로드와 'b' 로의 스토어 사이에는 조건적 관계가 없기 때문에 CPU 773 - 는 이들의 순서를 바꿀 수 있게 됩니다: 이런 경우에 조건적 관계는 반드시 774 - 필요한데, 모든 컴파일러 최적화가 이루어지고 난 후의 어셈블리 코드에서도 775 - 마찬가지입니다. 따라서, 이 예에서 순서를 지키기 위해서는 smp_store_release() 776 - 와 같은 명시적 메모리 배리어가 필요합니다: 777 - 778 - q = READ_ONCE(a); 779 - if (q) { 780 - smp_store_release(&b, 1); 781 - do_something(); 782 - } else { 783 - smp_store_release(&b, 1); 784 - do_something_else(); 785 - } 786 - 787 - 반면에 명시적 메모리 배리어가 없다면, 이런 경우의 순서는 스토어 오퍼레이션들이 788 - 서로 다를 때에만 보장되는데, 예를 들면 다음과 같은 경우입니다: 789 - 790 - q = READ_ONCE(a); 791 - if (q) { 792 - WRITE_ONCE(b, 1); 793 - do_something(); 794 - } else { 795 - WRITE_ONCE(b, 2); 796 - do_something_else(); 797 - } 798 - 799 - 처음의 READ_ONCE() 는 컴파일러가 'a' 의 값을 증명해내는 것을 막기 위해 여전히 800 - 필요합니다. 801 - 802 - 또한, 로컬 변수 'q' 를 가지고 하는 일에 대해 주의해야 하는데, 그러지 않으면 803 - 컴파일러는 그 값을 추측하고 또다시 필요한 조건관계를 없애버릴 수 있습니다. 804 - 예를 들면: 805 - 806 - q = READ_ONCE(a); 807 - if (q % MAX) { 808 - WRITE_ONCE(b, 1); 809 - do_something(); 810 - } else { 811 - WRITE_ONCE(b, 2); 812 - do_something_else(); 813 - } 814 - 815 - 만약 MAX 가 1 로 정의된 상수라면, 컴파일러는 (q % MAX) 는 0이란 것을 알아채고, 816 - 위의 코드를 아래와 같이 바꿔버릴 수 있습니다: 817 - 818 - q = READ_ONCE(a); 819 - WRITE_ONCE(b, 2); 820 - do_something_else(); 821 - 822 - 이렇게 되면, CPU 는 변수 'a' 로부터의 로드와 변수 'b' 로의 스토어 사이의 순서를 823 - 지켜줄 필요가 없어집니다. barrier() 를 추가해 해결해 보고 싶겠지만, 그건 824 - 도움이 안됩니다. 조건 관계는 사라졌고, barrier() 는 이를 되돌리지 못합니다. 825 - 따라서, 이 순서를 지켜야 한다면, MAX 가 1 보다 크다는 것을, 다음과 같은 방법을 826 - 사용해 분명히 해야 합니다: 827 - 828 - q = READ_ONCE(a); 829 - BUILD_BUG_ON(MAX <= 1); /* Order load from a with store to b. */ 830 - if (q % MAX) { 831 - WRITE_ONCE(b, 1); 832 - do_something(); 833 - } else { 834 - WRITE_ONCE(b, 2); 835 - do_something_else(); 836 - } 837 - 838 - 'b' 로의 스토어들은 여전히 서로 다름을 알아두세요. 만약 그것들이 동일하면, 839 - 앞에서 이야기했듯, 컴파일러가 그 스토어 오퍼레이션들을 'if' 문 바깥으로 840 - 끄집어낼 수 있습니다. 841 - 842 - 또한 이진 조건문 평가에 너무 의존하지 않도록 조심해야 합니다. 다음의 예를 843 - 봅시다: 844 - 845 - q = READ_ONCE(a); 846 - if (q || 1 > 0) 847 - WRITE_ONCE(b, 1); 848 - 849 - 첫번째 조건만으로는 브랜치 조건 전체를 거짓으로 만들 수 없고 두번째 조건은 항상 850 - 참이기 때문에, 컴파일러는 이 예를 다음과 같이 바꿔서 컨트롤 의존성을 없애버릴 851 - 수 있습니다: 852 - 853 - q = READ_ONCE(a); 854 - WRITE_ONCE(b, 1); 855 - 856 - 이 예는 컴파일러가 코드를 추측으로 수정할 수 없도록 분명히 해야 한다는 점을 857 - 강조합니다. 조금 더 일반적으로 말해서, READ_ONCE() 는 컴파일러에게 주어진 로드 858 - 오퍼레이션을 위한 코드를 정말로 만들도록 하지만, 컴파일러가 그렇게 만들어진 859 - 코드의 수행 결과를 사용하도록 강제하지는 않습니다. 860 - 861 - 또한, 컨트롤 의존성은 if 문의 then 절과 else 절에 대해서만 적용됩니다. 상세히 862 - 말해서, 컨트롤 의존성은 if 문을 뒤따르는 코드에는 적용되지 않습니다: 863 - 864 - q = READ_ONCE(a); 865 - if (q) { 866 - WRITE_ONCE(b, 1); 867 - } else { 868 - WRITE_ONCE(b, 2); 869 - } 870 - WRITE_ONCE(c, 1); /* BUG: No ordering against the read from 'a'. */ 871 - 872 - 컴파일러는 volatile 타입에 대한 액세스를 재배치 할 수 없고 이 조건 하의 'b' 873 - 로의 쓰기를 재배치 할 수 없기 때문에 여기에 순서 규칙이 존재한다고 주장하고 874 - 싶을 겁니다. 불행히도 이 경우에, 컴파일러는 다음의 가상의 pseudo-assembly 언어 875 - 코드처럼 'b' 로의 두개의 쓰기 오퍼레이션을 conditional-move 인스트럭션으로 876 - 번역할 수 있습니다: 877 - 878 - ld r1,a 879 - cmp r1,$0 880 - cmov,ne r4,$1 881 - cmov,eq r4,$2 882 - st r4,b 883 - st $1,c 884 - 885 - 완화된 순서 규칙의 CPU 는 'a' 로부터의 로드와 'c' 로의 스토어 사이에 어떤 886 - 종류의 의존성도 갖지 않을 겁니다. 이 컨트롤 의존성은 두개의 cmov 인스트럭션과 887 - 거기에 의존하는 스토어 에게만 적용될 겁니다. 짧게 말하자면, 컨트롤 의존성은 888 - 주어진 if 문의 then 절과 else 절에게만 (그리고 이 두 절 내에서 호출되는 889 - 함수들에게까지) 적용되지, 이 if 문을 뒤따르는 코드에는 적용되지 않습니다. 890 - 891 - 892 - 컨트롤 의존성에 의해 제공되는 이 순서규칙은 이를 포함하고 있는 CPU 에 893 - 지역적입니다. 더 많은 정보를 위해선 "Multicopy 원자성" 섹션을 참고하세요. 894 - 895 - 896 - 요약하자면: 897 - 898 - (*) 컨트롤 의존성은 앞의 로드들을 뒤의 스토어들에 대해 순서를 맞춰줍니다. 899 - 하지만, 그 외의 어떤 순서도 보장하지 -않습니다-: 앞의 로드와 뒤의 로드들 900 - 사이에도, 앞의 스토어와 뒤의 스토어들 사이에도요. 이런 다른 형태의 901 - 순서가 필요하다면 smp_rmb() 나 smp_wmb()를, 또는, 앞의 스토어들과 뒤의 902 - 로드들 사이의 순서를 위해서는 smp_mb() 를 사용하세요. 903 - 904 - (*) "if" 문의 양갈래 브랜치가 같은 변수에의 동일한 스토어로 시작한다면, 그 905 - 스토어들은 각 스토어 앞에 smp_mb() 를 넣거나 smp_store_release() 를 906 - 사용해서 스토어를 하는 식으로 순서를 맞춰줘야 합니다. 이 문제를 해결하기 907 - 위해 "if" 문의 양갈래 브랜치의 시작 지점에 barrier() 를 넣는 것만으로는 908 - 충분한 해결이 되지 않는데, 이는 앞의 예에서 본것과 같이, 컴파일러의 909 - 최적화는 barrier() 가 의미하는 바를 지키면서도 컨트롤 의존성을 손상시킬 910 - 수 있기 때문이라는 점을 부디 알아두시기 바랍니다. 911 - 912 - (*) 컨트롤 의존성은 앞의 로드와 뒤의 스토어 사이에 최소 하나의, 실행 913 - 시점에서의 조건관계를 필요로 하며, 이 조건관계는 앞의 로드와 관계되어야 914 - 합니다. 만약 컴파일러가 조건 관계를 최적화로 없앨수 있다면, 순서도 915 - 최적화로 없애버렸을 겁니다. READ_ONCE() 와 WRITE_ONCE() 의 주의 깊은 916 - 사용은 주어진 조건 관계를 유지하는데 도움이 될 수 있습니다. 917 - 918 - (*) 컨트롤 의존성을 위해선 컴파일러가 조건관계를 없애버리는 것을 막아야 919 - 합니다. 주의 깊은 READ_ONCE() 나 atomic{,64}_read() 의 사용이 컨트롤 920 - 의존성이 사라지지 않게 하는데 도움을 줄 수 있습니다. 더 많은 정보를 921 - 위해선 "컴파일러 배리어" 섹션을 참고하시기 바랍니다. 922 - 923 - (*) 컨트롤 의존성은 컨트롤 의존성을 갖는 if 문의 then 절과 else 절과 이 두 절 924 - 내에서 호출되는 함수들에만 적용됩니다. 컨트롤 의존성은 컨트롤 의존성을 925 - 갖는 if 문을 뒤따르는 코드에는 적용되지 -않습니다-. 926 - 927 - (*) 컨트롤 의존성은 보통 다른 타입의 배리어들과 짝을 맞춰 사용됩니다. 928 - 929 - (*) 컨트롤 의존성은 multicopy 원자성을 제공하지 -않습니다-. 모든 CPU 들이 930 - 특정 스토어를 동시에 보길 원한다면, smp_mb() 를 사용하세요. 931 - 932 - (*) 컴파일러는 컨트롤 의존성을 이해하고 있지 않습니다. 따라서 컴파일러가 933 - 여러분의 코드를 망가뜨리지 않도록 하는건 여러분이 해야 하는 일입니다. 934 - 935 - 936 - SMP 배리어 짝맞추기 937 - -------------------- 938 - 939 - CPU 간 상호작용을 다룰 때에 일부 타입의 메모리 배리어는 항상 짝을 맞춰 940 - 사용되어야 합니다. 적절하게 짝을 맞추지 않은 코드는 사실상 에러에 가깝습니다. 941 - 942 - 범용 배리어들은 범용 배리어끼리도 짝을 맞추지만 multicopy 원자성이 없는 943 - 대부분의 다른 타입의 배리어들과도 짝을 맞춥니다. ACQUIRE 배리어는 RELEASE 944 - 배리어와 짝을 맞춥니다만, 둘 다 범용 배리어를 포함해 다른 배리어들과도 짝을 945 - 맞출 수 있습니다. 쓰기 배리어는 주소 의존성 배리어나 컨트롤 의존성, ACQUIRE 946 - 배리어, RELEASE 배리어, 읽기 배리어, 또는 범용 배리어와 짝을 맞춥니다. 947 - 비슷하게 읽기 배리어나 컨트롤 의존성, 또는 주소 의존성 배리어는 쓰기 배리어나 948 - ACQUIRE 배리어, RELEASE 배리어, 또는 범용 배리어와 짝을 맞추는데, 다음과 949 - 같습니다: 950 - 951 - CPU 1 CPU 2 952 - =============== =============== 953 - WRITE_ONCE(a, 1); 954 - <쓰기 배리어> 955 - WRITE_ONCE(b, 2); x = READ_ONCE(b); 956 - <읽기 배리어> 957 - y = READ_ONCE(a); 958 - 959 - 또는: 960 - 961 - CPU 1 CPU 2 962 - =============== =============================== 963 - a = 1; 964 - <쓰기 배리어> 965 - WRITE_ONCE(b, &a); x = READ_ONCE(b); 966 - <묵시적 주소 의존성 배리어> 967 - y = *x; 968 - 969 - 또는: 970 - 971 - CPU 1 CPU 2 972 - =============== =============================== 973 - r1 = READ_ONCE(y); 974 - <범용 배리어> 975 - WRITE_ONCE(x, 1); if (r2 = READ_ONCE(x)) { 976 - <묵시적 컨트롤 의존성> 977 - WRITE_ONCE(y, 1); 978 - } 979 - 980 - assert(r1 == 0 || r2 == 0); 981 - 982 - 기본적으로, 여기서의 읽기 배리어는 "더 완화된" 타입일 순 있어도 항상 존재해야 983 - 합니다. 984 - 985 - [!] 쓰기 배리어 앞의 스토어 오퍼레이션은 일반적으로 읽기 배리어나 주소 의존성 986 - 배리어 뒤의 로드 오퍼레이션과 매치될 것이고, 반대도 마찬가지입니다: 987 - 988 - CPU 1 CPU 2 989 - =================== =================== 990 - WRITE_ONCE(a, 1); }---- --->{ v = READ_ONCE(c); 991 - WRITE_ONCE(b, 2); } \ / { w = READ_ONCE(d); 992 - <쓰기 배리어> \ <읽기 배리어> 993 - WRITE_ONCE(c, 3); } / \ { x = READ_ONCE(a); 994 - WRITE_ONCE(d, 4); }---- --->{ y = READ_ONCE(b); 995 - 996 - 997 - 메모리 배리어 시퀀스의 예 998 - ------------------------- 999 - 1000 - 첫째, 쓰기 배리어는 스토어 오퍼레이션들의 부분적 순서 세우기로 동작합니다. 1001 - 아래의 이벤트 시퀀스를 보세요: 1002 - 1003 - CPU 1 1004 - ======================= 1005 - STORE A = 1 1006 - STORE B = 2 1007 - STORE C = 3 1008 - <쓰기 배리어> 1009 - STORE D = 4 1010 - STORE E = 5 1011 - 1012 - 이 이벤트 시퀀스는 메모리 일관성 시스템에 원소끼리의 순서가 존재하지 않는 집합 1013 - { STORE A, STORE B, STORE C } 가 역시 원소끼리의 순서가 존재하지 않는 집합 1014 - { STORE D, STORE E } 보다 먼저 일어난 것으로 시스템의 나머지 요소들에 보이도록 1015 - 전달됩니다: 1016 - 1017 - +-------+ : : 1018 - | | +------+ 1019 - | |------>| C=3 | } /\ 1020 - | | : +------+ }----- \ -----> 시스템의 나머지 요소에 1021 - | | : | A=1 | } \/ 보여질 수 있는 이벤트들 1022 - | | : +------+ } 1023 - | CPU 1 | : | B=2 | } 1024 - | | +------+ } 1025 - | | wwwwwwwwwwwwwwww } <--- 여기서 쓰기 배리어는 배리어 앞의 1026 - | | +------+ } 모든 스토어가 배리어 뒤의 스토어 1027 - | | : | E=5 | } 전에 메모리 시스템에 전달되도록 1028 - | | : +------+ } 합니다 1029 - | |------>| D=4 | } 1030 - | | +------+ 1031 - +-------+ : : 1032 - | 1033 - | CPU 1 에 의해 메모리 시스템에 전달되는 1034 - | 일련의 스토어 오퍼레이션들 1035 - V 1036 - 1037 - 1038 - 둘째, 주소 의존성 배리어는 데이터 의존적 로드 오퍼레이션들의 부분적 순서 1039 - 세우기로 동작합니다. 다음 일련의 이벤트들을 보세요: 1040 - 1041 - CPU 1 CPU 2 1042 - ======================= ======================= 1043 - { B = 7; X = 9; Y = 8; C = &Y } 1044 - STORE A = 1 1045 - STORE B = 2 1046 - <쓰기 배리어> 1047 - STORE C = &B LOAD X 1048 - STORE D = 4 LOAD C (gets &B) 1049 - LOAD *C (reads B) 1050 - 1051 - 여기에 별다른 개입이 없다면, CPU 1 의 쓰기 배리어에도 불구하고 CPU 2 는 CPU 1 1052 - 의 이벤트들을 완전히 무작위적 순서로 인지하게 됩니다: 1053 - 1054 - +-------+ : : : : 1055 - | | +------+ +-------+ | CPU 2 에 인지되는 1056 - | |------>| B=2 |----- --->| Y->8 | | 업데이트 이벤트 1057 - | | : +------+ \ +-------+ | 시퀀스 1058 - | CPU 1 | : | A=1 | \ --->| C->&Y | V 1059 - | | +------+ | +-------+ 1060 - | | wwwwwwwwwwwwwwww | : : 1061 - | | +------+ | : : 1062 - | | : | C=&B |--- | : : +-------+ 1063 - | | : +------+ \ | +-------+ | | 1064 - | |------>| D=4 | ----------->| C->&B |------>| | 1065 - | | +------+ | +-------+ | | 1066 - +-------+ : : | : : | | 1067 - | : : | | 1068 - | : : | CPU 2 | 1069 - | +-------+ | | 1070 - 분명히 잘못된 ---> | | B->7 |------>| | 1071 - B 의 값 인지 (!) | +-------+ | | 1072 - | : : | | 1073 - | +-------+ | | 1074 - X 의 로드가 B 의 ---> \ | X->9 |------>| | 1075 - 일관성 유지를 \ +-------+ | | 1076 - 지연시킴 ----->| B->2 | +-------+ 1077 - +-------+ 1078 - : : 1079 - 1080 - 1081 - 앞의 예에서, CPU 2 는 (B 의 값이 될) *C 의 값 읽기가 C 의 LOAD 뒤에 이어짐에도 1082 - B 가 7 이라는 결과를 얻습니다. 1083 - 1084 - 하지만, 만약 주소 의존성 배리어가 C 의 로드와 *C (즉, B) 의 로드 사이에 1085 - 있었다면: 1086 - 1087 - CPU 1 CPU 2 1088 - ======================= ======================= 1089 - { B = 7; X = 9; Y = 8; C = &Y } 1090 - STORE A = 1 1091 - STORE B = 2 1092 - <쓰기 배리어> 1093 - STORE C = &B LOAD X 1094 - STORE D = 4 LOAD C (gets &B) 1095 - <주소 의존성 배리어> 1096 - LOAD *C (reads B) 1097 - 1098 - 다음과 같이 됩니다: 1099 - 1100 - +-------+ : : : : 1101 - | | +------+ +-------+ 1102 - | |------>| B=2 |----- --->| Y->8 | 1103 - | | : +------+ \ +-------+ 1104 - | CPU 1 | : | A=1 | \ --->| C->&Y | 1105 - | | +------+ | +-------+ 1106 - | | wwwwwwwwwwwwwwww | : : 1107 - | | +------+ | : : 1108 - | | : | C=&B |--- | : : +-------+ 1109 - | | : +------+ \ | +-------+ | | 1110 - | |------>| D=4 | ----------->| C->&B |------>| | 1111 - | | +------+ | +-------+ | | 1112 - +-------+ : : | : : | | 1113 - | : : | | 1114 - | : : | CPU 2 | 1115 - | +-------+ | | 1116 - | | X->9 |------>| | 1117 - | +-------+ | | 1118 - C 로의 스토어 앞의 ---> \ aaaaaaaaaaaaaaaaa | | 1119 - 모든 이벤트 결과가 \ +-------+ | | 1120 - 뒤의 로드에게 ----->| B->2 |------>| | 1121 - 보이게 강제한다 +-------+ | | 1122 - : : +-------+ 1123 - 1124 - 1125 - 셋째, 읽기 배리어는 로드 오퍼레이션들에의 부분적 순서 세우기로 동작합니다. 1126 - 아래의 일련의 이벤트를 봅시다: 1127 - 1128 - CPU 1 CPU 2 1129 - ======================= ======================= 1130 - { A = 0, B = 9 } 1131 - STORE A=1 1132 - <쓰기 배리어> 1133 - STORE B=2 1134 - LOAD B 1135 - LOAD A 1136 - 1137 - CPU 1 은 쓰기 배리어를 쳤지만, 별다른 개입이 없다면 CPU 2 는 CPU 1 에서 행해진 1138 - 이벤트의 결과를 무작위적 순서로 인지하게 됩니다. 1139 - 1140 - +-------+ : : : : 1141 - | | +------+ +-------+ 1142 - | |------>| A=1 |------ --->| A->0 | 1143 - | | +------+ \ +-------+ 1144 - | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 | 1145 - | | +------+ | +-------+ 1146 - | |------>| B=2 |--- | : : 1147 - | | +------+ \ | : : +-------+ 1148 - +-------+ : : \ | +-------+ | | 1149 - ---------->| B->2 |------>| | 1150 - | +-------+ | CPU 2 | 1151 - | | A->0 |------>| | 1152 - | +-------+ | | 1153 - | : : +-------+ 1154 - \ : : 1155 - \ +-------+ 1156 - ---->| A->1 | 1157 - +-------+ 1158 - : : 1159 - 1160 - 1161 - 하지만, 만약 읽기 배리어가 B 의 로드와 A 의 로드 사이에 존재한다면: 1162 - 1163 - CPU 1 CPU 2 1164 - ======================= ======================= 1165 - { A = 0, B = 9 } 1166 - STORE A=1 1167 - <쓰기 배리어> 1168 - STORE B=2 1169 - LOAD B 1170 - <읽기 배리어> 1171 - LOAD A 1172 - 1173 - CPU 1 에 의해 만들어진 부분적 순서가 CPU 2 에도 그대로 인지됩니다: 1174 - 1175 - +-------+ : : : : 1176 - | | +------+ +-------+ 1177 - | |------>| A=1 |------ --->| A->0 | 1178 - | | +------+ \ +-------+ 1179 - | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 | 1180 - | | +------+ | +-------+ 1181 - | |------>| B=2 |--- | : : 1182 - | | +------+ \ | : : +-------+ 1183 - +-------+ : : \ | +-------+ | | 1184 - ---------->| B->2 |------>| | 1185 - | +-------+ | CPU 2 | 1186 - | : : | | 1187 - | : : | | 1188 - 여기서 읽기 배리어는 ----> \ rrrrrrrrrrrrrrrrr | | 1189 - B 로의 스토어 전의 \ +-------+ | | 1190 - 모든 결과를 CPU 2 에 ---->| A->1 |------>| | 1191 - 보이도록 한다 +-------+ | | 1192 - : : +-------+ 1193 - 1194 - 1195 - 더 완벽한 설명을 위해, A 의 로드가 읽기 배리어 앞과 뒤에 있으면 어떻게 될지 1196 - 생각해 봅시다: 1197 - 1198 - CPU 1 CPU 2 1199 - ======================= ======================= 1200 - { A = 0, B = 9 } 1201 - STORE A=1 1202 - <쓰기 배리어> 1203 - STORE B=2 1204 - LOAD B 1205 - LOAD A [first load of A] 1206 - <읽기 배리어> 1207 - LOAD A [second load of A] 1208 - 1209 - A 의 로드 두개가 모두 B 의 로드 뒤에 있지만, 서로 다른 값을 얻어올 수 1210 - 있습니다: 1211 - 1212 - +-------+ : : : : 1213 - | | +------+ +-------+ 1214 - | |------>| A=1 |------ --->| A->0 | 1215 - | | +------+ \ +-------+ 1216 - | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 | 1217 - | | +------+ | +-------+ 1218 - | |------>| B=2 |--- | : : 1219 - | | +------+ \ | : : +-------+ 1220 - +-------+ : : \ | +-------+ | | 1221 - ---------->| B->2 |------>| | 1222 - | +-------+ | CPU 2 | 1223 - | : : | | 1224 - | : : | | 1225 - | +-------+ | | 1226 - | | A->0 |------>| 1st | 1227 - | +-------+ | | 1228 - 여기서 읽기 배리어는 ----> \ rrrrrrrrrrrrrrrrr | | 1229 - B 로의 스토어 전의 \ +-------+ | | 1230 - 모든 결과를 CPU 2 에 ---->| A->1 |------>| 2nd | 1231 - 보이도록 한다 +-------+ | | 1232 - : : +-------+ 1233 - 1234 - 1235 - 하지만 CPU 1 에서의 A 업데이트는 읽기 배리어가 완료되기 전에도 보일 수도 1236 - 있긴 합니다: 1237 - 1238 - +-------+ : : : : 1239 - | | +------+ +-------+ 1240 - | |------>| A=1 |------ --->| A->0 | 1241 - | | +------+ \ +-------+ 1242 - | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 | 1243 - | | +------+ | +-------+ 1244 - | |------>| B=2 |--- | : : 1245 - | | +------+ \ | : : +-------+ 1246 - +-------+ : : \ | +-------+ | | 1247 - ---------->| B->2 |------>| | 1248 - | +-------+ | CPU 2 | 1249 - | : : | | 1250 - \ : : | | 1251 - \ +-------+ | | 1252 - ---->| A->1 |------>| 1st | 1253 - +-------+ | | 1254 - rrrrrrrrrrrrrrrrr | | 1255 - +-------+ | | 1256 - | A->1 |------>| 2nd | 1257 - +-------+ | | 1258 - : : +-------+ 1259 - 1260 - 1261 - 여기서 보장되는 건, 만약 B 의 로드가 B == 2 라는 결과를 봤다면, A 에의 두번째 1262 - 로드는 항상 A == 1 을 보게 될 것이라는 겁니다. A 에의 첫번째 로드에는 그런 1263 - 보장이 없습니다; A == 0 이거나 A == 1 이거나 둘 중 하나의 결과를 보게 될겁니다. 1264 - 1265 - 1266 - 읽기 메모리 배리어 VS 로드 예측 1267 - ------------------------------- 1268 - 1269 - 많은 CPU들이 로드를 예측적으로 (speculatively) 합니다: 어떤 데이터를 메모리에서 1270 - 로드해야 하게 될지 예측을 했다면, 해당 데이터를 로드하는 인스트럭션을 실제로는 1271 - 아직 만나지 않았더라도 다른 로드 작업이 없어 버스 (bus) 가 아무 일도 하고 있지 1272 - 않다면, 그 데이터를 로드합니다. 이후에 실제 로드 인스트럭션이 실행되면 CPU 가 1273 - 이미 그 값을 가지고 있기 때문에 그 로드 인스트럭션은 즉시 완료됩니다. 1274 - 1275 - 해당 CPU 는 실제로는 그 값이 필요치 않았다는 사실이 나중에 드러날 수도 있는데 - 1276 - 해당 로드 인스트럭션이 브랜치로 우회되거나 했을 수 있겠죠 - , 그렇게 되면 앞서 1277 - 읽어둔 값을 버리거나 나중의 사용을 위해 캐시에 넣어둘 수 있습니다. 1278 - 1279 - 다음을 생각해 봅시다: 1280 - 1281 - CPU 1 CPU 2 1282 - ======================= ======================= 1283 - LOAD B 1284 - DIVIDE } 나누기 명령은 일반적으로 1285 - DIVIDE } 긴 시간을 필요로 합니다 1286 - LOAD A 1287 - 1288 - 는 이렇게 될 수 있습니다: 1289 - 1290 - : : +-------+ 1291 - +-------+ | | 1292 - --->| B->2 |------>| | 1293 - +-------+ | CPU 2 | 1294 - : :DIVIDE | | 1295 - +-------+ | | 1296 - 나누기 하느라 바쁜 ---> --->| A->0 |~~~~ | | 1297 - CPU 는 A 의 LOAD 를 +-------+ ~ | | 1298 - 예측해서 수행한다 : : ~ | | 1299 - : :DIVIDE | | 1300 - : : ~ | | 1301 - 나누기가 끝나면 ---> ---> : : ~-->| | 1302 - CPU 는 해당 LOAD 를 : : | | 1303 - 즉각 완료한다 : : +-------+ 1304 - 1305 - 1306 - 읽기 배리어나 주소 의존성 배리어를 두번째 로드 직전에 놓는다면: 1307 - 1308 - CPU 1 CPU 2 1309 - ======================= ======================= 1310 - LOAD B 1311 - DIVIDE 1312 - DIVIDE 1313 - <읽기 배리어> 1314 - LOAD A 1315 - 1316 - 예측으로 얻어진 값은 사용된 배리어의 타입에 따라서 해당 값이 옳은지 검토되게 1317 - 됩니다. 만약 해당 메모리 영역에 변화가 없었다면, 예측으로 얻어두었던 값이 1318 - 사용됩니다: 1319 - 1320 - : : +-------+ 1321 - +-------+ | | 1322 - --->| B->2 |------>| | 1323 - +-------+ | CPU 2 | 1324 - : :DIVIDE | | 1325 - +-------+ | | 1326 - 나누기 하느라 바쁜 ---> --->| A->0 |~~~~ | | 1327 - CPU 는 A 의 LOAD 를 +-------+ ~ | | 1328 - 예측한다 : : ~ | | 1329 - : :DIVIDE | | 1330 - : : ~ | | 1331 - : : ~ | | 1332 - rrrrrrrrrrrrrrrr~ | | 1333 - : : ~ | | 1334 - : : ~-->| | 1335 - : : | | 1336 - : : +-------+ 1337 - 1338 - 1339 - 하지만 다른 CPU 에서 업데이트나 무효화가 있었다면, 그 예측은 무효화되고 그 값은 1340 - 다시 읽혀집니다: 1341 - 1342 - : : +-------+ 1343 - +-------+ | | 1344 - --->| B->2 |------>| | 1345 - +-------+ | CPU 2 | 1346 - : :DIVIDE | | 1347 - +-------+ | | 1348 - 나누기 하느라 바쁜 ---> --->| A->0 |~~~~ | | 1349 - CPU 는 A 의 LOAD 를 +-------+ ~ | | 1350 - 예측한다 : : ~ | | 1351 - : :DIVIDE | | 1352 - : : ~ | | 1353 - : : ~ | | 1354 - rrrrrrrrrrrrrrrrr | | 1355 - +-------+ | | 1356 - 예측성 동작은 무효화 되고 ---> --->| A->1 |------>| | 1357 - 업데이트된 값이 다시 읽혀진다 +-------+ | | 1358 - : : +-------+ 1359 - 1360 - 1361 - MULTICOPY 원자성 1362 - ---------------- 1363 - 1364 - Multicopy 원자성은 실제의 컴퓨터 시스템에서 항상 제공되지는 않는, 순서 맞추기에 1365 - 대한 상당히 직관적인 개념으로, 특정 스토어가 모든 CPU 들에게 동시에 보여지게 1366 - 됨을, 달리 말하자면 모든 CPU 들이 모든 스토어들이 보여지는 순서를 동의하게 되는 1367 - 것입니다. 하지만, 완전한 multicopy 원자성의 사용은 가치있는 하드웨어 1368 - 최적화들을 무능하게 만들어버릴 수 있어서, 보다 완화된 형태의 ``다른 multicopy 1369 - 원자성'' 라는 이름의, 특정 스토어가 모든 -다른- CPU 들에게는 동시에 보여지게 1370 - 하는 보장을 대신 제공합니다. 이 문서의 뒷부분들은 이 완화된 형태에 대해 논하게 1371 - 됩니다만, 단순히 ``multicopy 원자성'' 이라고 부르겠습니다. 1372 - 1373 - 다음의 예가 multicopy 원자성을 보입니다: 1374 - 1375 - CPU 1 CPU 2 CPU 3 1376 - ======================= ======================= ======================= 1377 - { X = 0, Y = 0 } 1378 - STORE X=1 r1=LOAD X (reads 1) LOAD Y (reads 1) 1379 - <범용 배리어> <읽기 배리어> 1380 - STORE Y=r1 LOAD X 1381 - 1382 - CPU 2 의 Y 로의 스토어에 사용되는 X 로드의 결과가 1 이었고 CPU 3 의 Y 로드가 1383 - 1을 리턴했다고 해봅시다. 이는 CPU 1 의 X 로의 스토어가 CPU 2 의 X 로부터의 1384 - 로드를 앞서고 CPU 2 의 Y 로의 스토어가 CPU 3 의 Y 로부터의 로드를 앞섬을 1385 - 의미합니다. 또한, 여기서의 메모리 배리어들은 CPU 2 가 자신의 로드를 자신의 1386 - 스토어 전에 수행하고, CPU 3 가 Y 로부터의 로드를 X 로부터의 로드 전에 수행함을 1387 - 보장합니다. 그럼 "CPU 3 의 X 로부터의 로드는 0 을 리턴할 수 있을까요?" 1388 - 1389 - CPU 3 의 X 로드가 CPU 2 의 로드보다 뒤에 이루어졌으므로, CPU 3 의 X 로부터의 1390 - 로드는 1 을 리턴한다고 예상하는게 당연합니다. 이런 예상은 multicopy 1391 - 원자성으로부터 나옵니다: CPU B 에서 수행된 로드가 CPU A 의 같은 변수로부터의 1392 - 로드를 뒤따른다면 (그리고 CPU A 가 자신이 읽은 값으로 먼저 해당 변수에 스토어 1393 - 하지 않았다면) multicopy 원자성을 제공하는 시스템에서는, CPU B 의 로드가 CPU A 1394 - 의 로드와 같은 값 또는 그 나중 값을 리턴해야만 합니다. 하지만, 리눅스 커널은 1395 - 시스템들이 multicopy 원자성을 제공할 것을 요구하지 않습니다. 1396 - 1397 - 앞의 범용 메모리 배리어의 사용은 모든 multicopy 원자성의 부족을 보상해줍니다. 1398 - 앞의 예에서, CPU 2 의 X 로부터의 로드가 1 을 리턴했고 CPU 3 의 Y 로부터의 1399 - 로드가 1 을 리턴했다면, CPU 3 의 X 로부터의 로드는 1을 리턴해야만 합니다. 1400 - 1401 - 하지만, 의존성, 읽기 배리어, 쓰기 배리어는 항상 non-multicopy 원자성을 보상해 1402 - 주지는 않습니다. 예를 들어, CPU 2 의 범용 배리어가 앞의 예에서 사라져서 1403 - 아래처럼 데이터 의존성만 남게 되었다고 해봅시다: 1404 - 1405 - CPU 1 CPU 2 CPU 3 1406 - ======================= ======================= ======================= 1407 - { X = 0, Y = 0 } 1408 - STORE X=1 r1=LOAD X (reads 1) LOAD Y (reads 1) 1409 - <데이터 의존성> <읽기 배리어> 1410 - STORE Y=r1 LOAD X (reads 0) 1411 - 1412 - 이 변화는 non-multicopy 원자성이 만연하게 합니다: 이 예에서, CPU 2 의 X 1413 - 로부터의 로드가 1을 리턴하고, CPU 3 의 Y 로부터의 로드가 1 을 리턴하는데, CPU 3 1414 - 의 X 로부터의 로드가 0 을 리턴하는게 완전히 합법적입니다. 1415 - 1416 - 핵심은, CPU 2 의 데이터 의존성이 자신의 로드와 스토어를 순서짓지만, CPU 1 의 1417 - 스토어에 대한 순서는 보장하지 않는다는 것입니다. 따라서, 이 예제가 CPU 1 과 1418 - CPU 2 가 스토어 버퍼나 한 수준의 캐시를 공유하는, multicopy 원자성을 제공하지 1419 - 않는 시스템에서 수행된다면 CPU 2 는 CPU 1 의 쓰기에 이른 접근을 할 수도 1420 - 있습니다. 따라서, 모든 CPU 들이 여러 접근들의 조합된 순서에 대해서 동의하게 1421 - 하기 위해서는 범용 배리어가 필요합니다. 1422 - 1423 - 범용 배리어는 non-multicopy 원자성만 보상할 수 있는게 아니라, -모든- CPU 들이 1424 - -모든- 오퍼레이션들의 순서를 동일하게 인식하게 하는 추가적인 순서 보장을 1425 - 만들어냅니다. 반대로, release-acquire 짝의 연결은 이런 추가적인 순서는 1426 - 제공하지 않는데, 해당 연결에 들어있는 CPU 들만이 메모리 접근의 조합된 순서에 1427 - 대해 동의할 것으로 보장됨을 의미합니다. 예를 들어, 존경스런 Herman Hollerith 1428 - 의 코드를 C 코드로 변환하면: 1429 - 1430 - int u, v, x, y, z; 1431 - 1432 - void cpu0(void) 1433 - { 1434 - r0 = smp_load_acquire(&x); 1435 - WRITE_ONCE(u, 1); 1436 - smp_store_release(&y, 1); 1437 - } 1438 - 1439 - void cpu1(void) 1440 - { 1441 - r1 = smp_load_acquire(&y); 1442 - r4 = READ_ONCE(v); 1443 - r5 = READ_ONCE(u); 1444 - smp_store_release(&z, 1); 1445 - } 1446 - 1447 - void cpu2(void) 1448 - { 1449 - r2 = smp_load_acquire(&z); 1450 - smp_store_release(&x, 1); 1451 - } 1452 - 1453 - void cpu3(void) 1454 - { 1455 - WRITE_ONCE(v, 1); 1456 - smp_mb(); 1457 - r3 = READ_ONCE(u); 1458 - } 1459 - 1460 - cpu0(), cpu1(), 그리고 cpu2() 는 smp_store_release()/smp_load_acquire() 쌍의 1461 - 연결에 참여되어 있으므로, 다음과 같은 결과는 나오지 않을 겁니다: 1462 - 1463 - r0 == 1 && r1 == 1 && r2 == 1 1464 - 1465 - 더 나아가서, cpu0() 와 cpu1() 사이의 release-acquire 관계로 인해, cpu1() 은 1466 - cpu0() 의 쓰기를 봐야만 하므로, 다음과 같은 결과도 없을 겁니다: 1467 - 1468 - r1 == 1 && r5 == 0 1469 - 1470 - 하지만, release-acquire 에 의해 제공되는 순서는 해당 연결에 동참한 CPU 들에만 1471 - 적용되므로 cpu3() 에, 적어도 스토어들 외에는 적용되지 않습니다. 따라서, 다음과 1472 - 같은 결과가 가능합니다: 1473 - 1474 - r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0 1475 - 1476 - 비슷하게, 다음과 같은 결과도 가능합니다: 1477 - 1478 - r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0 && r5 == 1 1479 - 1480 - cpu0(), cpu1(), 그리고 cpu2() 는 그들의 읽기와 쓰기를 순서대로 보게 되지만, 1481 - release-acquire 체인에 관여되지 않은 CPU 들은 그 순서에 이견을 가질 수 1482 - 있습니다. 이런 이견은 smp_load_acquire() 와 smp_store_release() 의 구현에 1483 - 사용되는 완화된 메모리 배리어 인스트럭션들은 항상 배리어 앞의 스토어들을 뒤의 1484 - 로드들에 앞세울 필요는 없다는 사실에서 기인합니다. 이 말은 cpu3() 는 cpu0() 의 1485 - u 로의 스토어를 cpu1() 의 v 로부터의 로드 뒤에 일어난 것으로 볼 수 있다는 1486 - 뜻입니다, cpu0() 와 cpu1() 은 이 두 오퍼레이션이 의도된 순서대로 일어났음에 1487 - 모두 동의하는데도 말입니다. 1488 - 1489 - 하지만, smp_load_acquire() 는 마술이 아님을 명심하시기 바랍니다. 구체적으로, 1490 - 이 함수는 단순히 순서 규칙을 지키며 인자로부터의 읽기를 수행합니다. 이것은 1491 - 어떤 특정한 값이 읽힐 것인지는 보장하지 -않습니다-. 따라서, 다음과 같은 결과도 1492 - 가능합니다: 1493 - 1494 - r0 == 0 && r1 == 0 && r2 == 0 && r5 == 0 1495 - 1496 - 이런 결과는 어떤 것도 재배치 되지 않는, 순차적 일관성을 가진 가상의 1497 - 시스템에서도 일어날 수 있음을 기억해 두시기 바랍니다. 1498 - 1499 - 다시 말하지만, 당신의 코드가 모든 오퍼레이션들의 완전한 순서를 필요로 한다면, 1500 - 범용 배리어를 사용하십시오. 1501 - 1502 - 1503 - ================== 1504 - 명시적 커널 배리어 1505 - ================== 1506 - 1507 - 리눅스 커널은 서로 다른 단계에서 동작하는 다양한 배리어들을 가지고 있습니다: 1508 - 1509 - (*) 컴파일러 배리어. 1510 - 1511 - (*) CPU 메모리 배리어. 1512 - 1513 - 1514 - 컴파일러 배리어 1515 - --------------- 1516 - 1517 - 리눅스 커널은 컴파일러가 메모리 액세스를 재배치 하는 것을 막아주는 명시적인 1518 - 컴파일러 배리어를 가지고 있습니다: 1519 - 1520 - barrier(); 1521 - 1522 - 이건 범용 배리어입니다 -- barrier() 의 읽기-읽기 나 쓰기-쓰기 변종은 없습니다. 1523 - 하지만, READ_ONCE() 와 WRITE_ONCE() 는 특정 액세스들에 대해서만 동작하는 1524 - barrier() 의 완화된 형태로 볼 수 있습니다. 1525 - 1526 - barrier() 함수는 다음과 같은 효과를 갖습니다: 1527 - 1528 - (*) 컴파일러가 barrier() 뒤의 액세스들이 barrier() 앞의 액세스보다 앞으로 1529 - 재배치되지 못하게 합니다. 예를 들어, 인터럽트 핸들러 코드와 인터럽트 당한 1530 - 코드 사이의 통신을 신중히 하기 위해 사용될 수 있습니다. 1531 - 1532 - (*) 루프에서, 컴파일러가 루프 조건에 사용된 변수를 매 이터레이션마다 1533 - 메모리에서 로드하지 않아도 되도록 최적화 하는걸 방지합니다. 1534 - 1535 - READ_ONCE() 와 WRITE_ONCE() 함수는 싱글 쓰레드 코드에서는 문제 없지만 동시성이 1536 - 있는 코드에서는 문제가 될 수 있는 모든 최적화를 막습니다. 이런 류의 최적화에 1537 - 대한 예를 몇가지 들어보면 다음과 같습니다: 1538 - 1539 - (*) 컴파일러는 같은 변수에 대한 로드와 스토어를 재배치 할 수 있고, 어떤 1540 - 경우에는 CPU가 같은 변수로부터의 로드들을 재배치할 수도 있습니다. 이는 1541 - 다음의 코드가: 1542 - 1543 - a[0] = x; 1544 - a[1] = x; 1545 - 1546 - x 의 예전 값이 a[1] 에, 새 값이 a[0] 에 있게 할 수 있다는 뜻입니다. 1547 - 컴파일러와 CPU가 이런 일을 못하게 하려면 다음과 같이 해야 합니다: 1548 - 1549 - a[0] = READ_ONCE(x); 1550 - a[1] = READ_ONCE(x); 1551 - 1552 - 즉, READ_ONCE() 와 WRITE_ONCE() 는 여러 CPU 에서 하나의 변수에 가해지는 1553 - 액세스들에 캐시 일관성을 제공합니다. 1554 - 1555 - (*) 컴파일러는 같은 변수에 대한 연속적인 로드들을 병합할 수 있습니다. 그런 1556 - 병합 작업으로 컴파일러는 다음의 코드를: 1557 - 1558 - while (tmp = a) 1559 - do_something_with(tmp); 1560 - 1561 - 다음과 같이, 싱글 쓰레드 코드에서는 말이 되지만 개발자의 의도와 전혀 맞지 1562 - 않는 방향으로 "최적화" 할 수 있습니다: 1563 - 1564 - if (tmp = a) 1565 - for (;;) 1566 - do_something_with(tmp); 1567 - 1568 - 컴파일러가 이런 짓을 하지 못하게 하려면 READ_ONCE() 를 사용하세요: 1569 - 1570 - while (tmp = READ_ONCE(a)) 1571 - do_something_with(tmp); 1572 - 1573 - (*) 예컨대 레지스터 사용량이 많아 컴파일러가 모든 데이터를 레지스터에 담을 수 1574 - 없는 경우, 컴파일러는 변수를 다시 로드할 수 있습니다. 따라서 컴파일러는 1575 - 앞의 예에서 변수 'tmp' 사용을 최적화로 없애버릴 수 있습니다: 1576 - 1577 - while (tmp = a) 1578 - do_something_with(tmp); 1579 - 1580 - 이 코드는 다음과 같이 싱글 쓰레드에서는 완벽하지만 동시성이 존재하는 1581 - 경우엔 치명적인 코드로 바뀔 수 있습니다: 1582 - 1583 - while (a) 1584 - do_something_with(a); 1585 - 1586 - 예를 들어, 최적화된 이 코드는 변수 a 가 다른 CPU 에 의해 "while" 문과 1587 - do_something_with() 호출 사이에 바뀌어 do_something_with() 에 0을 넘길 1588 - 수도 있습니다. 1589 - 1590 - 이번에도, 컴파일러가 그런 짓을 하는걸 막기 위해 READ_ONCE() 를 사용하세요: 1591 - 1592 - while (tmp = READ_ONCE(a)) 1593 - do_something_with(tmp); 1594 - 1595 - 레지스터가 부족한 상황을 겪는 경우, 컴파일러는 tmp 를 스택에 저장해둘 수도 1596 - 있습니다. 컴파일러가 변수를 다시 읽어들이는건 이렇게 저장해두고 후에 다시 1597 - 읽어들이는데 드는 오버헤드 때문입니다. 그렇게 하는게 싱글 쓰레드 1598 - 코드에서는 안전하므로, 안전하지 않은 경우에는 컴파일러에게 직접 알려줘야 1599 - 합니다. 1600 - 1601 - (*) 컴파일러는 그 값이 무엇일지 알고 있다면 로드를 아예 안할 수도 있습니다. 1602 - 예를 들어, 다음의 코드는 변수 'a' 의 값이 항상 0임을 증명할 수 있다면: 1603 - 1604 - while (tmp = a) 1605 - do_something_with(tmp); 1606 - 1607 - 이렇게 최적화 되어버릴 수 있습니다: 1608 - 1609 - do { } while (0); 1610 - 1611 - 이 변환은 싱글 쓰레드 코드에서는 도움이 되는데 로드와 브랜치를 제거했기 1612 - 때문입니다. 문제는 컴파일러가 'a' 의 값을 업데이트 하는건 현재의 CPU 하나 1613 - 뿐이라는 가정 위에서 증명을 했다는데 있습니다. 만약 변수 'a' 가 공유되어 1614 - 있다면, 컴파일러의 증명은 틀린 것이 될겁니다. 컴파일러는 그 자신이 1615 - 생각하는 것만큼 많은 것을 알고 있지 못함을 컴파일러에게 알리기 위해 1616 - READ_ONCE() 를 사용하세요: 1617 - 1618 - while (tmp = READ_ONCE(a)) 1619 - do_something_with(tmp); 1620 - 1621 - 하지만 컴파일러는 READ_ONCE() 뒤에 나오는 값에 대해서도 눈길을 두고 있음을 1622 - 기억하세요. 예를 들어, 다음의 코드에서 MAX 는 전처리기 매크로로, 1의 값을 1623 - 갖는다고 해봅시다: 1624 - 1625 - while ((tmp = READ_ONCE(a)) % MAX) 1626 - do_something_with(tmp); 1627 - 1628 - 이렇게 되면 컴파일러는 MAX 를 가지고 수행되는 "%" 오퍼레이터의 결과가 항상 1629 - 0이라는 것을 알게 되고, 컴파일러가 코드를 실질적으로는 존재하지 않는 1630 - 것처럼 최적화 하는 것이 허용되어 버립니다. ('a' 변수의 로드는 여전히 1631 - 행해질 겁니다.) 1632 - 1633 - (*) 비슷하게, 컴파일러는 변수가 저장하려 하는 값을 이미 가지고 있다는 것을 1634 - 알면 스토어 자체를 제거할 수 있습니다. 이번에도, 컴파일러는 현재의 CPU 1635 - 만이 그 변수에 값을 쓰는 오로지 하나의 존재라고 생각하여 공유된 변수에 1636 - 대해서는 잘못된 일을 하게 됩니다. 예를 들어, 다음과 같은 경우가 있을 수 1637 - 있습니다: 1638 - 1639 - a = 0; 1640 - ... 변수 a 에 스토어를 하지 않는 코드 ... 1641 - a = 0; 1642 - 1643 - 컴파일러는 변수 'a' 의 값은 이미 0이라는 것을 알고, 따라서 두번째 스토어를 1644 - 삭제할 겁니다. 만약 다른 CPU 가 그 사이 변수 'a' 에 다른 값을 썼다면 1645 - 황당한 결과가 나올 겁니다. 1646 - 1647 - 컴파일러가 그런 잘못된 추측을 하지 않도록 WRITE_ONCE() 를 사용하세요: 1648 - 1649 - WRITE_ONCE(a, 0); 1650 - ... 변수 a 에 스토어를 하지 않는 코드 ... 1651 - WRITE_ONCE(a, 0); 1652 - 1653 - (*) 컴파일러는 하지 말라고 하지 않으면 메모리 액세스들을 재배치 할 수 1654 - 있습니다. 예를 들어, 다음의 프로세스 레벨 코드와 인터럽트 핸들러 사이의 1655 - 상호작용을 생각해 봅시다: 1656 - 1657 - void process_level(void) 1658 - { 1659 - msg = get_message(); 1660 - flag = true; 1661 - } 1662 - 1663 - void interrupt_handler(void) 1664 - { 1665 - if (flag) 1666 - process_message(msg); 1667 - } 1668 - 1669 - 이 코드에는 컴파일러가 process_level() 을 다음과 같이 변환하는 것을 막을 1670 - 수단이 없고, 이런 변환은 싱글쓰레드에서라면 실제로 훌륭한 선택일 수 1671 - 있습니다: 1672 - 1673 - void process_level(void) 1674 - { 1675 - flag = true; 1676 - msg = get_message(); 1677 - } 1678 - 1679 - 이 두개의 문장 사이에 인터럽트가 발생한다면, interrupt_handler() 는 의미를 1680 - 알 수 없는 메세지를 받을 수도 있습니다. 이걸 막기 위해 다음과 같이 1681 - WRITE_ONCE() 를 사용하세요: 1682 - 1683 - void process_level(void) 1684 - { 1685 - WRITE_ONCE(msg, get_message()); 1686 - WRITE_ONCE(flag, true); 1687 - } 1688 - 1689 - void interrupt_handler(void) 1690 - { 1691 - if (READ_ONCE(flag)) 1692 - process_message(READ_ONCE(msg)); 1693 - } 1694 - 1695 - interrupt_handler() 안에서도 중첩된 인터럽트나 NMI 와 같이 인터럽트 핸들러 1696 - 역시 'flag' 와 'msg' 에 접근하는 또다른 무언가에 인터럽트 될 수 있다면 1697 - READ_ONCE() 와 WRITE_ONCE() 를 사용해야 함을 기억해 두세요. 만약 그런 1698 - 가능성이 없다면, interrupt_handler() 안에서는 문서화 목적이 아니라면 1699 - READ_ONCE() 와 WRITE_ONCE() 는 필요치 않습니다. (근래의 리눅스 커널에서 1700 - 중첩된 인터럽트는 보통 잘 일어나지 않음도 기억해 두세요, 실제로, 어떤 1701 - 인터럽트 핸들러가 인터럽트가 활성화된 채로 리턴하면 WARN_ONCE() 가 1702 - 실행됩니다.) 1703 - 1704 - 컴파일러는 READ_ONCE() 와 WRITE_ONCE() 뒤의 READ_ONCE() 나 WRITE_ONCE(), 1705 - barrier(), 또는 비슷한 것들을 담고 있지 않은 코드를 움직일 수 있을 것으로 1706 - 가정되어야 합니다. 1707 - 1708 - 이 효과는 barrier() 를 통해서도 만들 수 있지만, READ_ONCE() 와 1709 - WRITE_ONCE() 가 좀 더 안목 높은 선택입니다: READ_ONCE() 와 WRITE_ONCE()는 1710 - 컴파일러에 주어진 메모리 영역에 대해서만 최적화 가능성을 포기하도록 1711 - 하지만, barrier() 는 컴파일러가 지금까지 기계의 레지스터에 캐시해 놓은 1712 - 모든 메모리 영역의 값을 버려야 하게 하기 때문입니다. 물론, 컴파일러는 1713 - READ_ONCE() 와 WRITE_ONCE() 가 일어난 순서도 지켜줍니다, CPU 는 당연히 1714 - 그 순서를 지킬 의무가 없지만요. 1715 - 1716 - (*) 컴파일러는 다음의 예에서와 같이 변수에의 스토어를 날조해낼 수도 있습니다: 1717 - 1718 - if (a) 1719 - b = a; 1720 - else 1721 - b = 42; 1722 - 1723 - 컴파일러는 아래와 같은 최적화로 브랜치를 줄일 겁니다: 1724 - 1725 - b = 42; 1726 - if (a) 1727 - b = a; 1728 - 1729 - 싱글 쓰레드 코드에서 이 최적화는 안전할 뿐 아니라 브랜치 갯수를 1730 - 줄여줍니다. 하지만 안타깝게도, 동시성이 있는 코드에서는 이 최적화는 다른 1731 - CPU 가 'b' 를 로드할 때, -- 'a' 가 0이 아닌데도 -- 가짜인 값, 42를 보게 1732 - 되는 경우를 가능하게 합니다. 이걸 방지하기 위해 WRITE_ONCE() 를 1733 - 사용하세요: 1734 - 1735 - if (a) 1736 - WRITE_ONCE(b, a); 1737 - else 1738 - WRITE_ONCE(b, 42); 1739 - 1740 - 컴파일러는 로드를 만들어낼 수도 있습니다. 일반적으로는 문제를 일으키지 1741 - 않지만, 캐시 라인 바운싱을 일으켜 성능과 확장성을 떨어뜨릴 수 있습니다. 1742 - 날조된 로드를 막기 위해선 READ_ONCE() 를 사용하세요. 1743 - 1744 - (*) 정렬된 메모리 주소에 위치한, 한번의 메모리 참조 인스트럭션으로 액세스 1745 - 가능한 크기의 데이터는 하나의 큰 액세스가 여러개의 작은 액세스들로 1746 - 대체되는 "로드 티어링(load tearing)" 과 "스토어 티어링(store tearing)" 을 1747 - 방지합니다. 예를 들어, 주어진 아키텍쳐가 7-bit imeediate field 를 갖는 1748 - 16-bit 스토어 인스트럭션을 제공한다면, 컴파일러는 다음의 32-bit 스토어를 1749 - 구현하는데에 두개의 16-bit store-immediate 명령을 사용하려 할겁니다: 1750 - 1751 - p = 0x00010002; 1752 - 1753 - 스토어 할 상수를 만들고 그 값을 스토어 하기 위해 두개가 넘는 인스트럭션을 1754 - 사용하게 되는, 이런 종류의 최적화를 GCC 는 실제로 함을 부디 알아 두십시오. 1755 - 이 최적화는 싱글 쓰레드 코드에서는 성공적인 최적화 입니다. 실제로, 근래에 1756 - 발생한 (그리고 고쳐진) 버그는 GCC 가 volatile 스토어에 비정상적으로 이 1757 - 최적화를 사용하게 했습니다. 그런 버그가 없다면, 다음의 예에서 1758 - WRITE_ONCE() 의 사용은 스토어 티어링을 방지합니다: 1759 - 1760 - WRITE_ONCE(p, 0x00010002); 1761 - 1762 - Packed 구조체의 사용 역시 다음의 예처럼 로드 / 스토어 티어링을 유발할 수 1763 - 있습니다: 1764 - 1765 - struct __attribute__((__packed__)) foo { 1766 - short a; 1767 - int b; 1768 - short c; 1769 - }; 1770 - struct foo foo1, foo2; 1771 - ... 1772 - 1773 - foo2.a = foo1.a; 1774 - foo2.b = foo1.b; 1775 - foo2.c = foo1.c; 1776 - 1777 - READ_ONCE() 나 WRITE_ONCE() 도 없고 volatile 마킹도 없기 때문에, 1778 - 컴파일러는 이 세개의 대입문을 두개의 32-bit 로드와 두개의 32-bit 스토어로 1779 - 변환할 수 있습니다. 이는 'foo1.b' 의 값의 로드 티어링과 'foo2.b' 의 1780 - 스토어 티어링을 초래할 겁니다. 이 예에서도 READ_ONCE() 와 WRITE_ONCE() 1781 - 가 티어링을 막을 수 있습니다: 1782 - 1783 - foo2.a = foo1.a; 1784 - WRITE_ONCE(foo2.b, READ_ONCE(foo1.b)); 1785 - foo2.c = foo1.c; 1786 - 1787 - 그렇지만, volatile 로 마크된 변수에 대해서는 READ_ONCE() 와 WRITE_ONCE() 가 1788 - 필요치 않습니다. 예를 들어, 'jiffies' 는 volatile 로 마크되어 있기 때문에, 1789 - READ_ONCE(jiffies) 라고 할 필요가 없습니다. READ_ONCE() 와 WRITE_ONCE() 가 1790 - 실은 volatile 캐스팅으로 구현되어 있어서 인자가 이미 volatile 로 마크되어 1791 - 있다면 또다른 효과를 내지는 않기 때문입니다. 1792 - 1793 - 이 컴파일러 배리어들은 CPU 에는 직접적 효과를 전혀 만들지 않기 때문에, 결국은 1794 - 재배치가 일어날 수도 있음을 부디 기억해 두십시오. 1795 - 1796 - 1797 - CPU 메모리 배리어 1798 - ----------------- 1799 - 1800 - 리눅스 커널은 다음의 일곱개 기본 CPU 메모리 배리어를 가지고 있습니다: 1801 - 1802 - TYPE MANDATORY SMP CONDITIONAL 1803 - =============== ======================= =============== 1804 - 범용 mb() smp_mb() 1805 - 쓰기 wmb() smp_wmb() 1806 - 읽기 rmb() smp_rmb() 1807 - 주소 의존성 READ_ONCE() 1808 - 1809 - 1810 - 주소 의존성 배리어를 제외한 모든 메모리 배리어는 컴파일러 배리어를 포함합니다. 1811 - 주소 의존성은 컴파일러에의 추가적인 순서 보장을 포함하지 않습니다. 1812 - 1813 - 방백: 주소 의존성이 있는 경우, 컴파일러는 해당 로드를 올바른 순서로 일으킬 1814 - 것으로 (예: `a[b]` 는 a[b] 를 로드 하기 전에 b 의 값을 먼저 로드한다) 1815 - 기대되지만, C 언어 사양에는 컴파일러가 b 의 값을 추측 (예: 1 과 같음) 해서 1816 - b 로드 전에 a 로드를 하는 코드 (예: tmp = a[1]; if (b != 1) tmp = a[b]; ) 를 1817 - 만들지 않아야 한다는 내용 같은 건 없습니다. 또한 컴파일러는 a[b] 를 로드한 1818 - 후에 b 를 또다시 로드할 수도 있어서, a[b] 보다 최신 버전의 b 값을 가질 수도 1819 - 있습니다. 이런 문제들의 해결책에 대한 의견 일치는 아직 없습니다만, 일단 1820 - READ_ONCE() 매크로부터 보기 시작하는게 좋은 시작이 될겁니다. 1821 - 1822 - SMP 메모리 배리어들은 유니프로세서로 컴파일된 시스템에서는 컴파일러 배리어로 1823 - 바뀌는데, 하나의 CPU 는 스스로 일관성을 유지하고, 겹치는 액세스들 역시 올바른 1824 - 순서로 행해질 것으로 생각되기 때문입니다. 하지만, 아래의 "Virtual Machine 1825 - Guests" 서브섹션을 참고하십시오. 1826 - 1827 - [!] SMP 시스템에서 공유메모리로의 접근들을 순서 세워야 할 때, SMP 메모리 1828 - 배리어는 _반드시_ 사용되어야 함을 기억하세요, 그대신 락을 사용하는 것으로도 1829 - 충분하긴 하지만 말이죠. 1830 - 1831 - Mandatory 배리어들은 SMP 시스템에서도 UP 시스템에서도 SMP 효과만 통제하기에는 1832 - 불필요한 오버헤드를 갖기 때문에 SMP 효과만 통제하면 되는 곳에는 사용되지 않아야 1833 - 합니다. 하지만, 느슨한 순서 규칙의 메모리 I/O 윈도우를 통한 MMIO 의 효과를 1834 - 통제할 때에는 mandatory 배리어들이 사용될 수 있습니다. 이 배리어들은 1835 - 컴파일러와 CPU 모두 재배치를 못하도록 함으로써 메모리 오퍼레이션들이 디바이스에 1836 - 보여지는 순서에도 영향을 주기 때문에, SMP 가 아닌 시스템이라 할지라도 필요할 수 1837 - 있습니다. 1838 - 1839 - 1840 - 일부 고급 배리어 함수들도 있습니다: 1841 - 1842 - (*) smp_store_mb(var, value) 1843 - 1844 - 이 함수는 특정 변수에 특정 값을 대입하고 범용 메모리 배리어를 칩니다. 1845 - UP 컴파일에서는 컴파일러 배리어보다 더한 것을 친다고는 보장되지 않습니다. 1846 - 1847 - 1848 - (*) smp_mb__before_atomic(); 1849 - (*) smp_mb__after_atomic(); 1850 - 1851 - 이것들은 메모리 배리어를 내포하지 않는 어토믹 RMW 함수를 사용하지만 코드에 1852 - 메모리 배리어가 필요한 경우를 위한 것들입니다. 메모리 배리어를 내포하지 1853 - 않는 어토믹 RMW 함수들의 예로는 더하기, 빼기, (실패한) 조건적 1854 - 오퍼레이션들, _relaxed 함수들이 있으며, atomic_read 나 atomic_set 은 이에 1855 - 해당되지 않습니다. 메모리 배리어가 필요해지는 흔한 예로는 어토믹 1856 - 오퍼레이션을 사용해 레퍼런스 카운트를 수정하는 경우를 들 수 있습니다. 1857 - 1858 - 이것들은 또한 (set_bit 과 clear_bit 같은) 메모리 배리어를 내포하지 않는 1859 - 어토믹 RMW bitop 함수들을 위해서도 사용될 수 있습니다. 1860 - 1861 - 한 예로, 객체 하나를 무효한 것으로 표시하고 그 객체의 레퍼런스 카운트를 1862 - 감소시키는 다음 코드를 보세요: 1863 - 1864 - obj->dead = 1; 1865 - smp_mb__before_atomic(); 1866 - atomic_dec(&obj->ref_count); 1867 - 1868 - 이 코드는 객체의 업데이트된 death 마크가 레퍼런스 카운터 감소 동작 1869 - *전에* 보일 것을 보장합니다. 1870 - 1871 - 더 많은 정보를 위해선 Documentation/atomic_{t,bitops}.txt 문서를 1872 - 참고하세요. 1873 - 1874 - 1875 - (*) dma_wmb(); 1876 - (*) dma_rmb(); 1877 - (*) dma_mb(); 1878 - 1879 - 이것들은 CPU 와 DMA 가능한 디바이스에서 모두 액세스 가능한 공유 메모리의 1880 - 읽기, 쓰기 작업들의 순서를 보장하기 위해 consistent memory 에서 사용하기 1881 - 위한 것들입니다. 1882 - 1883 - 예를 들어, 디바이스와 메모리를 공유하며, 디스크립터 상태 값을 사용해 1884 - 디스크립터가 디바이스에 속해 있는지 아니면 CPU 에 속해 있는지 표시하고, 1885 - 공지용 초인종(doorbell) 을 사용해 업데이트된 디스크립터가 디바이스에 사용 1886 - 가능해졌음을 공지하는 디바이스 드라이버를 생각해 봅시다: 1887 - 1888 - if (desc->status != DEVICE_OWN) { 1889 - /* 디스크립터를 소유하기 전에는 데이터를 읽지 않음 */ 1890 - dma_rmb(); 1891 - 1892 - /* 데이터를 읽고 씀 */ 1893 - read_data = desc->data; 1894 - desc->data = write_data; 1895 - 1896 - /* 상태 업데이트 전 수정사항을 반영 */ 1897 - dma_wmb(); 1898 - 1899 - /* 소유권을 수정 */ 1900 - desc->status = DEVICE_OWN; 1901 - 1902 - /* 업데이트된 디스크립터의 디바이스에 공지 */ 1903 - writel(DESC_NOTIFY, doorbell); 1904 - } 1905 - 1906 - dma_rmb() 는 디스크립터로부터 데이터를 읽어오기 전에 디바이스가 소유권을 1907 - 내려놓았을 것을 보장하고, dma_wmb() 는 디바이스가 자신이 소유권을 다시 1908 - 가졌음을 보기 전에 디스크립터에 데이터가 쓰였을 것을 보장합니다. dma_mb() 1909 - 는 dma_rmb() 와 dma_wmb() 를 모두 내포합니다. 참고로, writel() 을 1910 - 사용하면 캐시 일관성이 있는 메모리 (cache coherent memory) 쓰기가 MMIO 1911 - 영역에의 쓰기 전에 완료되었을 것을 보장하므로 writel() 앞에 wmb() 를 1912 - 실행할 필요가 없음을 알아두시기 바랍니다. writel() 보다 비용이 저렴한 1913 - writel_relaxed() 는 이런 보장을 제공하지 않으므로 여기선 사용되지 않아야 1914 - 합니다. 1915 - 1916 - writel_relaxed() 와 같은 완화된 I/O 접근자들에 대한 자세한 내용을 위해서는 1917 - "커널 I/O 배리어의 효과" 섹션을, consistent memory 에 대한 자세한 내용을 1918 - 위해선 Documentation/core-api/dma-api.rst 문서를 참고하세요. 1919 - 1920 - (*) pmem_wmb(); 1921 - 1922 - 이것은 persistent memory 를 위한 것으로, persistent 저장소에 가해진 변경 1923 - 사항이 플랫폼 연속성 도메인에 도달했을 것을 보장하기 위한 것입니다. 1924 - 1925 - 예를 들어, 임시적이지 않은 pmem 영역으로의 쓰기 후, 우리는 쓰기가 플랫폼 1926 - 연속성 도메인에 도달했을 것을 보장하기 위해 pmem_wmb() 를 사용합니다. 1927 - 이는 쓰기가 뒤따르는 instruction 들이 유발하는 어떠한 데이터 액세스나 1928 - 데이터 전송의 시작 전에 persistent 저장소를 업데이트 했을 것을 보장합니다. 1929 - 이는 wmb() 에 의해 이뤄지는 순서 규칙을 포함합니다. 1930 - 1931 - Persistent memory 에서의 로드를 위해선 현재의 읽기 메모리 배리어로도 읽기 1932 - 순서를 보장하는데 충분합니다. 1933 - 1934 - (*) io_stop_wc(); 1935 - 1936 - 쓰기와 결합된 특성을 갖는 메모리 액세스의 경우 (예: ioremap_wc() 에 의해 1937 - 리턴되는 것들), CPU 는 앞의 액세스들이 뒤따르는 것들과 병합되게끔 기다릴 1938 - 수 있습니다. io_stop_wc() 는 그런 기다림이 성능에 영향을 끼칠 수 있을 때, 1939 - 이 매크로 앞의 쓰기-결합된 메모리 액세스들이 매크로 뒤의 것들과 병합되는 1940 - 것을 방지하기 위해 사용될 수 있습니다. 1941 - 1942 - ========================= 1943 - 암묵적 커널 메모리 배리어 1944 - ========================= 1945 - 1946 - 리눅스 커널의 일부 함수들은 메모리 배리어를 내장하고 있는데, 락(lock)과 1947 - 스케쥴링 관련 함수들이 대부분입니다. 1948 - 1949 - 여기선 _최소한의_ 보장을 설명합니다; 특정 아키텍쳐에서는 이 설명보다 더 많은 1950 - 보장을 제공할 수도 있습니다만 해당 아키텍쳐에 종속적인 코드 외의 부분에서는 1951 - 그런 보장을 기대해선 안될겁니다. 1952 - 1953 - 1954 - 락 ACQUISITION 함수 1955 - ------------------- 1956 - 1957 - 리눅스 커널은 다양한 락 구성체를 가지고 있습니다: 1958 - 1959 - (*) 스핀 락 1960 - (*) R/W 스핀 락 1961 - (*) 뮤텍스 1962 - (*) 세마포어 1963 - (*) R/W 세마포어 1964 - 1965 - 각 구성체마다 모든 경우에 "ACQUIRE" 오퍼레이션과 "RELEASE" 오퍼레이션의 변종이 1966 - 존재합니다. 이 오퍼레이션들은 모두 적절한 배리어를 내포하고 있습니다: 1967 - 1968 - (1) ACQUIRE 오퍼레이션의 영향: 1969 - 1970 - ACQUIRE 뒤에서 요청된 메모리 오퍼레이션은 ACQUIRE 오퍼레이션이 완료된 1971 - 뒤에 완료됩니다. 1972 - 1973 - ACQUIRE 앞에서 요청된 메모리 오퍼레이션은 ACQUIRE 오퍼레이션이 완료된 후에 1974 - 완료될 수 있습니다. 1975 - 1976 - (2) RELEASE 오퍼레이션의 영향: 1977 - 1978 - RELEASE 앞에서 요청된 메모리 오퍼레이션은 RELEASE 오퍼레이션이 완료되기 1979 - 전에 완료됩니다. 1980 - 1981 - RELEASE 뒤에서 요청된 메모리 오퍼레이션은 RELEASE 오퍼레이션 완료 전에 1982 - 완료될 수 있습니다. 1983 - 1984 - (3) ACQUIRE vs ACQUIRE 영향: 1985 - 1986 - 어떤 ACQUIRE 오퍼레이션보다 앞에서 요청된 모든 ACQUIRE 오퍼레이션은 그 1987 - ACQUIRE 오퍼레이션 전에 완료됩니다. 1988 - 1989 - (4) ACQUIRE vs RELEASE implication: 1990 - 1991 - 어떤 RELEASE 오퍼레이션보다 앞서 요청된 ACQUIRE 오퍼레이션은 그 RELEASE 1992 - 오퍼레이션보다 먼저 완료됩니다. 1993 - 1994 - (5) 실패한 조건적 ACQUIRE 영향: 1995 - 1996 - ACQUIRE 오퍼레이션의 일부 락(lock) 변종은 락이 곧바로 획득하기에는 1997 - 불가능한 상태이거나 락이 획득 가능해지도록 기다리는 도중 시그널을 받거나 1998 - 해서 실패할 수 있습니다. 실패한 락은 어떤 배리어도 내포하지 않습니다. 1999 - 2000 - [!] 참고: 락 ACQUIRE 와 RELEASE 가 단방향 배리어여서 나타나는 현상 중 하나는 2001 - 크리티컬 섹션 바깥의 인스트럭션의 영향이 크리티컬 섹션 내부로도 들어올 수 2002 - 있다는 것입니다. 2003 - 2004 - RELEASE 후에 요청되는 ACQUIRE 는 전체 메모리 배리어라 여겨지면 안되는데, 2005 - ACQUIRE 앞의 액세스가 ACQUIRE 후에 수행될 수 있고, RELEASE 후의 액세스가 2006 - RELEASE 전에 수행될 수도 있으며, 그 두개의 액세스가 서로를 지나칠 수도 있기 2007 - 때문입니다: 2008 - 2009 - *A = a; 2010 - ACQUIRE M 2011 - RELEASE M 2012 - *B = b; 2013 - 2014 - 는 다음과 같이 될 수도 있습니다: 2015 - 2016 - ACQUIRE M, STORE *B, STORE *A, RELEASE M 2017 - 2018 - ACQUIRE 와 RELEASE 가 락 획득과 해제라면, 그리고 락의 ACQUIRE 와 RELEASE 가 2019 - 같은 락 변수에 대한 것이라면, 해당 락을 쥐고 있지 않은 다른 CPU 의 시야에는 2020 - 이와 같은 재배치가 일어나는 것으로 보일 수 있습니다. 요약하자면, ACQUIRE 에 2021 - 이어 RELEASE 오퍼레이션을 순차적으로 실행하는 행위가 전체 메모리 배리어로 2022 - 생각되어선 -안됩니다-. 2023 - 2024 - 비슷하게, 앞의 반대 케이스인 RELEASE 와 ACQUIRE 두개 오퍼레이션의 순차적 실행 2025 - 역시 전체 메모리 배리어를 내포하지 않습니다. 따라서, RELEASE, ACQUIRE 로 2026 - 규정되는 크리티컬 섹션의 CPU 수행은 RELEASE 와 ACQUIRE 를 가로지를 수 있으므로, 2027 - 다음과 같은 코드는: 2028 - 2029 - *A = a; 2030 - RELEASE M 2031 - ACQUIRE N 2032 - *B = b; 2033 - 2034 - 다음과 같이 수행될 수 있습니다: 2035 - 2036 - ACQUIRE N, STORE *B, STORE *A, RELEASE M 2037 - 2038 - 이런 재배치는 데드락을 일으킬 수도 있을 것처럼 보일 수 있습니다. 하지만, 그런 2039 - 데드락의 조짐이 있다면 RELEASE 는 단순히 완료될 것이므로 데드락은 존재할 수 2040 - 없습니다. 2041 - 2042 - 이게 어떻게 올바른 동작을 할 수 있을까요? 2043 - 2044 - 우리가 이야기 하고 있는건 재배치를 하는 CPU 에 대한 이야기이지, 2045 - 컴파일러에 대한 것이 아니란 점이 핵심입니다. 컴파일러 (또는, 개발자) 2046 - 가 오퍼레이션들을 이렇게 재배치하면, 데드락이 일어날 수 -있습-니다. 2047 - 2048 - 하지만 CPU 가 오퍼레이션들을 재배치 했다는걸 생각해 보세요. 이 예에서, 2049 - 어셈블리 코드 상으로는 언락이 락을 앞서게 되어 있습니다. CPU 가 이를 2050 - 재배치해서 뒤의 락 오퍼레이션을 먼저 실행하게 됩니다. 만약 데드락이 2051 - 존재한다면, 이 락 오퍼레이션은 그저 스핀을 하며 계속해서 락을 2052 - 시도합니다 (또는, 한참 후에겠지만, 잠듭니다). CPU 는 언젠가는 2053 - (어셈블리 코드에서는 락을 앞서는) 언락 오퍼레이션을 실행하는데, 이 언락 2054 - 오퍼레이션이 잠재적 데드락을 해결하고, 락 오퍼레이션도 뒤이어 성공하게 2055 - 됩니다. 2056 - 2057 - 하지만 만약 락이 잠을 자는 타입이었다면요? 그런 경우에 코드는 2058 - 스케쥴러로 들어가려 할 거고, 여기서 결국은 메모리 배리어를 만나게 2059 - 되는데, 이 메모리 배리어는 앞의 언락 오퍼레이션이 완료되도록 만들고, 2060 - 데드락은 이번에도 해결됩니다. 잠을 자는 행위와 언락 사이의 경주 상황 2061 - (race) 도 있을 수 있겠습니다만, 락 관련 기능들은 그런 경주 상황을 모든 2062 - 경우에 제대로 해결할 수 있어야 합니다. 2063 - 2064 - 락과 세마포어는 UP 컴파일된 시스템에서의 순서에 대해 보장을 하지 않기 때문에, 2065 - 그런 상황에서 인터럽트 비활성화 오퍼레이션과 함께가 아니라면 어떤 일에도 - 특히 2066 - I/O 액세스와 관련해서는 - 제대로 사용될 수 없을 겁니다. 2067 - 2068 - "CPU 간 ACQUIRING 배리어 효과" 섹션도 참고하시기 바랍니다. 2069 - 2070 - 2071 - 예를 들어, 다음과 같은 코드를 생각해 봅시다: 2072 - 2073 - *A = a; 2074 - *B = b; 2075 - ACQUIRE 2076 - *C = c; 2077 - *D = d; 2078 - RELEASE 2079 - *E = e; 2080 - *F = f; 2081 - 2082 - 여기선 다음의 이벤트 시퀀스가 생길 수 있습니다: 2083 - 2084 - ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE 2085 - 2086 - [+] {*F,*A} 는 조합된 액세스를 의미합니다. 2087 - 2088 - 하지만 다음과 같은 건 불가능하죠: 2089 - 2090 - {*F,*A}, *B, ACQUIRE, *C, *D, RELEASE, *E 2091 - *A, *B, *C, ACQUIRE, *D, RELEASE, *E, *F 2092 - *A, *B, ACQUIRE, *C, RELEASE, *D, *E, *F 2093 - *B, ACQUIRE, *C, *D, RELEASE, {*F,*A}, *E 2094 - 2095 - 2096 - 2097 - 인터럽트 비활성화 함수 2098 - ---------------------- 2099 - 2100 - 인터럽트를 비활성화 하는 함수 (ACQUIRE 와 동일) 와 인터럽트를 활성화 하는 함수 2101 - (RELEASE 와 동일) 는 컴파일러 배리어처럼만 동작합니다. 따라서, 별도의 메모리 2102 - 배리어나 I/O 배리어가 필요한 상황이라면 그 배리어들은 인터럽트 비활성화 함수 2103 - 외의 방법으로 제공되어야만 합니다. 2104 - 2105 - 2106 - 슬립과 웨이크업 함수 2107 - -------------------- 2108 - 2109 - 글로벌 데이터에 표시된 이벤트에 의해 프로세스를 잠에 빠트리는 것과 깨우는 것은 2110 - 해당 이벤트를 기다리는 태스크의 태스크 상태와 그 이벤트를 알리기 위해 사용되는 2111 - 글로벌 데이터, 두 데이터간의 상호작용으로 볼 수 있습니다. 이것이 옳은 순서대로 2112 - 일어남을 분명히 하기 위해, 프로세스를 잠에 들게 하는 기능과 깨우는 기능은 2113 - 몇가지 배리어를 내포합니다. 2114 - 2115 - 먼저, 잠을 재우는 쪽은 일반적으로 다음과 같은 이벤트 시퀀스를 따릅니다: 2116 - 2117 - for (;;) { 2118 - set_current_state(TASK_UNINTERRUPTIBLE); 2119 - if (event_indicated) 2120 - break; 2121 - schedule(); 2122 - } 2123 - 2124 - set_current_state() 에 의해, 태스크 상태가 바뀐 후 범용 메모리 배리어가 2125 - 자동으로 삽입됩니다: 2126 - 2127 - CPU 1 2128 - =============================== 2129 - set_current_state(); 2130 - smp_store_mb(); 2131 - STORE current->state 2132 - <범용 배리어> 2133 - LOAD event_indicated 2134 - 2135 - set_current_state() 는 다음의 것들로 감싸질 수도 있습니다: 2136 - 2137 - prepare_to_wait(); 2138 - prepare_to_wait_exclusive(); 2139 - 2140 - 이것들 역시 상태를 설정한 후 범용 메모리 배리어를 삽입합니다. 2141 - 앞의 전체 시퀀스는 다음과 같은 함수들로 한번에 수행 가능한데, 이것들은 모두 2142 - 올바른 장소에 메모리 배리어를 삽입합니다: 2143 - 2144 - wait_event(); 2145 - wait_event_interruptible(); 2146 - wait_event_interruptible_exclusive(); 2147 - wait_event_interruptible_timeout(); 2148 - wait_event_killable(); 2149 - wait_event_timeout(); 2150 - wait_on_bit(); 2151 - wait_on_bit_lock(); 2152 - 2153 - 2154 - 두번째로, 깨우기를 수행하는 코드는 일반적으로 다음과 같을 겁니다: 2155 - 2156 - event_indicated = 1; 2157 - wake_up(&event_wait_queue); 2158 - 2159 - 또는: 2160 - 2161 - event_indicated = 1; 2162 - wake_up_process(event_daemon); 2163 - 2164 - wake_up() 이 무언가를 깨우게 되면, 이 함수는 범용 메모리 배리어를 수행합니다. 2165 - 이 함수가 아무것도 깨우지 않는다면 메모리 배리어는 수행될 수도, 수행되지 않을 2166 - 수도 있습니다; 이 경우에 메모리 배리어를 수행할 거라 오해해선 안됩니다. 이 2167 - 배리어는 태스크 상태가 접근되기 전에 수행되는데, 자세히 말하면 이 이벤트를 2168 - 알리기 위한 STORE 와 TASK_RUNNING 으로 상태를 쓰는 STORE 사이에 수행됩니다: 2169 - 2170 - CPU 1 (Sleeper) CPU 2 (Waker) 2171 - =============================== =============================== 2172 - set_current_state(); STORE event_indicated 2173 - smp_store_mb(); wake_up(); 2174 - STORE current->state ... 2175 - <범용 배리어> <범용 배리어> 2176 - LOAD event_indicated if ((LOAD task->state) & TASK_NORMAL) 2177 - STORE task->state 2178 - 2179 - 여기서 "task" 는 깨어나지는 쓰레드이고 CPU 1 의 "current" 와 같습니다. 2180 - 2181 - 반복하지만, wake_up() 이 무언가를 정말 깨운다면 범용 메모리 배리어가 수행될 2182 - 것이 보장되지만, 그렇지 않다면 그런 보장이 없습니다. 이걸 이해하기 위해, X 와 2183 - Y 는 모두 0 으로 초기화 되어 있다는 가정 하에 아래의 이벤트 시퀀스를 생각해 2184 - 봅시다: 2185 - 2186 - CPU 1 CPU 2 2187 - =============================== =============================== 2188 - X = 1; Y = 1; 2189 - smp_mb(); wake_up(); 2190 - LOAD Y LOAD X 2191 - 2192 - 정말로 깨우기가 행해졌다면, 두 로드 중 (최소한) 하나는 1 을 보게 됩니다. 2193 - 반면에, 실제 깨우기가 행해지지 않았다면, 두 로드 모두 0을 볼 수도 있습니다. 2194 - 2195 - wake_up_process() 는 항상 범용 메모리 배리어를 수행합니다. 이 배리어 역시 2196 - 태스크 상태가 접근되기 전에 수행됩니다. 특히, 앞의 예제 코드에서 wake_up() 이 2197 - wake_up_process() 로 대체된다면 두 로드 중 하나는 1을 볼 것이 보장됩니다. 2198 - 2199 - 사용 가능한 깨우기류 함수들로 다음과 같은 것들이 있습니다: 2200 - 2201 - complete(); 2202 - wake_up(); 2203 - wake_up_all(); 2204 - wake_up_bit(); 2205 - wake_up_interruptible(); 2206 - wake_up_interruptible_all(); 2207 - wake_up_interruptible_nr(); 2208 - wake_up_interruptible_poll(); 2209 - wake_up_interruptible_sync(); 2210 - wake_up_interruptible_sync_poll(); 2211 - wake_up_locked(); 2212 - wake_up_locked_poll(); 2213 - wake_up_nr(); 2214 - wake_up_poll(); 2215 - wake_up_process(); 2216 - 2217 - 메모리 순서규칙 관점에서, 이 함수들은 모두 wake_up() 과 같거나 보다 강한 순서 2218 - 보장을 제공합니다. 2219 - 2220 - [!] 잠재우는 코드와 깨우는 코드에 내포되는 메모리 배리어들은 깨우기 전에 2221 - 이루어진 스토어를 잠재우는 코드가 set_current_state() 를 호출한 후에 행하는 2222 - 로드에 대해 순서를 맞추지 _않는다는_ 점을 기억하세요. 예를 들어, 잠재우는 2223 - 코드가 다음과 같고: 2224 - 2225 - set_current_state(TASK_INTERRUPTIBLE); 2226 - if (event_indicated) 2227 - break; 2228 - __set_current_state(TASK_RUNNING); 2229 - do_something(my_data); 2230 - 2231 - 깨우는 코드는 다음과 같다면: 2232 - 2233 - my_data = value; 2234 - event_indicated = 1; 2235 - wake_up(&event_wait_queue); 2236 - 2237 - event_indecated 에의 변경이 잠재우는 코드에게 my_data 에의 변경 후에 이루어진 2238 - 것으로 인지될 것이라는 보장이 없습니다. 이런 경우에는 양쪽 코드 모두 각각의 2239 - 데이터 액세스 사이에 메모리 배리어를 직접 쳐야 합니다. 따라서 앞의 재우는 2240 - 코드는 다음과 같이: 2241 - 2242 - set_current_state(TASK_INTERRUPTIBLE); 2243 - if (event_indicated) { 2244 - smp_rmb(); 2245 - do_something(my_data); 2246 - } 2247 - 2248 - 그리고 깨우는 코드는 다음과 같이 되어야 합니다: 2249 - 2250 - my_data = value; 2251 - smp_wmb(); 2252 - event_indicated = 1; 2253 - wake_up(&event_wait_queue); 2254 - 2255 - 2256 - 그외의 함수들 2257 - ------------- 2258 - 2259 - 그외의 배리어를 내포하는 함수들은 다음과 같습니다: 2260 - 2261 - (*) schedule() 과 그 유사한 것들이 완전한 메모리 배리어를 내포합니다. 2262 - 2263 - 2264 - ============================== 2265 - CPU 간 ACQUIRING 배리어의 효과 2266 - ============================== 2267 - 2268 - SMP 시스템에서의 락 기능들은 더욱 강력한 형태의 배리어를 제공합니다: 이 2269 - 배리어는 동일한 락을 사용하는 다른 CPU 들의 메모리 액세스 순서에도 영향을 2270 - 끼칩니다. 2271 - 2272 - 2273 - ACQUIRE VS 메모리 액세스 2274 - ------------------------ 2275 - 2276 - 다음의 예를 생각해 봅시다: 시스템은 두개의 스핀락 (M) 과 (Q), 그리고 세개의 CPU 2277 - 를 가지고 있습니다; 여기에 다음의 이벤트 시퀀스가 발생합니다: 2278 - 2279 - CPU 1 CPU 2 2280 - =============================== =============================== 2281 - WRITE_ONCE(*A, a); WRITE_ONCE(*E, e); 2282 - ACQUIRE M ACQUIRE Q 2283 - WRITE_ONCE(*B, b); WRITE_ONCE(*F, f); 2284 - WRITE_ONCE(*C, c); WRITE_ONCE(*G, g); 2285 - RELEASE M RELEASE Q 2286 - WRITE_ONCE(*D, d); WRITE_ONCE(*H, h); 2287 - 2288 - *A 로의 액세스부터 *H 로의 액세스까지가 어떤 순서로 CPU 3 에게 보여질지에 2289 - 대해서는 각 CPU 에서의 락 사용에 의해 내포되어 있는 제약을 제외하고는 어떤 2290 - 보장도 존재하지 않습니다. 예를 들어, CPU 3 에게 다음과 같은 순서로 보여지는 2291 - 것이 가능합니다: 2292 - 2293 - *E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M 2294 - 2295 - 하지만 다음과 같이 보이지는 않을 겁니다: 2296 - 2297 - *B, *C or *D preceding ACQUIRE M 2298 - *A, *B or *C following RELEASE M 2299 - *F, *G or *H preceding ACQUIRE Q 2300 - *E, *F or *G following RELEASE Q 2301 - 2302 - 2303 - ========================= 2304 - 메모리 배리어가 필요한 곳 2305 - ========================= 2306 - 2307 - 설령 SMP 커널을 사용하더라도 싱글 쓰레드로 동작하는 코드는 올바르게 동작하는 2308 - 것으로 보여질 것이기 때문에, 평범한 시스템 운영중에 메모리 오퍼레이션 재배치는 2309 - 일반적으로 문제가 되지 않습니다. 하지만, 재배치가 문제가 _될 수 있는_ 네가지 2310 - 환경이 있습니다: 2311 - 2312 - (*) 프로세서간 상호 작용. 2313 - 2314 - (*) 어토믹 오퍼레이션. 2315 - 2316 - (*) 디바이스 액세스. 2317 - 2318 - (*) 인터럽트. 2319 - 2320 - 2321 - 프로세서간 상호 작용 2322 - -------------------- 2323 - 2324 - 두개 이상의 프로세서를 가진 시스템이 있다면, 시스템의 두개 이상의 CPU 는 동시에 2325 - 같은 데이터에 대한 작업을 할 수 있습니다. 이는 동기화 문제를 일으킬 수 있고, 2326 - 이 문제를 해결하는 일반적 방법은 락을 사용하는 것입니다. 하지만, 락은 상당히 2327 - 비용이 비싸서 가능하면 락을 사용하지 않고 일을 처리하는 것이 낫습니다. 이런 2328 - 경우, 두 CPU 모두에 영향을 끼치는 오퍼레이션들은 오동작을 막기 위해 신중하게 2329 - 순서가 맞춰져야 합니다. 2330 - 2331 - 예를 들어, R/W 세마포어의 느린 수행경로 (slow path) 를 생각해 봅시다. 2332 - 세마포어를 위해 대기를 하는 하나의 프로세스가 자신의 스택 중 일부를 이 2333 - 세마포어의 대기 프로세스 리스트에 링크한 채로 있습니다: 2334 - 2335 - struct rw_semaphore { 2336 - ... 2337 - spinlock_t lock; 2338 - struct list_head waiters; 2339 - }; 2340 - 2341 - struct rwsem_waiter { 2342 - struct list_head list; 2343 - struct task_struct *task; 2344 - }; 2345 - 2346 - 특정 대기 상태 프로세스를 깨우기 위해, up_read() 나 up_write() 함수는 다음과 2347 - 같은 일을 합니다: 2348 - 2349 - (1) 다음 대기 상태 프로세스 레코드는 어디있는지 알기 위해 이 대기 상태 2350 - 프로세스 레코드의 next 포인터를 읽습니다; 2351 - 2352 - (2) 이 대기 상태 프로세스의 task 구조체로의 포인터를 읽습니다; 2353 - 2354 - (3) 이 대기 상태 프로세스가 세마포어를 획득했음을 알리기 위해 task 2355 - 포인터를 초기화 합니다; 2356 - 2357 - (4) 해당 태스크에 대해 wake_up_process() 를 호출합니다; 그리고 2358 - 2359 - (5) 해당 대기 상태 프로세스의 task 구조체를 잡고 있던 레퍼런스를 해제합니다. 2360 - 2361 - 달리 말하자면, 다음 이벤트 시퀀스를 수행해야 합니다: 2362 - 2363 - LOAD waiter->list.next; 2364 - LOAD waiter->task; 2365 - STORE waiter->task; 2366 - CALL wakeup 2367 - RELEASE task 2368 - 2369 - 그리고 이 이벤트들이 다른 순서로 수행된다면, 오동작이 일어날 수 있습니다. 2370 - 2371 - 한번 세마포어의 대기줄에 들어갔고 세마포어 락을 놓았다면, 해당 대기 프로세스는 2372 - 락을 다시는 잡지 않습니다; 대신 자신의 task 포인터가 초기화 되길 기다립니다. 2373 - 그 레코드는 대기 프로세스의 스택에 있기 때문에, 리스트의 next 포인터가 읽혀지기 2374 - _전에_ task 포인터가 지워진다면, 다른 CPU 는 해당 대기 프로세스를 시작해 버리고 2375 - up*() 함수가 next 포인터를 읽기 전에 대기 프로세스의 스택을 마구 건드릴 수 2376 - 있습니다. 2377 - 2378 - 그렇게 되면 위의 이벤트 시퀀스에 어떤 일이 일어나는지 생각해 보죠: 2379 - 2380 - CPU 1 CPU 2 2381 - =============================== =============================== 2382 - down_xxx() 2383 - Queue waiter 2384 - Sleep 2385 - up_yyy() 2386 - LOAD waiter->task; 2387 - STORE waiter->task; 2388 - Woken up by other event 2389 - <preempt> 2390 - Resume processing 2391 - down_xxx() returns 2392 - call foo() 2393 - foo() clobbers *waiter 2394 - </preempt> 2395 - LOAD waiter->list.next; 2396 - --- OOPS --- 2397 - 2398 - 이 문제는 세마포어 락의 사용으로 해결될 수도 있겠지만, 그렇게 되면 깨어난 후에 2399 - down_xxx() 함수가 불필요하게 스핀락을 또다시 얻어야만 합니다. 2400 - 2401 - 이 문제를 해결하는 방법은 범용 SMP 메모리 배리어를 추가하는 겁니다: 2402 - 2403 - LOAD waiter->list.next; 2404 - LOAD waiter->task; 2405 - smp_mb(); 2406 - STORE waiter->task; 2407 - CALL wakeup 2408 - RELEASE task 2409 - 2410 - 이 경우에, 배리어는 시스템의 나머지 CPU 들에게 모든 배리어 앞의 메모리 액세스가 2411 - 배리어 뒤의 메모리 액세스보다 앞서 일어난 것으로 보이게 만듭니다. 배리어 앞의 2412 - 메모리 액세스들이 배리어 명령 자체가 완료되는 시점까지 완료된다고는 보장하지 2413 - _않습니다_. 2414 - 2415 - (이게 문제가 되지 않을) 단일 프로세서 시스템에서 smp_mb() 는 실제로는 그저 2416 - 컴파일러가 CPU 안에서의 순서를 바꾸거나 하지 않고 주어진 순서대로 명령을 2417 - 내리도록 하는 컴파일러 배리어일 뿐입니다. 오직 하나의 CPU 만 있으니, CPU 의 2418 - 의존성 순서 로직이 그 외의 모든것을 알아서 처리할 겁니다. 2419 - 2420 - 2421 - 어토믹 오퍼레이션 2422 - ----------------- 2423 - 2424 - 어토믹 오퍼레이션은 기술적으로 프로세서간 상호작용으로 분류되며 그 중 일부는 2425 - 전체 메모리 배리어를 내포하고 또 일부는 내포하지 않지만, 커널에서 상당히 2426 - 의존적으로 사용하는 기능 중 하나입니다. 2427 - 2428 - 더 많은 내용을 위해선 Documentation/atomic_t.txt 를 참고하세요. 2429 - 2430 - 2431 - 디바이스 액세스 2432 - --------------- 2433 - 2434 - 많은 디바이스가 메모리 매핑 기법으로 제어될 수 있는데, 그렇게 제어되는 2435 - 디바이스는 CPU 에는 단지 특정 메모리 영역의 집합처럼 보이게 됩니다. 드라이버는 2436 - 그런 디바이스를 제어하기 위해 정확히 올바른 순서로 올바른 메모리 액세스를 2437 - 만들어야 합니다. 2438 - 2439 - 하지만, 액세스들을 재배치 하거나 조합하거나 병합하는게 더 효율적이라 판단하는 2440 - 영리한 CPU 나 컴파일러들을 사용하면 드라이버 코드의 조심스럽게 순서 맞춰진 2441 - 액세스들이 디바이스에는 요청된 순서대로 도착하지 못하게 할 수 있는 - 디바이스가 2442 - 오동작을 하게 할 - 잠재적 문제가 생길 수 있습니다. 2443 - 2444 - 리눅스 커널 내부에서, I/O 는 어떻게 액세스들을 적절히 순차적이게 만들 수 있는지 2445 - 알고 있는, - inb() 나 writel() 과 같은 - 적절한 액세스 루틴을 통해 이루어져야만 2446 - 합니다. 이것들은 대부분의 경우에는 명시적 메모리 배리어 와 함께 사용될 필요가 2447 - 없습니다만, 완화된 메모리 액세스 속성으로 I/O 메모리 윈도우로의 참조를 위해 2448 - 액세스 함수가 사용된다면 순서를 강제하기 위해 _mandatory_ 메모리 배리어가 2449 - 필요합니다. 2450 - 2451 - 더 많은 정보를 위해선 Documentation/driver-api/device-io.rst 를 참고하십시오. 2452 - 2453 - 2454 - 인터럽트 2455 - -------- 2456 - 2457 - 드라이버는 자신의 인터럽트 서비스 루틴에 의해 인터럽트 당할 수 있기 때문에 2458 - 드라이버의 이 두 부분은 서로의 디바이스 제어 또는 액세스 부분과 상호 간섭할 수 2459 - 있습니다. 2460 - 2461 - 스스로에게 인터럽트 당하는 걸 불가능하게 하고, 드라이버의 크리티컬한 2462 - 오퍼레이션들을 모두 인터럽트가 불가능하게 된 영역에 집어넣거나 하는 방법 (락의 2463 - 한 형태) 으로 이런 상호 간섭을 - 최소한 부분적으로라도 - 줄일 수 있습니다. 2464 - 드라이버의 인터럽트 루틴이 실행 중인 동안, 해당 드라이버의 코어는 같은 CPU 에서 2465 - 수행되지 않을 것이며, 현재의 인터럽트가 처리되는 중에는 또다시 인터럽트가 2466 - 일어나지 못하도록 되어 있으니 인터럽트 핸들러는 그에 대해서는 락을 잡지 않아도 2467 - 됩니다. 2468 - 2469 - 하지만, 어드레스 레지스터와 데이터 레지스터를 갖는 이더넷 카드를 다루는 2470 - 드라이버를 생각해 봅시다. 만약 이 드라이버의 코어가 인터럽트를 비활성화시킨 2471 - 채로 이더넷 카드와 대화하고 드라이버의 인터럽트 핸들러가 호출되었다면: 2472 - 2473 - LOCAL IRQ DISABLE 2474 - writew(ADDR, 3); 2475 - writew(DATA, y); 2476 - LOCAL IRQ ENABLE 2477 - <interrupt> 2478 - writew(ADDR, 4); 2479 - q = readw(DATA); 2480 - </interrupt> 2481 - 2482 - 만약 순서 규칙이 충분히 완화되어 있다면 데이터 레지스터에의 스토어는 어드레스 2483 - 레지스터에 두번째로 행해지는 스토어 뒤에 일어날 수도 있습니다: 2484 - 2485 - STORE *ADDR = 3, STORE *ADDR = 4, STORE *DATA = y, q = LOAD *DATA 2486 - 2487 - 2488 - 만약 순서 규칙이 충분히 완화되어 있고 묵시적으로든 명시적으로든 배리어가 2489 - 사용되지 않았다면 인터럽트 비활성화 섹션에서 일어난 액세스가 바깥으로 새어서 2490 - 인터럽트 내에서 일어난 액세스와 섞일 수 있다고 - 그리고 그 반대도 - 가정해야만 2491 - 합니다. 2492 - 2493 - 그런 영역 안에서 일어나는 I/O 액세스는 묵시적 I/O 배리어를 형성하는, 엄격한 2494 - 순서 규칙의 I/O 레지스터로의 로드 오퍼레이션을 포함하기 때문에 일반적으로는 2495 - 문제가 되지 않습니다. 2496 - 2497 - 2498 - 하나의 인터럽트 루틴과 별도의 CPU 에서 수행중이며 서로 통신을 하는 두 루틴 2499 - 사이에도 비슷한 상황이 일어날 수 있습니다. 만약 그런 경우가 발생할 가능성이 2500 - 있다면, 순서를 보장하기 위해 인터럽트 비활성화 락이 사용되어져야만 합니다. 2501 - 2502 - 2503 - ====================== 2504 - 커널 I/O 배리어의 효과 2505 - ====================== 2506 - 2507 - I/O 액세스를 통한 주변장치와의 통신은 아키텍쳐와 기기에 매우 종속적입니다. 2508 - 따라서, 본질적으로 이식성이 없는 드라이버는 가능한 가장 적은 오버헤드로 2509 - 동기화를 하기 위해 각자의 타겟 시스템의 특정 동작에 의존할 겁니다. 다양한 2510 - 아키텍쳐와 버스 구현에 이식성을 가지려 하는 드라이버를 위해, 커널은 다양한 2511 - 정도의 순서 보장을 제공하는 일련의 액세스 함수를 제공합니다. 2512 - 2513 - (*) readX(), writeX(): 2514 - 2515 - readX() 와 writeX() MMIO 액세스 함수는 접근되는 주변장치로의 포인터를 2516 - __iomem * 패러미터로 받습니다. 디폴트 I/O 기능으로 매핑되는 포인터 2517 - (예: ioremap() 으로 반환되는 것) 의 순서 보장은 다음과 같습니다: 2518 - 2519 - 1. 같은 주변장치로의 모든 readX() 와 writeX() 액세스는 각자에 대해 2520 - 순서지어집니다. 이는 같은 CPU 쓰레드에 의한 특정 디바이스로의 MMIO 2521 - 레지스터 액세스가 프로그램 순서대로 도착할 것을 보장합니다. 2522 - 2523 - 2. 한 스핀락을 잡은 CPU 쓰레드에 의한 writeX() 는 같은 스핀락을 나중에 2524 - 잡은 다른 CPU 쓰레드에 의해 같은 주변장치를 향해 호출된 writeX() 2525 - 앞으로 순서지어집니다. 이는 스핀락을 잡은 채 특정 디바이스를 향해 2526 - 호출된 MMIO 레지스터 쓰기는 해당 락의 획득에 일관적인 순서로 도달할 2527 - 것을 보장합니다. 2528 - 2529 - 3. 특정 주변장치를 향한 특정 CPU 쓰레드의 writeX() 는 먼저 해당 2530 - 쓰레드로 전파되는, 또는 해당 쓰레드에 의해 요청된 모든 앞선 메모리 2531 - 쓰기가 완료되기 전까지 먼저 기다립니다. 이는 dma_alloc_coherent() 2532 - 를 통해 할당된 전송용 DMA 버퍼로의 해당 CPU 의 쓰기가 이 CPU 가 이 2533 - 전송을 시작시키기 위해 MMIO 컨트롤 레지스터에 쓰기를 할 때 DMA 2534 - 엔진에 보여질 것을 보장합니다. 2535 - 2536 - 4. 특정 CPU 쓰레드에 의한 주변장치로의 readX() 는 같은 쓰레드에 의한 2537 - 모든 뒤따르는 메모리 읽기가 시작되기 전에 완료됩니다. 이는 2538 - dma_alloc_coherent() 를 통해 할당된 수신용 DMA 버퍼로부터의 CPU 의 2539 - 읽기는 이 DMA 수신의 완료를 표시하는 DMA 엔진의 MMIO 상태 레지스터 2540 - 읽기 후에는 오염된 데이터를 읽지 않을 것을 보장합니다. 2541 - 2542 - 5. CPU 에 의한 주변장치로의 readX() 는 모든 뒤따르는 delay() 루프가 2543 - 수행을 시작하기 전에 완료됩니다. 이는 CPU 의 특정 2544 - 주변장치로의 두개의 MMIO 레지스터 쓰기가 행해지는데 첫번째 쓰기가 2545 - readX() 를 통해 곧바로 읽어졌고 이어 두번째 writeX() 전에 udelay(1) 2546 - 이 호출되었다면 이 두개의 쓰기는 최소 1us 의 간격을 두고 행해질 것을 2547 - 보장합니다: 2548 - 2549 - writel(42, DEVICE_REGISTER_0); // 디바이스에 도착함... 2550 - readl(DEVICE_REGISTER_0); 2551 - udelay(1); 2552 - writel(42, DEVICE_REGISTER_1); // ...이것보다 최소 1us 전에. 2553 - 2554 - 디폴트가 아닌 기능을 통해 얻어지는 __iomem 포인터 (예: ioremap_wc() 를 2555 - 통해 리턴되는 것) 의 순서 속성은 실제 아키텍쳐에 의존적이어서 이런 2556 - 종류의 매핑으로의 액세스는 앞서 설명된 보장사항에 의존할 수 없습니다. 2557 - 2558 - (*) readX_relaxed(), writeX_relaxed() 2559 - 2560 - 이것들은 readX() 와 writeX() 랑 비슷하지만, 더 완화된 메모리 순서 2561 - 보장을 제공합니다. 구체적으로, 이것들은 일반적 메모리 액세스나 delay() 2562 - 루프 (예:앞의 2-5 항목) 에 대해 순서를 보장하지 않습니다만 디폴트 I/O 2563 - 기능으로 매핑된 __iomem 포인터에 대해 동작할 때, 같은 CPU 쓰레드에 의한 2564 - 같은 주변장치로의 액세스에는 순서가 맞춰질 것이 보장됩니다. 2565 - 2566 - (*) readsX(), writesX(): 2567 - 2568 - readsX() 와 writesX() MMIO 액세스 함수는 DMA 를 수행하는데 적절치 않은, 2569 - 주변장치 내의 메모리 매핑된 레지스터 기반 FIFO 로의 액세스를 위해 2570 - 설계되었습니다. 따라서, 이 기능들은 앞서 설명된 readX_relaxed() 와 2571 - writeX_relaxed() 의 순서 보장만을 제공합니다. 2572 - 2573 - (*) inX(), outX(): 2574 - 2575 - inX() 와 outX() 액세스 함수는 일부 아키텍쳐 (특히 x86) 에서는 특수한 2576 - 명령어를 필요로 하며 포트에 매핑되는, 과거의 유산인 I/O 주변장치로의 2577 - 접근을 위해 만들어졌습니다. 2578 - 2579 - 많은 CPU 아키텍쳐가 결국은 이런 주변장치를 내부의 가상 메모리 매핑을 2580 - 통해 접근하기 때문에, inX() 와 outX() 가 제공하는 이식성 있는 순서 2581 - 보장은 디폴트 I/O 기능을 통한 매핑을 접근할 때의 readX() 와 writeX() 에 2582 - 의해 제공되는 것과 각각 동일합니다. 2583 - 2584 - 디바이스 드라이버는 outX() 가 리턴하기 전에 해당 I/O 주변장치로부터의 2585 - 완료 응답을 기다리는 쓰기 트랜잭션을 만들어 낸다고 기대할 수도 2586 - 있습니다. 이는 모든 아키텍쳐에서 보장되지는 않고, 따라서 이식성 있는 2587 - 순서 규칙의 일부분이 아닙니다. 2588 - 2589 - (*) insX(), outsX(): 2590 - 2591 - 앞에서와 같이, insX() 와 outsX() 액세스 함수는 디폴트 I/O 기능을 통한 2592 - 매핑을 접근할 때 각각 readX() 와 writeX() 와 같은 순서 보장을 2593 - 제공합니다. 2594 - 2595 - (*) ioreadX(), iowriteX() 2596 - 2597 - 이것들은 inX()/outX() 나 readX()/writeX() 처럼 실제로 수행하는 액세스의 2598 - 종류에 따라 적절하게 수행될 것입니다. 2599 - 2600 - String 액세스 함수 (insX(), outsX(), readsX() 그리고 writesX()) 의 예외를 2601 - 제외하고는, 앞의 모든 것이 아랫단의 주변장치가 little-endian 이라 가정하며, 2602 - 따라서 big-endian 아키텍쳐에서는 byte-swapping 오퍼레이션을 수행합니다. 2603 - 2604 - 2605 - =================================== 2606 - 가정되는 가장 완화된 실행 순서 모델 2607 - =================================== 2608 - 2609 - 컨셉적으로 CPU 는 주어진 프로그램에 대해 프로그램 그 자체에는 인과성 (program 2610 - causality) 을 지키는 것처럼 보이게 하지만 일반적으로는 순서를 거의 지켜주지 2611 - 않는다고 가정되어야만 합니다. (i386 이나 x86_64 같은) 일부 CPU 들은 코드 2612 - 재배치에 (powerpc 나 frv 와 같은) 다른 것들에 비해 강한 제약을 갖지만, 아키텍쳐 2613 - 종속적 코드 이외의 코드에서는 순서에 대한 제약이 가장 완화된 경우 (DEC Alpha) 2614 - 를 가정해야 합니다. 2615 - 2616 - 이 말은, CPU 에게 주어지는 인스트럭션 스트림 내의 한 인스트럭션이 앞의 2617 - 인스트럭션에 종속적이라면 앞의 인스트럭션은 뒤의 종속적 인스트럭션이 실행되기 2618 - 전에 완료[*]될 수 있어야 한다는 제약 (달리 말해서, 인과성이 지켜지는 것으로 2619 - 보이게 함) 외에는 자신이 원하는 순서대로 - 심지어 병렬적으로도 - 그 스트림을 2620 - 실행할 수 있음을 의미합니다 2621 - 2622 - [*] 일부 인스트럭션은 하나 이상의 영향 - 조건 코드를 바꾼다던지, 레지스터나 2623 - 메모리를 바꾼다던지 - 을 만들어내며, 다른 인스트럭션은 다른 효과에 2624 - 종속적일 수 있습니다. 2625 - 2626 - CPU 는 최종적으로 아무 효과도 만들지 않는 인스트럭션 시퀀스는 없애버릴 수도 2627 - 있습니다. 예를 들어, 만약 두개의 연속되는 인스트럭션이 둘 다 같은 레지스터에 2628 - 직접적인 값 (immediate value) 을 집어넣는다면, 첫번째 인스트럭션은 버려질 수도 2629 - 있습니다. 2630 - 2631 - 2632 - 비슷하게, 컴파일러 역시 프로그램의 인과성만 지켜준다면 인스트럭션 스트림을 2633 - 자신이 보기에 올바르다 생각되는대로 재배치 할 수 있습니다. 2634 - 2635 - 2636 - =============== 2637 - CPU 캐시의 영향 2638 - =============== 2639 - 2640 - 캐시된 메모리 오퍼레이션들이 시스템 전체에 어떻게 인지되는지는 CPU 와 메모리 2641 - 사이에 존재하는 캐시들, 그리고 시스템 상태의 일관성을 관리하는 메모리 일관성 2642 - 시스템에 상당 부분 영향을 받습니다. 2643 - 2644 - 한 CPU 가 시스템의 다른 부분들과 캐시를 통해 상호작용한다면, 메모리 시스템은 2645 - CPU 의 캐시들을 포함해야 하며, CPU 와 CPU 자신의 캐시 사이에서의 동작을 위한 2646 - 메모리 배리어를 가져야 합니다. (메모리 배리어는 논리적으로는 다음 그림의 2647 - 점선에서 동작합니다): 2648 - 2649 - <--- CPU ---> : <----------- Memory -----------> 2650 - : 2651 - +--------+ +--------+ : +--------+ +-----------+ 2652 - | | | | : | | | | +--------+ 2653 - | CPU | | Memory | : | CPU | | | | | 2654 - | Core |--->| Access |----->| Cache |<-->| | | | 2655 - | | | Queue | : | | | |--->| Memory | 2656 - | | | | : | | | | | | 2657 - +--------+ +--------+ : +--------+ | | | | 2658 - : | Cache | +--------+ 2659 - : | Coherency | 2660 - : | Mechanism | +--------+ 2661 - +--------+ +--------+ : +--------+ | | | | 2662 - | | | | : | | | | | | 2663 - | CPU | | Memory | : | CPU | | |--->| Device | 2664 - | Core |--->| Access |----->| Cache |<-->| | | | 2665 - | | | Queue | : | | | | | | 2666 - | | | | : | | | | +--------+ 2667 - +--------+ +--------+ : +--------+ +-----------+ 2668 - : 2669 - : 2670 - 2671 - 특정 로드나 스토어는 해당 오퍼레이션을 요청한 CPU 의 캐시 내에서 동작을 완료할 2672 - 수도 있기 때문에 해당 CPU 의 바깥에는 보이지 않을 수 있지만, 다른 CPU 가 관심을 2673 - 갖는다면 캐시 일관성 메커니즘이 해당 캐시라인을 해당 CPU 에게 전달하고, 해당 2674 - 메모리 영역에 대한 오퍼레이션이 발생할 때마다 그 영향을 전파시키기 때문에, 해당 2675 - 오퍼레이션은 메모리에 실제로 액세스를 한것처럼 나타날 것입니다. 2676 - 2677 - CPU 코어는 프로그램의 인과성이 유지된다고만 여겨진다면 인스트럭션들을 어떤 2678 - 순서로든 재배치해서 수행할 수 있습니다. 일부 인스트럭션들은 로드나 스토어 2679 - 오퍼레이션을 만드는데 이 오퍼레이션들은 이후 수행될 메모리 액세스 큐에 들어가게 2680 - 됩니다. 코어는 이 오퍼레이션들을 해당 큐에 어떤 순서로든 원하는대로 넣을 수 2681 - 있고, 다른 인스트럭션의 완료를 기다리도록 강제되기 전까지는 수행을 계속합니다. 2682 - 2683 - 메모리 배리어가 하는 일은 CPU 쪽에서 메모리 쪽으로 넘어가는 액세스들의 순서, 2684 - 그리고 그 액세스의 결과가 시스템의 다른 관찰자들에게 인지되는 순서를 제어하는 2685 - 것입니다. 2686 - 2687 - [!] CPU 들은 항상 그들 자신의 로드와 스토어는 프로그램 순서대로 일어난 것으로 2688 - 보기 때문에, 주어진 CPU 내에서는 메모리 배리어를 사용할 필요가 _없습니다_. 2689 - 2690 - [!] MMIO 나 다른 디바이스 액세스들은 캐시 시스템을 우회할 수도 있습니다. 우회 2691 - 여부는 디바이스가 액세스 되는 메모리 윈도우의 특성에 의해 결정될 수도 있고, CPU 2692 - 가 가지고 있을 수 있는 특수한 디바이스 통신 인스트럭션의 사용에 의해서 결정될 2693 - 수도 있습니다. 2694 - 2695 - 2696 - 캐시 일관성 VS DMA 2697 - ------------------ 2698 - 2699 - 모든 시스템이 DMA 를 하는 디바이스에 대해서까지 캐시 일관성을 유지하지는 2700 - 않습니다. 그런 경우, DMA 를 시도하는 디바이스는 RAM 으로부터 잘못된 데이터를 2701 - 읽을 수 있는데, 더티 캐시 라인이 CPU 의 캐시에 머무르고 있고, 바뀐 값이 아직 2702 - RAM 에 써지지 않았을 수 있기 때문입니다. 이 문제를 해결하기 위해선, 커널의 2703 - 적절한 부분에서 각 CPU 캐시의 문제되는 비트들을 플러시 (flush) 시켜야만 합니다 2704 - (그리고 그것들을 무효화 - invalidation - 시킬 수도 있겠죠). 2705 - 2706 - 또한, 디바이스에 의해 RAM 에 DMA 로 쓰여진 값은 디바이스가 쓰기를 완료한 후에 2707 - CPU 의 캐시에서 RAM 으로 쓰여지는 더티 캐시 라인에 의해 덮어써질 수도 있고, CPU 2708 - 의 캐시에 존재하는 캐시 라인이 해당 캐시에서 삭제되고 다시 값을 읽어들이기 2709 - 전까지는 RAM 이 업데이트 되었다는 사실 자체가 숨겨져 버릴 수도 있습니다. 이 2710 - 문제를 해결하기 위해선, 커널의 적절한 부분에서 각 CPU 의 캐시 안의 문제가 되는 2711 - 비트들을 무효화 시켜야 합니다. 2712 - 2713 - 캐시 관리에 대한 더 많은 정보를 위해선 Documentation/core-api/cachetlb.rst 를 2714 - 참고하세요. 2715 - 2716 - 2717 - 캐시 일관성 VS MMIO 2718 - ------------------- 2719 - 2720 - Memory mapped I/O 는 일반적으로 CPU 의 메모리 공간 내의 한 윈도우의 특정 부분 2721 - 내의 메모리 지역에 이루어지는데, 이 윈도우는 일반적인, RAM 으로 향하는 2722 - 윈도우와는 다른 특성을 갖습니다. 2723 - 2724 - 그런 특성 가운데 하나는, 일반적으로 그런 액세스는 캐시를 완전히 우회하고 2725 - 디바이스 버스로 곧바로 향한다는 것입니다. 이 말은 MMIO 액세스는 먼저 2726 - 시작되어서 캐시에서 완료된 메모리 액세스를 추월할 수 있다는 뜻입니다. 이런 2727 - 경우엔 메모리 배리어만으로는 충분치 않고, 만약 캐시된 메모리 쓰기 오퍼레이션과 2728 - MMIO 액세스가 어떤 방식으로든 의존적이라면 해당 캐시는 두 오퍼레이션 사이에 2729 - 비워져(flush)야만 합니다. 2730 - 2731 - 2732 - ====================== 2733 - CPU 들이 저지르는 일들 2734 - ====================== 2735 - 2736 - 프로그래머는 CPU 가 메모리 오퍼레이션들을 정확히 요청한대로 수행해 줄 것이라고 2737 - 생각하는데, 예를 들어 다음과 같은 코드를 CPU 에게 넘긴다면: 2738 - 2739 - a = READ_ONCE(*A); 2740 - WRITE_ONCE(*B, b); 2741 - c = READ_ONCE(*C); 2742 - d = READ_ONCE(*D); 2743 - WRITE_ONCE(*E, e); 2744 - 2745 - CPU 는 다음 인스트럭션을 처리하기 전에 현재의 인스트럭션을 위한 메모리 2746 - 오퍼레이션을 완료할 것이라 생각하고, 따라서 시스템 외부에서 관찰하기에도 정해진 2747 - 순서대로 오퍼레이션이 수행될 것으로 예상합니다: 2748 - 2749 - LOAD *A, STORE *B, LOAD *C, LOAD *D, STORE *E. 2750 - 2751 - 2752 - 당연하지만, 실제로는 훨씬 엉망입니다. 많은 CPU 와 컴파일러에서 앞의 가정은 2753 - 성립하지 못하는데 그 이유는 다음과 같습니다: 2754 - 2755 - (*) 로드 오퍼레이션들은 실행을 계속 해나가기 위해 곧바로 완료될 필요가 있는 2756 - 경우가 많은 반면, 스토어 오퍼레이션들은 종종 별다른 문제 없이 유예될 수 2757 - 있습니다; 2758 - 2759 - (*) 로드 오퍼레이션들은 예측적으로 수행될 수 있으며, 필요없는 로드였다고 2760 - 증명된 예측적 로드의 결과는 버려집니다; 2761 - 2762 - (*) 로드 오퍼레이션들은 예측적으로 수행될 수 있으므로, 예상된 이벤트의 2763 - 시퀀스와 다른 시간에 로드가 이뤄질 수 있습니다; 2764 - 2765 - (*) 메모리 액세스 순서는 CPU 버스와 캐시를 좀 더 잘 사용할 수 있도록 재배치 2766 - 될 수 있습니다; 2767 - 2768 - (*) 로드와 스토어는 인접한 위치에의 액세스들을 일괄적으로 처리할 수 있는 2769 - 메모리나 I/O 하드웨어 (메모리와 PCI 디바이스 둘 다 이게 가능할 수 2770 - 있습니다) 에 대해 요청되는 경우, 개별 오퍼레이션을 위한 트랜잭션 설정 2771 - 비용을 아끼기 위해 조합되어 실행될 수 있습니다; 그리고 2772 - 2773 - (*) 해당 CPU 의 데이터 캐시가 순서에 영향을 끼칠 수도 있고, 캐시 일관성 2774 - 메커니즘이 - 스토어가 실제로 캐시에 도달한다면 - 이 문제를 완화시킬 수는 2775 - 있지만 이 일관성 관리가 다른 CPU 들에도 같은 순서로 전달된다는 보장은 2776 - 없습니다. 2777 - 2778 - 따라서, 앞의 코드에 대해 다른 CPU 가 보는 결과는 다음과 같을 수 있습니다: 2779 - 2780 - LOAD *A, ..., LOAD {*C,*D}, STORE *E, STORE *B 2781 - 2782 - ("LOAD {*C,*D}" 는 조합된 로드입니다) 2783 - 2784 - 2785 - 하지만, CPU 는 스스로는 일관적일 것을 보장합니다: CPU _자신_ 의 액세스들은 2786 - 자신에게는 메모리 배리어가 없음에도 불구하고 정확히 순서 세워진 것으로 보여질 2787 - 것입니다. 예를 들어 다음의 코드가 주어졌다면: 2788 - 2789 - U = READ_ONCE(*A); 2790 - WRITE_ONCE(*A, V); 2791 - WRITE_ONCE(*A, W); 2792 - X = READ_ONCE(*A); 2793 - WRITE_ONCE(*A, Y); 2794 - Z = READ_ONCE(*A); 2795 - 2796 - 그리고 외부의 영향에 의한 간섭이 없다고 가정하면, 최종 결과는 다음과 같이 2797 - 나타날 것이라고 예상될 수 있습니다: 2798 - 2799 - U == *A 의 최초 값 2800 - X == W 2801 - Z == Y 2802 - *A == Y 2803 - 2804 - 앞의 코드는 CPU 가 다음의 메모리 액세스 시퀀스를 만들도록 할겁니다: 2805 - 2806 - U=LOAD *A, STORE *A=V, STORE *A=W, X=LOAD *A, STORE *A=Y, Z=LOAD *A 2807 - 2808 - 하지만, 별다른 개입이 없고 프로그램의 시야에 이 세상이 여전히 일관적이라고 2809 - 보인다는 보장만 지켜진다면 이 시퀀스는 어떤 조합으로든 재구성될 수 있으며, 각 2810 - 액세스들은 합쳐지거나 버려질 수 있습니다. 일부 아키텍쳐에서 CPU 는 같은 위치에 2811 - 대한 연속적인 로드 오퍼레이션들을 재배치 할 수 있기 때문에 앞의 예에서의 2812 - READ_ONCE() 와 WRITE_ONCE() 는 반드시 존재해야 함을 알아두세요. 그런 종류의 2813 - 아키텍쳐에서 READ_ONCE() 와 WRITE_ONCE() 는 이 문제를 막기 위해 필요한 일을 2814 - 뭐가 됐든지 하게 되는데, 예를 들어 Itanium 에서는 READ_ONCE() 와 WRITE_ONCE() 2815 - 가 사용하는 volatile 캐스팅은 GCC 가 그런 재배치를 방지하는 특수 인스트럭션인 2816 - ld.acq 와 stl.rel 인스트럭션을 각각 만들어 내도록 합니다. 2817 - 2818 - 컴파일러 역시 이 시퀀스의 액세스들을 CPU 가 보기도 전에 합치거나 버리거나 뒤로 2819 - 미뤄버릴 수 있습니다. 2820 - 2821 - 예를 들어: 2822 - 2823 - *A = V; 2824 - *A = W; 2825 - 2826 - 는 다음과 같이 변형될 수 있습니다: 2827 - 2828 - *A = W; 2829 - 2830 - 따라서, 쓰기 배리어나 WRITE_ONCE() 가 없다면 *A 로의 V 값의 저장의 효과는 2831 - 사라진다고 가정될 수 있습니다. 비슷하게: 2832 - 2833 - *A = Y; 2834 - Z = *A; 2835 - 2836 - 는, 메모리 배리어나 READ_ONCE() 와 WRITE_ONCE() 없이는 다음과 같이 변형될 수 2837 - 있습니다: 2838 - 2839 - *A = Y; 2840 - Z = Y; 2841 - 2842 - 그리고 이 LOAD 오퍼레이션은 CPU 바깥에는 아예 보이지 않습니다. 2843 - 2844 - 2845 - 그리고, ALPHA 가 있다 2846 - --------------------- 2847 - 2848 - DEC Alpha CPU 는 가장 완화된 메모리 순서의 CPU 중 하나입니다. 뿐만 아니라, 2849 - Alpha CPU 의 일부 버전은 분할된 데이터 캐시를 가지고 있어서, 의미적으로 2850 - 관계되어 있는 두개의 캐시 라인이 서로 다른 시간에 업데이트 되는게 가능합니다. 2851 - 이게 주소 의존성 배리어가 정말 필요해지는 부분인데, 주소 의존성 배리어는 메모리 2852 - 일관성 시스템과 함께 두개의 캐시를 동기화 시켜서, 포인터 변경과 새로운 데이터의 2853 - 발견을 올바른 순서로 일어나게 하기 때문입니다. 2854 - 2855 - 리눅스 커널의 메모리 배리어 모델은 Alpha 에 기초해서 정의되었습니다만, v4.15 2856 - 부터는 Alpha 용 READ_ONCE() 코드 내에 smp_mb() 가 추가되어서 메모리 모델로의 2857 - Alpha 의 영향력이 크게 줄어들었습니다. 2858 - 2859 - 2860 - 가상 머신 게스트 2861 - ---------------- 2862 - 2863 - 가상 머신에서 동작하는 게스트들은 게스트 자체는 SMP 지원 없이 컴파일 되었다 2864 - 해도 SMP 영향을 받을 수 있습니다. 이건 UP 커널을 사용하면서 SMP 호스트와 2865 - 결부되어 발생하는 부작용입니다. 이 경우에는 mandatory 배리어를 사용해서 문제를 2866 - 해결할 수 있겠지만 그런 해결은 대부분의 경우 최적의 해결책이 아닙니다. 2867 - 2868 - 이 문제를 완벽하게 해결하기 위해, 로우 레벨의 virt_mb() 등의 매크로를 사용할 수 2869 - 있습니다. 이것들은 SMP 가 활성화 되어 있다면 smp_mb() 등과 동일한 효과를 2870 - 갖습니다만, SMP 와 SMP 아닌 시스템 모두에 대해 동일한 코드를 만들어냅니다. 2871 - 예를 들어, 가상 머신 게스트들은 (SMP 일 수 있는) 호스트와 동기화를 할 때에는 2872 - smp_mb() 가 아니라 virt_mb() 를 사용해야 합니다. 2873 - 2874 - 이것들은 smp_mb() 류의 것들과 모든 부분에서 동일하며, 특히, MMIO 의 영향에 2875 - 대해서는 간여하지 않습니다: MMIO 의 영향을 제어하려면, mandatory 배리어를 2876 - 사용하시기 바랍니다. 2877 - 2878 - 2879 - ======= 2880 - 사용 예 2881 - ======= 2882 - 2883 - 순환식 버퍼 2884 - ----------- 2885 - 2886 - 메모리 배리어는 순환식 버퍼를 생성자(producer)와 소비자(consumer) 사이의 2887 - 동기화에 락을 사용하지 않고 구현하는데에 사용될 수 있습니다. 더 자세한 내용을 2888 - 위해선 다음을 참고하세요: 2889 - 2890 - Documentation/core-api/circular-buffers.rst 2891 - 2892 - 2893 - ========= 2894 - 참고 문헌 2895 - ========= 2896 - 2897 - Alpha AXP Architecture Reference Manual, Second Edition (Sites & Witek, 2898 - Digital Press) 2899 - Chapter 5.2: Physical Address Space Characteristics 2900 - Chapter 5.4: Caches and Write Buffers 2901 - Chapter 5.5: Data Sharing 2902 - Chapter 5.6: Read/Write Ordering 2903 - 2904 - AMD64 Architecture Programmer's Manual Volume 2: System Programming 2905 - Chapter 7.1: Memory-Access Ordering 2906 - Chapter 7.4: Buffering and Combining Memory Writes 2907 - 2908 - ARM Architecture Reference Manual (ARMv8, for ARMv8-A architecture profile) 2909 - Chapter B2: The AArch64 Application Level Memory Model 2910 - 2911 - IA-32 Intel Architecture Software Developer's Manual, Volume 3: 2912 - System Programming Guide 2913 - Chapter 7.1: Locked Atomic Operations 2914 - Chapter 7.2: Memory Ordering 2915 - Chapter 7.4: Serializing Instructions 2916 - 2917 - The SPARC Architecture Manual, Version 9 2918 - Chapter 8: Memory Models 2919 - Appendix D: Formal Specification of the Memory Models 2920 - Appendix J: Programming with the Memory Models 2921 - 2922 - Storage in the PowerPC (Stone and Fitzgerald) 2923 - 2924 - UltraSPARC Programmer Reference Manual 2925 - Chapter 5: Memory Accesses and Cacheability 2926 - Chapter 15: Sparc-V9 Memory Models 2927 - 2928 - UltraSPARC III Cu User's Manual 2929 - Chapter 9: Memory Models 2930 - 2931 - UltraSPARC IIIi Processor User's Manual 2932 - Chapter 8: Memory Models 2933 - 2934 - UltraSPARC Architecture 2005 2935 - Chapter 9: Memory 2936 - Appendix D: Formal Specifications of the Memory Models 2937 - 2938 - UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005 2939 - Chapter 8: Memory Models 2940 - Appendix F: Caches and Cache Coherency 2941 - 2942 - Solaris Internals, Core Kernel Architecture, p63-68: 2943 - Chapter 3.3: Hardware Considerations for Locks and 2944 - Synchronization 2945 - 2946 - Unix Systems for Modern Architectures, Symmetric Multiprocessing and Caching 2947 - for Kernel Programmers: 2948 - Chapter 13: Other Memory Models 2949 - 2950 - Intel Itanium Architecture Software Developer's Manual: Volume 1: 2951 - Section 2.6: Speculation 2952 - Section 4.4: Memory Access
+8 -8
Documentation/translations/sp_SP/process/adding-syscalls.rst
··· 128 128 userspace cuando el kernel ya tiene mecanismos y semánticas bien definidas 129 129 para usar los descriptores de archivos. 130 130 131 - Si su nueva llamada a sistema :manpage:`xyzzy(2)` retorna un nuevo 131 + Si su nueva llamada a sistema xyzzy(2) retorna un nuevo 132 132 descriptor de archivo, entonces el argumento flag debe incluir un valor que 133 133 sea equivalente a definir ``O_CLOEXEC`` en el nuevo FD. Esto hace posible 134 134 al userspace acortar la brecha de tiempo entre ``xyzzy()`` y la llamada a ··· 145 145 indique al espacio de usuario que un evento ha ocurrido en el 146 146 correspondiente objeto del kernel. 147 147 148 - Si su nueva llamada de sistema :manpage:`xyzzy(2)` involucra algún nombre 148 + Si su nueva llamada de sistema xyzzy(2) involucra algún nombre 149 149 de archivo como argumento:: 150 150 151 151 int sys_xyzzy(const char __user *path, ..., unsigned int flags); 152 152 153 - debería considerar también si una versión :manpage:`xyzzyat(2)` es mas 153 + debería considerar también si una versión xyzzyat(2) es mas 154 154 apropiada:: 155 155 156 156 int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags); ··· 158 158 Esto permite más flexibilidad en como el userspace especifica el archivo en 159 159 cuestión; en particular esto permite al userspace pedir la funcionalidad a 160 160 un descriptor de archivo ya abierto usando el flag ``AT_EMPTY_PATH``, 161 - efectivamente dando una operación :manpage:`fxyzzy(3)` gratis:: 161 + efectivamente dando una operación fxyzzy(3) gratis:: 162 162 163 163 - xyzzyat(AT_FDCWD, path, ..., 0) es equivalente a xyzzy(path, ...) 164 164 - xyzzyat(fd, "", ..., AT_EMPTY_PATH) es equivalente a fxyzzy(fd, ...) ··· 167 167 revise el man page :manpage:`openat(2)`; para un ejemplo de AT_EMPTY_PATH, 168 168 mire el man page :manpage:`fstatat(2)` manpage.) 169 169 170 - Si su nueva llamada de sistema :manpage:`xyzzy(2)` involucra un parámetro 170 + Si su nueva llamada de sistema xyzzy(2) involucra un parámetro 171 171 describiendo un describiendo un movimiento dentro de un archivo, ponga de 172 172 tipo ``loff_t`` para que movimientos de 64-bit puedan ser soportados 173 173 incluso en arquitecturas de 32-bit. 174 174 175 - Si su nueva llamada de sistema :manpage:`xyzzy` involucra una 175 + Si su nueva llamada de sistema xyzzy(2) involucra una 176 176 funcionalidad privilegiada, esta necesita ser gobernada por la capability 177 177 bit linux apropiada (revisado con una llamada a ``capable()``), como se 178 178 describe en el man page :manpage:`capabilities(7)`. Elija una parte de ··· 182 182 dividir el poder del usuario root. En particular, evite agregar nuevos usos 183 183 de la capacidad ya demasiado general de la capabilities ``CAP_SYS_ADMIN``. 184 184 185 - Si su nueva llamada de sistema :manpage:`xyzzy(2)` manipula un proceso que 185 + Si su nueva llamada de sistema xyzzy(2) manipula un proceso que 186 186 no es el proceso invocado, este debería ser restringido (usando una llamada 187 187 a ``ptrace_may_access()``) de forma que el único proceso con los mismos 188 188 permisos del proceso objetivo, o con las capacidades (capabilities) ··· 221 221 Implementation de Llamada de Sistema Generica 222 222 --------------------------------------------- 223 223 224 - La entrada principal a su nueva llamada de sistema :manpage:`xyzzy(2)` será 224 + La entrada principal a su nueva llamada de sistema xyzzy(2) será 225 225 llamada ``sys_xyzzy()``, pero incluya este punto de entrada con la macro 226 226 ``SYSCALL_DEFINEn()`` apropiada en vez de explicitamente. El 'n' indica el 227 227 numero de argumentos de la llamada de sistema, y la macro toma el nombre de
+1 -1
Documentation/translations/sp_SP/process/coding-style.rst
··· 633 633 634 634 Al comentar las funciones de la API del kernel, utilice el formato 635 635 kernel-doc. Consulte los archivos en :ref:`Documentation/doc-guide/ <doc_guide>` 636 - y ``scripts/kernel-doc`` para más detalles. 636 + y ``tools/docs/kernel-doc`` para más detalles. 637 637 638 638 El estilo preferido para comentarios largos (de varias líneas) es: 639 639
+5 -5
Documentation/translations/zh_CN/doc-guide/kernel-doc.rst
··· 43 43 用详细模式和不生成实际输出来运行 ``kernel-doc`` 工具,可以验证文档注释的格式 44 44 是否正确。例如:: 45 45 46 - scripts/kernel-doc -v -none drivers/foo/bar.c 46 + tools/docs/kernel-doc -v -none drivers/foo/bar.c 47 47 48 48 当请求执行额外的gcc检查时,内核构建将验证文档格式:: 49 49 ··· 473 473 如果没有选项,kernel-doc指令将包含源文件中的所有文档注释。 474 474 475 475 kernel-doc扩展包含在内核源代码树中,位于 ``Documentation/sphinx/kerneldoc.py`` 。 476 - 在内部,它使用 ``scripts/kernel-doc`` 脚本从源代码中提取文档注释。 476 + 在内部,它使用 ``tools/docs/kernel-doc`` 脚本从源代码中提取文档注释。 477 477 478 478 .. _kernel_doc_zh: 479 479 ··· 482 482 483 483 如果您只想使用kernel-doc生成手册页,可以从内核git树这样做:: 484 484 485 - $ scripts/kernel-doc -man \ 485 + $ tools/docs/kernel-doc -man \ 486 486 $(git grep -l '/\*\*' -- :^Documentation :^tools) \ 487 487 | scripts/split-man.pl /tmp/man 488 488 489 489 一些旧版本的git不支持路径排除语法的某些变体。 490 490 以下命令之一可能适用于这些版本:: 491 491 492 - $ scripts/kernel-doc -man \ 492 + $ tools/docs/kernel-doc -man \ 493 493 $(git grep -l '/\*\*' -- . ':!Documentation' ':!tools') \ 494 494 | scripts/split-man.pl /tmp/man 495 495 496 - $ scripts/kernel-doc -man \ 496 + $ tools/docs/kernel-doc -man \ 497 497 $(git grep -l '/\*\*' -- . ":(exclude)Documentation" ":(exclude)tools") \ 498 498 | scripts/split-man.pl /tmp/man 499 499
+1 -1
Documentation/translations/zh_CN/kbuild/kbuild.rst
··· 174 174 KDOCFLAGS 175 175 --------- 176 176 指定在构建过程中用于 kernel-doc 检查的额外(警告/错误)标志,查看 177 - scripts/kernel-doc 了解支持的标志。请注意,这目前不适用于文档构建。 177 + tools/docs/kernel-doc 了解支持的标志。请注意,这目前不适用于文档构建。 178 178 179 179 ARCH 180 180 ----
+1 -1
Documentation/translations/zh_CN/process/coding-style.rst
··· 545 545 也可以加上它做这些事情的原因。 546 546 547 547 当注释内核 API 函数时,请使用 kernel-doc 格式。详见 548 - Documentation/translations/zh_CN/doc-guide/index.rst 和 scripts/kernel-doc 。 548 + Documentation/translations/zh_CN/doc-guide/index.rst 和 tools/docs/kernel-doc 。 549 549 550 550 长 (多行) 注释的首选风格是: 551 551
+1 -1
Documentation/translations/zh_TW/process/coding-style.rst
··· 548 548 也可以加上它做這些事情的原因。 549 549 550 550 當註釋內核 API 函數時,請使用 kernel-doc 格式。詳見 551 - Documentation/translations/zh_CN/doc-guide/index.rst 和 scripts/kernel-doc 。 551 + Documentation/translations/zh_CN/doc-guide/index.rst 和 tools/docs/kernel-doc 。 552 552 553 553 長 (多行) 註釋的首選風格是: 554 554
-7
Documentation/usb/index.rst
··· 31 31 32 32 usb-help 33 33 text_files 34 - 35 - .. only:: subproject and html 36 - 37 - Indices 38 - ======= 39 - 40 - * :ref:`genindex`
-7
Documentation/userspace-api/gpio/index.rst
··· 9 9 10 10 Character Device Userspace API <chardev> 11 11 Obsolete Userspace APIs <obsolete> 12 - 13 - .. only:: subproject and html 14 - 15 - Indices 16 - ======= 17 - 18 - * :ref:`genindex`
-7
Documentation/userspace-api/index.rst
··· 68 68 futex2 69 69 perf_ring_buffer 70 70 ntsync 71 - 72 - .. only:: subproject and html 73 - 74 - Indices 75 - ======= 76 - 77 - * :ref:`genindex`
+1 -1
Documentation/userspace-api/ioctl/ioctl-number.rst
··· 15 15 ====== =========================== 16 16 _IO none 17 17 _IOW write (read from userspace) 18 - _IOR read (write to userpace) 18 + _IOR read (write to userspace) 19 19 _IOWR write and read 20 20 ====== =========================== 21 21
-7
Documentation/virt/index.rst
··· 16 16 coco/sev-guest 17 17 coco/tdx-guest 18 18 hyperv/index 19 - 20 - .. only:: html and subproject 21 - 22 - Indices 23 - ======= 24 - 25 - * :ref:`genindex`
-7
Documentation/w1/index.rst
··· 12 12 w1-netlink.rst 13 13 masters/index 14 14 slaves/index 15 - 16 - .. only:: subproject and html 17 - 18 - Indices 19 - ======= 20 - 21 - * :ref:`genindex`
-7
Documentation/watchdog/index.rst
··· 16 16 watchdog-pm 17 17 wdt 18 18 convert_drivers_to_kernel_api 19 - 20 - .. only:: subproject and html 21 - 22 - Indices 23 - ======= 24 - 25 - * :ref:`genindex`
-7
Documentation/wmi/devices/index.rst
··· 13 13 :glob: 14 14 15 15 * 16 - 17 - .. only:: subproject and html 18 - 19 - Indices 20 - ======= 21 - 22 - * :ref:`genindex`
-8
Documentation/wmi/index.rst
··· 10 10 acpi-interface 11 11 driver-development-guide 12 12 devices/index 13 - 14 - .. only:: subproject and html 15 - 16 - 17 - Indices 18 - ======= 19 - 20 - * :ref:`genindex`
+3 -2
MAINTAINERS
··· 7528 7528 7529 7529 DOCUMENTATION 7530 7530 M: Jonathan Corbet <corbet@lwn.net> 7531 + R: Shuah Khan <skhan@linuxfoundation.org> 7531 7532 L: linux-doc@vger.kernel.org 7532 7533 S: Maintained 7533 7534 P: Documentation/doc-guide/maintainer-profile.rst 7534 7535 T: git git://git.lwn.net/linux.git docs-next 7535 7536 F: Documentation/ 7536 - F: scripts/kernel-doc* 7537 7537 F: tools/lib/python/* 7538 7538 F: tools/docs/ 7539 7539 F: tools/net/ynl/pyynl/lib/doc_generator.py ··· 7550 7550 7551 7551 DOCUMENTATION PROCESS 7552 7552 M: Jonathan Corbet <corbet@lwn.net> 7553 + R: Shuah Khan <skhan@linuxfoundation.org> 7553 7554 L: workflows@vger.kernel.org 7554 7555 S: Maintained 7555 7556 F: Documentation/dev-tools/ ··· 7571 7570 L: linux-doc@vger.kernel.org 7572 7571 S: Maintained 7573 7572 F: Documentation/sphinx/ 7574 - F: scripts/kernel-doc* 7575 7573 F: tools/lib/python/* 7576 7574 F: tools/docs/ 7577 7575 ··· 21985 21985 M: Steven Rostedt <rostedt@goodmis.org> 21986 21986 L: linux-rt-devel@lists.linux.dev 21987 21987 S: Supported 21988 + F: Documentation/core-api/real-time/ 21988 21989 K: PREEMPT_RT 21989 21990 21990 21991 REALTEK AUDIO CODECS
+1 -1
Makefile
··· 460 460 461 461 # the KERNELDOC macro needs to be exported, as scripts/Makefile.build 462 462 # has a logic to call it 463 - KERNELDOC = $(srctree)/scripts/kernel-doc.py 463 + KERNELDOC = $(srctree)/tools/docs/kernel-doc 464 464 export KERNELDOC 465 465 466 466 KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
+12
README
··· 38 38 * Maintainer - Leading subsystems and reviewing patches 39 39 * Hardware Vendor - Writing drivers for new hardware 40 40 * Distribution Maintainer - Packaging kernels for distros 41 + * AI Coding Assistant - LLMs and AI-powered development tools 41 42 42 43 43 44 For Specific Users ··· 145 144 * Kernel Parameters: Documentation/admin-guide/kernel-parameters.rst 146 145 * Tainted Kernels: Documentation/admin-guide/tainted-kernels.rst 147 146 147 + AI Coding Assistant 148 + ------------------- 149 + 150 + CRITICAL: If you are an LLM or AI-powered coding assistant, you MUST read and 151 + follow the AI coding assistants documentation before contributing to the Linux 152 + kernel: 153 + 154 + * Documentation/process/coding-assistants.rst 155 + 156 + This documentation contains essential requirements about licensing, attribution, 157 + and the Developer Certificate of Origin that all AI tools must comply with. 148 158 149 159 150 160 Communication and Support
+1 -1
drivers/gpu/drm/i915/Makefile
··· 443 443 444 444 quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) 445 445 cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; \ 446 - $(srctree)/scripts/kernel-doc -none -Werror $<; touch $@ 446 + $(KERNELDOC) -none -Werror $<; touch $@ 447 447 448 448 $(obj)/%.hdrtest: $(src)/%.h FORCE 449 449 $(call if_changed_dep,hdrtest)
+1 -1
include/linux/util_macros.h
··· 119 119 * a fuss about it. This makes the programmer responsible for tagging 120 120 * the functions that can be garbage-collected. 121 121 * 122 - * With the macro it is possible to write the following: 122 + * With the macro it is possible to write the following:: 123 123 * 124 124 * static int foo_suspend(struct device *dev) 125 125 * {
+15
include/media/v4l2-ioctl.h
··· 663 663 struct video_device; 664 664 665 665 /* names for fancy debug output */ 666 + 667 + /** 668 + * var v4l2_field_names - Helper array mapping ``V4L2_FIELD_*`` to strings. 669 + * 670 + * Specially when printing debug messages, it is interesting to output 671 + * the field order at the V4L2 buffers. This array associates all possible 672 + * values of field pix format from V4L2 API into a string. 673 + */ 666 674 extern const char *v4l2_field_names[]; 675 + 676 + /** 677 + * var v4l2_type_names - Helper array mapping ``V4L2_BUF_TYPE_*`` to strings. 678 + * 679 + * When printing debug messages, it is interesting to output the V4L2 buffer 680 + * type number with a name that represents its content. 681 + */ 667 682 extern const char *v4l2_type_names[]; 668 683 669 684 #ifdef CONFIG_COMPAT
+58 -31
scripts/kernel-doc.py tools/docs/kernel-doc
··· 3 3 # Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>. 4 4 # 5 5 # pylint: disable=C0103,R0912,R0914,R0915 6 - 6 + # 7 7 # NOTE: While kernel-doc requires at least version 3.6 to run, the 8 8 # command line should work with Python 3.2+ (tested with 3.4). 9 9 # The rationale is that it shall fail gracefully during Kernel 10 10 # compilation with older Kernel versions. Due to that: 11 11 # - encoding line is needed here; 12 - # - no f-strings can be used on this file. 13 - # - the libraries that require newer versions can only be included 14 - # after Python version is checked. 15 - 12 + # - f-strings cannot be used in this file. 13 + # - libraries that require newer versions can only be included 14 + # after the Python version has been checked. 15 + # 16 16 # Converted from the kernel-doc script originally written in Perl 17 17 # under GPLv2, copyrighted since 1998 by the following authors: 18 18 # ··· 88 88 # Yujie Liu <yujie.liu@intel.com> 89 89 90 90 """ 91 - kernel_doc 92 - ========== 93 - 94 - Print formatted kernel documentation to stdout 91 + Print formatted kernel documentation to stdout. 95 92 96 93 Read C language source or header FILEs, extract embedded 97 94 documentation comments, and print formatted documentation 98 95 to standard output. 99 96 100 - The documentation comments are identified by the "/**" 97 + The documentation comments are identified by the ``/**`` 101 98 opening comment mark. 102 99 103 100 See Documentation/doc-guide/kernel-doc.rst for the ··· 108 111 109 112 # Import Python modules 110 113 111 - LIB_DIR = "../tools/lib/python" 114 + LIB_DIR = "../lib/python" 112 115 SRC_DIR = os.path.dirname(os.path.realpath(__file__)) 113 116 114 117 sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR)) 118 + 119 + WERROR_RETURN_CODE = 3 115 120 116 121 DESC = """ 117 122 Read C language source or header FILEs, extract embedded documentation comments, ··· 131 132 """ 132 133 133 134 EXPORT_DESC = """ 134 - Only output documentation for the symbols that have been 135 + Only output documentation for symbols that have been 135 136 exported using EXPORT_SYMBOL() and related macros in any input 136 137 FILE or -export-file FILE. 137 138 """ 138 139 139 140 INTERNAL_DESC = """ 140 - Only output documentation for the symbols that have NOT been 141 + Only output documentation for symbols that have NOT been 141 142 exported using EXPORT_SYMBOL() and related macros in any input 142 143 FILE or -export-file FILE. 143 144 """ ··· 160 161 """ 161 162 162 163 WARN_CONTENTS_BEFORE_SECTIONS_DESC = """ 163 - Warns if there are contents before sections (deprecated). 164 + Warn if there are contents before sections (deprecated). 164 165 165 166 This option is kept just for backward-compatibility, but it does nothing, 166 167 neither here nor at the original Perl script. 167 168 """ 168 169 170 + EPILOG = """ 171 + The return value is: 172 + 173 + - 0: success or Python version is not compatible with 174 + kernel-doc. If -Werror is not used, it will also 175 + return 0 if there are issues at kernel-doc markups; 176 + 177 + - 1: an abnormal condition happened; 178 + 179 + - 2: argparse issued an error; 180 + 181 + - 3: When -Werror is used, it means that one or more unfiltered parse 182 + warnings happened. 183 + """ 169 184 170 185 class MsgFormatter(logging.Formatter): 171 - """Helper class to format warnings on a similar way to kernel-doc.pl""" 186 + """ 187 + Helper class to capitalize errors and warnings, the same way 188 + the venerable (now retired) kernel-doc.pl used to do. 189 + """ 172 190 173 191 def format(self, record): 174 192 record.levelname = record.levelname.capitalize() 175 193 return logging.Formatter.format(self, record) 176 194 177 195 def main(): 178 - """Main program""" 196 + """ 197 + Main program. 198 + 199 + """ 179 200 180 201 parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 181 - description=DESC) 202 + description=DESC, epilog=EPILOG) 182 203 204 + # 183 205 # Normal arguments 184 - 206 + # 185 207 parser.add_argument("-v", "-verbose", "--verbose", action="store_true", 186 208 help="Verbose output, more warnings and other information.") 187 209 ··· 217 197 action="store_true", 218 198 help="Enable line number output (only in ReST mode)") 219 199 200 + # 220 201 # Arguments to control the warning behavior 221 - 202 + # 222 203 parser.add_argument("-Wreturn", "--wreturn", action="store_true", 223 204 help="Warns about the lack of a return markup on functions.") 224 205 ··· 240 219 parser.add_argument("-export-file", "--export-file", action='append', 241 220 help=EXPORT_FILE_DESC) 242 221 222 + # 243 223 # Output format mutually-exclusive group 244 - 224 + # 245 225 out_group = parser.add_argument_group("Output format selection (mutually exclusive)") 246 226 247 227 out_fmt = out_group.add_mutually_exclusive_group() ··· 254 232 out_fmt.add_argument("-N", "-none", "--none", action="store_true", 255 233 help="Do not output documentation, only warnings.") 256 234 235 + # 257 236 # Output selection mutually-exclusive group 258 - 237 + # 259 238 sel_group = parser.add_argument_group("Output selection (mutually exclusive)") 260 239 sel_mut = sel_group.add_mutually_exclusive_group() 261 240 ··· 269 246 sel_mut.add_argument("-s", "-function", "--symbol", action='append', 270 247 help=FUNCTION_DESC) 271 248 249 + # 272 250 # Those are valid for all 3 types of filter 251 + # 273 252 parser.add_argument("-n", "-nosymbol", "--nosymbol", action='append', 274 253 help=NOSYMBOL_DESC) 275 254 276 255 parser.add_argument("-D", "-no-doc-sections", "--no-doc-sections", 277 - action='store_true', help="Don't outputt DOC sections") 256 + action='store_true', help="Don't output DOC sections") 278 257 279 258 parser.add_argument("files", metavar="FILE", 280 259 nargs="+", help=FILES_DESC) ··· 304 279 305 280 python_ver = sys.version_info[:2] 306 281 if python_ver < (3,6): 307 - # Depending on Kernel configuration, kernel-doc --none is called at 282 + # 283 + # Depending on the Kernel configuration, kernel-doc --none is called at 308 284 # build time. As we don't want to break compilation due to the 309 285 # usage of an old Python version, return 0 here. 286 + # 310 287 if args.none: 311 - logger.error("Python 3.6 or later is required by kernel-doc. skipping checks") 288 + logger.error("Python 3.6 or later is required by kernel-doc. Skipping checks") 312 289 sys.exit(0) 313 290 314 291 sys.exit("Python 3.6 or later is required by kernel-doc. Aborting.") ··· 318 291 if python_ver < (3,7): 319 292 logger.warning("Python 3.7 or later is required for correct results") 320 293 321 - # Import kernel-doc libraries only after checking Python version 294 + # 295 + # Import kernel-doc libraries only after checking the Python version 296 + # 322 297 from kdoc.kdoc_files import KernelFiles # pylint: disable=C0415 323 298 from kdoc.kdoc_output import RestFormat, ManFormat # pylint: disable=C0415 324 299 ··· 352 323 353 324 if args.werror: 354 325 print("%s warnings as errors" % error_count) # pylint: disable=C0209 355 - sys.exit(error_count) 326 + sys.exit(WERROR_RETURN_CODE) 356 327 357 328 if args.verbose: 358 329 print("%s errors" % error_count) # pylint: disable=C0209 359 330 360 - if args.none: 361 - sys.exit(0) 331 + sys.exit(0) 362 332 363 - sys.exit(error_count) 364 - 365 - 333 + # 366 334 # Call main method 335 + # 367 336 if __name__ == "__main__": 368 337 main()
+2 -2
tools/docs/find-unused-docs.sh
··· 28 28 fi 29 29 30 30 cd "$( dirname "${BASH_SOURCE[0]}" )" 31 - cd .. 31 + cd ../.. 32 32 33 33 cd Documentation/ 34 34 ··· 54 54 if [[ ${FILES_INCLUDED[$file]+_} ]]; then 55 55 continue; 56 56 fi 57 - str=$(PYTHONDONTWRITEBYTECODE=1 scripts/kernel-doc -export "$file" 2>/dev/null) 57 + str=$(PYTHONDONTWRITEBYTECODE=1 tools/docs/kernel-doc -export "$file" 2>/dev/null) 58 58 if [[ -n "$str" ]]; then 59 59 echo "$file" 60 60 fi
+85 -54
tools/docs/sphinx-build-wrapper
··· 119 119 120 120 return path 121 121 122 - def check_rust(self): 122 + def check_rust(self, sphinxdirs): 123 123 """ 124 124 Checks if Rust is enabled 125 125 """ 126 - self.rustdoc = False 127 - 128 126 config = os.path.join(self.srctree, ".config") 129 127 128 + if not {'.', 'rust'}.intersection(sphinxdirs): 129 + return False 130 + 130 131 if not os.path.isfile(config): 131 - return 132 + return False 132 133 133 134 re_rust = re.compile(r"CONFIG_RUST=(m|y)") 134 135 ··· 137 136 with open(config, "r", encoding="utf-8") as fp: 138 137 for line in fp: 139 138 if re_rust.match(line): 140 - self.rustdoc = True 141 - return 139 + return True 142 140 143 141 except OSError as e: 144 142 print(f"Failed to open {config}", file=sys.stderr) 143 + return False 144 + 145 + return False 145 146 146 147 def get_sphinx_extra_opts(self, n_jobs): 147 148 """ ··· 168 165 parser = argparse.ArgumentParser() 169 166 parser.add_argument('-j', '--jobs', type=int) 170 167 parser.add_argument('-q', '--quiet', action='store_true') 168 + parser.add_argument('-v', '--verbose', default=0, action='count') 171 169 172 170 # 173 171 # Other sphinx-build arguments go as-is, so place them ··· 180 176 # Build a list of sphinx args, honoring verbosity here if specified 181 177 # 182 178 183 - verbose = self.verbose 184 179 sphinx_args, self.sphinxopts = parser.parse_known_args(sphinxopts) 180 + 181 + verbose = sphinx_args.verbose 182 + if self.verbose: 183 + verbose += 1 184 + 185 185 if sphinx_args.quiet is True: 186 - verbose = False 186 + verbose = 0 187 187 188 188 # 189 189 # If the user explicitly sets "-j" at command line, use it. ··· 200 192 else: 201 193 self.n_jobs = None 202 194 203 - if not verbose: 195 + if verbose < 1: 204 196 self.sphinxopts += ["-q"] 197 + else: 198 + for i in range(1, sphinx_args.verbose): 199 + self.sphinxopts += ["-v"] 205 200 206 201 def __init__(self, builddir, venv=None, verbose=False, n_jobs=None, 207 202 interactive=None): ··· 257 246 # 258 247 self.sphinxbuild = os.environ.get("SPHINXBUILD", "sphinx-build") 259 248 self.kerneldoc = self.get_path(os.environ.get("KERNELDOC", 260 - "scripts/kernel-doc.py")) 249 + "tools/docs/kernel-doc")) 261 250 self.builddir = self.get_path(builddir, use_cwd=True, abs_path=True) 262 251 263 252 # ··· 269 258 self.env = os.environ.copy() 270 259 271 260 self.get_sphinx_extra_opts(n_jobs) 272 - 273 - self.check_rust() 274 261 275 262 # 276 263 # If venv command line argument is specified, run Sphinx from venv ··· 360 351 shutil.copy2(css, static_dir) 361 352 except (OSError, IOError) as e: 362 353 print(f"Warning: Failed to copy CSS: {e}", file=sys.stderr) 363 - 364 - if self.rustdoc: 365 - print("Building rust docs") 366 - if "MAKE" in self.env: 367 - cmd = [self.env["MAKE"]] 368 - else: 369 - cmd = ["make", "LLVM=1"] 370 - 371 - cmd += [ "rustdoc"] 372 - if self.verbose: 373 - print(" ".join(cmd)) 374 - 375 - try: 376 - subprocess.run(cmd, check=True) 377 - except subprocess.CalledProcessError as e: 378 - print(f"Ignored errors when building rustdoc: {e}. Is RUST enabled?", 379 - file=sys.stderr) 380 354 381 355 def build_pdf_file(self, latex_cmd, from_dir, path): 382 356 """Builds a single pdf file using latex_cmd""" ··· 681 689 if kerneldoc.startswith(self.srctree): 682 690 kerneldoc = os.path.relpath(kerneldoc, self.srctree) 683 691 684 - args = [ "-b", builder, "-c", docs_dir ] 685 - 686 - if builder == "latex": 687 - if not paper: 688 - paper = PAPER[1] 689 - 690 - args.extend(["-D", f"latex_elements.papersize={paper}paper"]) 691 - 692 - if self.rustdoc: 693 - args.extend(["-t", "rustdoc"]) 694 - 695 692 if not sphinxdirs: 696 693 sphinxdirs = os.environ.get("SPHINXDIRS", ".") 697 - 698 - # 699 - # The sphinx-build tool has a bug: internally, it tries to set 700 - # locale with locale.setlocale(locale.LC_ALL, ''). This causes a 701 - # crash if language is not set. Detect and fix it. 702 - # 703 - try: 704 - locale.setlocale(locale.LC_ALL, '') 705 - except locale.Error: 706 - self.env["LC_ALL"] = "C" 707 694 708 695 # 709 696 # sphinxdirs can be a list or a whitespace-separated string ··· 693 722 sphinxdirs_list += sphinxdir 694 723 else: 695 724 sphinxdirs_list += sphinxdir.split() 725 + 726 + args = [ "-b", builder, "-c", docs_dir ] 727 + 728 + if builder == "latex": 729 + if not paper: 730 + paper = PAPER[1] 731 + 732 + args.extend(["-D", f"latex_elements.papersize={paper}paper"]) 733 + 734 + rustdoc = self.check_rust(sphinxdirs_list) 735 + if rustdoc: 736 + args.extend(["-t", "rustdoc"]) 737 + 738 + # 739 + # The sphinx-build tool has a bug: internally, it tries to set 740 + # locale with locale.setlocale(locale.LC_ALL, ''). This causes a 741 + # crash if language is not set. Detect and fix it. 742 + # 743 + try: 744 + locale.setlocale(locale.LC_ALL, '') 745 + except locale.Error: 746 + self.env["LC_ALL"] = "C" 696 747 697 748 # 698 749 # Step 1: Build each directory in separate. ··· 743 750 744 751 build_args = args + [ 745 752 "-d", doctree_dir, 746 - "-D", f"kerneldoc_bin={kerneldoc}", 747 753 "-D", f"version={self.kernelversion}", 748 754 "-D", f"release={self.kernelrelease}", 749 755 "-D", f"kerneldoc_srctree={self.srctree}", ··· 778 786 elif target == "infodocs": 779 787 self.handle_info(output_dirs) 780 788 789 + if rustdoc and target in ["htmldocs", "epubdocs"]: 790 + print("Building rust docs") 791 + if "MAKE" in self.env: 792 + cmd = [self.env["MAKE"]] 793 + else: 794 + cmd = ["make", "LLVM=1"] 795 + 796 + cmd += [ "rustdoc"] 797 + if self.verbose: 798 + print(" ".join(cmd)) 799 + 800 + try: 801 + subprocess.run(cmd, check=True) 802 + except subprocess.CalledProcessError as e: 803 + print(f"Ignored errors when building rustdoc: {e}. Is RUST enabled?", 804 + file=sys.stderr) 805 + 781 806 def jobs_type(value): 782 807 """ 783 808 Handle valid values for -j. Accepts Sphinx "-jauto", plus a number ··· 814 805 except ValueError: 815 806 raise argparse.ArgumentTypeError(f"Must be 'auto' or positive integer, got {value}") # pylint: disable=W0707 816 807 808 + EPILOG=""" 809 + Besides the command line arguments, several environment variables affect its 810 + default behavior, meant to be used when called via Kernel Makefile: 811 + 812 + - KERNELVERSION: Kernel major version 813 + - KERNELRELEASE: Kernel release 814 + - KBUILD_VERBOSE: Contains the value of "make V=[0|1] variable. 815 + When V=0 (KBUILD_VERBOSE=0), sets verbose level to "-q". 816 + - SPHINXBUILD: Documentation build tool (default: "sphinx-build"). 817 + - SPHINXOPTS: Extra options pased to SPHINXBUILD 818 + (default: "-j auto" and "-q" if KBUILD_VERBOSE=0). 819 + The "-v" flag can be used to increase verbosity. 820 + If V=0, the first "-v" will drop "-q". 821 + - PYTHON3: Python command to run SPHINXBUILD 822 + - PDFLATEX: LaTeX PDF engine. (default: "xelatex") 823 + - LATEXOPTS: Optional set of command line arguments to the LaTeX engine 824 + - srctree: Location of the Kernel root directory (default: "."). 825 + 826 + """ 827 + 817 828 def main(): 818 829 """ 819 830 Main function. The only mandatory argument is the target. If not 820 831 specified, the other arguments will use default values if not 821 832 specified at os.environ. 822 833 """ 823 - parser = argparse.ArgumentParser(description="Kernel documentation builder") 834 + parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 835 + description=__doc__, 836 + epilog=EPILOG) 824 837 825 838 parser.add_argument("target", choices=list(TARGETS.keys()), 826 839 help="Documentation target to build") 827 840 parser.add_argument("--sphinxdirs", nargs="+", 828 841 help="Specific directories to build") 829 842 parser.add_argument("--builddir", default="output", 830 - help="Sphinx configuration file") 843 + help="Sphinx configuration file (default: %(default)s)") 831 844 832 845 parser.add_argument("--theme", help="Sphinx theme to use") 833 846 ··· 865 834 help="place build in verbose mode") 866 835 867 836 parser.add_argument('-j', '--jobs', type=jobs_type, 868 - help="Sets number of jobs to use with sphinx-build") 837 + help="Sets number of jobs to use with sphinx-build(default: auto)") 869 838 870 839 parser.add_argument('-i', '--interactive', action='store_true', 871 840 help="Change latex default to run in interactive mode")
+18 -15
tools/lib/python/abi/abi_parser.py
··· 21 21 22 22 23 23 class AbiParser: 24 - """Main class to parse ABI files""" 24 + """Main class to parse ABI files.""" 25 25 26 + #: Valid tags at Documentation/ABI. 26 27 TAGS = r"(what|where|date|kernelversion|contact|description|users)" 28 + 29 + #: ABI elements that will auto-generate cross-references. 27 30 XREF = r"(?:^|\s|\()(\/(?:sys|config|proc|dev|kvd)\/[^,.:;\)\s]+)(?:[,.:;\)\s]|\Z)" 28 31 29 32 def __init__(self, directory, logger=None, 30 33 enable_lineno=False, show_warnings=True, debug=0): 31 - """Stores arguments for the class and initialize class vars""" 34 + """Stores arguments for the class and initialize class vars.""" 32 35 33 36 self.directory = directory 34 37 self.enable_lineno = enable_lineno ··· 68 65 self.re_xref_node = re.compile(self.XREF) 69 66 70 67 def warn(self, fdata, msg, extra=None): 71 - """Displays a parse error if warning is enabled""" 68 + """Displays a parse error if warning is enabled.""" 72 69 73 70 if not self.show_warnings: 74 71 return ··· 80 77 self.log.warning(msg) 81 78 82 79 def add_symbol(self, what, fname, ln=None, xref=None): 83 - """Create a reference table describing where each 'what' is located""" 80 + """Create a reference table describing where each 'what' is located.""" 84 81 85 82 if what not in self.what_symbols: 86 83 self.what_symbols[what] = {"file": {}} ··· 95 92 self.what_symbols[what]["xref"] = xref 96 93 97 94 def _parse_line(self, fdata, line): 98 - """Parse a single line of an ABI file""" 95 + """Parse a single line of an ABI file.""" 99 96 100 97 new_what = False 101 98 new_tag = False ··· 267 264 self.warn(fdata, "Unexpected content", line) 268 265 269 266 def parse_readme(self, nametag, fname): 270 - """Parse ABI README file""" 267 + """Parse ABI README file.""" 271 268 272 269 nametag["what"] = ["Introduction"] 273 270 nametag["path"] = "README" ··· 285 282 nametag["description"] += line 286 283 287 284 def parse_file(self, fname, path, basename): 288 - """Parse a single file""" 285 + """Parse a single file.""" 289 286 290 287 ref = f"abi_file_{path}_{basename}" 291 288 ref = self.re_unprintable.sub("_", ref).strip("_") ··· 351 348 self.add_symbol(what=w, fname=fname, xref=fdata.key) 352 349 353 350 def _parse_abi(self, root=None): 354 - """Internal function to parse documentation ABI recursively""" 351 + """Internal function to parse documentation ABI recursively.""" 355 352 356 353 if not root: 357 354 root = self.directory ··· 380 377 self.parse_file(name, path, basename) 381 378 382 379 def parse_abi(self, root=None): 383 - """Parse documentation ABI""" 380 + """Parse documentation ABI.""" 384 381 385 382 self._parse_abi(root) 386 383 ··· 388 385 self.log.debug(pformat(self.data)) 389 386 390 387 def desc_txt(self, desc): 391 - """Print description as found inside ABI files""" 388 + """Print description as found inside ABI files.""" 392 389 393 390 desc = desc.strip(" \t\n") 394 391 ··· 396 393 397 394 def xref(self, fname): 398 395 """ 399 - Converts a Documentation/ABI + basename into a ReST cross-reference 396 + Converts a Documentation/ABI + basename into a ReST cross-reference. 400 397 """ 401 398 402 399 xref = self.file_refs.get(fname) ··· 406 403 return xref 407 404 408 405 def desc_rst(self, desc): 409 - """Enrich ReST output by creating cross-references""" 406 + """Enrich ReST output by creating cross-references.""" 410 407 411 408 # Remove title markups from the description 412 409 # Having titles inside ABI files will only work if extra ··· 462 459 463 460 def doc(self, output_in_txt=False, show_symbols=True, show_file=True, 464 461 filter_path=None): 465 - """Print ABI at stdout""" 462 + """Print ABI at stdout.""" 466 463 467 464 part = None 468 465 for key, v in sorted(self.data.items(), ··· 552 549 yield (msg, file_ref[0][0], ln) 553 550 554 551 def check_issues(self): 555 - """Warn about duplicated ABI entries""" 552 + """Warn about duplicated ABI entries.""" 556 553 557 554 for what, v in self.what_symbols.items(): 558 555 files = v.get("file") ··· 578 575 self.log.warning("%s is defined %d times: %s", what, len(f), "; ".join(f)) 579 576 580 577 def search_symbols(self, expr): 581 - """ Searches for ABI symbols """ 578 + """ Searches for ABI symbols.""" 582 579 583 580 regex = re.compile(expr, re.I) 584 581
+20 -6
tools/lib/python/abi/abi_regex.py
··· 16 16 from abi.helpers import AbiDebug 17 17 18 18 class AbiRegex(AbiParser): 19 - """Extends AbiParser to search ABI nodes with regular expressions""" 19 + """ 20 + Extends AbiParser to search ABI nodes with regular expressions. 20 21 21 - # Escape only ASCII visible characters 22 + There some optimizations here to allow a quick symbol search: 23 + instead of trying to place all symbols altogether an doing linear 24 + search which is very time consuming, create a tree with one depth, 25 + grouping similar symbols altogether. 26 + 27 + Yet, sometimes a full search will be needed, so we have a special branch 28 + on such group tree where other symbols are placed. 29 + """ 30 + 31 + #: Escape only ASCII visible characters. 22 32 escape_symbols = r"([\x21-\x29\x2b-\x2d\x3a-\x40\x5c\x60\x7b-\x7e])" 33 + 34 + #: Special group for other nodes. 23 35 leave_others = "others" 24 36 25 37 # Tuples with regular expressions to be compiled and replacement data ··· 100 88 # Recover plus characters 101 89 (re.compile(r"\xf7"), "+"), 102 90 ] 91 + 92 + #: Regex to check if the symbol name has a number on it. 103 93 re_has_num = re.compile(r"\\d") 104 94 105 - # Symbol name after escape_chars that are considered a devnode basename 95 + #: Symbol name after escape_chars that are considered a devnode basename. 106 96 re_symbol_name = re.compile(r"(\w|\\[\.\-\:])+$") 107 97 108 - # List of popular group names to be skipped to minimize regex group size 109 - # Use AbiDebug.SUBGROUP_SIZE to detect those 98 + #: List of popular group names to be skipped to minimize regex group size 99 + #: Use AbiDebug.SUBGROUP_SIZE to detect those. 110 100 skip_names = set(["devices", "hwmon"]) 111 101 112 102 def regex_append(self, what, new): ··· 162 148 def get_regexes(self, what): 163 149 """ 164 150 Given an ABI devnode, return a list of all regular expressions that 165 - may match it, based on the sub-groups created by regex_append() 151 + may match it, based on the sub-groups created by regex_append(). 166 152 """ 167 153 168 154 re_list = []
+22 -20
tools/lib/python/abi/helpers.py
··· 13 13 class AbiDebug: 14 14 """Debug levels""" 15 15 16 - WHAT_PARSING = 1 17 - WHAT_OPEN = 2 18 - DUMP_ABI_STRUCTS = 4 19 - UNDEFINED = 8 20 - REGEX = 16 21 - SUBGROUP_MAP = 32 22 - SUBGROUP_DICT = 64 23 - SUBGROUP_SIZE = 128 24 - GRAPH = 256 16 + WHAT_PARSING = 1 #: Enable debug parsing logic. 17 + WHAT_OPEN = 2 #: Enable debug messages on file open. 18 + DUMP_ABI_STRUCTS = 4 #: Enable debug for ABI parse data. 19 + UNDEFINED = 8 #: Enable extra undefined symbol data. 20 + REGEX = 16 #: Enable debug for what to regex conversion. 21 + SUBGROUP_MAP = 32 #: Enable debug for symbol regex subgroups 22 + SUBGROUP_DICT = 64 #: Enable debug for sysfs graph tree variable. 23 + SUBGROUP_SIZE = 128 #: Enable debug of search groups. 24 + GRAPH = 256 #: Display ref tree graph for undefined symbols. 25 25 26 - 26 + #: Helper messages for each debug variable 27 27 DEBUG_HELP = """ 28 - 1 - enable debug parsing logic 29 - 2 - enable debug messages on file open 30 - 4 - enable debug for ABI parse data 31 - 8 - enable extra debug information to identify troubles 32 - with ABI symbols found at the local machine that 33 - weren't found on ABI documentation (used only for 34 - undefined subcommand) 35 - 16 - enable debug for what to regex conversion 36 - 32 - enable debug for symbol regex subgroups 37 - 64 - enable debug for sysfs graph tree variable 28 + 1 - enable debug parsing logic 29 + 2 - enable debug messages on file open 30 + 4 - enable debug for ABI parse data 31 + 8 - enable extra debug information to identify troubles 32 + with ABI symbols found at the local machine that 33 + weren't found on ABI documentation (used only for 34 + undefined subcommand) 35 + 16 - enable debug for what to regex conversion 36 + 32 - enable debug for symbol regex subgroups 37 + 64 - enable debug for sysfs graph tree variable 38 + 128 - enable debug of search groups 39 + 256 - enable displaying refrence tree graphs for undefined symbols. 38 40 """
+7 -7
tools/lib/python/abi/system_symbols.py
··· 18 18 from abi.helpers import AbiDebug 19 19 20 20 class SystemSymbols: 21 - """Stores arguments for the class and initialize class vars""" 21 + """Stores arguments for the class and initialize class vars.""" 22 22 23 23 def graph_add_file(self, path, link=None): 24 24 """ 25 - add a file path to the sysfs graph stored at self.root 25 + add a file path to the sysfs graph stored at self.root. 26 26 """ 27 27 28 28 if path in self.files: ··· 43 43 self.files.add(path) 44 44 45 45 def print_graph(self, root_prefix="", root=None, level=0): 46 - """Prints a reference tree graph using UTF-8 characters""" 46 + """Prints a reference tree graph using UTF-8 characters.""" 47 47 48 48 if not root: 49 49 root = self.root ··· 173 173 self._walk(sysfs) 174 174 175 175 def check_file(self, refs, found): 176 - """Check missing ABI symbols for a given sysfs file""" 176 + """Check missing ABI symbols for a given sysfs file.""" 177 177 178 178 res_list = [] 179 179 ··· 214 214 return res_list 215 215 216 216 def _ref_interactor(self, root): 217 - """Recursive function to interact over the sysfs tree""" 217 + """Recursive function to interact over the sysfs tree.""" 218 218 219 219 for k, v in root.items(): 220 220 if isinstance(v, dict): ··· 232 232 233 233 234 234 def get_fileref(self, all_refs, chunk_size): 235 - """Interactor to group refs into chunks""" 235 + """Interactor to group refs into chunks.""" 236 236 237 237 n = 0 238 238 refs = [] ··· 250 250 251 251 def check_undefined_symbols(self, max_workers=None, chunk_size=50, 252 252 found=None, dry_run=None): 253 - """Seach ABI for sysfs symbols missing documentation""" 253 + """Seach ABI for sysfs symbols missing documentation.""" 254 254 255 255 self.abi.parse_abi() 256 256
+20 -7
tools/lib/python/feat/parse_features.py
··· 21 21 from it. 22 22 """ 23 23 24 + #: feature header string. 24 25 h_name = "Feature" 26 + 27 + #: Kernel config header string. 25 28 h_kconfig = "Kconfig" 29 + 30 + #: description header string. 26 31 h_description = "Description" 32 + 33 + #: subsystem header string. 27 34 h_subsys = "Subsystem" 35 + 36 + #: status header string. 28 37 h_status = "Status" 38 + 39 + #: architecture header string. 29 40 h_arch = "Architecture" 30 41 31 - # Sort order for status. Others will be mapped at the end. 42 + #: Sort order for status. Others will be mapped at the end. 32 43 status_map = { 33 44 "ok": 0, 34 45 "TODO": 1, ··· 51 40 52 41 def __init__(self, prefix, debug=0, enable_fname=False): 53 42 """ 54 - Sets internal variables 43 + Sets internal variables. 55 44 """ 56 45 57 46 self.prefix = prefix ··· 74 63 self.msg = "" 75 64 76 65 def emit(self, msg="", end="\n"): 66 + """Helper function to append a new message for feature output.""" 67 + 77 68 self.msg += msg + end 78 69 79 70 def parse_error(self, fname, ln, msg, data=None): 80 71 """ 81 - Displays an error message, printing file name and line 72 + Displays an error message, printing file name and line. 82 73 """ 83 74 84 75 if ln: ··· 95 82 print("", file=sys.stderr) 96 83 97 84 def parse_feat_file(self, fname): 98 - """Parses a single arch-support.txt feature file""" 85 + """Parses a single arch-support.txt feature file.""" 99 86 100 87 if os.path.isdir(fname): 101 88 return ··· 217 204 self.max_size_arch_with_header = self.max_size_arch + len(self.h_arch) 218 205 219 206 def parse(self): 220 - """Parses all arch-support.txt feature files inside self.prefix""" 207 + """Parses all arch-support.txt feature files inside self.prefix.""" 221 208 222 209 path = os.path.expanduser(self.prefix) 223 210 ··· 294 281 295 282 def output_feature(self, feat): 296 283 """ 297 - Output a feature on all architectures 284 + Output a feature on all architectures. 298 285 """ 299 286 300 287 title = f"Feature {feat}" ··· 344 331 345 332 def matrix_lines(self, desc_size, max_size_status, header): 346 333 """ 347 - Helper function to split element tables at the output matrix 334 + Helper function to split element tables at the output matrix. 348 335 """ 349 336 350 337 if header:
+102 -56
tools/lib/python/jobserver.py
··· 11 11 A "normal" jobserver task, like the one initiated by a make subrocess would do: 12 12 13 13 - open read/write file descriptors to communicate with the job server; 14 - - ask for one slot by calling: 14 + - ask for one slot by calling:: 15 + 15 16 claim = os.read(reader, 1) 16 - - when the job finshes, call: 17 + 18 + - when the job finshes, call:: 19 + 17 20 os.write(writer, b"+") # os.write(writer, claim) 18 21 19 22 Here, the goal is different: This script aims to get the remaining number 20 23 of slots available, using all of them to run a command which handle tasks in 21 24 parallel. To to that, it has a loop that ends only after there are no 22 25 slots left. It then increments the number by one, in order to allow a 23 - call equivalent to make -j$((claim+1)), e.g. having a parent make creating 26 + call equivalent to ``make -j$((claim+1))``, e.g. having a parent make creating 24 27 $claim child to do the actual work. 25 28 26 29 The end goal here is to keep the total number of build tasks under the 27 - limit established by the initial make -j$n_proc call. 30 + limit established by the initial ``make -j$n_proc`` call. 28 31 29 32 See: 30 33 https://www.gnu.org/software/make/manual/html_node/POSIX-Jobserver.html#POSIX-Jobserver ··· 38 35 import subprocess 39 36 import sys 40 37 38 + def warn(text, *args): 39 + print(f'WARNING: {text}', *args, file = sys.stderr) 40 + 41 41 class JobserverExec: 42 42 """ 43 43 Claim all slots from make using POSIX Jobserver. 44 44 45 45 The main methods here are: 46 + 46 47 - open(): reserves all slots; 47 48 - close(): method returns all used slots back to make; 48 - - run(): executes a command setting PARALLELISM=<available slots jobs + 1> 49 + - run(): executes a command setting PARALLELISM=<available slots jobs + 1>. 49 50 """ 50 51 51 52 def __init__(self): 52 - """Initialize internal vars""" 53 + """Initialize internal vars.""" 53 54 self.claim = 0 54 55 self.jobs = b"" 55 56 self.reader = None ··· 61 54 self.is_open = False 62 55 63 56 def open(self): 64 - """Reserve all available slots to be claimed later on""" 57 + """Reserve all available slots to be claimed later on.""" 65 58 66 59 if self.is_open: 67 60 return 68 - 69 - try: 70 - # Fetch the make environment options. 71 - flags = os.environ["MAKEFLAGS"] 72 - # Look for "--jobserver=R,W" 73 - # Note that GNU Make has used --jobserver-fds and --jobserver-auth 74 - # so this handles all of them. 75 - opts = [x for x in flags.split(" ") if x.startswith("--jobserver")] 76 - 77 - # Parse out R,W file descriptor numbers and set them nonblocking. 78 - # If the MAKEFLAGS variable contains multiple instances of the 79 - # --jobserver-auth= option, the last one is relevant. 80 - fds = opts[-1].split("=", 1)[1] 81 - 82 - # Starting with GNU Make 4.4, named pipes are used for reader 83 - # and writer. 84 - # Example argument: --jobserver-auth=fifo:/tmp/GMfifo8134 85 - _, _, path = fds.partition("fifo:") 86 - 87 - if path: 61 + self.is_open = True # We only try once 62 + self.claim = None 63 + # 64 + # Check the make flags for "--jobserver=R,W" 65 + # Note that GNU Make has used --jobserver-fds and --jobserver-auth 66 + # so this handles all of them. 67 + # 68 + flags = os.environ.get('MAKEFLAGS', '') 69 + opts = [x for x in flags.split(" ") if x.startswith("--jobserver")] 70 + if not opts: 71 + return 72 + # 73 + # Separate out the provided file descriptors 74 + # 75 + split_opt = opts[-1].split('=', 1) 76 + if len(split_opt) != 2: 77 + warn('unparseable option:', opts[-1]) 78 + return 79 + fds = split_opt[1] 80 + # 81 + # As of GNU Make 4.4, we'll be looking for a named pipe 82 + # identified as fifo:path 83 + # 84 + if fds.startswith('fifo:'): 85 + path = fds[len('fifo:'):] 86 + try: 88 87 self.reader = os.open(path, os.O_RDONLY | os.O_NONBLOCK) 89 88 self.writer = os.open(path, os.O_WRONLY) 90 - else: 91 - self.reader, self.writer = [int(x) for x in fds.split(",", 1)] 89 + except (OSError, IOError): 90 + warn('unable to open jobserver pipe', path) 91 + return 92 + # 93 + # Otherwise look for integer file-descriptor numbers. 94 + # 95 + else: 96 + split_fds = fds.split(',') 97 + if len(split_fds) != 2: 98 + warn('malformed jobserver file descriptors:', fds) 99 + return 100 + try: 101 + self.reader = int(split_fds[0]) 102 + self.writer = int(split_fds[1]) 103 + except ValueError: 104 + warn('non-integer jobserver file-descriptors:', fds) 105 + return 106 + try: 107 + # 92 108 # Open a private copy of reader to avoid setting nonblocking 93 109 # on an unexpecting process with the same reader fd. 94 - self.reader = os.open("/proc/self/fd/%d" % (self.reader), 110 + # 111 + self.reader = os.open(f"/proc/self/fd/{self.reader}", 95 112 os.O_RDONLY | os.O_NONBLOCK) 96 - 97 - # Read out as many jobserver slots as possible 98 - while True: 99 - try: 100 - slot = os.read(self.reader, 8) 101 - self.jobs += slot 102 - except (OSError, IOError) as e: 103 - if e.errno == errno.EWOULDBLOCK: 104 - # Stop at the end of the jobserver queue. 105 - break 106 - # If something went wrong, give back the jobs. 107 - if self.jobs: 108 - os.write(self.writer, self.jobs) 109 - raise e 110 - 111 - # Add a bump for our caller's reserveration, since we're just going 112 - # to sit here blocked on our child. 113 - self.claim = len(self.jobs) + 1 114 - 115 - except (KeyError, IndexError, ValueError, OSError, IOError): 116 - # Any missing environment strings or bad fds should result in just 117 - # not being parallel. 118 - self.claim = None 119 - 120 - self.is_open = True 113 + except (IOError, OSError) as e: 114 + warn('Unable to reopen jobserver read-side pipe:', repr(e)) 115 + return 116 + # 117 + # OK, we have the channel to the job server; read out as many jobserver 118 + # slots as possible. 119 + # 120 + while True: 121 + try: 122 + slot = os.read(self.reader, 8) 123 + if not slot: 124 + # 125 + # Something went wrong. Clear self.jobs to avoid writing 126 + # weirdness back to the jobserver and give up. 127 + self.jobs = b"" 128 + warn("unexpected empty token from jobserver;" 129 + " possible invalid '--jobserver-auth=' setting") 130 + self.claim = None 131 + return 132 + except (OSError, IOError) as e: 133 + # 134 + # If there is nothing more to read then we are done. 135 + # 136 + if e.errno == errno.EWOULDBLOCK: 137 + break 138 + # 139 + # Anything else says that something went weird; give back 140 + # the jobs and give up. 141 + # 142 + if self.jobs: 143 + os.write(self.writer, self.jobs) 144 + self.claim = None 145 + warn('error reading from jobserver pipe', repr(e)) 146 + return 147 + self.jobs += slot 148 + # 149 + # Add a bump for our caller's reserveration, since we're just going 150 + # to sit here blocked on our child. 151 + # 152 + self.claim = len(self.jobs) + 1 121 153 122 154 def close(self): 123 - """Return all reserved slots to Jobserver""" 155 + """Return all reserved slots to Jobserver.""" 124 156 125 157 if not self.is_open: 126 158 return
+15 -5
tools/lib/python/kdoc/enrich_formatter.py
··· 26 26 and how they're used at the __doc__ description. 27 27 """ 28 28 def __init__(self, *args, **kwargs): 29 - """Initialize class and check if is TTY""" 29 + """ 30 + Initialize class and check if is TTY. 31 + """ 30 32 super().__init__(*args, **kwargs) 31 33 self._tty = sys.stdout.isatty() 32 34 33 35 def enrich_text(self, text): 34 - """Handle ReST markups (currently, only ``foo``)""" 36 + r""" 37 + Handle ReST markups (currently, only \`\`text\`\` markups). 38 + """ 35 39 if self._tty and text: 36 40 # Replace ``text`` with ANSI SGR (bold) 37 41 return re.sub(r'\`\`(.+?)\`\`', ··· 43 39 return text 44 40 45 41 def _fill_text(self, text, width, indent): 46 - """Enrich descriptions with markups on it""" 42 + """ 43 + Enrich descriptions with markups on it. 44 + """ 47 45 enriched = self.enrich_text(text) 48 46 return "\n".join(indent + line for line in enriched.splitlines()) 49 47 50 48 def _format_usage(self, usage, actions, groups, prefix): 51 - """Enrich positional arguments at usage: line""" 49 + """ 50 + Enrich positional arguments at usage: line. 51 + """ 52 52 53 53 prog = self._prog 54 54 parts = [] ··· 71 63 return usage_text 72 64 73 65 def _format_action_invocation(self, action): 74 - """Enrich argument names""" 66 + """ 67 + Enrich argument names. 68 + """ 75 69 if not action.option_strings: 76 70 return self.enrich_text(f"``{action.dest.upper()}``") 77 71
+12 -11
tools/lib/python/kdoc/kdoc_files.py
··· 5 5 # pylint: disable=R0903,R0913,R0914,R0917 6 6 7 7 """ 8 - Parse lernel-doc tags on multiple kernel source files. 8 + Classes for navigating through the files that kernel-doc needs to handle 9 + to generate documentation. 9 10 """ 10 11 11 12 import argparse ··· 44 43 self.srctree = srctree 45 44 46 45 def _parse_dir(self, dirname): 47 - """Internal function to parse files recursively""" 46 + """Internal function to parse files recursively.""" 48 47 49 48 with os.scandir(dirname) as obj: 50 49 for entry in obj: ··· 66 65 def parse_files(self, file_list, file_not_found_cb): 67 66 """ 68 67 Define an iterator to parse all source files from file_list, 69 - handling directories if any 68 + handling directories if any. 70 69 """ 71 70 72 71 if not file_list: ··· 92 91 93 92 There are two type of parsers defined here: 94 93 - self.parse_file(): parses both kernel-doc markups and 95 - EXPORT_SYMBOL* macros; 96 - - self.process_export_file(): parses only EXPORT_SYMBOL* macros. 94 + ``EXPORT_SYMBOL*`` macros; 95 + - self.process_export_file(): parses only ``EXPORT_SYMBOL*`` macros. 97 96 """ 98 97 99 98 def warning(self, msg): 100 - """Ancillary routine to output a warning and increment error count""" 99 + """Ancillary routine to output a warning and increment error count.""" 101 100 102 101 self.config.log.warning(msg) 103 102 self.errors += 1 104 103 105 104 def error(self, msg): 106 - """Ancillary routine to output an error and increment error count""" 105 + """Ancillary routine to output an error and increment error count.""" 107 106 108 107 self.config.log.error(msg) 109 108 self.errors += 1 ··· 129 128 130 129 def process_export_file(self, fname): 131 130 """ 132 - Parses EXPORT_SYMBOL* macros from a single Kernel source file. 131 + Parses ``EXPORT_SYMBOL*`` macros from a single Kernel source file. 133 132 """ 134 133 135 134 # Prevent parsing the same file twice if results are cached ··· 158 157 wcontents_before_sections=False, 159 158 logger=None): 160 159 """ 161 - Initialize startup variables and parse all files 160 + Initialize startup variables and parse all files. 162 161 """ 163 162 164 163 if not verbose: ··· 214 213 215 214 def parse(self, file_list, export_file=None): 216 215 """ 217 - Parse all files 216 + Parse all files. 218 217 """ 219 218 220 219 glob = GlobSourceFiles(srctree=self.config.src_tree) ··· 243 242 filenames=None, export_file=None): 244 243 """ 245 244 Interacts over the kernel-doc results and output messages, 246 - returning kernel-doc markups on each interaction 245 + returning kernel-doc markups on each interaction. 247 246 """ 248 247 249 248 self.out_style.set_config(self.config)
+18
tools/lib/python/kdoc/kdoc_item.py
··· 4 4 # then pass into the output modules. 5 5 # 6 6 7 + """ 8 + Data class to store a kernel-doc Item. 9 + """ 10 + 7 11 class KdocItem: 12 + """ 13 + A class that will, eventually, encapsulate all of the parsed data that we 14 + then pass into the output modules. 15 + """ 16 + 8 17 def __init__(self, name, fname, type, start_line, **other_stuff): 9 18 self.name = name 10 19 self.fname = fname ··· 33 24 self.other_stuff = other_stuff 34 25 35 26 def get(self, key, default = None): 27 + """ 28 + Get a value from optional keys. 29 + """ 36 30 return self.other_stuff.get(key, default) 37 31 38 32 def __getitem__(self, key): ··· 45 33 # Tracking of section and parameter information. 46 34 # 47 35 def set_sections(self, sections, start_lines): 36 + """ 37 + Set sections and start lines. 38 + """ 48 39 self.sections = sections 49 40 self.section_start_lines = start_lines 50 41 51 42 def set_params(self, names, descs, types, starts): 43 + """ 44 + Set parameter list: names, descriptions, types and start lines. 45 + """ 52 46 self.parameterlist = names 53 47 self.parameterdescs = descs 54 48 self.parametertypes = types
+80 -24
tools/lib/python/kdoc/kdoc_output.py
··· 5 5 # pylint: disable=C0301,R0902,R0911,R0912,R0913,R0914,R0915,R0917 6 6 7 7 """ 8 - Implement output filters to print kernel-doc documentation. 8 + Classes to implement output filters to print kernel-doc documentation. 9 9 10 - The implementation uses a virtual base class (OutputFormat) which 10 + The implementation uses a virtual base class ``OutputFormat``. It 11 11 contains dispatches to virtual methods, and some code to filter 12 12 out output messages. 13 13 14 14 The actual implementation is done on one separate class per each type 15 - of output. Currently, there are output classes for ReST and man/troff. 15 + of output, e.g. ``RestFormat`` and ``ManFormat`` classes. 16 + 17 + Currently, there are output classes for ReST and man/troff. 16 18 """ 17 19 18 20 import os ··· 56 54 """ 57 55 58 56 # output mode. 59 - OUTPUT_ALL = 0 # output all symbols and doc sections 60 - OUTPUT_INCLUDE = 1 # output only specified symbols 61 - OUTPUT_EXPORTED = 2 # output exported symbols 62 - OUTPUT_INTERNAL = 3 # output non-exported symbols 57 + OUTPUT_ALL = 0 #: Output all symbols and doc sections. 58 + OUTPUT_INCLUDE = 1 #: Output only specified symbols. 59 + OUTPUT_EXPORTED = 2 #: Output exported symbols. 60 + OUTPUT_INTERNAL = 3 #: Output non-exported symbols. 63 61 64 - # Virtual member to be overridden at the inherited classes 62 + #: Highlights to be used in ReST format. 65 63 highlights = [] 66 64 65 + #: Blank line character. 66 + blankline = "" 67 + 67 68 def __init__(self): 68 - """Declare internal vars and set mode to OUTPUT_ALL""" 69 + """Declare internal vars and set mode to ``OUTPUT_ALL``.""" 69 70 70 71 self.out_mode = self.OUTPUT_ALL 71 72 self.enable_lineno = None ··· 133 128 self.config.warning(log_msg) 134 129 135 130 def check_doc(self, name, args): 136 - """Check if DOC should be output""" 131 + """Check if DOC should be output.""" 137 132 138 133 if self.no_doc_sections: 139 134 return False ··· 182 177 183 178 def msg(self, fname, name, args): 184 179 """ 185 - Handles a single entry from kernel-doc parser 180 + Handles a single entry from kernel-doc parser. 186 181 """ 187 182 188 183 self.data = "" ··· 204 199 self.out_enum(fname, name, args) 205 200 return self.data 206 201 202 + if dtype == "var": 203 + self.out_var(fname, name, args) 204 + return self.data 205 + 207 206 if dtype == "typedef": 208 207 self.out_typedef(fname, name, args) 209 208 return self.data ··· 225 216 # Virtual methods to be overridden by inherited classes 226 217 # At the base class, those do nothing. 227 218 def set_symbols(self, symbols): 228 - """Get a list of all symbols from kernel_doc""" 219 + """Get a list of all symbols from kernel_doc.""" 229 220 230 221 def out_doc(self, fname, name, args): 231 - """Outputs a DOC block""" 222 + """Outputs a DOC block.""" 232 223 233 224 def out_function(self, fname, name, args): 234 - """Outputs a function""" 225 + """Outputs a function.""" 235 226 236 227 def out_enum(self, fname, name, args): 237 - """Outputs an enum""" 228 + """Outputs an enum.""" 229 + 230 + def out_var(self, fname, name, args): 231 + """Outputs a variable.""" 238 232 239 233 def out_typedef(self, fname, name, args): 240 - """Outputs a typedef""" 234 + """Outputs a typedef.""" 241 235 242 236 def out_struct(self, fname, name, args): 243 - """Outputs a struct""" 237 + """Outputs a struct.""" 244 238 245 239 246 240 class RestFormat(OutputFormat): 247 - """Consts and functions used by ReST output""" 241 + """Consts and functions used by ReST output.""" 248 242 243 + #: Highlights to be used in ReST format 249 244 highlights = [ 250 245 (type_constant, r"``\1``"), 251 246 (type_constant2, r"``\1``"), ··· 269 256 (type_fallback, r":c:type:`\1`"), 270 257 (type_param_ref, r"**\1\2**") 271 258 ] 259 + 272 260 blankline = "\n" 273 261 262 + #: Sphinx literal block regex. 274 263 sphinx_literal = KernRe(r'^[^.].*::$', cache=False) 264 + 265 + #: Sphinx code block regex. 275 266 sphinx_cblock = KernRe(r'^\.\.\ +code-block::', cache=False) 276 267 277 268 def __init__(self): ··· 290 273 self.lineprefix = "" 291 274 292 275 def print_lineno(self, ln): 293 - """Outputs a line number""" 276 + """Outputs a line number.""" 294 277 295 278 if self.enable_lineno and ln is not None: 296 279 ln += 1 ··· 299 282 def output_highlight(self, args): 300 283 """ 301 284 Outputs a C symbol that may require being converted to ReST using 302 - the self.highlights variable 285 + the self.highlights variable. 303 286 """ 304 287 305 288 input_text = args ··· 489 472 self.lineprefix = oldprefix 490 473 self.out_section(args) 491 474 475 + def out_var(self, fname, name, args): 476 + oldprefix = self.lineprefix 477 + ln = args.declaration_start_line 478 + full_proto = args.other_stuff["full_proto"] 479 + 480 + self.lineprefix = " " 481 + 482 + self.data += f"\n\n.. c:macro:: {name}\n\n{self.lineprefix}``{full_proto}``\n\n" 483 + 484 + self.print_lineno(ln) 485 + self.output_highlight(args.get('purpose', '')) 486 + self.data += "\n" 487 + 488 + if args.other_stuff["default_val"]: 489 + self.data += f'{self.lineprefix}**Initialization**\n\n' 490 + self.output_highlight(f'default: ``{args.other_stuff["default_val"]}``') 491 + 492 + self.out_section(args) 493 + 492 494 def out_typedef(self, fname, name, args): 493 495 494 496 oldprefix = self.lineprefix ··· 580 544 581 545 582 546 class ManFormat(OutputFormat): 583 - """Consts and functions used by man pages output""" 547 + """Consts and functions used by man pages output.""" 584 548 585 549 highlights = ( 586 550 (type_constant, r"\1"), ··· 597 561 ) 598 562 blankline = "" 599 563 564 + #: Allowed timestamp formats. 600 565 date_formats = [ 601 566 "%a %b %d %H:%M:%S %Z %Y", 602 567 "%a %b %d %H:%M:%S %Y", ··· 664 627 self.symbols = symbols 665 628 666 629 def out_tail(self, fname, name, args): 667 - """Adds a tail for all man pages""" 630 + """Adds a tail for all man pages.""" 668 631 669 632 # SEE ALSO section 670 633 self.data += f'.SH "SEE ALSO"' + "\n.PP\n" ··· 700 663 def output_highlight(self, block): 701 664 """ 702 665 Outputs a C symbol that may require being highlighted with 703 - self.highlights variable using troff syntax 666 + self.highlights variable using troff syntax. 704 667 """ 705 668 706 669 contents = self.highlight_block(block) ··· 731 694 self.output_highlight(text) 732 695 733 696 def out_function(self, fname, name, args): 734 - """output function in man""" 735 697 736 698 out_name = self.arg_name(args, name) 737 699 ··· 804 768 parameter_name = KernRe(r'\[.*').sub('', parameter) 805 769 self.data += f'.IP "{parameter}" 12' + "\n" 806 770 self.output_highlight(args.parameterdescs.get(parameter_name, "")) 771 + 772 + for section, text in args.sections.items(): 773 + self.data += f'.SH "{section}"' + "\n" 774 + self.output_highlight(text) 775 + 776 + def out_var(self, fname, name, args): 777 + out_name = self.arg_name(args, name) 778 + full_proto = args.other_stuff["full_proto"] 779 + 780 + self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n" 781 + 782 + self.data += ".SH NAME\n" 783 + self.data += f"{name} \\- {args['purpose']}\n" 784 + 785 + self.data += ".SH SYNOPSIS\n" 786 + self.data += f"{full_proto}\n" 787 + 788 + if args.other_stuff["default_val"]: 789 + self.data += f'.SH "Initialization"' + "\n" 790 + self.output_highlight(f'default: {args.other_stuff["default_val"]}') 807 791 808 792 for section, text in args.sections.items(): 809 793 self.data += f'.SH "{section}"' + "\n"
+199 -86
tools/lib/python/kdoc/kdoc_parser.py
··· 5 5 # pylint: disable=C0301,C0302,R0904,R0912,R0913,R0914,R0915,R0917,R1702 6 6 7 7 """ 8 - kdoc_parser 9 - =========== 10 - 11 - Read a C language source or header FILE and extract embedded 12 - documentation comments 8 + Classes and functions related to reading a C language source or header FILE 9 + and extract embedded documentation comments from it. 13 10 """ 14 11 15 12 import sys ··· 50 53 doc_inline_start = KernRe(r'^\s*/\*\*\s*$', cache=False) 51 54 doc_inline_sect = KernRe(r'\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)', cache=False) 52 55 doc_inline_end = KernRe(r'^\s*\*/\s*$', cache=False) 53 - doc_inline_oneline = KernRe(r'^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$', cache=False) 56 + doc_inline_oneline = KernRe(r'^\s*/\*\*\s*(@\s*[\w][\w\.]*\s*):\s*(.*)\s*\*/\s*$', cache=False) 54 57 55 58 export_symbol = KernRe(r'^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*', cache=False) 56 59 export_symbol_ns = KernRe(r'^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*"\S+"\)\s*', cache=False) ··· 61 64 # Tests for the beginning of a kerneldoc block in its various forms. 62 65 # 63 66 doc_block = doc_com + KernRe(r'DOC:\s*(.*)?', cache=False) 64 - doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)", cache = False) 67 + doc_begin_data = KernRe(r"^\s*\*?\s*(struct|union|enum|typedef|var)\b\s*(\w*)", cache = False) 65 68 doc_begin_func = KernRe(str(doc_com) + # initial " * ' 66 69 r"(?:\w+\s*\*\s*)?" + # type (not captured) 67 70 r'(?:define\s+)?' + # possible "define" (not captured) ··· 192 195 ] 193 196 194 197 # 195 - # Apply a set of transforms to a block of text. 198 + # Ancillary functions 196 199 # 200 + 197 201 def apply_transforms(xforms, text): 202 + """ 203 + Apply a set of transforms to a block of text. 204 + """ 198 205 for search, subst in xforms: 199 206 text = search.sub(subst, text) 200 207 return text 201 208 202 - # 203 - # A little helper to get rid of excess white space 204 - # 205 209 multi_space = KernRe(r'\s\s+') 206 210 def trim_whitespace(s): 211 + """ 212 + A little helper to get rid of excess white space. 213 + """ 207 214 return multi_space.sub(' ', s.strip()) 208 215 209 - # 210 - # Remove struct/enum members that have been marked "private". 211 - # 212 216 def trim_private_members(text): 213 - # 217 + """ 218 + Remove ``struct``/``enum`` members that have been marked "private". 219 + """ 214 220 # First look for a "public:" block that ends a private region, then 215 221 # handle the "private until the end" case. 216 222 # ··· 226 226 227 227 class state: 228 228 """ 229 - State machine enums 229 + States used by the parser's state machine. 230 230 """ 231 231 232 232 # Parser states 233 - NORMAL = 0 # normal code 234 - NAME = 1 # looking for function name 235 - DECLARATION = 2 # We have seen a declaration which might not be done 236 - BODY = 3 # the body of the comment 237 - SPECIAL_SECTION = 4 # doc section ending with a blank line 238 - PROTO = 5 # scanning prototype 239 - DOCBLOCK = 6 # documentation block 240 - INLINE_NAME = 7 # gathering doc outside main block 241 - INLINE_TEXT = 8 # reading the body of inline docs 233 + NORMAL = 0 #: Normal code. 234 + NAME = 1 #: Looking for function name. 235 + DECLARATION = 2 #: We have seen a declaration which might not be done. 236 + BODY = 3 #: The body of the comment. 237 + SPECIAL_SECTION = 4 #: Doc section ending with a blank line. 238 + PROTO = 5 #: Scanning prototype. 239 + DOCBLOCK = 6 #: Documentation block. 240 + INLINE_NAME = 7 #: Gathering doc outside main block. 241 + INLINE_TEXT = 8 #: Reading the body of inline docs. 242 242 243 + #: Names for each parser state. 243 244 name = [ 244 245 "NORMAL", 245 246 "NAME", ··· 254 253 ] 255 254 256 255 257 - SECTION_DEFAULT = "Description" # default section 256 + SECTION_DEFAULT = "Description" #: Default section. 258 257 259 258 class KernelEntry: 259 + """ 260 + Encapsulates a Kernel documentation entry. 261 + """ 260 262 261 263 def __init__(self, config, fname, ln): 262 264 self.config = config ··· 292 288 # Management of section contents 293 289 # 294 290 def add_text(self, text): 291 + """Add a new text to the entry contents list.""" 295 292 self._contents.append(text) 296 293 297 294 def contents(self): 295 + """Returns a string with all content texts that were added.""" 298 296 return '\n'.join(self._contents) + '\n' 299 297 300 298 # TODO: rename to emit_message after removal of kernel-doc.pl 301 299 def emit_msg(self, ln, msg, *, warning=True): 302 - """Emit a message""" 300 + """Emit a message.""" 303 301 304 302 log_msg = f"{self.fname}:{ln} {msg}" 305 303 ··· 315 309 self.warnings.append(log_msg) 316 310 return 317 311 318 - # 319 - # Begin a new section. 320 - # 321 312 def begin_section(self, line_no, title = SECTION_DEFAULT, dump = False): 313 + """ 314 + Begin a new section. 315 + """ 322 316 if dump: 323 317 self.dump_section(start_new = True) 324 318 self.section = title ··· 372 366 documentation comments. 373 367 """ 374 368 375 - # Section names 376 - 369 + #: Name of context section. 377 370 section_context = "Context" 371 + 372 + #: Name of return section. 378 373 section_return = "Return" 379 374 375 + #: String to write when a parameter is not described. 380 376 undescribed = "-- undescribed --" 381 377 382 378 def __init__(self, config, fname): ··· 424 416 425 417 def dump_section(self, start_new=True): 426 418 """ 427 - Dumps section contents to arrays/hashes intended for that purpose. 419 + Dump section contents to arrays/hashes intended for that purpose. 428 420 """ 429 421 430 422 if self.entry: ··· 433 425 # TODO: rename it to store_declaration after removal of kernel-doc.pl 434 426 def output_declaration(self, dtype, name, **args): 435 427 """ 436 - Stores the entry into an entry array. 428 + Store the entry into an entry array. 437 429 438 - The actual output and output filters will be handled elsewhere 430 + The actual output and output filters will be handled elsewhere. 439 431 """ 440 432 441 433 item = KdocItem(name, self.fname, dtype, ··· 456 448 457 449 self.config.log.debug("Output: %s:%s = %s", dtype, name, pformat(args)) 458 450 451 + def emit_unused_warnings(self): 452 + """ 453 + When the parser fails to produce a valid entry, it places some 454 + warnings under `entry.warnings` that will be discarded when resetting 455 + the state. 456 + 457 + Ensure that those warnings are not lost. 458 + 459 + .. note:: 460 + 461 + Because we are calling `config.warning()` here, those 462 + warnings are not filtered by the `-W` parameters: they will all 463 + be produced even when `-Wreturn`, `-Wshort-desc`, and/or 464 + `-Wcontents-before-sections` are used. 465 + 466 + Allowing those warnings to be filtered is complex, because it 467 + would require storing them in a buffer and then filtering them 468 + during the output step of the code, depending on the 469 + selected symbols. 470 + """ 471 + if self.entry and self.entry not in self.entries: 472 + for log_msg in self.entry.warnings: 473 + self.config.warning(log_msg) 474 + 459 475 def reset_state(self, ln): 460 476 """ 461 477 Ancillary routine to create a new entry. It initializes all 462 478 variables used by the state machine. 463 479 """ 464 480 465 - # 466 - # Flush the warnings out before we proceed further 467 - # 468 - if self.entry and self.entry not in self.entries: 469 - for log_msg in self.entry.warnings: 470 - self.config.log.warning(log_msg) 481 + self.emit_unused_warnings() 471 482 472 483 self.entry = KernelEntry(self.config, self.fname, ln) 473 484 ··· 690 663 self.emit_msg(ln, 691 664 f"No description found for return value of '{declaration_name}'") 692 665 693 - # 694 - # Split apart a structure prototype; returns (struct|union, name, members) or None 695 - # 696 666 def split_struct_proto(self, proto): 667 + """ 668 + Split apart a structure prototype; returns (struct|union, name, 669 + members) or ``None``. 670 + """ 671 + 697 672 type_pattern = r'(struct|union)' 698 673 qualifiers = [ 699 674 "__attribute__", ··· 714 685 if r.search(proto): 715 686 return (r.group(1), r.group(3), r.group(2)) 716 687 return None 717 - # 718 - # Rewrite the members of a structure or union for easier formatting later on. 719 - # Among other things, this function will turn a member like: 720 - # 721 - # struct { inner_members; } foo; 722 - # 723 - # into: 724 - # 725 - # struct foo; inner_members; 726 - # 688 + 727 689 def rewrite_struct_members(self, members): 690 + """ 691 + Process ``struct``/``union`` members from the most deeply nested 692 + outward. 693 + 694 + Rewrite the members of a ``struct`` or ``union`` for easier formatting 695 + later on. Among other things, this function will turn a member like:: 696 + 697 + struct { inner_members; } foo; 698 + 699 + into:: 700 + 701 + struct foo; inner_members; 702 + """ 703 + 728 704 # 729 - # Process struct/union members from the most deeply nested outward. The 730 - # trick is in the ^{ below - it prevents a match of an outer struct/union 731 - # until the inner one has been munged (removing the "{" in the process). 705 + # The trick is in the ``^{`` below - it prevents a match of an outer 706 + # ``struct``/``union`` until the inner one has been munged 707 + # (removing the ``{`` in the process). 732 708 # 733 709 struct_members = KernRe(r'(struct|union)' # 0: declaration type 734 710 r'([^\{\};]+)' # 1: possible name ··· 811 777 tuples = struct_members.findall(members) 812 778 return members 813 779 814 - # 815 - # Format the struct declaration into a standard form for inclusion in the 816 - # resulting docs. 817 - # 818 780 def format_struct_decl(self, declaration): 781 + """ 782 + Format the ``struct`` declaration into a standard form for inclusion 783 + in the resulting docs. 784 + """ 785 + 819 786 # 820 787 # Insert newlines, get rid of extra spaces. 821 788 # ··· 850 815 851 816 def dump_struct(self, ln, proto): 852 817 """ 853 - Store an entry for a struct or union 818 + Store an entry for a ``struct`` or ``union`` 854 819 """ 855 820 # 856 821 # Do the basic parse to get the pieces of the declaration. ··· 892 857 893 858 def dump_enum(self, ln, proto): 894 859 """ 895 - Stores an enum inside self.entries array. 860 + Store an ``enum`` inside self.entries array. 896 861 """ 897 862 # 898 863 # Strip preprocessor directives. Note that this depends on the ··· 962 927 self.output_declaration('enum', declaration_name, 963 928 purpose=self.entry.declaration_purpose) 964 929 930 + def dump_var(self, ln, proto): 931 + """ 932 + Store variables that are part of kAPI. 933 + """ 934 + VAR_ATTRIBS = [ 935 + "extern", 936 + ] 937 + OPTIONAL_VAR_ATTR = "^(?:" + "|".join(VAR_ATTRIBS) + ")?" 938 + 939 + sub_prefixes = [ 940 + (KernRe(r"__read_mostly"), ""), 941 + (KernRe(r"__ro_after_init"), ""), 942 + (KernRe(r"(?://.*)$"), ""), 943 + (KernRe(r"(?:/\*.*\*/)"), ""), 944 + (KernRe(r";$"), ""), 945 + (KernRe(r"=.*"), ""), 946 + ] 947 + 948 + # 949 + # Store the full prototype before modifying it 950 + # 951 + full_proto = proto 952 + declaration_name = None 953 + 954 + # 955 + # Handle macro definitions 956 + # 957 + macro_prefixes = [ 958 + KernRe(r"DEFINE_[\w_]+\s*\(([\w_]+)\)"), 959 + ] 960 + 961 + for r in macro_prefixes: 962 + match = r.search(proto) 963 + if match: 964 + declaration_name = match.group(1) 965 + break 966 + 967 + # 968 + # Drop comments and macros to have a pure C prototype 969 + # 970 + if not declaration_name: 971 + for r, sub in sub_prefixes: 972 + proto = r.sub(sub, proto) 973 + 974 + proto = proto.rstrip() 975 + 976 + # 977 + # Variable name is at the end of the declaration 978 + # 979 + 980 + default_val = None 981 + 982 + r= KernRe(OPTIONAL_VAR_ATTR + r"\w.*\s+(?:\*+)?([\w_]+)\s*[\d\]\[]*\s*(=.*)?") 983 + if r.match(proto): 984 + if not declaration_name: 985 + declaration_name = r.group(1) 986 + 987 + default_val = r.group(2) 988 + else: 989 + r= KernRe(OPTIONAL_VAR_ATTR + r"(?:\w.*)?\s+(?:\*+)?(?:[\w_]+)\s*[\d\]\[]*\s*(=.*)?") 990 + if r.match(proto): 991 + default_val = r.group(1) 992 + 993 + if not declaration_name: 994 + self.emit_msg(ln,f"{proto}: can't parse variable") 995 + return 996 + 997 + if default_val: 998 + default_val = default_val.lstrip("=").strip() 999 + 1000 + self.output_declaration("var", declaration_name, 1001 + full_proto=full_proto, 1002 + default_val=default_val, 1003 + purpose=self.entry.declaration_purpose) 1004 + 965 1005 def dump_declaration(self, ln, prototype): 966 1006 """ 967 - Stores a data declaration inside self.entries array. 1007 + Store a data declaration inside self.entries array. 968 1008 """ 969 1009 970 1010 if self.entry.decl_type == "enum": ··· 1048 938 self.dump_typedef(ln, prototype) 1049 939 elif self.entry.decl_type in ["union", "struct"]: 1050 940 self.dump_struct(ln, prototype) 941 + elif self.entry.decl_type == "var": 942 + self.dump_var(ln, prototype) 1051 943 else: 1052 944 # This would be a bug 1053 945 self.emit_message(ln, f'Unknown declaration type: {self.entry.decl_type}') 1054 946 1055 947 def dump_function(self, ln, prototype): 1056 948 """ 1057 - Stores a function or function macro inside self.entries array. 949 + Store a function or function macro inside self.entries array. 1058 950 """ 1059 951 1060 952 found = func_macro = False ··· 1157 1045 1158 1046 def dump_typedef(self, ln, proto): 1159 1047 """ 1160 - Stores a typedef inside self.entries array. 1048 + Store a ``typedef`` inside self.entries array. 1161 1049 """ 1162 1050 # 1163 1051 # We start by looking for function typedefs. ··· 1211 1099 @staticmethod 1212 1100 def process_export(function_set, line): 1213 1101 """ 1214 - process EXPORT_SYMBOL* tags 1102 + process ``EXPORT_SYMBOL*`` tags 1215 1103 1216 1104 This method doesn't use any variable from the class, so declare it 1217 1105 with a staticmethod decorator. ··· 1242 1130 1243 1131 def process_normal(self, ln, line): 1244 1132 """ 1245 - STATE_NORMAL: looking for the /** to begin everything. 1133 + STATE_NORMAL: looking for the ``/**`` to begin everything. 1246 1134 """ 1247 1135 1248 1136 if not doc_start.match(line): ··· 1332 1220 else: 1333 1221 self.emit_msg(ln, f"Cannot find identifier on line:\n{line}") 1334 1222 1335 - # 1336 - # Helper function to determine if a new section is being started. 1337 - # 1338 1223 def is_new_section(self, ln, line): 1224 + """ 1225 + Helper function to determine if a new section is being started. 1226 + """ 1339 1227 if doc_sect.search(line): 1340 1228 self.state = state.BODY 1341 1229 # ··· 1367 1255 return True 1368 1256 return False 1369 1257 1370 - # 1371 - # Helper function to detect (and effect) the end of a kerneldoc comment. 1372 - # 1373 1258 def is_comment_end(self, ln, line): 1259 + """ 1260 + Helper function to detect (and effect) the end of a kerneldoc comment. 1261 + """ 1374 1262 if doc_end.search(line): 1375 1263 self.dump_section() 1376 1264 ··· 1389 1277 1390 1278 def process_decl(self, ln, line): 1391 1279 """ 1392 - STATE_DECLARATION: We've seen the beginning of a declaration 1280 + STATE_DECLARATION: We've seen the beginning of a declaration. 1393 1281 """ 1394 1282 if self.is_new_section(ln, line) or self.is_comment_end(ln, line): 1395 1283 return ··· 1418 1306 1419 1307 def process_special(self, ln, line): 1420 1308 """ 1421 - STATE_SPECIAL_SECTION: a section ending with a blank line 1309 + STATE_SPECIAL_SECTION: a section ending with a blank line. 1422 1310 """ 1423 1311 # 1424 1312 # If we have hit a blank line (only the " * " marker), then this ··· 1508 1396 1509 1397 def syscall_munge(self, ln, proto): # pylint: disable=W0613 1510 1398 """ 1511 - Handle syscall definitions 1399 + Handle syscall definitions. 1512 1400 """ 1513 1401 1514 1402 is_void = False ··· 1547 1435 1548 1436 def tracepoint_munge(self, ln, proto): 1549 1437 """ 1550 - Handle tracepoint definitions 1438 + Handle tracepoint definitions. 1551 1439 """ 1552 1440 1553 1441 tracepointname = None ··· 1583 1471 return proto 1584 1472 1585 1473 def process_proto_function(self, ln, line): 1586 - """Ancillary routine to process a function prototype""" 1474 + """Ancillary routine to process a function prototype.""" 1587 1475 1588 1476 # strip C99-style comments to end of line 1589 1477 line = KernRe(r"//.*$", re.S).sub('', line) ··· 1628 1516 self.reset_state(ln) 1629 1517 1630 1518 def process_proto_type(self, ln, line): 1631 - """Ancillary routine to process a type""" 1519 + """ 1520 + Ancillary routine to process a type. 1521 + """ 1632 1522 1633 1523 # Strip C99-style comments and surrounding whitespace 1634 1524 line = KernRe(r"//.*$", re.S).sub('', line).strip() ··· 1684 1570 self.process_proto_type(ln, line) 1685 1571 1686 1572 def process_docblock(self, ln, line): 1687 - """STATE_DOCBLOCK: within a DOC: block.""" 1573 + """STATE_DOCBLOCK: within a ``DOC:`` block.""" 1688 1574 1689 1575 if doc_end.search(line): 1690 1576 self.dump_section() ··· 1696 1582 1697 1583 def parse_export(self): 1698 1584 """ 1699 - Parses EXPORT_SYMBOL* macros from a single Kernel source file. 1585 + Parses ``EXPORT_SYMBOL*`` macros from a single Kernel source file. 1700 1586 """ 1701 1587 1702 1588 export_table = set() ··· 1713 1599 1714 1600 return export_table 1715 1601 1716 - # 1717 - # The state/action table telling us which function to invoke in 1718 - # each state. 1719 - # 1602 + #: The state/action table telling us which function to invoke in each state. 1720 1603 state_actions = { 1721 1604 state.NORMAL: process_normal, 1722 1605 state.NAME: process_name, ··· 1774 1663 not self.process_export(export_table, line): 1775 1664 # Hand this line to the appropriate state handler 1776 1665 self.state_actions[self.state](self, ln, line) 1666 + 1667 + self.emit_unused_warnings() 1777 1668 1778 1669 except OSError: 1779 1670 self.config.log.error(f"Error: Cannot open file {self.fname}")
+18 -10
tools/lib/python/kdoc/kdoc_re.py
··· 51 51 """ 52 52 return self.regex.pattern 53 53 54 + def __repr__(self): 55 + return f're.compile("{self.regex.pattern}")' 56 + 54 57 def __add__(self, other): 55 58 """ 56 59 Allows adding two regular expressions into one. ··· 64 61 65 62 def match(self, string): 66 63 """ 67 - Handles a re.match storing its results 64 + Handles a re.match storing its results. 68 65 """ 69 66 70 67 self.last_match = self.regex.match(string) ··· 72 69 73 70 def search(self, string): 74 71 """ 75 - Handles a re.search storing its results 72 + Handles a re.search storing its results. 76 73 """ 77 74 78 75 self.last_match = self.regex.search(string) ··· 80 77 81 78 def findall(self, string): 82 79 """ 83 - Alias to re.findall 80 + Alias to re.findall. 84 81 """ 85 82 86 83 return self.regex.findall(string) 87 84 88 85 def split(self, string): 89 86 """ 90 - Alias to re.split 87 + Alias to re.split. 91 88 """ 92 89 93 90 return self.regex.split(string) 94 91 95 92 def sub(self, sub, string, count=0): 96 93 """ 97 - Alias to re.sub 94 + Alias to re.sub. 98 95 """ 99 96 100 97 return self.regex.sub(sub, string, count=count) 101 98 102 99 def group(self, num): 103 100 """ 104 - Returns the group results of the last match 101 + Returns the group results of the last match. 105 102 """ 106 103 107 104 return self.last_match.group(num) ··· 113 110 even harder on Python with its normal re module, as there are several 114 111 advanced regular expressions that are missing. 115 112 116 - This is the case of this pattern: 113 + This is the case of this pattern:: 117 114 118 115 '\\bSTRUCT_GROUP(\\(((?:(?>[^)(]+)|(?1))*)\\))[^;]*;' 119 116 ··· 124 121 replace nested expressions. 125 122 126 123 The original approach was suggested by: 124 + 127 125 https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex 128 126 129 127 Although I re-implemented it to make it more generic and match 3 types ··· 228 224 yield line[t[0]:t[2]] 229 225 230 226 def sub(self, regex, sub, line, count=0): 231 - """ 227 + r""" 232 228 This is similar to re.sub: 233 229 234 230 It matches a regex that it is followed by a delimiter, 235 231 replacing occurrences only if all delimiters are paired. 236 232 237 - if r'\1' is used, it works just like re: it places there the 238 - matched paired data with the delimiter stripped. 233 + if the sub argument contains:: 234 + 235 + r'\1' 236 + 237 + it will work just like re: it places there the matched paired data 238 + with the delimiter stripped. 239 239 240 240 If count is different than zero, it will replace at most count 241 241 items.
+56 -39
tools/lib/python/kdoc/latex_fonts.py
··· 5 5 # Ported to Python by (c) Mauro Carvalho Chehab, 2025 6 6 7 7 """ 8 - Detect problematic Noto CJK variable fonts. 8 + Detect problematic Noto CJK variable fonts 9 + ========================================== 9 10 10 - For "make pdfdocs", reports of build errors of translations.pdf started 11 - arriving early 2024 [1, 2]. It turned out that Fedora and openSUSE 12 - tumbleweed have started deploying variable-font [3] format of "Noto CJK" 13 - fonts [4, 5]. For PDF, a LaTeX package named xeCJK is used for CJK 11 + For ``make pdfdocs``, reports of build errors of translations.pdf started 12 + arriving early 2024 [1]_ [2]_. It turned out that Fedora and openSUSE 13 + tumbleweed have started deploying variable-font [3]_ format of "Noto CJK" 14 + fonts [4]_ [5]_. For PDF, a LaTeX package named xeCJK is used for CJK 14 15 (Chinese, Japanese, Korean) pages. xeCJK requires XeLaTeX/XeTeX, which 15 16 does not (and likely never will) understand variable fonts for historical 16 17 reasons. ··· 26 25 suggestions if variable-font files of "Noto CJK" fonts are in the list of 27 26 fonts accessible from XeTeX. 28 27 29 - References: 30 - [1]: https://lore.kernel.org/r/8734tqsrt7.fsf@meer.lwn.net/ 31 - [2]: https://lore.kernel.org/r/1708585803.600323099@f111.i.mail.ru/ 32 - [3]: https://en.wikipedia.org/wiki/Variable_font 33 - [4]: https://fedoraproject.org/wiki/Changes/Noto_CJK_Variable_Fonts 34 - [5]: https://build.opensuse.org/request/show/1157217 28 + .. [1] https://lore.kernel.org/r/8734tqsrt7.fsf@meer.lwn.net/ 29 + .. [2] https://lore.kernel.org/r/1708585803.600323099@f111.i.mail.ru/ 30 + .. [3] https://en.wikipedia.org/wiki/Variable_font 31 + .. [4] https://fedoraproject.org/wiki/Changes/Noto_CJK_Variable_Fonts 32 + .. [5] https://build.opensuse.org/request/show/1157217 35 33 36 - #=========================================================================== 37 34 Workarounds for building translations.pdf 38 - #=========================================================================== 35 + ----------------------------------------- 39 36 40 37 * Denylist "variable font" Noto CJK fonts. 38 + 41 39 - Create $HOME/deny-vf/fontconfig/fonts.conf from template below, with 42 40 tweaks if necessary. Remove leading "". 41 + 43 42 - Path of fontconfig/fonts.conf can be overridden by setting an env 44 43 variable FONTS_CONF_DENY_VF. 45 44 46 - * Template: 47 - ----------------------------------------------------------------- 48 - <?xml version="1.0"?> 49 - <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> 50 - <fontconfig> 51 - <!-- 52 - Ignore variable-font glob (not to break xetex) 53 - --> 54 - <selectfont> 55 - <rejectfont> 56 - <!-- 57 - for Fedora 58 - --> 59 - <glob>/usr/share/fonts/google-noto-*-cjk-vf-fonts</glob> 60 - <!-- 61 - for openSUSE tumbleweed 62 - --> 63 - <glob>/usr/share/fonts/truetype/Noto*CJK*-VF.otf</glob> 64 - </rejectfont> 65 - </selectfont> 66 - </fontconfig> 67 - ----------------------------------------------------------------- 45 + * Template:: 46 + 47 + <?xml version="1.0"?> 48 + <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> 49 + <fontconfig> 50 + <!-- 51 + Ignore variable-font glob (not to break xetex) 52 + --> 53 + <selectfont> 54 + <rejectfont> 55 + <!-- 56 + for Fedora 57 + --> 58 + <glob>/usr/share/fonts/google-noto-*-cjk-vf-fonts</glob> 59 + <!-- 60 + for openSUSE tumbleweed 61 + --> 62 + <glob>/usr/share/fonts/truetype/Noto*CJK*-VF.otf</glob> 63 + </rejectfont> 64 + </selectfont> 65 + </fontconfig> 68 66 69 67 The denylisting is activated for "make pdfdocs". 70 68 71 69 * For skipping CJK pages in PDF 70 + 72 71 - Uninstall texlive-xecjk. 73 72 Denylisting is not needed in this case. 74 73 75 74 * For printing CJK pages in PDF 75 + 76 76 - Need non-variable "Noto CJK" fonts. 77 + 77 78 * Fedora 79 + 78 80 - google-noto-sans-cjk-fonts 79 81 - google-noto-serif-cjk-fonts 82 + 80 83 * openSUSE tumbleweed 84 + 81 85 - Non-variable "Noto CJK" fonts are not available as distro packages 82 86 as of April, 2024. Fetch a set of font files from upstream Noto 83 87 CJK Font released at: 88 + 84 89 https://github.com/notofonts/noto-cjk/tree/main/Sans#super-otc 90 + 85 91 and at: 92 + 86 93 https://github.com/notofonts/noto-cjk/tree/main/Serif#super-otc 87 - , then uncompress and deploy them. 94 + 95 + then uncompress and deploy them. 88 96 - Remember to update fontconfig cache by running fc-cache. 89 97 90 - !!! Caution !!! 98 + .. caution:: 91 99 Uninstalling "variable font" packages can be dangerous. 92 100 They might be depended upon by other packages important for your work. 93 101 Denylisting should be less invasive, as it is effective only while ··· 125 115 self.re_cjk = re.compile(r"([^:]+):\s*Noto\s+(Sans|Sans Mono|Serif) CJK") 126 116 127 117 def description(self): 118 + """ 119 + Returns module description. 120 + """ 128 121 return __doc__ 129 122 130 123 def get_noto_cjk_vf_fonts(self): 131 - """Get Noto CJK fonts""" 124 + """ 125 + Get Noto CJK fonts. 126 + """ 132 127 133 128 cjk_fonts = set() 134 129 cmd = ["fc-list", ":", "file", "family", "variable"] ··· 158 143 return sorted(cjk_fonts) 159 144 160 145 def check(self): 161 - """Check for problems with CJK fonts""" 146 + """ 147 + Check for problems with CJK fonts. 148 + """ 162 149 163 150 fonts = textwrap.indent("\n".join(self.get_noto_cjk_vf_fonts()), " ") 164 151 if not fonts:
+39 -23
tools/lib/python/kdoc/parse_data_structs.py
··· 9 9 It accepts an optional file to change the default symbol reference or to 10 10 suppress symbols from the output. 11 11 12 - It is capable of identifying defines, functions, structs, typedefs, 13 - enums and enum symbols and create cross-references for all of them. 12 + It is capable of identifying ``define``, function, ``struct``, ``typedef``, 13 + ``enum`` and ``enum`` symbols and create cross-references for all of them. 14 14 It is also capable of distinguish #define used for specifying a Linux 15 15 ioctl. 16 16 17 - The optional rules file contains a set of rules like: 17 + The optional rules file contains a set of rules like:: 18 18 19 19 ignore ioctl VIDIOC_ENUM_FMT 20 20 replace ioctl VIDIOC_DQBUF vidioc_qbuf ··· 34 34 It is meant to allow having a more comprehensive documentation, where 35 35 uAPI headers will create cross-reference links to the code. 36 36 37 - It is capable of identifying defines, functions, structs, typedefs, 38 - enums and enum symbols and create cross-references for all of them. 37 + It is capable of identifying ``define``, function, ``struct``, ``typedef``, 38 + ``enum`` and ``enum`` symbols and create cross-references for all of them. 39 39 It is also capable of distinguish #define used for specifying a Linux 40 40 ioctl. 41 41 ··· 43 43 allows parsing an exception file. Such file contains a set of rules 44 44 using the syntax below: 45 45 46 - 1. Ignore rules: 46 + 1. Ignore rules:: 47 47 48 48 ignore <type> <symbol>` 49 49 50 50 Removes the symbol from reference generation. 51 51 52 - 2. Replace rules: 52 + 2. Replace rules:: 53 53 54 54 replace <type> <old_symbol> <new_reference> 55 55 ··· 58 58 - A simple symbol name; 59 59 - A full Sphinx reference. 60 60 61 - 3. Namespace rules 61 + 3. Namespace rules:: 62 62 63 63 namespace <namespace> 64 64 65 65 Sets C namespace to be used during cross-reference generation. Can 66 66 be overridden by replace rules. 67 67 68 - On ignore and replace rules, <type> can be: 69 - - ioctl: for defines that end with _IO*, e.g. ioctl definitions 70 - - define: for other defines 71 - - symbol: for symbols defined within enums; 72 - - typedef: for typedefs; 73 - - enum: for the name of a non-anonymous enum; 74 - - struct: for structs. 68 + On ignore and replace rules, ``<type>`` can be: 69 + - ``ioctl``: for defines that end with ``_IO*``, e.g. ioctl definitions 70 + - ``define``: for other defines 71 + - ``symbol``: for symbols defined within enums; 72 + - ``typedef``: for typedefs; 73 + - ``enum``: for the name of a non-anonymous enum; 74 + - ``struct``: for structs. 75 75 76 - Examples: 76 + Examples:: 77 77 78 78 ignore define __LINUX_MEDIA_H 79 79 ignore ioctl VIDIOC_ENUM_FMT ··· 83 83 namespace MC 84 84 """ 85 85 86 - # Parser regexes with multiple ways to capture enums and structs 86 + #: Parser regex with multiple ways to capture enums. 87 87 RE_ENUMS = [ 88 88 re.compile(r"^\s*enum\s+([\w_]+)\s*\{"), 89 89 re.compile(r"^\s*enum\s+([\w_]+)\s*$"), 90 90 re.compile(r"^\s*typedef\s*enum\s+([\w_]+)\s*\{"), 91 91 re.compile(r"^\s*typedef\s*enum\s+([\w_]+)\s*$"), 92 92 ] 93 + 94 + #: Parser regex with multiple ways to capture structs. 93 95 RE_STRUCTS = [ 94 96 re.compile(r"^\s*struct\s+([_\w][\w\d_]+)\s*\{"), 95 97 re.compile(r"^\s*struct\s+([_\w][\w\d_]+)$"), ··· 99 97 re.compile(r"^\s*typedef\s*struct\s+([_\w][\w\d_]+)$"), 100 98 ] 101 99 102 - # FIXME: the original code was written a long time before Sphinx C 100 + # NOTE: the original code was written a long time before Sphinx C 103 101 # domain to have multiple namespaces. To avoid to much turn at the 104 102 # existing hyperlinks, the code kept using "c:type" instead of the 105 103 # right types. To change that, we need to change the types not only 106 104 # here, but also at the uAPI media documentation. 105 + 106 + #: Dictionary containing C type identifiers to be transformed. 107 107 DEF_SYMBOL_TYPES = { 108 108 "ioctl": { 109 109 "prefix": "\\ ", ··· 162 158 self.symbols[symbol_type] = {} 163 159 164 160 def read_exceptions(self, fname: str): 161 + """ 162 + Read an optional exceptions file, used to override defaults. 163 + """ 164 + 165 165 if not fname: 166 166 return 167 167 ··· 250 242 def store_type(self, ln, symbol_type: str, symbol: str, 251 243 ref_name: str = None, replace_underscores: bool = True): 252 244 """ 253 - Stores a new symbol at self.symbols under symbol_type. 245 + Store a new symbol at self.symbols under symbol_type. 254 246 255 - By default, underscores are replaced by "-" 247 + By default, underscores are replaced by ``-``. 256 248 """ 257 249 defs = self.DEF_SYMBOL_TYPES[symbol_type] 258 250 ··· 284 276 self.symbols[symbol_type][symbol] = (f"{prefix}{ref_link}{suffix}", ln) 285 277 286 278 def store_line(self, line): 287 - """Stores a line at self.data, properly indented""" 279 + """ 280 + Store a line at self.data, properly indented. 281 + """ 288 282 line = " " + line.expandtabs() 289 283 self.data += line.rstrip(" ") 290 284 291 285 def parse_file(self, file_in: str, exceptions: str = None): 292 - """Reads a C source file and get identifiers""" 286 + """ 287 + Read a C source file and get identifiers. 288 + """ 293 289 self.data = "" 294 290 is_enum = False 295 291 is_comment = False ··· 445 433 446 434 def gen_toc(self): 447 435 """ 448 - Create a list of symbols to be part of a TOC contents table 436 + Create a list of symbols to be part of a TOC contents table. 449 437 """ 450 438 text = [] 451 439 ··· 476 464 return "\n".join(text) 477 465 478 466 def write_output(self, file_in: str, file_out: str, toc: bool): 467 + """ 468 + Write a ReST output file. 469 + """ 470 + 479 471 title = os.path.basename(file_in) 480 472 481 473 if toc:
+16 -4
tools/lib/python/kdoc/python_version.py
··· 33 33 """ 34 34 35 35 def __init__(self, version): 36 - """Ïnitialize self.version tuple from a version string""" 36 + """ 37 + Ïnitialize self.version tuple from a version string. 38 + """ 37 39 self.version = self.parse_version(version) 38 40 39 41 @staticmethod 40 42 def parse_version(version): 41 - """Convert a major.minor.patch version into a tuple""" 43 + """ 44 + Convert a major.minor.patch version into a tuple. 45 + """ 42 46 return tuple(int(x) for x in version.split(".")) 43 47 44 48 @staticmethod 45 49 def ver_str(version): 46 - """Returns a version tuple as major.minor.patch""" 50 + """ 51 + Returns a version tuple as major.minor.patch. 52 + """ 47 53 return ".".join([str(x) for x in version]) 48 54 49 55 @staticmethod 50 56 def cmd_print(cmd, max_len=80): 57 + """ 58 + Outputs a command line, repecting maximum width. 59 + """ 60 + 51 61 cmd_line = [] 52 62 53 63 for w in cmd: ··· 76 66 return "\n ".join(cmd_line) 77 67 78 68 def __str__(self): 79 - """Returns a version tuple as major.minor.patch from self.version""" 69 + """ 70 + Return a version tuple as major.minor.patch from self.version. 71 + """ 80 72 return self.ver_str(self.version) 81 73 82 74 @staticmethod