cleaning up the git
192
Documentation/PCI/acpi-info.rst
Normal file
@ -0,0 +1,192 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
========================================
|
||||
ACPI considerations for PCI host bridges
|
||||
========================================
|
||||
|
||||
The general rule is that the ACPI namespace should describe everything the
|
||||
OS might use unless there's another way for the OS to find it [1, 2].
|
||||
|
||||
For example, there's no standard hardware mechanism for enumerating PCI
|
||||
host bridges, so the ACPI namespace must describe each host bridge, the
|
||||
method for accessing PCI config space below it, the address space windows
|
||||
the host bridge forwards to PCI (using _CRS), and the routing of legacy
|
||||
INTx interrupts (using _PRT).
|
||||
|
||||
PCI devices, which are below the host bridge, generally do not need to be
|
||||
described via ACPI. The OS can discover them via the standard PCI
|
||||
enumeration mechanism, using config accesses to discover and identify
|
||||
devices and read and size their BARs. However, ACPI may describe PCI
|
||||
devices if it provides power management or hotplug functionality for them
|
||||
or if the device has INTx interrupts connected by platform interrupt
|
||||
controllers and a _PRT is needed to describe those connections.
|
||||
|
||||
ACPI resource description is done via _CRS objects of devices in the ACPI
|
||||
namespace [2]. The _CRS is like a generalized PCI BAR: the OS can read
|
||||
_CRS and figure out what resource is being consumed even if it doesn't have
|
||||
a driver for the device [3]. That's important because it means an old OS
|
||||
can work correctly even on a system with new devices unknown to the OS.
|
||||
The new devices might not do anything, but the OS can at least make sure no
|
||||
resources conflict with them.
|
||||
|
||||
Static tables like MCFG, HPET, ECDT, etc., are *not* mechanisms for
|
||||
reserving address space. The static tables are for things the OS needs to
|
||||
know early in boot, before it can parse the ACPI namespace. If a new table
|
||||
is defined, an old OS needs to operate correctly even though it ignores the
|
||||
table. _CRS allows that because it is generic and understood by the old
|
||||
OS; a static table does not.
|
||||
|
||||
If the OS is expected to manage a non-discoverable device described via
|
||||
ACPI, that device will have a specific _HID/_CID that tells the OS what
|
||||
driver to bind to it, and the _CRS tells the OS and the driver where the
|
||||
device's registers are.
|
||||
|
||||
PCI host bridges are PNP0A03 or PNP0A08 devices. Their _CRS should
|
||||
describe all the address space they consume. This includes all the windows
|
||||
they forward down to the PCI bus, as well as registers of the host bridge
|
||||
itself that are not forwarded to PCI. The host bridge registers include
|
||||
things like secondary/subordinate bus registers that determine the bus
|
||||
range below the bridge, window registers that describe the apertures, etc.
|
||||
These are all device-specific, non-architected things, so the only way a
|
||||
PNP0A03/PNP0A08 driver can manage them is via _PRS/_CRS/_SRS, which contain
|
||||
the device-specific details. The host bridge registers also include ECAM
|
||||
space, since it is consumed by the host bridge.
|
||||
|
||||
ACPI defines a Consumer/Producer bit to distinguish the bridge registers
|
||||
("Consumer") from the bridge apertures ("Producer") [4, 5], but early
|
||||
BIOSes didn't use that bit correctly. The result is that the current ACPI
|
||||
spec defines Consumer/Producer only for the Extended Address Space
|
||||
descriptors; the bit should be ignored in the older QWord/DWord/Word
|
||||
Address Space descriptors. Consequently, OSes have to assume all
|
||||
QWord/DWord/Word descriptors are windows.
|
||||
|
||||
Prior to the addition of Extended Address Space descriptors, the failure of
|
||||
Consumer/Producer meant there was no way to describe bridge registers in
|
||||
the PNP0A03/PNP0A08 device itself. The workaround was to describe the
|
||||
bridge registers (including ECAM space) in PNP0C02 catch-all devices [6].
|
||||
With the exception of ECAM, the bridge register space is device-specific
|
||||
anyway, so the generic PNP0A03/PNP0A08 driver (pci_root.c) has no need to
|
||||
know about it.
|
||||
|
||||
New architectures should be able to use "Consumer" Extended Address Space
|
||||
descriptors in the PNP0A03 device for bridge registers, including ECAM,
|
||||
although a strict interpretation of [6] might prohibit this. Old x86 and
|
||||
ia64 kernels assume all address space descriptors, including "Consumer"
|
||||
Extended Address Space ones, are windows, so it would not be safe to
|
||||
describe bridge registers this way on those architectures.
|
||||
|
||||
PNP0C02 "motherboard" devices are basically a catch-all. There's no
|
||||
programming model for them other than "don't use these resources for
|
||||
anything else." So a PNP0C02 _CRS should claim any address space that is
|
||||
(1) not claimed by _CRS under any other device object in the ACPI namespace
|
||||
and (2) should not be assigned by the OS to something else.
|
||||
|
||||
The PCIe spec requires the Enhanced Configuration Access Method (ECAM)
|
||||
unless there's a standard firmware interface for config access, e.g., the
|
||||
ia64 SAL interface [7]. A host bridge consumes ECAM memory address space
|
||||
and converts memory accesses into PCI configuration accesses. The spec
|
||||
defines the ECAM address space layout and functionality; only the base of
|
||||
the address space is device-specific. An ACPI OS learns the base address
|
||||
from either the static MCFG table or a _CBA method in the PNP0A03 device.
|
||||
|
||||
The MCFG table must describe the ECAM space of non-hot pluggable host
|
||||
bridges [8]. Since MCFG is a static table and can't be updated by hotplug,
|
||||
a _CBA method in the PNP0A03 device describes the ECAM space of a
|
||||
hot-pluggable host bridge [9]. Note that for both MCFG and _CBA, the base
|
||||
address always corresponds to bus 0, even if the bus range below the bridge
|
||||
(which is reported via _CRS) doesn't start at 0.
|
||||
|
||||
|
||||
[1] ACPI 6.2, sec 6.1:
|
||||
For any device that is on a non-enumerable type of bus (for example, an
|
||||
ISA bus), OSPM enumerates the devices' identifier(s) and the ACPI
|
||||
system firmware must supply an _HID object ... for each device to
|
||||
enable OSPM to do that.
|
||||
|
||||
[2] ACPI 6.2, sec 3.7:
|
||||
The OS enumerates motherboard devices simply by reading through the
|
||||
ACPI Namespace looking for devices with hardware IDs.
|
||||
|
||||
Each device enumerated by ACPI includes ACPI-defined objects in the
|
||||
ACPI Namespace that report the hardware resources the device could
|
||||
occupy [_PRS], an object that reports the resources that are currently
|
||||
used by the device [_CRS], and objects for configuring those resources
|
||||
[_SRS]. The information is used by the Plug and Play OS (OSPM) to
|
||||
configure the devices.
|
||||
|
||||
[3] ACPI 6.2, sec 6.2:
|
||||
OSPM uses device configuration objects to configure hardware resources
|
||||
for devices enumerated via ACPI. Device configuration objects provide
|
||||
information about current and possible resource requirements, the
|
||||
relationship between shared resources, and methods for configuring
|
||||
hardware resources.
|
||||
|
||||
When OSPM enumerates a device, it calls _PRS to determine the resource
|
||||
requirements of the device. It may also call _CRS to find the current
|
||||
resource settings for the device. Using this information, the Plug and
|
||||
Play system determines what resources the device should consume and
|
||||
sets those resources by calling the device’s _SRS control method.
|
||||
|
||||
In ACPI, devices can consume resources (for example, legacy keyboards),
|
||||
provide resources (for example, a proprietary PCI bridge), or do both.
|
||||
Unless otherwise specified, resources for a device are assumed to be
|
||||
taken from the nearest matching resource above the device in the device
|
||||
hierarchy.
|
||||
|
||||
[4] ACPI 6.2, sec 6.4.3.5.1, 2, 3, 4:
|
||||
QWord/DWord/Word Address Space Descriptor (.1, .2, .3)
|
||||
General Flags: Bit [0] Ignored
|
||||
|
||||
Extended Address Space Descriptor (.4)
|
||||
General Flags: Bit [0] Consumer/Producer:
|
||||
|
||||
* 1 – This device consumes this resource
|
||||
* 0 – This device produces and consumes this resource
|
||||
|
||||
[5] ACPI 6.2, sec 19.6.43:
|
||||
ResourceUsage specifies whether the Memory range is consumed by
|
||||
this device (ResourceConsumer) or passed on to child devices
|
||||
(ResourceProducer). If nothing is specified, then
|
||||
ResourceConsumer is assumed.
|
||||
|
||||
[6] PCI Firmware 3.2, sec 4.1.2:
|
||||
If the operating system does not natively comprehend reserving the
|
||||
MMCFG region, the MMCFG region must be reserved by firmware. The
|
||||
address range reported in the MCFG table or by _CBA method (see Section
|
||||
4.1.3) must be reserved by declaring a motherboard resource. For most
|
||||
systems, the motherboard resource would appear at the root of the ACPI
|
||||
namespace (under \_SB) in a node with a _HID of EISAID (PNP0C02), and
|
||||
the resources in this case should not be claimed in the root PCI bus’s
|
||||
_CRS. The resources can optionally be returned in Int15 E820 or
|
||||
EFIGetMemoryMap as reserved memory but must always be reported through
|
||||
ACPI as a motherboard resource.
|
||||
|
||||
[7] PCI Express 4.0, sec 7.2.2:
|
||||
For systems that are PC-compatible, or that do not implement a
|
||||
processor-architecture-specific firmware interface standard that allows
|
||||
access to the Configuration Space, the ECAM is required as defined in
|
||||
this section.
|
||||
|
||||
[8] PCI Firmware 3.2, sec 4.1.2:
|
||||
The MCFG table is an ACPI table that is used to communicate the base
|
||||
addresses corresponding to the non-hot removable PCI Segment Groups
|
||||
range within a PCI Segment Group available to the operating system at
|
||||
boot. This is required for the PC-compatible systems.
|
||||
|
||||
The MCFG table is only used to communicate the base addresses
|
||||
corresponding to the PCI Segment Groups available to the system at
|
||||
boot.
|
||||
|
||||
[9] PCI Firmware 3.2, sec 4.1.3:
|
||||
The _CBA (Memory mapped Configuration Base Address) control method is
|
||||
an optional ACPI object that returns the 64-bit memory mapped
|
||||
configuration base address for the hot plug capable host bridge. The
|
||||
base address returned by _CBA is processor-relative address. The _CBA
|
||||
control method evaluates to an Integer.
|
||||
|
||||
This control method appears under a host bridge object. When the _CBA
|
||||
method appears under an active host bridge object, the operating system
|
||||
evaluates this structure to identify the memory mapped configuration
|
||||
base address corresponding to the PCI Segment Group for the bus number
|
||||
range specified in _CRS method. An ACPI name space object that contains
|
||||
the _CBA method must also contain a corresponding _SEG method.
|
159
Documentation/PCI/boot-interrupts.rst
Normal file
@ -0,0 +1,159 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===============
|
||||
Boot Interrupts
|
||||
===============
|
||||
|
||||
:Author: - Sean V Kelley <sean.v.kelley@linux.intel.com>
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
On PCI Express, interrupts are represented with either MSI or inbound
|
||||
interrupt messages (Assert_INTx/Deassert_INTx). The integrated IO-APIC in a
|
||||
given Core IO converts the legacy interrupt messages from PCI Express to
|
||||
MSI interrupts. If the IO-APIC is disabled (via the mask bits in the
|
||||
IO-APIC table entries), the messages are routed to the legacy PCH. This
|
||||
in-band interrupt mechanism was traditionally necessary for systems that
|
||||
did not support the IO-APIC and for boot. Intel in the past has used the
|
||||
term "boot interrupts" to describe this mechanism. Further, the PCI Express
|
||||
protocol describes this in-band legacy wire-interrupt INTx mechanism for
|
||||
I/O devices to signal PCI-style level interrupts. The subsequent paragraphs
|
||||
describe problems with the Core IO handling of INTx message routing to the
|
||||
PCH and mitigation within BIOS and the OS.
|
||||
|
||||
|
||||
Issue
|
||||
=====
|
||||
|
||||
When in-band legacy INTx messages are forwarded to the PCH, they in turn
|
||||
trigger a new interrupt for which the OS likely lacks a handler. When an
|
||||
interrupt goes unhandled over time, they are tracked by the Linux kernel as
|
||||
Spurious Interrupts. The IRQ will be disabled by the Linux kernel after it
|
||||
reaches a specific count with the error "nobody cared". This disabled IRQ
|
||||
now prevents valid usage by an existing interrupt which may happen to share
|
||||
the IRQ line::
|
||||
|
||||
irq 19: nobody cared (try booting with the "irqpoll" option)
|
||||
CPU: 0 PID: 2988 Comm: irq/34-nipalk Tainted: 4.14.87-rt49-02410-g4a640ec-dirty #1
|
||||
Hardware name: National Instruments NI PXIe-8880/NI PXIe-8880, BIOS 2.1.5f1 01/09/2020
|
||||
Call Trace:
|
||||
|
||||
<IRQ>
|
||||
? dump_stack+0x46/0x5e
|
||||
? __report_bad_irq+0x2e/0xb0
|
||||
? note_interrupt+0x242/0x290
|
||||
? nNIKAL100_memoryRead16+0x8/0x10 [nikal]
|
||||
? handle_irq_event_percpu+0x55/0x70
|
||||
? handle_irq_event+0x4f/0x80
|
||||
? handle_fasteoi_irq+0x81/0x180
|
||||
? handle_irq+0x1c/0x30
|
||||
? do_IRQ+0x41/0xd0
|
||||
? common_interrupt+0x84/0x84
|
||||
</IRQ>
|
||||
|
||||
handlers:
|
||||
irq_default_primary_handler threaded usb_hcd_irq
|
||||
Disabling IRQ #19
|
||||
|
||||
|
||||
Conditions
|
||||
==========
|
||||
|
||||
The use of threaded interrupts is the most likely condition to trigger
|
||||
this problem today. Threaded interrupts may not be reenabled after the IRQ
|
||||
handler wakes. These "one shot" conditions mean that the threaded interrupt
|
||||
needs to keep the interrupt line masked until the threaded handler has run.
|
||||
Especially when dealing with high data rate interrupts, the thread needs to
|
||||
run to completion; otherwise some handlers will end up in stack overflows
|
||||
since the interrupt of the issuing device is still active.
|
||||
|
||||
Affected Chipsets
|
||||
=================
|
||||
|
||||
The legacy interrupt forwarding mechanism exists today in a number of
|
||||
devices including but not limited to chipsets from AMD/ATI, Broadcom, and
|
||||
Intel. Changes made through the mitigations below have been applied to
|
||||
drivers/pci/quirks.c
|
||||
|
||||
Starting with ICX there are no longer any IO-APICs in the Core IO's
|
||||
devices. IO-APIC is only in the PCH. Devices connected to the Core IO's
|
||||
PCIe Root Ports will use native MSI/MSI-X mechanisms.
|
||||
|
||||
Mitigations
|
||||
===========
|
||||
|
||||
The mitigations take the form of PCI quirks. The preference has been to
|
||||
first identify and make use of a means to disable the routing to the PCH.
|
||||
In such a case a quirk to disable boot interrupt generation can be
|
||||
added. [1]_
|
||||
|
||||
Intel® 6300ESB I/O Controller Hub
|
||||
Alternate Base Address Register:
|
||||
BIE: Boot Interrupt Enable
|
||||
|
||||
== ===========================
|
||||
0 Boot interrupt is enabled.
|
||||
1 Boot interrupt is disabled.
|
||||
== ===========================
|
||||
|
||||
Intel® Sandy Bridge through Sky Lake based Xeon servers:
|
||||
Coherent Interface Protocol Interrupt Control
|
||||
dis_intx_route2pch/dis_intx_route2ich/dis_intx_route2dmi2:
|
||||
When this bit is set. Local INTx messages received from the
|
||||
Intel® Quick Data DMA/PCI Express ports are not routed to legacy
|
||||
PCH - they are either converted into MSI via the integrated IO-APIC
|
||||
(if the IO-APIC mask bit is clear in the appropriate entries)
|
||||
or cause no further action (when mask bit is set)
|
||||
|
||||
In the absence of a way to directly disable the routing, another approach
|
||||
has been to make use of PCI Interrupt pin to INTx routing tables for
|
||||
purposes of redirecting the interrupt handler to the rerouted interrupt
|
||||
line by default. Therefore, on chipsets where this INTx routing cannot be
|
||||
disabled, the Linux kernel will reroute the valid interrupt to its legacy
|
||||
interrupt. This redirection of the handler will prevent the occurrence of
|
||||
the spurious interrupt detection which would ordinarily disable the IRQ
|
||||
line due to excessive unhandled counts. [2]_
|
||||
|
||||
The config option X86_REROUTE_FOR_BROKEN_BOOT_IRQS exists to enable (or
|
||||
disable) the redirection of the interrupt handler to the PCH interrupt
|
||||
line. The option can be overridden by either pci=ioapicreroute or
|
||||
pci=noioapicreroute. [3]_
|
||||
|
||||
|
||||
More Documentation
|
||||
==================
|
||||
|
||||
There is an overview of the legacy interrupt handling in several datasheets
|
||||
(6300ESB and 6700PXH below). While largely the same, it provides insight
|
||||
into the evolution of its handling with chipsets.
|
||||
|
||||
Example of disabling of the boot interrupt
|
||||
------------------------------------------
|
||||
|
||||
- Intel® 6300ESB I/O Controller Hub (Document # 300641-004US)
|
||||
5.7.3 Boot Interrupt
|
||||
https://www.intel.com/content/dam/doc/datasheet/6300esb-io-controller-hub-datasheet.pdf
|
||||
|
||||
- Intel® Xeon® Processor E5-1600/2400/2600/4600 v3 Product Families
|
||||
Datasheet - Volume 2: Registers (Document # 330784-003)
|
||||
6.6.41 cipintrc Coherent Interface Protocol Interrupt Control
|
||||
https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e5-v3-datasheet-vol-2.pdf
|
||||
|
||||
Example of handler rerouting
|
||||
----------------------------
|
||||
|
||||
- Intel® 6700PXH 64-bit PCI Hub (Document # 302628)
|
||||
2.15.2 PCI Express Legacy INTx Support and Boot Interrupt
|
||||
https://www.intel.com/content/dam/doc/datasheet/6700pxh-64-bit-pci-hub-datasheet.pdf
|
||||
|
||||
|
||||
If you have any legacy PCI interrupt questions that aren't answered, email me.
|
||||
|
||||
Cheers,
|
||||
Sean V Kelley
|
||||
sean.v.kelley@linux.intel.com
|
||||
|
||||
.. [1] https://lore.kernel.org/r/12131949181903-git-send-email-sassmann@suse.de/
|
||||
.. [2] https://lore.kernel.org/r/12131949182094-git-send-email-sassmann@suse.de/
|
||||
.. [3] https://lore.kernel.org/r/487C8EA7.6020205@suse.de/
|
38
Documentation/PCI/endpoint/function/binding/pci-ntb.rst
Normal file
@ -0,0 +1,38 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==========================
|
||||
PCI NTB Endpoint Function
|
||||
==========================
|
||||
|
||||
1) Create a subdirectory to pci_epf_ntb directory in configfs.
|
||||
|
||||
Standard EPF Configurable Fields:
|
||||
|
||||
================ ===========================================================
|
||||
vendorid should be 0x104c
|
||||
deviceid should be 0xb00d for TI's J721E SoC
|
||||
revid don't care
|
||||
progif_code don't care
|
||||
subclass_code should be 0x00
|
||||
baseclass_code should be 0x5
|
||||
cache_line_size don't care
|
||||
subsys_vendor_id don't care
|
||||
subsys_id don't care
|
||||
interrupt_pin don't care
|
||||
msi_interrupts don't care
|
||||
msix_interrupts don't care
|
||||
================ ===========================================================
|
||||
|
||||
2) Create a subdirectory to directory created in 1
|
||||
|
||||
NTB EPF specific configurable fields:
|
||||
|
||||
================ ===========================================================
|
||||
db_count Number of doorbells; default = 4
|
||||
mw1 size of memory window1
|
||||
mw2 size of memory window2
|
||||
mw3 size of memory window3
|
||||
mw4 size of memory window4
|
||||
num_mws Number of memory windows; max = 4
|
||||
spad_count Number of scratchpad registers; default = 64
|
||||
================ ===========================================================
|
26
Documentation/PCI/endpoint/function/binding/pci-test.rst
Normal file
@ -0,0 +1,26 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==========================
|
||||
PCI Test Endpoint Function
|
||||
==========================
|
||||
|
||||
name: Should be "pci_epf_test" to bind to the pci_epf_test driver.
|
||||
|
||||
Configurable Fields:
|
||||
|
||||
================ ===========================================================
|
||||
vendorid should be 0x104c
|
||||
deviceid should be 0xb500 for DRA74x and 0xb501 for DRA72x
|
||||
revid don't care
|
||||
progif_code don't care
|
||||
subclass_code don't care
|
||||
baseclass_code should be 0xff
|
||||
cache_line_size don't care
|
||||
subsys_vendor_id don't care
|
||||
subsys_id don't care
|
||||
interrupt_pin Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD
|
||||
msi_interrupts Should be 1 to 32 depending on the number of MSI interrupts
|
||||
to test
|
||||
msix_interrupts Should be 1 to 2048 depending on the number of MSI-X
|
||||
interrupts to test
|
||||
================ ===========================================================
|
18
Documentation/PCI/endpoint/index.rst
Normal file
@ -0,0 +1,18 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
======================
|
||||
PCI Endpoint Framework
|
||||
======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
pci-endpoint
|
||||
pci-endpoint-cfs
|
||||
pci-test-function
|
||||
pci-test-howto
|
||||
pci-ntb-function
|
||||
pci-ntb-howto
|
||||
|
||||
function/binding/pci-test
|
||||
function/binding/pci-ntb
|
138
Documentation/PCI/endpoint/pci-endpoint-cfs.rst
Normal file
@ -0,0 +1,138 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=======================================
|
||||
Configuring PCI Endpoint Using CONFIGFS
|
||||
=======================================
|
||||
|
||||
:Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
|
||||
The PCI Endpoint Core exposes configfs entry (pci_ep) to configure the
|
||||
PCI endpoint function and to bind the endpoint function
|
||||
with the endpoint controller. (For introducing other mechanisms to
|
||||
configure the PCI Endpoint Function refer to [1]).
|
||||
|
||||
Mounting configfs
|
||||
=================
|
||||
|
||||
The PCI Endpoint Core layer creates pci_ep directory in the mounted configfs
|
||||
directory. configfs can be mounted using the following command::
|
||||
|
||||
mount -t configfs none /sys/kernel/config
|
||||
|
||||
Directory Structure
|
||||
===================
|
||||
|
||||
The pci_ep configfs has two directories at its root: controllers and
|
||||
functions. Every EPC device present in the system will have an entry in
|
||||
the *controllers* directory and every EPF driver present in the system
|
||||
will have an entry in the *functions* directory.
|
||||
::
|
||||
|
||||
/sys/kernel/config/pci_ep/
|
||||
.. controllers/
|
||||
.. functions/
|
||||
|
||||
Creating EPF Device
|
||||
===================
|
||||
|
||||
Every registered EPF driver will be listed in controllers directory. The
|
||||
entries corresponding to EPF driver will be created by the EPF core.
|
||||
::
|
||||
|
||||
/sys/kernel/config/pci_ep/functions/
|
||||
.. <EPF Driver1>/
|
||||
... <EPF Device 11>/
|
||||
... <EPF Device 21>/
|
||||
... <EPF Device 31>/
|
||||
.. <EPF Driver2>/
|
||||
... <EPF Device 12>/
|
||||
... <EPF Device 22>/
|
||||
|
||||
In order to create a <EPF device> of the type probed by <EPF Driver>, the
|
||||
user has to create a directory inside <EPF DriverN>.
|
||||
|
||||
Every <EPF device> directory consists of the following entries that can be
|
||||
used to configure the standard configuration header of the endpoint function.
|
||||
(These entries are created by the framework when any new <EPF Device> is
|
||||
created)
|
||||
::
|
||||
|
||||
.. <EPF Driver1>/
|
||||
... <EPF Device 11>/
|
||||
... vendorid
|
||||
... deviceid
|
||||
... revid
|
||||
... progif_code
|
||||
... subclass_code
|
||||
... baseclass_code
|
||||
... cache_line_size
|
||||
... subsys_vendor_id
|
||||
... subsys_id
|
||||
... interrupt_pin
|
||||
... <Symlink EPF Device 31>/
|
||||
... primary/
|
||||
... <Symlink EPC Device1>/
|
||||
... secondary/
|
||||
... <Symlink EPC Device2>/
|
||||
|
||||
If an EPF device has to be associated with 2 EPCs (like in the case of
|
||||
Non-transparent bridge), symlink of endpoint controller connected to primary
|
||||
interface should be added in 'primary' directory and symlink of endpoint
|
||||
controller connected to secondary interface should be added in 'secondary'
|
||||
directory.
|
||||
|
||||
The <EPF Device> directory can have a list of symbolic links
|
||||
(<Symlink EPF Device 31>) to other <EPF Device>. These symbolic links should
|
||||
be created by the user to represent the virtual functions that are bound to
|
||||
the physical function. In the above directory structure <EPF Device 11> is a
|
||||
physical function and <EPF Device 31> is a virtual function. An EPF device once
|
||||
it's linked to another EPF device, cannot be linked to a EPC device.
|
||||
|
||||
EPC Device
|
||||
==========
|
||||
|
||||
Every registered EPC device will be listed in controllers directory. The
|
||||
entries corresponding to EPC device will be created by the EPC core.
|
||||
::
|
||||
|
||||
/sys/kernel/config/pci_ep/controllers/
|
||||
.. <EPC Device1>/
|
||||
... <Symlink EPF Device11>/
|
||||
... <Symlink EPF Device12>/
|
||||
... start
|
||||
.. <EPC Device2>/
|
||||
... <Symlink EPF Device21>/
|
||||
... <Symlink EPF Device22>/
|
||||
... start
|
||||
|
||||
The <EPC Device> directory will have a list of symbolic links to
|
||||
<EPF Device>. These symbolic links should be created by the user to
|
||||
represent the functions present in the endpoint device. Only <EPF Device>
|
||||
that represents a physical function can be linked to a EPC device.
|
||||
|
||||
The <EPC Device> directory will also have a *start* field. Once
|
||||
"1" is written to this field, the endpoint device will be ready to
|
||||
establish the link with the host. This is usually done after
|
||||
all the EPF devices are created and linked with the EPC device.
|
||||
::
|
||||
|
||||
| controllers/
|
||||
| <Directory: EPC name>/
|
||||
| <Symbolic Link: Function>
|
||||
| start
|
||||
| functions/
|
||||
| <Directory: EPF driver>/
|
||||
| <Directory: EPF device>/
|
||||
| vendorid
|
||||
| deviceid
|
||||
| revid
|
||||
| progif_code
|
||||
| subclass_code
|
||||
| baseclass_code
|
||||
| cache_line_size
|
||||
| subsys_vendor_id
|
||||
| subsys_id
|
||||
| interrupt_pin
|
||||
| function
|
||||
|
||||
[1] Documentation/PCI/endpoint/pci-endpoint.rst
|
231
Documentation/PCI/endpoint/pci-endpoint.rst
Normal file
@ -0,0 +1,231 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
:Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
|
||||
This document is a guide to use the PCI Endpoint Framework in order to create
|
||||
endpoint controller driver, endpoint function driver, and using configfs
|
||||
interface to bind the function driver to the controller driver.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
Linux has a comprehensive PCI subsystem to support PCI controllers that
|
||||
operates in Root Complex mode. The subsystem has capability to scan PCI bus,
|
||||
assign memory resources and IRQ resources, load PCI driver (based on
|
||||
vendor ID, device ID), support other services like hot-plug, power management,
|
||||
advanced error reporting and virtual channels.
|
||||
|
||||
However the PCI controller IP integrated in some SoCs is capable of operating
|
||||
either in Root Complex mode or Endpoint mode. PCI Endpoint Framework will
|
||||
add endpoint mode support in Linux. This will help to run Linux in an
|
||||
EP system which can have a wide variety of use cases from testing or
|
||||
validation, co-processor accelerator, etc.
|
||||
|
||||
PCI Endpoint Core
|
||||
=================
|
||||
|
||||
The PCI Endpoint Core layer comprises 3 components: the Endpoint Controller
|
||||
library, the Endpoint Function library, and the configfs layer to bind the
|
||||
endpoint function with the endpoint controller.
|
||||
|
||||
PCI Endpoint Controller(EPC) Library
|
||||
------------------------------------
|
||||
|
||||
The EPC library provides APIs to be used by the controller that can operate
|
||||
in endpoint mode. It also provides APIs to be used by function driver/library
|
||||
in order to implement a particular endpoint function.
|
||||
|
||||
APIs for the PCI controller Driver
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This section lists the APIs that the PCI Endpoint core provides to be used
|
||||
by the PCI controller driver.
|
||||
|
||||
* devm_pci_epc_create()/pci_epc_create()
|
||||
|
||||
The PCI controller driver should implement the following ops:
|
||||
|
||||
* write_header: ops to populate configuration space header
|
||||
* set_bar: ops to configure the BAR
|
||||
* clear_bar: ops to reset the BAR
|
||||
* alloc_addr_space: ops to allocate in PCI controller address space
|
||||
* free_addr_space: ops to free the allocated address space
|
||||
* raise_irq: ops to raise a legacy, MSI or MSI-X interrupt
|
||||
* start: ops to start the PCI link
|
||||
* stop: ops to stop the PCI link
|
||||
|
||||
The PCI controller driver can then create a new EPC device by invoking
|
||||
devm_pci_epc_create()/pci_epc_create().
|
||||
|
||||
* devm_pci_epc_destroy()/pci_epc_destroy()
|
||||
|
||||
The PCI controller driver can destroy the EPC device created by either
|
||||
devm_pci_epc_create() or pci_epc_create() using devm_pci_epc_destroy() or
|
||||
pci_epc_destroy().
|
||||
|
||||
* pci_epc_linkup()
|
||||
|
||||
In order to notify all the function devices that the EPC device to which
|
||||
they are linked has established a link with the host, the PCI controller
|
||||
driver should invoke pci_epc_linkup().
|
||||
|
||||
* pci_epc_mem_init()
|
||||
|
||||
Initialize the pci_epc_mem structure used for allocating EPC addr space.
|
||||
|
||||
* pci_epc_mem_exit()
|
||||
|
||||
Cleanup the pci_epc_mem structure allocated during pci_epc_mem_init().
|
||||
|
||||
|
||||
EPC APIs for the PCI Endpoint Function Driver
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This section lists the APIs that the PCI Endpoint core provides to be used
|
||||
by the PCI endpoint function driver.
|
||||
|
||||
* pci_epc_write_header()
|
||||
|
||||
The PCI endpoint function driver should use pci_epc_write_header() to
|
||||
write the standard configuration header to the endpoint controller.
|
||||
|
||||
* pci_epc_set_bar()
|
||||
|
||||
The PCI endpoint function driver should use pci_epc_set_bar() to configure
|
||||
the Base Address Register in order for the host to assign PCI addr space.
|
||||
Register space of the function driver is usually configured
|
||||
using this API.
|
||||
|
||||
* pci_epc_clear_bar()
|
||||
|
||||
The PCI endpoint function driver should use pci_epc_clear_bar() to reset
|
||||
the BAR.
|
||||
|
||||
* pci_epc_raise_irq()
|
||||
|
||||
The PCI endpoint function driver should use pci_epc_raise_irq() to raise
|
||||
Legacy Interrupt, MSI or MSI-X Interrupt.
|
||||
|
||||
* pci_epc_mem_alloc_addr()
|
||||
|
||||
The PCI endpoint function driver should use pci_epc_mem_alloc_addr(), to
|
||||
allocate memory address from EPC addr space which is required to access
|
||||
RC's buffer
|
||||
|
||||
* pci_epc_mem_free_addr()
|
||||
|
||||
The PCI endpoint function driver should use pci_epc_mem_free_addr() to
|
||||
free the memory space allocated using pci_epc_mem_alloc_addr().
|
||||
|
||||
Other EPC APIs
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
There are other APIs provided by the EPC library. These are used for binding
|
||||
the EPF device with EPC device. pci-ep-cfs.c can be used as reference for
|
||||
using these APIs.
|
||||
|
||||
* pci_epc_get()
|
||||
|
||||
Get a reference to the PCI endpoint controller based on the device name of
|
||||
the controller.
|
||||
|
||||
* pci_epc_put()
|
||||
|
||||
Release the reference to the PCI endpoint controller obtained using
|
||||
pci_epc_get()
|
||||
|
||||
* pci_epc_add_epf()
|
||||
|
||||
Add a PCI endpoint function to a PCI endpoint controller. A PCIe device
|
||||
can have up to 8 functions according to the specification.
|
||||
|
||||
* pci_epc_remove_epf()
|
||||
|
||||
Remove the PCI endpoint function from PCI endpoint controller.
|
||||
|
||||
* pci_epc_start()
|
||||
|
||||
The PCI endpoint function driver should invoke pci_epc_start() once it
|
||||
has configured the endpoint function and wants to start the PCI link.
|
||||
|
||||
* pci_epc_stop()
|
||||
|
||||
The PCI endpoint function driver should invoke pci_epc_stop() to stop
|
||||
the PCI LINK.
|
||||
|
||||
|
||||
PCI Endpoint Function(EPF) Library
|
||||
----------------------------------
|
||||
|
||||
The EPF library provides APIs to be used by the function driver and the EPC
|
||||
library to provide endpoint mode functionality.
|
||||
|
||||
EPF APIs for the PCI Endpoint Function Driver
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This section lists the APIs that the PCI Endpoint core provides to be used
|
||||
by the PCI endpoint function driver.
|
||||
|
||||
* pci_epf_register_driver()
|
||||
|
||||
The PCI Endpoint Function driver should implement the following ops:
|
||||
* bind: ops to perform when a EPC device has been bound to EPF device
|
||||
* unbind: ops to perform when a binding has been lost between a EPC
|
||||
device and EPF device
|
||||
* linkup: ops to perform when the EPC device has established a
|
||||
connection with a host system
|
||||
|
||||
The PCI Function driver can then register the PCI EPF driver by using
|
||||
pci_epf_register_driver().
|
||||
|
||||
* pci_epf_unregister_driver()
|
||||
|
||||
The PCI Function driver can unregister the PCI EPF driver by using
|
||||
pci_epf_unregister_driver().
|
||||
|
||||
* pci_epf_alloc_space()
|
||||
|
||||
The PCI Function driver can allocate space for a particular BAR using
|
||||
pci_epf_alloc_space().
|
||||
|
||||
* pci_epf_free_space()
|
||||
|
||||
The PCI Function driver can free the allocated space
|
||||
(using pci_epf_alloc_space) by invoking pci_epf_free_space().
|
||||
|
||||
APIs for the PCI Endpoint Controller Library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This section lists the APIs that the PCI Endpoint core provides to be used
|
||||
by the PCI endpoint controller library.
|
||||
|
||||
* pci_epf_linkup()
|
||||
|
||||
The PCI endpoint controller library invokes pci_epf_linkup() when the
|
||||
EPC device has established the connection to the host.
|
||||
|
||||
Other EPF APIs
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
There are other APIs provided by the EPF library. These are used to notify
|
||||
the function driver when the EPF device is bound to the EPC device.
|
||||
pci-ep-cfs.c can be used as reference for using these APIs.
|
||||
|
||||
* pci_epf_create()
|
||||
|
||||
Create a new PCI EPF device by passing the name of the PCI EPF device.
|
||||
This name will be used to bind the EPF device to a EPF driver.
|
||||
|
||||
* pci_epf_destroy()
|
||||
|
||||
Destroy the created PCI EPF device.
|
||||
|
||||
* pci_epf_bind()
|
||||
|
||||
pci_epf_bind() should be invoked when the EPF device has been bound to
|
||||
a EPC device.
|
||||
|
||||
* pci_epf_unbind()
|
||||
|
||||
pci_epf_unbind() should be invoked when the binding between EPC device
|
||||
and EPF device is lost.
|
348
Documentation/PCI/endpoint/pci-ntb-function.rst
Normal file
@ -0,0 +1,348 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=================
|
||||
PCI NTB Function
|
||||
=================
|
||||
|
||||
:Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
|
||||
PCI Non-Transparent Bridges (NTB) allow two host systems to communicate
|
||||
with each other by exposing each host as a device to the other host.
|
||||
NTBs typically support the ability to generate interrupts on the remote
|
||||
machine, expose memory ranges as BARs, and perform DMA. They also support
|
||||
scratchpads, which are areas of memory within the NTB that are accessible
|
||||
from both machines.
|
||||
|
||||
PCI NTB Function allows two different systems (or hosts) to communicate
|
||||
with each other by configuring the endpoint instances in such a way that
|
||||
transactions from one system are routed to the other system.
|
||||
|
||||
In the below diagram, PCI NTB function configures the SoC with multiple
|
||||
PCI Endpoint (EP) instances in such a way that transactions from one EP
|
||||
controller are routed to the other EP controller. Once PCI NTB function
|
||||
configures the SoC with multiple EP instances, HOST1 and HOST2 can
|
||||
communicate with each other using SoC as a bridge.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
+-------------+ +-------------+
|
||||
| | | |
|
||||
| HOST1 | | HOST2 |
|
||||
| | | |
|
||||
+------^------+ +------^------+
|
||||
| |
|
||||
| |
|
||||
+---------|-------------------------------------------------|---------+
|
||||
| +------v------+ +------v------+ |
|
||||
| | | | | |
|
||||
| | EP | | EP | |
|
||||
| | CONTROLLER1 | | CONTROLLER2 | |
|
||||
| | <-----------------------------------> | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | | SoC With Multiple EP Instances | | |
|
||||
| | | (Configured using NTB Function) | | |
|
||||
| +-------------+ +-------------+ |
|
||||
+---------------------------------------------------------------------+
|
||||
|
||||
Constructs used for Implementing NTB
|
||||
====================================
|
||||
|
||||
1) Config Region
|
||||
2) Self Scratchpad Registers
|
||||
3) Peer Scratchpad Registers
|
||||
4) Doorbell (DB) Registers
|
||||
5) Memory Window (MW)
|
||||
|
||||
|
||||
Config Region:
|
||||
--------------
|
||||
|
||||
Config Region is a construct that is specific to NTB implemented using NTB
|
||||
Endpoint Function Driver. The host and endpoint side NTB function driver will
|
||||
exchange information with each other using this region. Config Region has
|
||||
Control/Status Registers for configuring the Endpoint Controller. Host can
|
||||
write into this region for configuring the outbound Address Translation Unit
|
||||
(ATU) and to indicate the link status. Endpoint can indicate the status of
|
||||
commands issued by host in this region. Endpoint can also indicate the
|
||||
scratchpad offset and number of memory windows to the host using this region.
|
||||
|
||||
The format of Config Region is given below. All the fields here are 32 bits.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
+------------------------+
|
||||
| COMMAND |
|
||||
+------------------------+
|
||||
| ARGUMENT |
|
||||
+------------------------+
|
||||
| STATUS |
|
||||
+------------------------+
|
||||
| TOPOLOGY |
|
||||
+------------------------+
|
||||
| ADDRESS (LOWER 32) |
|
||||
+------------------------+
|
||||
| ADDRESS (UPPER 32) |
|
||||
+------------------------+
|
||||
| SIZE |
|
||||
+------------------------+
|
||||
| NO OF MEMORY WINDOW |
|
||||
+------------------------+
|
||||
| MEMORY WINDOW1 OFFSET |
|
||||
+------------------------+
|
||||
| SPAD OFFSET |
|
||||
+------------------------+
|
||||
| SPAD COUNT |
|
||||
+------------------------+
|
||||
| DB ENTRY SIZE |
|
||||
+------------------------+
|
||||
| DB DATA |
|
||||
+------------------------+
|
||||
| : |
|
||||
+------------------------+
|
||||
| : |
|
||||
+------------------------+
|
||||
| DB DATA |
|
||||
+------------------------+
|
||||
|
||||
|
||||
COMMAND:
|
||||
|
||||
NTB function supports three commands:
|
||||
|
||||
CMD_CONFIGURE_DOORBELL (0x1): Command to configure doorbell. Before
|
||||
invoking this command, the host should allocate and initialize
|
||||
MSI/MSI-X vectors (i.e., initialize the MSI/MSI-X Capability in the
|
||||
Endpoint). The endpoint on receiving this command will configure
|
||||
the outbound ATU such that transactions to Doorbell BAR will be routed
|
||||
to the MSI/MSI-X address programmed by the host. The ARGUMENT
|
||||
register should be populated with number of DBs to configure (in the
|
||||
lower 16 bits) and if MSI or MSI-X should be configured (BIT 16).
|
||||
|
||||
CMD_CONFIGURE_MW (0x2): Command to configure memory window (MW). The
|
||||
host invokes this command after allocating a buffer that can be
|
||||
accessed by remote host. The allocated address should be programmed
|
||||
in the ADDRESS register (64 bit), the size should be programmed in
|
||||
the SIZE register and the memory window index should be programmed
|
||||
in the ARGUMENT register. The endpoint on receiving this command
|
||||
will configure the outbound ATU such that transactions to MW BAR
|
||||
are routed to the address provided by the host.
|
||||
|
||||
CMD_LINK_UP (0x3): Command to indicate an NTB application is
|
||||
bound to the EP device on the host side. Once the endpoint
|
||||
receives this command from both the hosts, the endpoint will
|
||||
raise a LINK_UP event to both the hosts to indicate the host
|
||||
NTB applications can start communicating with each other.
|
||||
|
||||
ARGUMENT:
|
||||
|
||||
The value of this register is based on the commands issued in
|
||||
command register. See COMMAND section for more information.
|
||||
|
||||
TOPOLOGY:
|
||||
|
||||
Set to NTB_TOPO_B2B_USD for Primary interface
|
||||
Set to NTB_TOPO_B2B_DSD for Secondary interface
|
||||
|
||||
ADDRESS/SIZE:
|
||||
|
||||
Address and Size to be used while configuring the memory window.
|
||||
See "CMD_CONFIGURE_MW" for more info.
|
||||
|
||||
MEMORY WINDOW1 OFFSET:
|
||||
|
||||
Memory Window 1 and Doorbell registers are packed together in the
|
||||
same BAR. The initial portion of the region will have doorbell
|
||||
registers and the latter portion of the region is for memory window 1.
|
||||
This register will specify the offset of the memory window 1.
|
||||
|
||||
NO OF MEMORY WINDOW:
|
||||
|
||||
Specifies the number of memory windows supported by the NTB device.
|
||||
|
||||
SPAD OFFSET:
|
||||
|
||||
Self scratchpad region and config region are packed together in the
|
||||
same BAR. The initial portion of the region will have config region
|
||||
and the latter portion of the region is for self scratchpad. This
|
||||
register will specify the offset of the self scratchpad registers.
|
||||
|
||||
SPAD COUNT:
|
||||
|
||||
Specifies the number of scratchpad registers supported by the NTB
|
||||
device.
|
||||
|
||||
DB ENTRY SIZE:
|
||||
|
||||
Used to determine the offset within the DB BAR that should be written
|
||||
in order to raise doorbell. EPF NTB can use either MSI or MSI-X to
|
||||
ring doorbell (MSI-X support will be added later). MSI uses same
|
||||
address for all the interrupts and MSI-X can provide different
|
||||
addresses for different interrupts. The MSI/MSI-X address is provided
|
||||
by the host and the address it gives is based on the MSI/MSI-X
|
||||
implementation supported by the host. For instance, ARM platform
|
||||
using GIC ITS will have the same MSI-X address for all the interrupts.
|
||||
In order to support all the combinations and use the same mechanism
|
||||
for both MSI and MSI-X, EPF NTB allocates a separate region in the
|
||||
Outbound Address Space for each of the interrupts. This region will
|
||||
be mapped to the MSI/MSI-X address provided by the host. If a host
|
||||
provides the same address for all the interrupts, all the regions
|
||||
will be translated to the same address. If a host provides different
|
||||
addresses, the regions will be translated to different addresses. This
|
||||
will ensure there is no difference while raising the doorbell.
|
||||
|
||||
DB DATA:
|
||||
|
||||
EPF NTB supports 32 interrupts, so there are 32 DB DATA registers.
|
||||
This holds the MSI/MSI-X data that has to be written to MSI address
|
||||
for raising doorbell interrupt. This will be populated by EPF NTB
|
||||
while invoking CMD_CONFIGURE_DOORBELL.
|
||||
|
||||
Scratchpad Registers:
|
||||
---------------------
|
||||
|
||||
Each host has its own register space allocated in the memory of NTB endpoint
|
||||
controller. They are both readable and writable from both sides of the bridge.
|
||||
They are used by applications built over NTB and can be used to pass control
|
||||
and status information between both sides of a device.
|
||||
|
||||
Scratchpad registers has 2 parts
|
||||
1) Self Scratchpad: Host's own register space
|
||||
2) Peer Scratchpad: Remote host's register space.
|
||||
|
||||
Doorbell Registers:
|
||||
-------------------
|
||||
|
||||
Doorbell Registers are used by the hosts to interrupt each other.
|
||||
|
||||
Memory Window:
|
||||
--------------
|
||||
|
||||
Actual transfer of data between the two hosts will happen using the
|
||||
memory window.
|
||||
|
||||
Modeling Constructs:
|
||||
====================
|
||||
|
||||
There are 5 or more distinct regions (config, self scratchpad, peer
|
||||
scratchpad, doorbell, one or more memory windows) to be modeled to achieve
|
||||
NTB functionality. At least one memory window is required while more than
|
||||
one is permitted. All these regions should be mapped to BARs for hosts to
|
||||
access these regions.
|
||||
|
||||
If one 32-bit BAR is allocated for each of these regions, the scheme would
|
||||
look like this:
|
||||
|
||||
====== ===============
|
||||
BAR NO CONSTRUCTS USED
|
||||
====== ===============
|
||||
BAR0 Config Region
|
||||
BAR1 Self Scratchpad
|
||||
BAR2 Peer Scratchpad
|
||||
BAR3 Doorbell
|
||||
BAR4 Memory Window 1
|
||||
BAR5 Memory Window 2
|
||||
====== ===============
|
||||
|
||||
However if we allocate a separate BAR for each of the regions, there would not
|
||||
be enough BARs for all the regions in a platform that supports only 64-bit
|
||||
BARs.
|
||||
|
||||
In order to be supported by most of the platforms, the regions should be
|
||||
packed and mapped to BARs in a way that provides NTB functionality and
|
||||
also makes sure the host doesn't access any region that it is not supposed
|
||||
to.
|
||||
|
||||
The following scheme is used in EPF NTB Function:
|
||||
|
||||
====== ===============================
|
||||
BAR NO CONSTRUCTS USED
|
||||
====== ===============================
|
||||
BAR0 Config Region + Self Scratchpad
|
||||
BAR1 Peer Scratchpad
|
||||
BAR2 Doorbell + Memory Window 1
|
||||
BAR3 Memory Window 2
|
||||
BAR4 Memory Window 3
|
||||
BAR5 Memory Window 4
|
||||
====== ===============================
|
||||
|
||||
With this scheme, for the basic NTB functionality 3 BARs should be sufficient.
|
||||
|
||||
Modeling Config/Scratchpad Region:
|
||||
----------------------------------
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
+-----------------+------->+------------------+ +-----------------+
|
||||
| BAR0 | | CONFIG REGION | | BAR0 |
|
||||
+-----------------+----+ +------------------+<-------+-----------------+
|
||||
| BAR1 | | |SCRATCHPAD REGION | | BAR1 |
|
||||
+-----------------+ +-->+------------------+<-------+-----------------+
|
||||
| BAR2 | Local Memory | BAR2 |
|
||||
+-----------------+ +-----------------+
|
||||
| BAR3 | | BAR3 |
|
||||
+-----------------+ +-----------------+
|
||||
| BAR4 | | BAR4 |
|
||||
+-----------------+ +-----------------+
|
||||
| BAR5 | | BAR5 |
|
||||
+-----------------+ +-----------------+
|
||||
EP CONTROLLER 1 EP CONTROLLER 2
|
||||
|
||||
Above diagram shows Config region + Scratchpad region for HOST1 (connected to
|
||||
EP controller 1) allocated in local memory. The HOST1 can access the config
|
||||
region and scratchpad region (self scratchpad) using BAR0 of EP controller 1.
|
||||
The peer host (HOST2 connected to EP controller 2) can also access this
|
||||
scratchpad region (peer scratchpad) using BAR1 of EP controller 2. This
|
||||
diagram shows the case where Config region and Scratchpad regions are allocated
|
||||
for HOST1, however the same is applicable for HOST2.
|
||||
|
||||
Modeling Doorbell/Memory Window 1:
|
||||
----------------------------------
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
+-----------------+ +----->+----------------+-----------+-----------------+
|
||||
| BAR0 | | | Doorbell 1 +-----------> MSI-X ADDRESS 1 |
|
||||
+-----------------+ | +----------------+ +-----------------+
|
||||
| BAR1 | | | Doorbell 2 +---------+ | |
|
||||
+-----------------+----+ +----------------+ | | |
|
||||
| BAR2 | | Doorbell 3 +-------+ | +-----------------+
|
||||
+-----------------+----+ +----------------+ | +-> MSI-X ADDRESS 2 |
|
||||
| BAR3 | | | Doorbell 4 +-----+ | +-----------------+
|
||||
+-----------------+ | |----------------+ | | | |
|
||||
| BAR4 | | | | | | +-----------------+
|
||||
+-----------------+ | | MW1 +---+ | +-->+ MSI-X ADDRESS 3||
|
||||
| BAR5 | | | | | | +-----------------+
|
||||
+-----------------+ +----->-----------------+ | | | |
|
||||
EP CONTROLLER 1 | | | | +-----------------+
|
||||
| | | +---->+ MSI-X ADDRESS 4 |
|
||||
+----------------+ | +-----------------+
|
||||
EP CONTROLLER 2 | | |
|
||||
(OB SPACE) | | |
|
||||
+-------> MW1 |
|
||||
| |
|
||||
| |
|
||||
+-----------------+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+-----------------+
|
||||
PCI Address Space
|
||||
(Managed by HOST2)
|
||||
|
||||
Above diagram shows how the doorbell and memory window 1 is mapped so that
|
||||
HOST1 can raise doorbell interrupt on HOST2 and also how HOST1 can access
|
||||
buffers exposed by HOST2 using memory window1 (MW1). Here doorbell and
|
||||
memory window 1 regions are allocated in EP controller 2 outbound (OB) address
|
||||
space. Allocating and configuring BARs for doorbell and memory window1
|
||||
is done during the initialization phase of NTB endpoint function driver.
|
||||
Mapping from EP controller 2 OB space to PCI address space is done when HOST2
|
||||
sends CMD_CONFIGURE_MW/CMD_CONFIGURE_DOORBELL.
|
||||
|
||||
Modeling Optional Memory Windows:
|
||||
---------------------------------
|
||||
|
||||
This is modeled the same was as MW1 but each of the additional memory windows
|
||||
is mapped to separate BARs.
|
161
Documentation/PCI/endpoint/pci-ntb-howto.rst
Normal file
@ -0,0 +1,161 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===================================================================
|
||||
PCI Non-Transparent Bridge (NTB) Endpoint Function (EPF) User Guide
|
||||
===================================================================
|
||||
|
||||
:Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
|
||||
This document is a guide to help users use pci-epf-ntb function driver
|
||||
and ntb_hw_epf host driver for NTB functionality. The list of steps to
|
||||
be followed in the host side and EP side is given below. For the hardware
|
||||
configuration and internals of NTB using configurable endpoints see
|
||||
Documentation/PCI/endpoint/pci-ntb-function.rst
|
||||
|
||||
Endpoint Device
|
||||
===============
|
||||
|
||||
Endpoint Controller Devices
|
||||
---------------------------
|
||||
|
||||
For implementing NTB functionality at least two endpoint controller devices
|
||||
are required.
|
||||
|
||||
To find the list of endpoint controller devices in the system::
|
||||
|
||||
# ls /sys/class/pci_epc/
|
||||
2900000.pcie-ep 2910000.pcie-ep
|
||||
|
||||
If PCI_ENDPOINT_CONFIGFS is enabled::
|
||||
|
||||
# ls /sys/kernel/config/pci_ep/controllers
|
||||
2900000.pcie-ep 2910000.pcie-ep
|
||||
|
||||
|
||||
Endpoint Function Drivers
|
||||
-------------------------
|
||||
|
||||
To find the list of endpoint function drivers in the system::
|
||||
|
||||
# ls /sys/bus/pci-epf/drivers
|
||||
pci_epf_ntb pci_epf_ntb
|
||||
|
||||
If PCI_ENDPOINT_CONFIGFS is enabled::
|
||||
|
||||
# ls /sys/kernel/config/pci_ep/functions
|
||||
pci_epf_ntb pci_epf_ntb
|
||||
|
||||
|
||||
Creating pci-epf-ntb Device
|
||||
----------------------------
|
||||
|
||||
PCI endpoint function device can be created using the configfs. To create
|
||||
pci-epf-ntb device, the following commands can be used::
|
||||
|
||||
# mount -t configfs none /sys/kernel/config
|
||||
# cd /sys/kernel/config/pci_ep/
|
||||
# mkdir functions/pci_epf_ntb/func1
|
||||
|
||||
The "mkdir func1" above creates the pci-epf-ntb function device that will
|
||||
be probed by pci_epf_ntb driver.
|
||||
|
||||
The PCI endpoint framework populates the directory with the following
|
||||
configurable fields::
|
||||
|
||||
# ls functions/pci_epf_ntb/func1
|
||||
baseclass_code deviceid msi_interrupts pci-epf-ntb.0
|
||||
progif_code secondary subsys_id vendorid
|
||||
cache_line_size interrupt_pin msix_interrupts primary
|
||||
revid subclass_code subsys_vendor_id
|
||||
|
||||
The PCI endpoint function driver populates these entries with default values
|
||||
when the device is bound to the driver. The pci-epf-ntb driver populates
|
||||
vendorid with 0xffff and interrupt_pin with 0x0001::
|
||||
|
||||
# cat functions/pci_epf_ntb/func1/vendorid
|
||||
0xffff
|
||||
# cat functions/pci_epf_ntb/func1/interrupt_pin
|
||||
0x0001
|
||||
|
||||
|
||||
Configuring pci-epf-ntb Device
|
||||
-------------------------------
|
||||
|
||||
The user can configure the pci-epf-ntb device using its configfs entry. In order
|
||||
to change the vendorid and the deviceid, the following
|
||||
commands can be used::
|
||||
|
||||
# echo 0x104c > functions/pci_epf_ntb/func1/vendorid
|
||||
# echo 0xb00d > functions/pci_epf_ntb/func1/deviceid
|
||||
|
||||
In order to configure NTB specific attributes, a new sub-directory to func1
|
||||
should be created::
|
||||
|
||||
# mkdir functions/pci_epf_ntb/func1/pci_epf_ntb.0/
|
||||
|
||||
The NTB function driver will populate this directory with various attributes
|
||||
that can be configured by the user::
|
||||
|
||||
# ls functions/pci_epf_ntb/func1/pci_epf_ntb.0/
|
||||
db_count mw1 mw2 mw3 mw4 num_mws
|
||||
spad_count
|
||||
|
||||
A sample configuration for NTB function is given below::
|
||||
|
||||
# echo 4 > functions/pci_epf_ntb/func1/pci_epf_ntb.0/db_count
|
||||
# echo 128 > functions/pci_epf_ntb/func1/pci_epf_ntb.0/spad_count
|
||||
# echo 2 > functions/pci_epf_ntb/func1/pci_epf_ntb.0/num_mws
|
||||
# echo 0x100000 > functions/pci_epf_ntb/func1/pci_epf_ntb.0/mw1
|
||||
# echo 0x100000 > functions/pci_epf_ntb/func1/pci_epf_ntb.0/mw2
|
||||
|
||||
Binding pci-epf-ntb Device to EP Controller
|
||||
--------------------------------------------
|
||||
|
||||
NTB function device should be attached to two PCI endpoint controllers
|
||||
connected to the two hosts. Use the 'primary' and 'secondary' entries
|
||||
inside NTB function device to attach one PCI endpoint controller to
|
||||
primary interface and the other PCI endpoint controller to the secondary
|
||||
interface::
|
||||
|
||||
# ln -s controllers/2900000.pcie-ep/ functions/pci-epf-ntb/func1/primary
|
||||
# ln -s controllers/2910000.pcie-ep/ functions/pci-epf-ntb/func1/secondary
|
||||
|
||||
Once the above step is completed, both the PCI endpoint controllers are ready to
|
||||
establish a link with the host.
|
||||
|
||||
|
||||
Start the Link
|
||||
--------------
|
||||
|
||||
In order for the endpoint device to establish a link with the host, the _start_
|
||||
field should be populated with '1'. For NTB, both the PCI endpoint controllers
|
||||
should establish link with the host::
|
||||
|
||||
# echo 1 > controllers/2900000.pcie-ep/start
|
||||
# echo 1 > controllers/2910000.pcie-ep/start
|
||||
|
||||
|
||||
RootComplex Device
|
||||
==================
|
||||
|
||||
lspci Output
|
||||
------------
|
||||
|
||||
Note that the devices listed here correspond to the values populated in
|
||||
"Creating pci-epf-ntb Device" section above::
|
||||
|
||||
# lspci
|
||||
0000:00:00.0 PCI bridge: Texas Instruments Device b00d
|
||||
0000:01:00.0 RAM memory: Texas Instruments Device b00d
|
||||
|
||||
|
||||
Using ntb_hw_epf Device
|
||||
-----------------------
|
||||
|
||||
The host side software follows the standard NTB software architecture in Linux.
|
||||
All the existing client side NTB utilities like NTB Transport Client and NTB
|
||||
Netdev, NTB Ping Pong Test Client and NTB Tool Test Client can be used with NTB
|
||||
function device.
|
||||
|
||||
For more information on NTB see
|
||||
:doc:`Non-Transparent Bridge <../../driver-api/ntb>`
|
103
Documentation/PCI/endpoint/pci-test-function.rst
Normal file
@ -0,0 +1,103 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=================
|
||||
PCI Test Function
|
||||
=================
|
||||
|
||||
:Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
|
||||
Traditionally PCI RC has always been validated by using standard
|
||||
PCI cards like ethernet PCI cards or USB PCI cards or SATA PCI cards.
|
||||
However with the addition of EP-core in linux kernel, it is possible
|
||||
to configure a PCI controller that can operate in EP mode to work as
|
||||
a test device.
|
||||
|
||||
The PCI endpoint test device is a virtual device (defined in software)
|
||||
used to test the endpoint functionality and serve as a sample driver
|
||||
for other PCI endpoint devices (to use the EP framework).
|
||||
|
||||
The PCI endpoint test device has the following registers:
|
||||
|
||||
1) PCI_ENDPOINT_TEST_MAGIC
|
||||
2) PCI_ENDPOINT_TEST_COMMAND
|
||||
3) PCI_ENDPOINT_TEST_STATUS
|
||||
4) PCI_ENDPOINT_TEST_SRC_ADDR
|
||||
5) PCI_ENDPOINT_TEST_DST_ADDR
|
||||
6) PCI_ENDPOINT_TEST_SIZE
|
||||
7) PCI_ENDPOINT_TEST_CHECKSUM
|
||||
8) PCI_ENDPOINT_TEST_IRQ_TYPE
|
||||
9) PCI_ENDPOINT_TEST_IRQ_NUMBER
|
||||
|
||||
* PCI_ENDPOINT_TEST_MAGIC
|
||||
|
||||
This register will be used to test BAR0. A known pattern will be written
|
||||
and read back from MAGIC register to verify BAR0.
|
||||
|
||||
* PCI_ENDPOINT_TEST_COMMAND
|
||||
|
||||
This register will be used by the host driver to indicate the function
|
||||
that the endpoint device must perform.
|
||||
|
||||
======== ================================================================
|
||||
Bitfield Description
|
||||
======== ================================================================
|
||||
Bit 0 raise legacy IRQ
|
||||
Bit 1 raise MSI IRQ
|
||||
Bit 2 raise MSI-X IRQ
|
||||
Bit 3 read command (read data from RC buffer)
|
||||
Bit 4 write command (write data to RC buffer)
|
||||
Bit 5 copy command (copy data from one RC buffer to another RC buffer)
|
||||
======== ================================================================
|
||||
|
||||
* PCI_ENDPOINT_TEST_STATUS
|
||||
|
||||
This register reflects the status of the PCI endpoint device.
|
||||
|
||||
======== ==============================
|
||||
Bitfield Description
|
||||
======== ==============================
|
||||
Bit 0 read success
|
||||
Bit 1 read fail
|
||||
Bit 2 write success
|
||||
Bit 3 write fail
|
||||
Bit 4 copy success
|
||||
Bit 5 copy fail
|
||||
Bit 6 IRQ raised
|
||||
Bit 7 source address is invalid
|
||||
Bit 8 destination address is invalid
|
||||
======== ==============================
|
||||
|
||||
* PCI_ENDPOINT_TEST_SRC_ADDR
|
||||
|
||||
This register contains the source address (RC buffer address) for the
|
||||
COPY/READ command.
|
||||
|
||||
* PCI_ENDPOINT_TEST_DST_ADDR
|
||||
|
||||
This register contains the destination address (RC buffer address) for
|
||||
the COPY/WRITE command.
|
||||
|
||||
* PCI_ENDPOINT_TEST_IRQ_TYPE
|
||||
|
||||
This register contains the interrupt type (Legacy/MSI) triggered
|
||||
for the READ/WRITE/COPY and raise IRQ (Legacy/MSI) commands.
|
||||
|
||||
Possible types:
|
||||
|
||||
====== ==
|
||||
Legacy 0
|
||||
MSI 1
|
||||
MSI-X 2
|
||||
====== ==
|
||||
|
||||
* PCI_ENDPOINT_TEST_IRQ_NUMBER
|
||||
|
||||
This register contains the triggered ID interrupt.
|
||||
|
||||
Admissible values:
|
||||
|
||||
====== ===========
|
||||
Legacy 0
|
||||
MSI [1 .. 32]
|
||||
MSI-X [1 .. 2048]
|
||||
====== ===========
|
235
Documentation/PCI/endpoint/pci-test-howto.rst
Normal file
@ -0,0 +1,235 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===================
|
||||
PCI Test User Guide
|
||||
===================
|
||||
|
||||
:Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
|
||||
This document is a guide to help users use pci-epf-test function driver
|
||||
and pci_endpoint_test host driver for testing PCI. The list of steps to
|
||||
be followed in the host side and EP side is given below.
|
||||
|
||||
Endpoint Device
|
||||
===============
|
||||
|
||||
Endpoint Controller Devices
|
||||
---------------------------
|
||||
|
||||
To find the list of endpoint controller devices in the system::
|
||||
|
||||
# ls /sys/class/pci_epc/
|
||||
51000000.pcie_ep
|
||||
|
||||
If PCI_ENDPOINT_CONFIGFS is enabled::
|
||||
|
||||
# ls /sys/kernel/config/pci_ep/controllers
|
||||
51000000.pcie_ep
|
||||
|
||||
|
||||
Endpoint Function Drivers
|
||||
-------------------------
|
||||
|
||||
To find the list of endpoint function drivers in the system::
|
||||
|
||||
# ls /sys/bus/pci-epf/drivers
|
||||
pci_epf_test
|
||||
|
||||
If PCI_ENDPOINT_CONFIGFS is enabled::
|
||||
|
||||
# ls /sys/kernel/config/pci_ep/functions
|
||||
pci_epf_test
|
||||
|
||||
|
||||
Creating pci-epf-test Device
|
||||
----------------------------
|
||||
|
||||
PCI endpoint function device can be created using the configfs. To create
|
||||
pci-epf-test device, the following commands can be used::
|
||||
|
||||
# mount -t configfs none /sys/kernel/config
|
||||
# cd /sys/kernel/config/pci_ep/
|
||||
# mkdir functions/pci_epf_test/func1
|
||||
|
||||
The "mkdir func1" above creates the pci-epf-test function device that will
|
||||
be probed by pci_epf_test driver.
|
||||
|
||||
The PCI endpoint framework populates the directory with the following
|
||||
configurable fields::
|
||||
|
||||
# ls functions/pci_epf_test/func1
|
||||
baseclass_code interrupt_pin progif_code subsys_id
|
||||
cache_line_size msi_interrupts revid subsys_vendorid
|
||||
deviceid msix_interrupts subclass_code vendorid
|
||||
|
||||
The PCI endpoint function driver populates these entries with default values
|
||||
when the device is bound to the driver. The pci-epf-test driver populates
|
||||
vendorid with 0xffff and interrupt_pin with 0x0001::
|
||||
|
||||
# cat functions/pci_epf_test/func1/vendorid
|
||||
0xffff
|
||||
# cat functions/pci_epf_test/func1/interrupt_pin
|
||||
0x0001
|
||||
|
||||
|
||||
Configuring pci-epf-test Device
|
||||
-------------------------------
|
||||
|
||||
The user can configure the pci-epf-test device using configfs entry. In order
|
||||
to change the vendorid and the number of MSI interrupts used by the function
|
||||
device, the following commands can be used::
|
||||
|
||||
# echo 0x104c > functions/pci_epf_test/func1/vendorid
|
||||
# echo 0xb500 > functions/pci_epf_test/func1/deviceid
|
||||
# echo 16 > functions/pci_epf_test/func1/msi_interrupts
|
||||
# echo 8 > functions/pci_epf_test/func1/msix_interrupts
|
||||
|
||||
|
||||
Binding pci-epf-test Device to EP Controller
|
||||
--------------------------------------------
|
||||
|
||||
In order for the endpoint function device to be useful, it has to be bound to
|
||||
a PCI endpoint controller driver. Use the configfs to bind the function
|
||||
device to one of the controller driver present in the system::
|
||||
|
||||
# ln -s functions/pci_epf_test/func1 controllers/51000000.pcie_ep/
|
||||
|
||||
Once the above step is completed, the PCI endpoint is ready to establish a link
|
||||
with the host.
|
||||
|
||||
|
||||
Start the Link
|
||||
--------------
|
||||
|
||||
In order for the endpoint device to establish a link with the host, the _start_
|
||||
field should be populated with '1'::
|
||||
|
||||
# echo 1 > controllers/51000000.pcie_ep/start
|
||||
|
||||
|
||||
RootComplex Device
|
||||
==================
|
||||
|
||||
lspci Output
|
||||
------------
|
||||
|
||||
Note that the devices listed here correspond to the value populated in 1.4
|
||||
above::
|
||||
|
||||
00:00.0 PCI bridge: Texas Instruments Device 8888 (rev 01)
|
||||
01:00.0 Unassigned class [ff00]: Texas Instruments Device b500
|
||||
|
||||
|
||||
Using Endpoint Test function Device
|
||||
-----------------------------------
|
||||
|
||||
pcitest.sh added in tools/pci/ can be used to run all the default PCI endpoint
|
||||
tests. To compile this tool the following commands should be used::
|
||||
|
||||
# cd <kernel-dir>
|
||||
# make -C tools/pci
|
||||
|
||||
or if you desire to compile and install in your system::
|
||||
|
||||
# cd <kernel-dir>
|
||||
# make -C tools/pci install
|
||||
|
||||
The tool and script will be located in <rootfs>/usr/bin/
|
||||
|
||||
|
||||
pcitest.sh Output
|
||||
~~~~~~~~~~~~~~~~~
|
||||
::
|
||||
|
||||
# pcitest.sh
|
||||
BAR tests
|
||||
|
||||
BAR0: OKAY
|
||||
BAR1: OKAY
|
||||
BAR2: OKAY
|
||||
BAR3: OKAY
|
||||
BAR4: NOT OKAY
|
||||
BAR5: NOT OKAY
|
||||
|
||||
Interrupt tests
|
||||
|
||||
SET IRQ TYPE TO LEGACY: OKAY
|
||||
LEGACY IRQ: NOT OKAY
|
||||
SET IRQ TYPE TO MSI: OKAY
|
||||
MSI1: OKAY
|
||||
MSI2: OKAY
|
||||
MSI3: OKAY
|
||||
MSI4: OKAY
|
||||
MSI5: OKAY
|
||||
MSI6: OKAY
|
||||
MSI7: OKAY
|
||||
MSI8: OKAY
|
||||
MSI9: OKAY
|
||||
MSI10: OKAY
|
||||
MSI11: OKAY
|
||||
MSI12: OKAY
|
||||
MSI13: OKAY
|
||||
MSI14: OKAY
|
||||
MSI15: OKAY
|
||||
MSI16: OKAY
|
||||
MSI17: NOT OKAY
|
||||
MSI18: NOT OKAY
|
||||
MSI19: NOT OKAY
|
||||
MSI20: NOT OKAY
|
||||
MSI21: NOT OKAY
|
||||
MSI22: NOT OKAY
|
||||
MSI23: NOT OKAY
|
||||
MSI24: NOT OKAY
|
||||
MSI25: NOT OKAY
|
||||
MSI26: NOT OKAY
|
||||
MSI27: NOT OKAY
|
||||
MSI28: NOT OKAY
|
||||
MSI29: NOT OKAY
|
||||
MSI30: NOT OKAY
|
||||
MSI31: NOT OKAY
|
||||
MSI32: NOT OKAY
|
||||
SET IRQ TYPE TO MSI-X: OKAY
|
||||
MSI-X1: OKAY
|
||||
MSI-X2: OKAY
|
||||
MSI-X3: OKAY
|
||||
MSI-X4: OKAY
|
||||
MSI-X5: OKAY
|
||||
MSI-X6: OKAY
|
||||
MSI-X7: OKAY
|
||||
MSI-X8: OKAY
|
||||
MSI-X9: NOT OKAY
|
||||
MSI-X10: NOT OKAY
|
||||
MSI-X11: NOT OKAY
|
||||
MSI-X12: NOT OKAY
|
||||
MSI-X13: NOT OKAY
|
||||
MSI-X14: NOT OKAY
|
||||
MSI-X15: NOT OKAY
|
||||
MSI-X16: NOT OKAY
|
||||
[...]
|
||||
MSI-X2047: NOT OKAY
|
||||
MSI-X2048: NOT OKAY
|
||||
|
||||
Read Tests
|
||||
|
||||
SET IRQ TYPE TO MSI: OKAY
|
||||
READ ( 1 bytes): OKAY
|
||||
READ ( 1024 bytes): OKAY
|
||||
READ ( 1025 bytes): OKAY
|
||||
READ (1024000 bytes): OKAY
|
||||
READ (1024001 bytes): OKAY
|
||||
|
||||
Write Tests
|
||||
|
||||
WRITE ( 1 bytes): OKAY
|
||||
WRITE ( 1024 bytes): OKAY
|
||||
WRITE ( 1025 bytes): OKAY
|
||||
WRITE (1024000 bytes): OKAY
|
||||
WRITE (1024001 bytes): OKAY
|
||||
|
||||
Copy Tests
|
||||
|
||||
COPY ( 1 bytes): OKAY
|
||||
COPY ( 1024 bytes): OKAY
|
||||
COPY ( 1025 bytes): OKAY
|
||||
COPY (1024000 bytes): OKAY
|
||||
COPY (1024001 bytes): OKAY
|
20
Documentation/PCI/index.rst
Normal file
@ -0,0 +1,20 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=======================
|
||||
Linux PCI Bus Subsystem
|
||||
=======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
|
||||
pci
|
||||
pciebus-howto
|
||||
pci-iov-howto
|
||||
msi-howto
|
||||
sysfs-pci
|
||||
acpi-info
|
||||
pci-error-recovery
|
||||
pcieaer-howto
|
||||
endpoint/index
|
||||
boot-interrupts
|
287
Documentation/PCI/msi-howto.rst
Normal file
@ -0,0 +1,287 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: <isonum.txt>
|
||||
|
||||
==========================
|
||||
The MSI Driver Guide HOWTO
|
||||
==========================
|
||||
|
||||
:Authors: Tom L Nguyen; Martine Silbermann; Matthew Wilcox
|
||||
|
||||
:Copyright: 2003, 2008 Intel Corporation
|
||||
|
||||
About this guide
|
||||
================
|
||||
|
||||
This guide describes the basics of Message Signaled Interrupts (MSIs),
|
||||
the advantages of using MSI over traditional interrupt mechanisms, how
|
||||
to change your driver to use MSI or MSI-X and some basic diagnostics to
|
||||
try if a device doesn't support MSIs.
|
||||
|
||||
|
||||
What are MSIs?
|
||||
==============
|
||||
|
||||
A Message Signaled Interrupt is a write from the device to a special
|
||||
address which causes an interrupt to be received by the CPU.
|
||||
|
||||
The MSI capability was first specified in PCI 2.2 and was later enhanced
|
||||
in PCI 3.0 to allow each interrupt to be masked individually. The MSI-X
|
||||
capability was also introduced with PCI 3.0. It supports more interrupts
|
||||
per device than MSI and allows interrupts to be independently configured.
|
||||
|
||||
Devices may support both MSI and MSI-X, but only one can be enabled at
|
||||
a time.
|
||||
|
||||
|
||||
Why use MSIs?
|
||||
=============
|
||||
|
||||
There are three reasons why using MSIs can give an advantage over
|
||||
traditional pin-based interrupts.
|
||||
|
||||
Pin-based PCI interrupts are often shared amongst several devices.
|
||||
To support this, the kernel must call each interrupt handler associated
|
||||
with an interrupt, which leads to reduced performance for the system as
|
||||
a whole. MSIs are never shared, so this problem cannot arise.
|
||||
|
||||
When a device writes data to memory, then raises a pin-based interrupt,
|
||||
it is possible that the interrupt may arrive before all the data has
|
||||
arrived in memory (this becomes more likely with devices behind PCI-PCI
|
||||
bridges). In order to ensure that all the data has arrived in memory,
|
||||
the interrupt handler must read a register on the device which raised
|
||||
the interrupt. PCI transaction ordering rules require that all the data
|
||||
arrive in memory before the value may be returned from the register.
|
||||
Using MSIs avoids this problem as the interrupt-generating write cannot
|
||||
pass the data writes, so by the time the interrupt is raised, the driver
|
||||
knows that all the data has arrived in memory.
|
||||
|
||||
PCI devices can only support a single pin-based interrupt per function.
|
||||
Often drivers have to query the device to find out what event has
|
||||
occurred, slowing down interrupt handling for the common case. With
|
||||
MSIs, a device can support more interrupts, allowing each interrupt
|
||||
to be specialised to a different purpose. One possible design gives
|
||||
infrequent conditions (such as errors) their own interrupt which allows
|
||||
the driver to handle the normal interrupt handling path more efficiently.
|
||||
Other possible designs include giving one interrupt to each packet queue
|
||||
in a network card or each port in a storage controller.
|
||||
|
||||
|
||||
How to use MSIs
|
||||
===============
|
||||
|
||||
PCI devices are initialised to use pin-based interrupts. The device
|
||||
driver has to set up the device to use MSI or MSI-X. Not all machines
|
||||
support MSIs correctly, and for those machines, the APIs described below
|
||||
will simply fail and the device will continue to use pin-based interrupts.
|
||||
|
||||
Include kernel support for MSIs
|
||||
-------------------------------
|
||||
|
||||
To support MSI or MSI-X, the kernel must be built with the CONFIG_PCI_MSI
|
||||
option enabled. This option is only available on some architectures,
|
||||
and it may depend on some other options also being set. For example,
|
||||
on x86, you must also enable X86_UP_APIC or SMP in order to see the
|
||||
CONFIG_PCI_MSI option.
|
||||
|
||||
Using MSI
|
||||
---------
|
||||
|
||||
Most of the hard work is done for the driver in the PCI layer. The driver
|
||||
simply has to request that the PCI layer set up the MSI capability for this
|
||||
device.
|
||||
|
||||
To automatically use MSI or MSI-X interrupt vectors, use the following
|
||||
function::
|
||||
|
||||
int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
|
||||
unsigned int max_vecs, unsigned int flags);
|
||||
|
||||
which allocates up to max_vecs interrupt vectors for a PCI device. It
|
||||
returns the number of vectors allocated or a negative error. If the device
|
||||
has a requirements for a minimum number of vectors the driver can pass a
|
||||
min_vecs argument set to this limit, and the PCI core will return -ENOSPC
|
||||
if it can't meet the minimum number of vectors.
|
||||
|
||||
The flags argument is used to specify which type of interrupt can be used
|
||||
by the device and the driver (PCI_IRQ_LEGACY, PCI_IRQ_MSI, PCI_IRQ_MSIX).
|
||||
A convenient short-hand (PCI_IRQ_ALL_TYPES) is also available to ask for
|
||||
any possible kind of interrupt. If the PCI_IRQ_AFFINITY flag is set,
|
||||
pci_alloc_irq_vectors() will spread the interrupts around the available CPUs.
|
||||
|
||||
To get the Linux IRQ numbers passed to request_irq() and free_irq() and the
|
||||
vectors, use the following function::
|
||||
|
||||
int pci_irq_vector(struct pci_dev *dev, unsigned int nr);
|
||||
|
||||
Any allocated resources should be freed before removing the device using
|
||||
the following function::
|
||||
|
||||
void pci_free_irq_vectors(struct pci_dev *dev);
|
||||
|
||||
If a device supports both MSI-X and MSI capabilities, this API will use the
|
||||
MSI-X facilities in preference to the MSI facilities. MSI-X supports any
|
||||
number of interrupts between 1 and 2048. In contrast, MSI is restricted to
|
||||
a maximum of 32 interrupts (and must be a power of two). In addition, the
|
||||
MSI interrupt vectors must be allocated consecutively, so the system might
|
||||
not be able to allocate as many vectors for MSI as it could for MSI-X. On
|
||||
some platforms, MSI interrupts must all be targeted at the same set of CPUs
|
||||
whereas MSI-X interrupts can all be targeted at different CPUs.
|
||||
|
||||
If a device supports neither MSI-X or MSI it will fall back to a single
|
||||
legacy IRQ vector.
|
||||
|
||||
The typical usage of MSI or MSI-X interrupts is to allocate as many vectors
|
||||
as possible, likely up to the limit supported by the device. If nvec is
|
||||
larger than the number supported by the device it will automatically be
|
||||
capped to the supported limit, so there is no need to query the number of
|
||||
vectors supported beforehand::
|
||||
|
||||
nvec = pci_alloc_irq_vectors(pdev, 1, nvec, PCI_IRQ_ALL_TYPES)
|
||||
if (nvec < 0)
|
||||
goto out_err;
|
||||
|
||||
If a driver is unable or unwilling to deal with a variable number of MSI
|
||||
interrupts it can request a particular number of interrupts by passing that
|
||||
number to pci_alloc_irq_vectors() function as both 'min_vecs' and
|
||||
'max_vecs' parameters::
|
||||
|
||||
ret = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_ALL_TYPES);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
|
||||
The most notorious example of the request type described above is enabling
|
||||
the single MSI mode for a device. It could be done by passing two 1s as
|
||||
'min_vecs' and 'max_vecs'::
|
||||
|
||||
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
|
||||
Some devices might not support using legacy line interrupts, in which case
|
||||
the driver can specify that only MSI or MSI-X is acceptable::
|
||||
|
||||
nvec = pci_alloc_irq_vectors(pdev, 1, nvec, PCI_IRQ_MSI | PCI_IRQ_MSIX);
|
||||
if (nvec < 0)
|
||||
goto out_err;
|
||||
|
||||
Legacy APIs
|
||||
-----------
|
||||
|
||||
The following old APIs to enable and disable MSI or MSI-X interrupts should
|
||||
not be used in new code::
|
||||
|
||||
pci_enable_msi() /* deprecated */
|
||||
pci_disable_msi() /* deprecated */
|
||||
pci_enable_msix_range() /* deprecated */
|
||||
pci_enable_msix_exact() /* deprecated */
|
||||
pci_disable_msix() /* deprecated */
|
||||
|
||||
Additionally there are APIs to provide the number of supported MSI or MSI-X
|
||||
vectors: pci_msi_vec_count() and pci_msix_vec_count(). In general these
|
||||
should be avoided in favor of letting pci_alloc_irq_vectors() cap the
|
||||
number of vectors. If you have a legitimate special use case for the count
|
||||
of vectors we might have to revisit that decision and add a
|
||||
pci_nr_irq_vectors() helper that handles MSI and MSI-X transparently.
|
||||
|
||||
Considerations when using MSIs
|
||||
------------------------------
|
||||
|
||||
Spinlocks
|
||||
~~~~~~~~~
|
||||
|
||||
Most device drivers have a per-device spinlock which is taken in the
|
||||
interrupt handler. With pin-based interrupts or a single MSI, it is not
|
||||
necessary to disable interrupts (Linux guarantees the same interrupt will
|
||||
not be re-entered). If a device uses multiple interrupts, the driver
|
||||
must disable interrupts while the lock is held. If the device sends
|
||||
a different interrupt, the driver will deadlock trying to recursively
|
||||
acquire the spinlock. Such deadlocks can be avoided by using
|
||||
spin_lock_irqsave() or spin_lock_irq() which disable local interrupts
|
||||
and acquire the lock (see Documentation/kernel-hacking/locking.rst).
|
||||
|
||||
How to tell whether MSI/MSI-X is enabled on a device
|
||||
----------------------------------------------------
|
||||
|
||||
Using 'lspci -v' (as root) may show some devices with "MSI", "Message
|
||||
Signalled Interrupts" or "MSI-X" capabilities. Each of these capabilities
|
||||
has an 'Enable' flag which is followed with either "+" (enabled)
|
||||
or "-" (disabled).
|
||||
|
||||
|
||||
MSI quirks
|
||||
==========
|
||||
|
||||
Several PCI chipsets or devices are known not to support MSIs.
|
||||
The PCI stack provides three ways to disable MSIs:
|
||||
|
||||
1. globally
|
||||
2. on all devices behind a specific bridge
|
||||
3. on a single device
|
||||
|
||||
Disabling MSIs globally
|
||||
-----------------------
|
||||
|
||||
Some host chipsets simply don't support MSIs properly. If we're
|
||||
lucky, the manufacturer knows this and has indicated it in the ACPI
|
||||
FADT table. In this case, Linux automatically disables MSIs.
|
||||
Some boards don't include this information in the table and so we have
|
||||
to detect them ourselves. The complete list of these is found near the
|
||||
quirk_disable_all_msi() function in drivers/pci/quirks.c.
|
||||
|
||||
If you have a board which has problems with MSIs, you can pass pci=nomsi
|
||||
on the kernel command line to disable MSIs on all devices. It would be
|
||||
in your best interests to report the problem to linux-pci@vger.kernel.org
|
||||
including a full 'lspci -v' so we can add the quirks to the kernel.
|
||||
|
||||
Disabling MSIs below a bridge
|
||||
-----------------------------
|
||||
|
||||
Some PCI bridges are not able to route MSIs between busses properly.
|
||||
In this case, MSIs must be disabled on all devices behind the bridge.
|
||||
|
||||
Some bridges allow you to enable MSIs by changing some bits in their
|
||||
PCI configuration space (especially the Hypertransport chipsets such
|
||||
as the nVidia nForce and Serverworks HT2000). As with host chipsets,
|
||||
Linux mostly knows about them and automatically enables MSIs if it can.
|
||||
If you have a bridge unknown to Linux, you can enable
|
||||
MSIs in configuration space using whatever method you know works, then
|
||||
enable MSIs on that bridge by doing::
|
||||
|
||||
echo 1 > /sys/bus/pci/devices/$bridge/msi_bus
|
||||
|
||||
where $bridge is the PCI address of the bridge you've enabled (eg
|
||||
0000:00:0e.0).
|
||||
|
||||
To disable MSIs, echo 0 instead of 1. Changing this value should be
|
||||
done with caution as it could break interrupt handling for all devices
|
||||
below this bridge.
|
||||
|
||||
Again, please notify linux-pci@vger.kernel.org of any bridges that need
|
||||
special handling.
|
||||
|
||||
Disabling MSIs on a single device
|
||||
---------------------------------
|
||||
|
||||
Some devices are known to have faulty MSI implementations. Usually this
|
||||
is handled in the individual device driver, but occasionally it's necessary
|
||||
to handle this with a quirk. Some drivers have an option to disable use
|
||||
of MSI. While this is a convenient workaround for the driver author,
|
||||
it is not good practice, and should not be emulated.
|
||||
|
||||
Finding why MSIs are disabled on a device
|
||||
-----------------------------------------
|
||||
|
||||
From the above three sections, you can see that there are many reasons
|
||||
why MSIs may not be enabled for a given device. Your first step should
|
||||
be to examine your dmesg carefully to determine whether MSIs are enabled
|
||||
for your machine. You should also check your .config to be sure you
|
||||
have enabled CONFIG_PCI_MSI.
|
||||
|
||||
Then, 'lspci -t' gives the list of bridges above a device. Reading
|
||||
`/sys/bus/pci/devices/*/msi_bus` will tell you whether MSIs are enabled (1)
|
||||
or disabled (0). If 0 is found in any of the msi_bus files belonging
|
||||
to bridges between the PCI root and the device, MSIs are disabled.
|
||||
|
||||
It is also worth checking the device driver to see whether it supports MSIs.
|
||||
For example, it may contain calls to pci_alloc_irq_vectors() with the
|
||||
PCI_IRQ_MSI or PCI_IRQ_MSIX flags.
|
426
Documentation/PCI/pci-error-recovery.rst
Normal file
@ -0,0 +1,426 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==================
|
||||
PCI Error Recovery
|
||||
==================
|
||||
|
||||
|
||||
:Authors: - Linas Vepstas <linasvepstas@gmail.com>
|
||||
- Richard Lary <rlary@us.ibm.com>
|
||||
- Mike Mason <mmlnx@us.ibm.com>
|
||||
|
||||
|
||||
Many PCI bus controllers are able to detect a variety of hardware
|
||||
PCI errors on the bus, such as parity errors on the data and address
|
||||
buses, as well as SERR and PERR errors. Some of the more advanced
|
||||
chipsets are able to deal with these errors; these include PCI-E chipsets,
|
||||
and the PCI-host bridges found on IBM Power4, Power5 and Power6-based
|
||||
pSeries boxes. A typical action taken is to disconnect the affected device,
|
||||
halting all I/O to it. The goal of a disconnection is to avoid system
|
||||
corruption; for example, to halt system memory corruption due to DMA's
|
||||
to "wild" addresses. Typically, a reconnection mechanism is also
|
||||
offered, so that the affected PCI device(s) are reset and put back
|
||||
into working condition. The reset phase requires coordination
|
||||
between the affected device drivers and the PCI controller chip.
|
||||
This document describes a generic API for notifying device drivers
|
||||
of a bus disconnection, and then performing error recovery.
|
||||
This API is currently implemented in the 2.6.16 and later kernels.
|
||||
|
||||
Reporting and recovery is performed in several steps. First, when
|
||||
a PCI hardware error has resulted in a bus disconnect, that event
|
||||
is reported as soon as possible to all affected device drivers,
|
||||
including multiple instances of a device driver on multi-function
|
||||
cards. This allows device drivers to avoid deadlocking in spinloops,
|
||||
waiting for some i/o-space register to change, when it never will.
|
||||
It also gives the drivers a chance to defer incoming I/O as
|
||||
needed.
|
||||
|
||||
Next, recovery is performed in several stages. Most of the complexity
|
||||
is forced by the need to handle multi-function devices, that is,
|
||||
devices that have multiple device drivers associated with them.
|
||||
In the first stage, each driver is allowed to indicate what type
|
||||
of reset it desires, the choices being a simple re-enabling of I/O
|
||||
or requesting a slot reset.
|
||||
|
||||
If any driver requests a slot reset, that is what will be done.
|
||||
|
||||
After a reset and/or a re-enabling of I/O, all drivers are
|
||||
again notified, so that they may then perform any device setup/config
|
||||
that may be required. After these have all completed, a final
|
||||
"resume normal operations" event is sent out.
|
||||
|
||||
The biggest reason for choosing a kernel-based implementation rather
|
||||
than a user-space implementation was the need to deal with bus
|
||||
disconnects of PCI devices attached to storage media, and, in particular,
|
||||
disconnects from devices holding the root file system. If the root
|
||||
file system is disconnected, a user-space mechanism would have to go
|
||||
through a large number of contortions to complete recovery. Almost all
|
||||
of the current Linux file systems are not tolerant of disconnection
|
||||
from/reconnection to their underlying block device. By contrast,
|
||||
bus errors are easy to manage in the device driver. Indeed, most
|
||||
device drivers already handle very similar recovery procedures;
|
||||
for example, the SCSI-generic layer already provides significant
|
||||
mechanisms for dealing with SCSI bus errors and SCSI bus resets.
|
||||
|
||||
|
||||
Detailed Design
|
||||
===============
|
||||
|
||||
Design and implementation details below, based on a chain of
|
||||
public email discussions with Ben Herrenschmidt, circa 5 April 2005.
|
||||
|
||||
The error recovery API support is exposed to the driver in the form of
|
||||
a structure of function pointers pointed to by a new field in struct
|
||||
pci_driver. A driver that fails to provide the structure is "non-aware",
|
||||
and the actual recovery steps taken are platform dependent. The
|
||||
arch/powerpc implementation will simulate a PCI hotplug remove/add.
|
||||
|
||||
This structure has the form::
|
||||
|
||||
struct pci_error_handlers
|
||||
{
|
||||
int (*error_detected)(struct pci_dev *dev, pci_channel_state_t);
|
||||
int (*mmio_enabled)(struct pci_dev *dev);
|
||||
int (*slot_reset)(struct pci_dev *dev);
|
||||
void (*resume)(struct pci_dev *dev);
|
||||
};
|
||||
|
||||
The possible channel states are::
|
||||
|
||||
typedef enum {
|
||||
pci_channel_io_normal, /* I/O channel is in normal state */
|
||||
pci_channel_io_frozen, /* I/O to channel is blocked */
|
||||
pci_channel_io_perm_failure, /* PCI card is dead */
|
||||
} pci_channel_state_t;
|
||||
|
||||
Possible return values are::
|
||||
|
||||
enum pci_ers_result {
|
||||
PCI_ERS_RESULT_NONE, /* no result/none/not supported in device driver */
|
||||
PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */
|
||||
PCI_ERS_RESULT_NEED_RESET, /* Device driver wants slot to be reset. */
|
||||
PCI_ERS_RESULT_DISCONNECT, /* Device has completely failed, is unrecoverable */
|
||||
PCI_ERS_RESULT_RECOVERED, /* Device driver is fully recovered and operational */
|
||||
};
|
||||
|
||||
A driver does not have to implement all of these callbacks; however,
|
||||
if it implements any, it must implement error_detected(). If a callback
|
||||
is not implemented, the corresponding feature is considered unsupported.
|
||||
For example, if mmio_enabled() and resume() aren't there, then it
|
||||
is assumed that the driver is not doing any direct recovery and requires
|
||||
a slot reset. Typically a driver will want to know about
|
||||
a slot_reset().
|
||||
|
||||
The actual steps taken by a platform to recover from a PCI error
|
||||
event will be platform-dependent, but will follow the general
|
||||
sequence described below.
|
||||
|
||||
STEP 0: Error Event
|
||||
-------------------
|
||||
A PCI bus error is detected by the PCI hardware. On powerpc, the slot
|
||||
is isolated, in that all I/O is blocked: all reads return 0xffffffff,
|
||||
all writes are ignored.
|
||||
|
||||
|
||||
STEP 1: Notification
|
||||
--------------------
|
||||
Platform calls the error_detected() callback on every instance of
|
||||
every driver affected by the error.
|
||||
|
||||
At this point, the device might not be accessible anymore, depending on
|
||||
the platform (the slot will be isolated on powerpc). The driver may
|
||||
already have "noticed" the error because of a failing I/O, but this
|
||||
is the proper "synchronization point", that is, it gives the driver
|
||||
a chance to cleanup, waiting for pending stuff (timers, whatever, etc...)
|
||||
to complete; it can take semaphores, schedule, etc... everything but
|
||||
touch the device. Within this function and after it returns, the driver
|
||||
shouldn't do any new IOs. Called in task context. This is sort of a
|
||||
"quiesce" point. See note about interrupts at the end of this doc.
|
||||
|
||||
All drivers participating in this system must implement this call.
|
||||
The driver must return one of the following result codes:
|
||||
|
||||
- PCI_ERS_RESULT_CAN_RECOVER
|
||||
Driver returns this if it thinks it might be able to recover
|
||||
the HW by just banging IOs or if it wants to be given
|
||||
a chance to extract some diagnostic information (see
|
||||
mmio_enable, below).
|
||||
- PCI_ERS_RESULT_NEED_RESET
|
||||
Driver returns this if it can't recover without a
|
||||
slot reset.
|
||||
- PCI_ERS_RESULT_DISCONNECT
|
||||
Driver returns this if it doesn't want to recover at all.
|
||||
|
||||
The next step taken will depend on the result codes returned by the
|
||||
drivers.
|
||||
|
||||
If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER,
|
||||
then the platform should re-enable IOs on the slot (or do nothing in
|
||||
particular, if the platform doesn't isolate slots), and recovery
|
||||
proceeds to STEP 2 (MMIO Enable).
|
||||
|
||||
If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET),
|
||||
then recovery proceeds to STEP 4 (Slot Reset).
|
||||
|
||||
If the platform is unable to recover the slot, the next step
|
||||
is STEP 6 (Permanent Failure).
|
||||
|
||||
.. note::
|
||||
|
||||
The current powerpc implementation assumes that a device driver will
|
||||
*not* schedule or semaphore in this routine; the current powerpc
|
||||
implementation uses one kernel thread to notify all devices;
|
||||
thus, if one device sleeps/schedules, all devices are affected.
|
||||
Doing better requires complex multi-threaded logic in the error
|
||||
recovery implementation (e.g. waiting for all notification threads
|
||||
to "join" before proceeding with recovery.) This seems excessively
|
||||
complex and not worth implementing.
|
||||
|
||||
The current powerpc implementation doesn't much care if the device
|
||||
attempts I/O at this point, or not. I/O's will fail, returning
|
||||
a value of 0xff on read, and writes will be dropped. If more than
|
||||
EEH_MAX_FAILS I/O's are attempted to a frozen adapter, EEH
|
||||
assumes that the device driver has gone into an infinite loop
|
||||
and prints an error to syslog. A reboot is then required to
|
||||
get the device working again.
|
||||
|
||||
STEP 2: MMIO Enabled
|
||||
--------------------
|
||||
The platform re-enables MMIO to the device (but typically not the
|
||||
DMA), and then calls the mmio_enabled() callback on all affected
|
||||
device drivers.
|
||||
|
||||
This is the "early recovery" call. IOs are allowed again, but DMA is
|
||||
not, with some restrictions. This is NOT a callback for the driver to
|
||||
start operations again, only to peek/poke at the device, extract diagnostic
|
||||
information, if any, and eventually do things like trigger a device local
|
||||
reset or some such, but not restart operations. This callback is made if
|
||||
all drivers on a segment agree that they can try to recover and if no automatic
|
||||
link reset was performed by the HW. If the platform can't just re-enable IOs
|
||||
without a slot reset or a link reset, it will not call this callback, and
|
||||
instead will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
|
||||
|
||||
.. note::
|
||||
|
||||
The following is proposed; no platform implements this yet:
|
||||
Proposal: All I/O's should be done _synchronously_ from within
|
||||
this callback, errors triggered by them will be returned via
|
||||
the normal pci_check_whatever() API, no new error_detected()
|
||||
callback will be issued due to an error happening here. However,
|
||||
such an error might cause IOs to be re-blocked for the whole
|
||||
segment, and thus invalidate the recovery that other devices
|
||||
on the same segment might have done, forcing the whole segment
|
||||
into one of the next states, that is, link reset or slot reset.
|
||||
|
||||
The driver should return one of the following result codes:
|
||||
- PCI_ERS_RESULT_RECOVERED
|
||||
Driver returns this if it thinks the device is fully
|
||||
functional and thinks it is ready to start
|
||||
normal driver operations again. There is no
|
||||
guarantee that the driver will actually be
|
||||
allowed to proceed, as another driver on the
|
||||
same segment might have failed and thus triggered a
|
||||
slot reset on platforms that support it.
|
||||
|
||||
- PCI_ERS_RESULT_NEED_RESET
|
||||
Driver returns this if it thinks the device is not
|
||||
recoverable in its current state and it needs a slot
|
||||
reset to proceed.
|
||||
|
||||
- PCI_ERS_RESULT_DISCONNECT
|
||||
Same as above. Total failure, no recovery even after
|
||||
reset driver dead. (To be defined more precisely)
|
||||
|
||||
The next step taken depends on the results returned by the drivers.
|
||||
If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform
|
||||
proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
|
||||
|
||||
If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
|
||||
proceeds to STEP 4 (Slot Reset)
|
||||
|
||||
STEP 3: Link Reset
|
||||
------------------
|
||||
The platform resets the link. This is a PCI-Express specific step
|
||||
and is done whenever a fatal error has been detected that can be
|
||||
"solved" by resetting the link.
|
||||
|
||||
STEP 4: Slot Reset
|
||||
------------------
|
||||
|
||||
In response to a return value of PCI_ERS_RESULT_NEED_RESET, the
|
||||
platform will perform a slot reset on the requesting PCI device(s).
|
||||
The actual steps taken by a platform to perform a slot reset
|
||||
will be platform-dependent. Upon completion of slot reset, the
|
||||
platform will call the device slot_reset() callback.
|
||||
|
||||
Powerpc platforms implement two levels of slot reset:
|
||||
soft reset(default) and fundamental(optional) reset.
|
||||
|
||||
Powerpc soft reset consists of asserting the adapter #RST line and then
|
||||
restoring the PCI BAR's and PCI configuration header to a state
|
||||
that is equivalent to what it would be after a fresh system
|
||||
power-on followed by power-on BIOS/system firmware initialization.
|
||||
Soft reset is also known as hot-reset.
|
||||
|
||||
Powerpc fundamental reset is supported by PCI Express cards only
|
||||
and results in device's state machines, hardware logic, port states and
|
||||
configuration registers to initialize to their default conditions.
|
||||
|
||||
For most PCI devices, a soft reset will be sufficient for recovery.
|
||||
Optional fundamental reset is provided to support a limited number
|
||||
of PCI Express devices for which a soft reset is not sufficient
|
||||
for recovery.
|
||||
|
||||
If the platform supports PCI hotplug, then the reset might be
|
||||
performed by toggling the slot electrical power off/on.
|
||||
|
||||
It is important for the platform to restore the PCI config space
|
||||
to the "fresh poweron" state, rather than the "last state". After
|
||||
a slot reset, the device driver will almost always use its standard
|
||||
device initialization routines, and an unusual config space setup
|
||||
may result in hung devices, kernel panics, or silent data corruption.
|
||||
|
||||
This call gives drivers the chance to re-initialize the hardware
|
||||
(re-download firmware, etc.). At this point, the driver may assume
|
||||
that the card is in a fresh state and is fully functional. The slot
|
||||
is unfrozen and the driver has full access to PCI config space,
|
||||
memory mapped I/O space and DMA. Interrupts (Legacy, MSI, or MSI-X)
|
||||
will also be available.
|
||||
|
||||
Drivers should not restart normal I/O processing operations
|
||||
at this point. If all device drivers report success on this
|
||||
callback, the platform will call resume() to complete the sequence,
|
||||
and let the driver restart normal I/O processing.
|
||||
|
||||
A driver can still return a critical failure for this function if
|
||||
it can't get the device operational after reset. If the platform
|
||||
previously tried a soft reset, it might now try a hard reset (power
|
||||
cycle) and then call slot_reset() again. If the device still can't
|
||||
be recovered, there is nothing more that can be done; the platform
|
||||
will typically report a "permanent failure" in such a case. The
|
||||
device will be considered "dead" in this case.
|
||||
|
||||
Drivers for multi-function cards will need to coordinate among
|
||||
themselves as to which driver instance will perform any "one-shot"
|
||||
or global device initialization. For example, the Symbios sym53cxx2
|
||||
driver performs device init only from PCI function 0::
|
||||
|
||||
+ if (PCI_FUNC(pdev->devfn) == 0)
|
||||
+ sym_reset_scsi_bus(np, 0);
|
||||
|
||||
Result codes:
|
||||
- PCI_ERS_RESULT_DISCONNECT
|
||||
Same as above.
|
||||
|
||||
Drivers for PCI Express cards that require a fundamental reset must
|
||||
set the needs_freset bit in the pci_dev structure in their probe function.
|
||||
For example, the QLogic qla2xxx driver sets the needs_freset bit for certain
|
||||
PCI card types::
|
||||
|
||||
+ /* Set EEH reset type to fundamental if required by hba */
|
||||
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha))
|
||||
+ pdev->needs_freset = 1;
|
||||
+
|
||||
|
||||
Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
|
||||
Failure).
|
||||
|
||||
.. note::
|
||||
|
||||
The current powerpc implementation does not try a power-cycle
|
||||
reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
|
||||
However, it probably should.
|
||||
|
||||
|
||||
STEP 5: Resume Operations
|
||||
-------------------------
|
||||
The platform will call the resume() callback on all affected device
|
||||
drivers if all drivers on the segment have returned
|
||||
PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks.
|
||||
The goal of this callback is to tell the driver to restart activity,
|
||||
that everything is back and running. This callback does not return
|
||||
a result code.
|
||||
|
||||
At this point, if a new error happens, the platform will restart
|
||||
a new error recovery sequence.
|
||||
|
||||
STEP 6: Permanent Failure
|
||||
-------------------------
|
||||
A "permanent failure" has occurred, and the platform cannot recover
|
||||
the device. The platform will call error_detected() with a
|
||||
pci_channel_state_t value of pci_channel_io_perm_failure.
|
||||
|
||||
The device driver should, at this point, assume the worst. It should
|
||||
cancel all pending I/O, refuse all new I/O, returning -EIO to
|
||||
higher layers. The device driver should then clean up all of its
|
||||
memory and remove itself from kernel operations, much as it would
|
||||
during system shutdown.
|
||||
|
||||
The platform will typically notify the system operator of the
|
||||
permanent failure in some way. If the device is hotplug-capable,
|
||||
the operator will probably want to remove and replace the device.
|
||||
Note, however, not all failures are truly "permanent". Some are
|
||||
caused by over-heating, some by a poorly seated card. Many
|
||||
PCI error events are caused by software bugs, e.g. DMA's to
|
||||
wild addresses or bogus split transactions due to programming
|
||||
errors. See the discussion in powerpc/eeh-pci-error-recovery.txt
|
||||
for additional detail on real-life experience of the causes of
|
||||
software errors.
|
||||
|
||||
|
||||
Conclusion; General Remarks
|
||||
---------------------------
|
||||
The way the callbacks are called is platform policy. A platform with
|
||||
no slot reset capability may want to just "ignore" drivers that can't
|
||||
recover (disconnect them) and try to let other cards on the same segment
|
||||
recover. Keep in mind that in most real life cases, though, there will
|
||||
be only one driver per segment.
|
||||
|
||||
Now, a note about interrupts. If you get an interrupt and your
|
||||
device is dead or has been isolated, there is a problem :)
|
||||
The current policy is to turn this into a platform policy.
|
||||
That is, the recovery API only requires that:
|
||||
|
||||
- There is no guarantee that interrupt delivery can proceed from any
|
||||
device on the segment starting from the error detection and until the
|
||||
slot_reset callback is called, at which point interrupts are expected
|
||||
to be fully operational.
|
||||
|
||||
- There is no guarantee that interrupt delivery is stopped, that is,
|
||||
a driver that gets an interrupt after detecting an error, or that detects
|
||||
an error within the interrupt handler such that it prevents proper
|
||||
ack'ing of the interrupt (and thus removal of the source) should just
|
||||
return IRQ_NOTHANDLED. It's up to the platform to deal with that
|
||||
condition, typically by masking the IRQ source during the duration of
|
||||
the error handling. It is expected that the platform "knows" which
|
||||
interrupts are routed to error-management capable slots and can deal
|
||||
with temporarily disabling that IRQ number during error processing (this
|
||||
isn't terribly complex). That means some IRQ latency for other devices
|
||||
sharing the interrupt, but there is simply no other way. High end
|
||||
platforms aren't supposed to share interrupts between many devices
|
||||
anyway :)
|
||||
|
||||
.. note::
|
||||
|
||||
Implementation details for the powerpc platform are discussed in
|
||||
the file Documentation/powerpc/eeh-pci-error-recovery.rst
|
||||
|
||||
As of this writing, there is a growing list of device drivers with
|
||||
patches implementing error recovery. Not all of these patches are in
|
||||
mainline yet. These may be used as "examples":
|
||||
|
||||
- drivers/scsi/ipr
|
||||
- drivers/scsi/sym53c8xx_2
|
||||
- drivers/scsi/qla2xxx
|
||||
- drivers/scsi/lpfc
|
||||
- drivers/next/bnx2.c
|
||||
- drivers/next/e100.c
|
||||
- drivers/net/e1000
|
||||
- drivers/net/e1000e
|
||||
- drivers/net/ixgb
|
||||
- drivers/net/ixgbe
|
||||
- drivers/net/cxgb3
|
||||
- drivers/net/s2io.c
|
||||
|
||||
The End
|
||||
-------
|
172
Documentation/PCI/pci-iov-howto.rst
Normal file
@ -0,0 +1,172 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: <isonum.txt>
|
||||
|
||||
====================================
|
||||
PCI Express I/O Virtualization Howto
|
||||
====================================
|
||||
|
||||
:Copyright: |copy| 2009 Intel Corporation
|
||||
:Authors: - Yu Zhao <yu.zhao@intel.com>
|
||||
- Donald Dutile <ddutile@redhat.com>
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
What is SR-IOV
|
||||
--------------
|
||||
|
||||
Single Root I/O Virtualization (SR-IOV) is a PCI Express Extended
|
||||
capability which makes one physical device appear as multiple virtual
|
||||
devices. The physical device is referred to as Physical Function (PF)
|
||||
while the virtual devices are referred to as Virtual Functions (VF).
|
||||
Allocation of the VF can be dynamically controlled by the PF via
|
||||
registers encapsulated in the capability. By default, this feature is
|
||||
not enabled and the PF behaves as traditional PCIe device. Once it's
|
||||
turned on, each VF's PCI configuration space can be accessed by its own
|
||||
Bus, Device and Function Number (Routing ID). And each VF also has PCI
|
||||
Memory Space, which is used to map its register set. VF device driver
|
||||
operates on the register set so it can be functional and appear as a
|
||||
real existing PCI device.
|
||||
|
||||
User Guide
|
||||
==========
|
||||
|
||||
How can I enable SR-IOV capability
|
||||
----------------------------------
|
||||
|
||||
Multiple methods are available for SR-IOV enablement.
|
||||
In the first method, the device driver (PF driver) will control the
|
||||
enabling and disabling of the capability via API provided by SR-IOV core.
|
||||
If the hardware has SR-IOV capability, loading its PF driver would
|
||||
enable it and all VFs associated with the PF. Some PF drivers require
|
||||
a module parameter to be set to determine the number of VFs to enable.
|
||||
In the second method, a write to the sysfs file sriov_numvfs will
|
||||
enable and disable the VFs associated with a PCIe PF. This method
|
||||
enables per-PF, VF enable/disable values versus the first method,
|
||||
which applies to all PFs of the same device. Additionally, the
|
||||
PCI SRIOV core support ensures that enable/disable operations are
|
||||
valid to reduce duplication in multiple drivers for the same
|
||||
checks, e.g., check numvfs == 0 if enabling VFs, ensure
|
||||
numvfs <= totalvfs.
|
||||
The second method is the recommended method for new/future VF devices.
|
||||
|
||||
How can I use the Virtual Functions
|
||||
-----------------------------------
|
||||
|
||||
The VF is treated as hot-plugged PCI devices in the kernel, so they
|
||||
should be able to work in the same way as real PCI devices. The VF
|
||||
requires device driver that is same as a normal PCI device's.
|
||||
|
||||
Developer Guide
|
||||
===============
|
||||
|
||||
SR-IOV API
|
||||
----------
|
||||
|
||||
To enable SR-IOV capability:
|
||||
|
||||
(a) For the first method, in the driver::
|
||||
|
||||
int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
|
||||
|
||||
'nr_virtfn' is number of VFs to be enabled.
|
||||
|
||||
(b) For the second method, from sysfs::
|
||||
|
||||
echo 'nr_virtfn' > \
|
||||
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
|
||||
|
||||
To disable SR-IOV capability:
|
||||
|
||||
(a) For the first method, in the driver::
|
||||
|
||||
void pci_disable_sriov(struct pci_dev *dev);
|
||||
|
||||
(b) For the second method, from sysfs::
|
||||
|
||||
echo 0 > \
|
||||
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
|
||||
|
||||
To enable auto probing VFs by a compatible driver on the host, run
|
||||
command below before enabling SR-IOV capabilities. This is the
|
||||
default behavior.
|
||||
::
|
||||
|
||||
echo 1 > \
|
||||
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
|
||||
|
||||
To disable auto probing VFs by a compatible driver on the host, run
|
||||
command below before enabling SR-IOV capabilities. Updating this
|
||||
entry will not affect VFs which are already probed.
|
||||
::
|
||||
|
||||
echo 0 > \
|
||||
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
|
||||
|
||||
Usage example
|
||||
-------------
|
||||
|
||||
Following piece of code illustrates the usage of the SR-IOV API.
|
||||
::
|
||||
|
||||
static int dev_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
pci_enable_sriov(dev, NR_VIRTFN);
|
||||
|
||||
...
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dev_remove(struct pci_dev *dev)
|
||||
{
|
||||
pci_disable_sriov(dev);
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
static int dev_suspend(struct pci_dev *dev, pm_message_t state)
|
||||
{
|
||||
...
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dev_resume(struct pci_dev *dev)
|
||||
{
|
||||
...
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dev_shutdown(struct pci_dev *dev)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
static int dev_sriov_configure(struct pci_dev *dev, int numvfs)
|
||||
{
|
||||
if (numvfs > 0) {
|
||||
...
|
||||
pci_enable_sriov(dev, numvfs);
|
||||
...
|
||||
return numvfs;
|
||||
}
|
||||
if (numvfs == 0) {
|
||||
....
|
||||
pci_disable_sriov(dev);
|
||||
...
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static struct pci_driver dev_driver = {
|
||||
.name = "SR-IOV Physical Function driver",
|
||||
.id_table = dev_id_table,
|
||||
.probe = dev_probe,
|
||||
.remove = dev_remove,
|
||||
.suspend = dev_suspend,
|
||||
.resume = dev_resume,
|
||||
.shutdown = dev_shutdown,
|
||||
.sriov_configure = dev_sriov_configure,
|
||||
};
|
578
Documentation/PCI/pci.rst
Normal file
@ -0,0 +1,578 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==============================
|
||||
How To Write Linux PCI Drivers
|
||||
==============================
|
||||
|
||||
:Authors: - Martin Mares <mj@ucw.cz>
|
||||
- Grant Grundler <grundler@parisc-linux.org>
|
||||
|
||||
The world of PCI is vast and full of (mostly unpleasant) surprises.
|
||||
Since each CPU architecture implements different chip-sets and PCI devices
|
||||
have different requirements (erm, "features"), the result is the PCI support
|
||||
in the Linux kernel is not as trivial as one would wish. This short paper
|
||||
tries to introduce all potential driver authors to Linux APIs for
|
||||
PCI device drivers.
|
||||
|
||||
A more complete resource is the third edition of "Linux Device Drivers"
|
||||
by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.
|
||||
LDD3 is available for free (under Creative Commons License) from:
|
||||
https://lwn.net/Kernel/LDD3/.
|
||||
|
||||
However, keep in mind that all documents are subject to "bit rot".
|
||||
Refer to the source code if things are not working as described here.
|
||||
|
||||
Please send questions/comments/patches about Linux PCI API to the
|
||||
"Linux PCI" <linux-pci@atrey.karlin.mff.cuni.cz> mailing list.
|
||||
|
||||
|
||||
Structure of PCI drivers
|
||||
========================
|
||||
PCI drivers "discover" PCI devices in a system via pci_register_driver().
|
||||
Actually, it's the other way around. When the PCI generic code discovers
|
||||
a new device, the driver with a matching "description" will be notified.
|
||||
Details on this below.
|
||||
|
||||
pci_register_driver() leaves most of the probing for devices to
|
||||
the PCI layer and supports online insertion/removal of devices [thus
|
||||
supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver].
|
||||
pci_register_driver() call requires passing in a table of function
|
||||
pointers and thus dictates the high level structure of a driver.
|
||||
|
||||
Once the driver knows about a PCI device and takes ownership, the
|
||||
driver generally needs to perform the following initialization:
|
||||
|
||||
- Enable the device
|
||||
- Request MMIO/IOP resources
|
||||
- Set the DMA mask size (for both coherent and streaming DMA)
|
||||
- Allocate and initialize shared control data (pci_allocate_coherent())
|
||||
- Access device configuration space (if needed)
|
||||
- Register IRQ handler (request_irq())
|
||||
- Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
|
||||
- Enable DMA/processing engines
|
||||
|
||||
When done using the device, and perhaps the module needs to be unloaded,
|
||||
the driver needs to take the follow steps:
|
||||
|
||||
- Disable the device from generating IRQs
|
||||
- Release the IRQ (free_irq())
|
||||
- Stop all DMA activity
|
||||
- Release DMA buffers (both streaming and coherent)
|
||||
- Unregister from other subsystems (e.g. scsi or netdev)
|
||||
- Release MMIO/IOP resources
|
||||
- Disable the device
|
||||
|
||||
Most of these topics are covered in the following sections.
|
||||
For the rest look at LDD3 or <linux/pci.h> .
|
||||
|
||||
If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
|
||||
the PCI functions described below are defined as inline functions either
|
||||
completely empty or just returning an appropriate error codes to avoid
|
||||
lots of ifdefs in the drivers.
|
||||
|
||||
|
||||
pci_register_driver() call
|
||||
==========================
|
||||
|
||||
PCI device drivers call ``pci_register_driver()`` during their
|
||||
initialization with a pointer to a structure describing the driver
|
||||
(``struct pci_driver``):
|
||||
|
||||
.. kernel-doc:: include/linux/pci.h
|
||||
:functions: pci_driver
|
||||
|
||||
The ID table is an array of ``struct pci_device_id`` entries ending with an
|
||||
all-zero entry. Definitions with static const are generally preferred.
|
||||
|
||||
.. kernel-doc:: include/linux/mod_devicetable.h
|
||||
:functions: pci_device_id
|
||||
|
||||
Most drivers only need ``PCI_DEVICE()`` or ``PCI_DEVICE_CLASS()`` to set up
|
||||
a pci_device_id table.
|
||||
|
||||
New PCI IDs may be added to a device driver pci_ids table at runtime
|
||||
as shown below::
|
||||
|
||||
echo "vendor device subvendor subdevice class class_mask driver_data" > \
|
||||
/sys/bus/pci/drivers/{driver}/new_id
|
||||
|
||||
All fields are passed in as hexadecimal values (no leading 0x).
|
||||
The vendor and device fields are mandatory, the others are optional. Users
|
||||
need pass only as many optional fields as necessary:
|
||||
|
||||
- subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
|
||||
- class and classmask fields default to 0
|
||||
- driver_data defaults to 0UL.
|
||||
- override_only field defaults to 0.
|
||||
|
||||
Note that driver_data must match the value used by any of the pci_device_id
|
||||
entries defined in the driver. This makes the driver_data field mandatory
|
||||
if all the pci_device_id entries have a non-zero driver_data value.
|
||||
|
||||
Once added, the driver probe routine will be invoked for any unclaimed
|
||||
PCI devices listed in its (newly updated) pci_ids list.
|
||||
|
||||
When the driver exits, it just calls pci_unregister_driver() and the PCI layer
|
||||
automatically calls the remove hook for all devices handled by the driver.
|
||||
|
||||
|
||||
"Attributes" for driver functions/data
|
||||
--------------------------------------
|
||||
|
||||
Please mark the initialization and cleanup functions where appropriate
|
||||
(the corresponding macros are defined in <linux/init.h>):
|
||||
|
||||
====== =================================================
|
||||
__init Initialization code. Thrown away after the driver
|
||||
initializes.
|
||||
__exit Exit code. Ignored for non-modular drivers.
|
||||
====== =================================================
|
||||
|
||||
Tips on when/where to use the above attributes:
|
||||
- The module_init()/module_exit() functions (and all
|
||||
initialization functions called _only_ from these)
|
||||
should be marked __init/__exit.
|
||||
|
||||
- Do not mark the struct pci_driver.
|
||||
|
||||
- Do NOT mark a function if you are not sure which mark to use.
|
||||
Better to not mark the function than mark the function wrong.
|
||||
|
||||
|
||||
How to find PCI devices manually
|
||||
================================
|
||||
|
||||
PCI drivers should have a really good reason for not using the
|
||||
pci_register_driver() interface to search for PCI devices.
|
||||
The main reason PCI devices are controlled by multiple drivers
|
||||
is because one PCI device implements several different HW services.
|
||||
E.g. combined serial/parallel port/floppy controller.
|
||||
|
||||
A manual search may be performed using the following constructs:
|
||||
|
||||
Searching by vendor and device ID::
|
||||
|
||||
struct pci_dev *dev = NULL;
|
||||
while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev))
|
||||
configure_device(dev);
|
||||
|
||||
Searching by class ID (iterate in a similar way)::
|
||||
|
||||
pci_get_class(CLASS_ID, dev)
|
||||
|
||||
Searching by both vendor/device and subsystem vendor/device ID::
|
||||
|
||||
pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
|
||||
|
||||
You can use the constant PCI_ANY_ID as a wildcard replacement for
|
||||
VENDOR_ID or DEVICE_ID. This allows searching for any device from a
|
||||
specific vendor, for example.
|
||||
|
||||
These functions are hotplug-safe. They increment the reference count on
|
||||
the pci_dev that they return. You must eventually (possibly at module unload)
|
||||
decrement the reference count on these devices by calling pci_dev_put().
|
||||
|
||||
|
||||
Device Initialization Steps
|
||||
===========================
|
||||
|
||||
As noted in the introduction, most PCI drivers need the following steps
|
||||
for device initialization:
|
||||
|
||||
- Enable the device
|
||||
- Request MMIO/IOP resources
|
||||
- Set the DMA mask size (for both coherent and streaming DMA)
|
||||
- Allocate and initialize shared control data (pci_allocate_coherent())
|
||||
- Access device configuration space (if needed)
|
||||
- Register IRQ handler (request_irq())
|
||||
- Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
|
||||
- Enable DMA/processing engines.
|
||||
|
||||
The driver can access PCI config space registers at any time.
|
||||
(Well, almost. When running BIST, config space can go away...but
|
||||
that will just result in a PCI Bus Master Abort and config reads
|
||||
will return garbage).
|
||||
|
||||
|
||||
Enable the PCI device
|
||||
---------------------
|
||||
Before touching any device registers, the driver needs to enable
|
||||
the PCI device by calling pci_enable_device(). This will:
|
||||
|
||||
- wake up the device if it was in suspended state,
|
||||
- allocate I/O and memory regions of the device (if BIOS did not),
|
||||
- allocate an IRQ (if BIOS did not).
|
||||
|
||||
.. note::
|
||||
pci_enable_device() can fail! Check the return value.
|
||||
|
||||
.. warning::
|
||||
OS BUG: we don't check resource allocations before enabling those
|
||||
resources. The sequence would make more sense if we called
|
||||
pci_request_resources() before calling pci_enable_device().
|
||||
Currently, the device drivers can't detect the bug when two
|
||||
devices have been allocated the same range. This is not a common
|
||||
problem and unlikely to get fixed soon.
|
||||
|
||||
This has been discussed before but not changed as of 2.6.19:
|
||||
https://lore.kernel.org/r/20060302180025.GC28895@flint.arm.linux.org.uk/
|
||||
|
||||
|
||||
pci_set_master() will enable DMA by setting the bus master bit
|
||||
in the PCI_COMMAND register. It also fixes the latency timer value if
|
||||
it's set to something bogus by the BIOS. pci_clear_master() will
|
||||
disable DMA by clearing the bus master bit.
|
||||
|
||||
If the PCI device can use the PCI Memory-Write-Invalidate transaction,
|
||||
call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
|
||||
and also ensures that the cache line size register is set correctly.
|
||||
Check the return value of pci_set_mwi() as not all architectures
|
||||
or chip-sets may support Memory-Write-Invalidate. Alternatively,
|
||||
if Mem-Wr-Inval would be nice to have but is not required, call
|
||||
pci_try_set_mwi() to have the system do its best effort at enabling
|
||||
Mem-Wr-Inval.
|
||||
|
||||
|
||||
Request MMIO/IOP resources
|
||||
--------------------------
|
||||
Memory (MMIO), and I/O port addresses should NOT be read directly
|
||||
from the PCI device config space. Use the values in the pci_dev structure
|
||||
as the PCI "bus address" might have been remapped to a "host physical"
|
||||
address by the arch/chip-set specific kernel support.
|
||||
|
||||
See Documentation/driver-api/io-mapping.rst for how to access device registers
|
||||
or device memory.
|
||||
|
||||
The device driver needs to call pci_request_region() to verify
|
||||
no other device is already using the same address resource.
|
||||
Conversely, drivers should call pci_release_region() AFTER
|
||||
calling pci_disable_device().
|
||||
The idea is to prevent two devices colliding on the same address range.
|
||||
|
||||
.. tip::
|
||||
See OS BUG comment above. Currently (2.6.19), The driver can only
|
||||
determine MMIO and IO Port resource availability _after_ calling
|
||||
pci_enable_device().
|
||||
|
||||
Generic flavors of pci_request_region() are request_mem_region()
|
||||
(for MMIO ranges) and request_region() (for IO Port ranges).
|
||||
Use these for address resources that are not described by "normal" PCI
|
||||
BARs.
|
||||
|
||||
Also see pci_request_selected_regions() below.
|
||||
|
||||
|
||||
Set the DMA mask size
|
||||
---------------------
|
||||
.. note::
|
||||
If anything below doesn't make sense, please refer to
|
||||
Documentation/core-api/dma-api.rst. This section is just a reminder that
|
||||
drivers need to indicate DMA capabilities of the device and is not
|
||||
an authoritative source for DMA interfaces.
|
||||
|
||||
While all drivers should explicitly indicate the DMA capability
|
||||
(e.g. 32 or 64 bit) of the PCI bus master, devices with more than
|
||||
32-bit bus master capability for streaming data need the driver
|
||||
to "register" this capability by calling pci_set_dma_mask() with
|
||||
appropriate parameters. In general this allows more efficient DMA
|
||||
on systems where System RAM exists above 4G _physical_ address.
|
||||
|
||||
Drivers for all PCI-X and PCIe compliant devices must call
|
||||
pci_set_dma_mask() as they are 64-bit DMA devices.
|
||||
|
||||
Similarly, drivers must also "register" this capability if the device
|
||||
can directly address "consistent memory" in System RAM above 4G physical
|
||||
address by calling pci_set_consistent_dma_mask().
|
||||
Again, this includes drivers for all PCI-X and PCIe compliant devices.
|
||||
Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
|
||||
64-bit DMA capable for payload ("streaming") data but not control
|
||||
("consistent") data.
|
||||
|
||||
|
||||
Setup shared control data
|
||||
-------------------------
|
||||
Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
|
||||
memory. See Documentation/core-api/dma-api.rst for a full description of
|
||||
the DMA APIs. This section is just a reminder that it needs to be done
|
||||
before enabling DMA on the device.
|
||||
|
||||
|
||||
Initialize device registers
|
||||
---------------------------
|
||||
Some drivers will need specific "capability" fields programmed
|
||||
or other "vendor specific" register initialized or reset.
|
||||
E.g. clearing pending interrupts.
|
||||
|
||||
|
||||
Register IRQ handler
|
||||
--------------------
|
||||
While calling request_irq() is the last step described here,
|
||||
this is often just another intermediate step to initialize a device.
|
||||
This step can often be deferred until the device is opened for use.
|
||||
|
||||
All interrupt handlers for IRQ lines should be registered with IRQF_SHARED
|
||||
and use the devid to map IRQs to devices (remember that all PCI IRQ lines
|
||||
can be shared).
|
||||
|
||||
request_irq() will associate an interrupt handler and device handle
|
||||
with an interrupt number. Historically interrupt numbers represent
|
||||
IRQ lines which run from the PCI device to the Interrupt controller.
|
||||
With MSI and MSI-X (more below) the interrupt number is a CPU "vector".
|
||||
|
||||
request_irq() also enables the interrupt. Make sure the device is
|
||||
quiesced and does not have any interrupts pending before registering
|
||||
the interrupt handler.
|
||||
|
||||
MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts"
|
||||
which deliver interrupts to the CPU via a DMA write to a Local APIC.
|
||||
The fundamental difference between MSI and MSI-X is how multiple
|
||||
"vectors" get allocated. MSI requires contiguous blocks of vectors
|
||||
while MSI-X can allocate several individual ones.
|
||||
|
||||
MSI capability can be enabled by calling pci_alloc_irq_vectors() with the
|
||||
PCI_IRQ_MSI and/or PCI_IRQ_MSIX flags before calling request_irq(). This
|
||||
causes the PCI support to program CPU vector data into the PCI device
|
||||
capability registers. Many architectures, chip-sets, or BIOSes do NOT
|
||||
support MSI or MSI-X and a call to pci_alloc_irq_vectors with just
|
||||
the PCI_IRQ_MSI and PCI_IRQ_MSIX flags will fail, so try to always
|
||||
specify PCI_IRQ_LEGACY as well.
|
||||
|
||||
Drivers that have different interrupt handlers for MSI/MSI-X and
|
||||
legacy INTx should chose the right one based on the msi_enabled
|
||||
and msix_enabled flags in the pci_dev structure after calling
|
||||
pci_alloc_irq_vectors.
|
||||
|
||||
There are (at least) two really good reasons for using MSI:
|
||||
|
||||
1) MSI is an exclusive interrupt vector by definition.
|
||||
This means the interrupt handler doesn't have to verify
|
||||
its device caused the interrupt.
|
||||
|
||||
2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed
|
||||
to be visible to the host CPU(s) when the MSI is delivered. This
|
||||
is important for both data coherency and avoiding stale control data.
|
||||
This guarantee allows the driver to omit MMIO reads to flush
|
||||
the DMA stream.
|
||||
|
||||
See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples
|
||||
of MSI/MSI-X usage.
|
||||
|
||||
|
||||
PCI device shutdown
|
||||
===================
|
||||
|
||||
When a PCI device driver is being unloaded, most of the following
|
||||
steps need to be performed:
|
||||
|
||||
- Disable the device from generating IRQs
|
||||
- Release the IRQ (free_irq())
|
||||
- Stop all DMA activity
|
||||
- Release DMA buffers (both streaming and consistent)
|
||||
- Unregister from other subsystems (e.g. scsi or netdev)
|
||||
- Disable device from responding to MMIO/IO Port addresses
|
||||
- Release MMIO/IO Port resource(s)
|
||||
|
||||
|
||||
Stop IRQs on the device
|
||||
-----------------------
|
||||
How to do this is chip/device specific. If it's not done, it opens
|
||||
the possibility of a "screaming interrupt" if (and only if)
|
||||
the IRQ is shared with another device.
|
||||
|
||||
When the shared IRQ handler is "unhooked", the remaining devices
|
||||
using the same IRQ line will still need the IRQ enabled. Thus if the
|
||||
"unhooked" device asserts IRQ line, the system will respond assuming
|
||||
it was one of the remaining devices asserted the IRQ line. Since none
|
||||
of the other devices will handle the IRQ, the system will "hang" until
|
||||
it decides the IRQ isn't going to get handled and masks the IRQ (100,000
|
||||
iterations later). Once the shared IRQ is masked, the remaining devices
|
||||
will stop functioning properly. Not a nice situation.
|
||||
|
||||
This is another reason to use MSI or MSI-X if it's available.
|
||||
MSI and MSI-X are defined to be exclusive interrupts and thus
|
||||
are not susceptible to the "screaming interrupt" problem.
|
||||
|
||||
|
||||
Release the IRQ
|
||||
---------------
|
||||
Once the device is quiesced (no more IRQs), one can call free_irq().
|
||||
This function will return control once any pending IRQs are handled,
|
||||
"unhook" the drivers IRQ handler from that IRQ, and finally release
|
||||
the IRQ if no one else is using it.
|
||||
|
||||
|
||||
Stop all DMA activity
|
||||
---------------------
|
||||
It's extremely important to stop all DMA operations BEFORE attempting
|
||||
to deallocate DMA control data. Failure to do so can result in memory
|
||||
corruption, hangs, and on some chip-sets a hard crash.
|
||||
|
||||
Stopping DMA after stopping the IRQs can avoid races where the
|
||||
IRQ handler might restart DMA engines.
|
||||
|
||||
While this step sounds obvious and trivial, several "mature" drivers
|
||||
didn't get this step right in the past.
|
||||
|
||||
|
||||
Release DMA buffers
|
||||
-------------------
|
||||
Once DMA is stopped, clean up streaming DMA first.
|
||||
I.e. unmap data buffers and return buffers to "upstream"
|
||||
owners if there is one.
|
||||
|
||||
Then clean up "consistent" buffers which contain the control data.
|
||||
|
||||
See Documentation/core-api/dma-api.rst for details on unmapping interfaces.
|
||||
|
||||
|
||||
Unregister from other subsystems
|
||||
--------------------------------
|
||||
Most low level PCI device drivers support some other subsystem
|
||||
like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your
|
||||
driver isn't losing resources from that other subsystem.
|
||||
If this happens, typically the symptom is an Oops (panic) when
|
||||
the subsystem attempts to call into a driver that has been unloaded.
|
||||
|
||||
|
||||
Disable Device from responding to MMIO/IO Port addresses
|
||||
--------------------------------------------------------
|
||||
io_unmap() MMIO or IO Port resources and then call pci_disable_device().
|
||||
This is the symmetric opposite of pci_enable_device().
|
||||
Do not access device registers after calling pci_disable_device().
|
||||
|
||||
|
||||
Release MMIO/IO Port Resource(s)
|
||||
--------------------------------
|
||||
Call pci_release_region() to mark the MMIO or IO Port range as available.
|
||||
Failure to do so usually results in the inability to reload the driver.
|
||||
|
||||
|
||||
How to access PCI config space
|
||||
==============================
|
||||
|
||||
You can use `pci_(read|write)_config_(byte|word|dword)` to access the config
|
||||
space of a device represented by `struct pci_dev *`. All these functions return
|
||||
0 when successful or an error code (`PCIBIOS_...`) which can be translated to a
|
||||
text string by pcibios_strerror. Most drivers expect that accesses to valid PCI
|
||||
devices don't fail.
|
||||
|
||||
If you don't have a struct pci_dev available, you can call
|
||||
`pci_bus_(read|write)_config_(byte|word|dword)` to access a given device
|
||||
and function on that bus.
|
||||
|
||||
If you access fields in the standard portion of the config header, please
|
||||
use symbolic names of locations and bits declared in <linux/pci.h>.
|
||||
|
||||
If you need to access Extended PCI Capability registers, just call
|
||||
pci_find_capability() for the particular capability and it will find the
|
||||
corresponding register block for you.
|
||||
|
||||
|
||||
Other interesting functions
|
||||
===========================
|
||||
|
||||
============================= ================================================
|
||||
pci_get_domain_bus_and_slot() Find pci_dev corresponding to given domain,
|
||||
bus and slot and number. If the device is
|
||||
found, its reference count is increased.
|
||||
pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3)
|
||||
pci_find_capability() Find specified capability in device's capability
|
||||
list.
|
||||
pci_resource_start() Returns bus start address for a given PCI region
|
||||
pci_resource_end() Returns bus end address for a given PCI region
|
||||
pci_resource_len() Returns the byte length of a PCI region
|
||||
pci_set_drvdata() Set private driver data pointer for a pci_dev
|
||||
pci_get_drvdata() Return private driver data pointer for a pci_dev
|
||||
pci_set_mwi() Enable Memory-Write-Invalidate transactions.
|
||||
pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
|
||||
============================= ================================================
|
||||
|
||||
|
||||
Miscellaneous hints
|
||||
===================
|
||||
|
||||
When displaying PCI device names to the user (for example when a driver wants
|
||||
to tell the user what card has it found), please use pci_name(pci_dev).
|
||||
|
||||
Always refer to the PCI devices by a pointer to the pci_dev structure.
|
||||
All PCI layer functions use this identification and it's the only
|
||||
reasonable one. Don't use bus/slot/function numbers except for very
|
||||
special purposes -- on systems with multiple primary buses their semantics
|
||||
can be pretty complex.
|
||||
|
||||
Don't try to turn on Fast Back to Back writes in your driver. All devices
|
||||
on the bus need to be capable of doing it, so this is something which needs
|
||||
to be handled by platform and generic code, not individual drivers.
|
||||
|
||||
|
||||
Vendor and device identifications
|
||||
=================================
|
||||
|
||||
Do not add new device or vendor IDs to include/linux/pci_ids.h unless they
|
||||
are shared across multiple drivers. You can add private definitions in
|
||||
your driver if they're helpful, or just use plain hex constants.
|
||||
|
||||
The device IDs are arbitrary hex numbers (vendor controlled) and normally used
|
||||
only in a single location, the pci_device_id table.
|
||||
|
||||
Please DO submit new vendor/device IDs to https://pci-ids.ucw.cz/.
|
||||
There's a mirror of the pci.ids file at https://github.com/pciutils/pciids.
|
||||
|
||||
|
||||
Obsolete functions
|
||||
==================
|
||||
|
||||
There are several functions which you might come across when trying to
|
||||
port an old driver to the new PCI interface. They are no longer present
|
||||
in the kernel as they aren't compatible with hotplug or PCI domains or
|
||||
having sane locking.
|
||||
|
||||
================= ===========================================
|
||||
pci_find_device() Superseded by pci_get_device()
|
||||
pci_find_subsys() Superseded by pci_get_subsys()
|
||||
pci_find_slot() Superseded by pci_get_domain_bus_and_slot()
|
||||
pci_get_slot() Superseded by pci_get_domain_bus_and_slot()
|
||||
================= ===========================================
|
||||
|
||||
The alternative is the traditional PCI device driver that walks PCI
|
||||
device lists. This is still possible but discouraged.
|
||||
|
||||
|
||||
MMIO Space and "Write Posting"
|
||||
==============================
|
||||
|
||||
Converting a driver from using I/O Port space to using MMIO space
|
||||
often requires some additional changes. Specifically, "write posting"
|
||||
needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2)
|
||||
already do this. I/O Port space guarantees write transactions reach the PCI
|
||||
device before the CPU can continue. Writes to MMIO space allow the CPU
|
||||
to continue before the transaction reaches the PCI device. HW weenies
|
||||
call this "Write Posting" because the write completion is "posted" to
|
||||
the CPU before the transaction has reached its destination.
|
||||
|
||||
Thus, timing sensitive code should add readl() where the CPU is
|
||||
expected to wait before doing other work. The classic "bit banging"
|
||||
sequence works fine for I/O Port space::
|
||||
|
||||
for (i = 8; --i; val >>= 1) {
|
||||
outb(val & 1, ioport_reg); /* write bit */
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
The same sequence for MMIO space should be::
|
||||
|
||||
for (i = 8; --i; val >>= 1) {
|
||||
writeb(val & 1, mmio_reg); /* write bit */
|
||||
readb(safe_mmio_reg); /* flush posted write */
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
It is important that "safe_mmio_reg" not have any side effects that
|
||||
interferes with the correct operation of the device.
|
||||
|
||||
Another case to watch out for is when resetting a PCI device. Use PCI
|
||||
Configuration space reads to flush the writel(). This will gracefully
|
||||
handle the PCI master abort on all platforms if the PCI device is
|
||||
expected to not respond to a readl(). Most x86 platforms will allow
|
||||
MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage
|
||||
(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").
|
300
Documentation/PCI/pcieaer-howto.rst
Normal file
@ -0,0 +1,300 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: <isonum.txt>
|
||||
|
||||
===========================================================
|
||||
The PCI Express Advanced Error Reporting Driver Guide HOWTO
|
||||
===========================================================
|
||||
|
||||
:Authors: - T. Long Nguyen <tom.l.nguyen@intel.com>
|
||||
- Yanmin Zhang <yanmin.zhang@intel.com>
|
||||
|
||||
:Copyright: |copy| 2006 Intel Corporation
|
||||
|
||||
Overview
|
||||
===========
|
||||
|
||||
About this guide
|
||||
----------------
|
||||
|
||||
This guide describes the basics of the PCI Express Advanced Error
|
||||
Reporting (AER) driver and provides information on how to use it, as
|
||||
well as how to enable the drivers of endpoint devices to conform with
|
||||
PCI Express AER driver.
|
||||
|
||||
|
||||
What is the PCI Express AER Driver?
|
||||
-----------------------------------
|
||||
|
||||
PCI Express error signaling can occur on the PCI Express link itself
|
||||
or on behalf of transactions initiated on the link. PCI Express
|
||||
defines two error reporting paradigms: the baseline capability and
|
||||
the Advanced Error Reporting capability. The baseline capability is
|
||||
required of all PCI Express components providing a minimum defined
|
||||
set of error reporting requirements. Advanced Error Reporting
|
||||
capability is implemented with a PCI Express advanced error reporting
|
||||
extended capability structure providing more robust error reporting.
|
||||
|
||||
The PCI Express AER driver provides the infrastructure to support PCI
|
||||
Express Advanced Error Reporting capability. The PCI Express AER
|
||||
driver provides three basic functions:
|
||||
|
||||
- Gathers the comprehensive error information if errors occurred.
|
||||
- Reports error to the users.
|
||||
- Performs error recovery actions.
|
||||
|
||||
AER driver only attaches root ports which support PCI-Express AER
|
||||
capability.
|
||||
|
||||
|
||||
User Guide
|
||||
==========
|
||||
|
||||
Include the PCI Express AER Root Driver into the Linux Kernel
|
||||
-------------------------------------------------------------
|
||||
|
||||
The PCI Express AER Root driver is a Root Port service driver attached
|
||||
to the PCI Express Port Bus driver. If a user wants to use it, the driver
|
||||
has to be compiled. Option CONFIG_PCIEAER supports this capability. It
|
||||
depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
|
||||
CONFIG_PCIEAER = y.
|
||||
|
||||
Load PCI Express AER Root Driver
|
||||
--------------------------------
|
||||
|
||||
Some systems have AER support in firmware. Enabling Linux AER support at
|
||||
the same time the firmware handles AER may result in unpredictable
|
||||
behavior. Therefore, Linux does not handle AER events unless the firmware
|
||||
grants AER control to the OS via the ACPI _OSC method. See the PCI FW 3.0
|
||||
Specification for details regarding _OSC usage.
|
||||
|
||||
AER error output
|
||||
----------------
|
||||
|
||||
When a PCIe AER error is captured, an error message will be output to
|
||||
console. If it's a correctable error, it is output as a warning.
|
||||
Otherwise, it is printed as an error. So users could choose different
|
||||
log level to filter out correctable error messages.
|
||||
|
||||
Below shows an example::
|
||||
|
||||
0000:50:00.0: PCIe Bus Error: severity=Uncorrected (Fatal), type=Transaction Layer, id=0500(Requester ID)
|
||||
0000:50:00.0: device [8086:0329] error status/mask=00100000/00000000
|
||||
0000:50:00.0: [20] Unsupported Request (First)
|
||||
0000:50:00.0: TLP Header: 04000001 00200a03 05010000 00050100
|
||||
|
||||
In the example, 'Requester ID' means the ID of the device who sends
|
||||
the error message to root port. Pls. refer to pci express specs for
|
||||
other fields.
|
||||
|
||||
AER Statistics / Counters
|
||||
-------------------------
|
||||
|
||||
When PCIe AER errors are captured, the counters / statistics are also exposed
|
||||
in the form of sysfs attributes which are documented at
|
||||
Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats
|
||||
|
||||
Developer Guide
|
||||
===============
|
||||
|
||||
To enable AER aware support requires a software driver to configure
|
||||
the AER capability structure within its device and to provide callbacks.
|
||||
|
||||
To support AER better, developers need understand how AER does work
|
||||
firstly.
|
||||
|
||||
PCI Express errors are classified into two types: correctable errors
|
||||
and uncorrectable errors. This classification is based on the impacts
|
||||
of those errors, which may result in degraded performance or function
|
||||
failure.
|
||||
|
||||
Correctable errors pose no impacts on the functionality of the
|
||||
interface. The PCI Express protocol can recover without any software
|
||||
intervention or any loss of data. These errors are detected and
|
||||
corrected by hardware. Unlike correctable errors, uncorrectable
|
||||
errors impact functionality of the interface. Uncorrectable errors
|
||||
can cause a particular transaction or a particular PCI Express link
|
||||
to be unreliable. Depending on those error conditions, uncorrectable
|
||||
errors are further classified into non-fatal errors and fatal errors.
|
||||
Non-fatal errors cause the particular transaction to be unreliable,
|
||||
but the PCI Express link itself is fully functional. Fatal errors, on
|
||||
the other hand, cause the link to be unreliable.
|
||||
|
||||
When AER is enabled, a PCI Express device will automatically send an
|
||||
error message to the PCIe root port above it when the device captures
|
||||
an error. The Root Port, upon receiving an error reporting message,
|
||||
internally processes and logs the error message in its PCI Express
|
||||
capability structure. Error information being logged includes storing
|
||||
the error reporting agent's requestor ID into the Error Source
|
||||
Identification Registers and setting the error bits of the Root Error
|
||||
Status Register accordingly. If AER error reporting is enabled in Root
|
||||
Error Command Register, the Root Port generates an interrupt if an
|
||||
error is detected.
|
||||
|
||||
Note that the errors as described above are related to the PCI Express
|
||||
hierarchy and links. These errors do not include any device specific
|
||||
errors because device specific errors will still get sent directly to
|
||||
the device driver.
|
||||
|
||||
Configure the AER capability structure
|
||||
--------------------------------------
|
||||
|
||||
AER aware drivers of PCI Express component need change the device
|
||||
control registers to enable AER. They also could change AER registers,
|
||||
including mask and severity registers. Helper function
|
||||
pci_enable_pcie_error_reporting could be used to enable AER. See
|
||||
section 3.3.
|
||||
|
||||
Provide callbacks
|
||||
-----------------
|
||||
|
||||
callback reset_link to reset pci express link
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This callback is used to reset the pci express physical link when a
|
||||
fatal error happens. The root port aer service driver provides a
|
||||
default reset_link function, but different upstream ports might
|
||||
have different specifications to reset pci express link, so all
|
||||
upstream ports should provide their own reset_link functions.
|
||||
|
||||
Section 3.2.2.2 provides more detailed info on when to call
|
||||
reset_link.
|
||||
|
||||
PCI error-recovery callbacks
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The PCI Express AER Root driver uses error callbacks to coordinate
|
||||
with downstream device drivers associated with a hierarchy in question
|
||||
when performing error recovery actions.
|
||||
|
||||
Data struct pci_driver has a pointer, err_handler, to point to
|
||||
pci_error_handlers who consists of a couple of callback function
|
||||
pointers. AER driver follows the rules defined in
|
||||
pci-error-recovery.txt except pci express specific parts (e.g.
|
||||
reset_link). Pls. refer to pci-error-recovery.txt for detailed
|
||||
definitions of the callbacks.
|
||||
|
||||
Below sections specify when to call the error callback functions.
|
||||
|
||||
Correctable errors
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Correctable errors pose no impacts on the functionality of
|
||||
the interface. The PCI Express protocol can recover without any
|
||||
software intervention or any loss of data. These errors do not
|
||||
require any recovery actions. The AER driver clears the device's
|
||||
correctable error status register accordingly and logs these errors.
|
||||
|
||||
Non-correctable (non-fatal and fatal) errors
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If an error message indicates a non-fatal error, performing link reset
|
||||
at upstream is not required. The AER driver calls error_detected(dev,
|
||||
pci_channel_io_normal) to all drivers associated within a hierarchy in
|
||||
question. for example::
|
||||
|
||||
EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort
|
||||
|
||||
If Upstream port A captures an AER error, the hierarchy consists of
|
||||
Downstream port B and EndPoint.
|
||||
|
||||
A driver may return PCI_ERS_RESULT_CAN_RECOVER,
|
||||
PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
|
||||
whether it can recover or the AER driver calls mmio_enabled as next.
|
||||
|
||||
If an error message indicates a fatal error, kernel will broadcast
|
||||
error_detected(dev, pci_channel_io_frozen) to all drivers within
|
||||
a hierarchy in question. Then, performing link reset at upstream is
|
||||
necessary. As different kinds of devices might use different approaches
|
||||
to reset link, AER port service driver is required to provide the
|
||||
function to reset link via callback parameter of pcie_do_recovery()
|
||||
function. If reset_link is not NULL, recovery function will use it
|
||||
to reset the link. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER
|
||||
and reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
|
||||
to mmio_enabled.
|
||||
|
||||
helper functions
|
||||
----------------
|
||||
::
|
||||
|
||||
int pci_enable_pcie_error_reporting(struct pci_dev *dev);
|
||||
|
||||
pci_enable_pcie_error_reporting enables the device to send error
|
||||
messages to root port when an error is detected. Note that devices
|
||||
don't enable the error reporting by default, so device drivers need
|
||||
call this function to enable it.
|
||||
|
||||
::
|
||||
|
||||
int pci_disable_pcie_error_reporting(struct pci_dev *dev);
|
||||
|
||||
pci_disable_pcie_error_reporting disables the device to send error
|
||||
messages to root port when an error is detected.
|
||||
|
||||
::
|
||||
|
||||
int pci_aer_clear_nonfatal_status(struct pci_dev *dev);`
|
||||
|
||||
pci_aer_clear_nonfatal_status clears non-fatal errors in the uncorrectable
|
||||
error status register.
|
||||
|
||||
Frequent Asked Questions
|
||||
------------------------
|
||||
|
||||
Q:
|
||||
What happens if a PCI Express device driver does not provide an
|
||||
error recovery handler (pci_driver->err_handler is equal to NULL)?
|
||||
|
||||
A:
|
||||
The devices attached with the driver won't be recovered. If the
|
||||
error is fatal, kernel will print out warning messages. Please refer
|
||||
to section 3 for more information.
|
||||
|
||||
Q:
|
||||
What happens if an upstream port service driver does not provide
|
||||
callback reset_link?
|
||||
|
||||
A:
|
||||
Fatal error recovery will fail if the errors are reported by the
|
||||
upstream ports who are attached by the service driver.
|
||||
|
||||
Q:
|
||||
How does this infrastructure deal with driver that is not PCI
|
||||
Express aware?
|
||||
|
||||
A:
|
||||
This infrastructure calls the error callback functions of the
|
||||
driver when an error happens. But if the driver is not aware of
|
||||
PCI Express, the device might not report its own errors to root
|
||||
port.
|
||||
|
||||
Q:
|
||||
What modifications will that driver need to make it compatible
|
||||
with the PCI Express AER Root driver?
|
||||
|
||||
A:
|
||||
It could call the helper functions to enable AER in devices and
|
||||
cleanup uncorrectable status register. Pls. refer to section 3.3.
|
||||
|
||||
|
||||
Software error injection
|
||||
========================
|
||||
|
||||
Debugging PCIe AER error recovery code is quite difficult because it
|
||||
is hard to trigger real hardware errors. Software based error
|
||||
injection can be used to fake various kinds of PCIe errors.
|
||||
|
||||
First you should enable PCIe AER software error injection in kernel
|
||||
configuration, that is, following item should be in your .config.
|
||||
|
||||
CONFIG_PCIEAER_INJECT=y or CONFIG_PCIEAER_INJECT=m
|
||||
|
||||
After reboot with new kernel or insert the module, a device file named
|
||||
/dev/aer_inject should be created.
|
||||
|
||||
Then, you need a user space tool named aer-inject, which can be gotten
|
||||
from:
|
||||
|
||||
https://git.kernel.org/cgit/linux/kernel/git/gong.chen/aer-inject.git/
|
||||
|
||||
More information about aer-inject can be found in the document comes
|
||||
with its source code.
|
220
Documentation/PCI/pciebus-howto.rst
Normal file
@ -0,0 +1,220 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: <isonum.txt>
|
||||
|
||||
===========================================
|
||||
The PCI Express Port Bus Driver Guide HOWTO
|
||||
===========================================
|
||||
|
||||
:Author: Tom L Nguyen tom.l.nguyen@intel.com 11/03/2004
|
||||
:Copyright: |copy| 2004 Intel Corporation
|
||||
|
||||
About this guide
|
||||
================
|
||||
|
||||
This guide describes the basics of the PCI Express Port Bus driver
|
||||
and provides information on how to enable the service drivers to
|
||||
register/unregister with the PCI Express Port Bus Driver.
|
||||
|
||||
|
||||
What is the PCI Express Port Bus Driver
|
||||
=======================================
|
||||
|
||||
A PCI Express Port is a logical PCI-PCI Bridge structure. There
|
||||
are two types of PCI Express Port: the Root Port and the Switch
|
||||
Port. The Root Port originates a PCI Express link from a PCI Express
|
||||
Root Complex and the Switch Port connects PCI Express links to
|
||||
internal logical PCI buses. The Switch Port, which has its secondary
|
||||
bus representing the switch's internal routing logic, is called the
|
||||
switch's Upstream Port. The switch's Downstream Port is bridging from
|
||||
switch's internal routing bus to a bus representing the downstream
|
||||
PCI Express link from the PCI Express Switch.
|
||||
|
||||
A PCI Express Port can provide up to four distinct functions,
|
||||
referred to in this document as services, depending on its port type.
|
||||
PCI Express Port's services include native hotplug support (HP),
|
||||
power management event support (PME), advanced error reporting
|
||||
support (AER), and virtual channel support (VC). These services may
|
||||
be handled by a single complex driver or be individually distributed
|
||||
and handled by corresponding service drivers.
|
||||
|
||||
Why use the PCI Express Port Bus Driver?
|
||||
========================================
|
||||
|
||||
In existing Linux kernels, the Linux Device Driver Model allows a
|
||||
physical device to be handled by only a single driver. The PCI
|
||||
Express Port is a PCI-PCI Bridge device with multiple distinct
|
||||
services. To maintain a clean and simple solution each service
|
||||
may have its own software service driver. In this case several
|
||||
service drivers will compete for a single PCI-PCI Bridge device.
|
||||
For example, if the PCI Express Root Port native hotplug service
|
||||
driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
|
||||
kernel therefore does not load other service drivers for that Root
|
||||
Port. In other words, it is impossible to have multiple service
|
||||
drivers load and run on a PCI-PCI Bridge device simultaneously
|
||||
using the current driver model.
|
||||
|
||||
To enable multiple service drivers running simultaneously requires
|
||||
having a PCI Express Port Bus driver, which manages all populated
|
||||
PCI Express Ports and distributes all provided service requests
|
||||
to the corresponding service drivers as required. Some key
|
||||
advantages of using the PCI Express Port Bus driver are listed below:
|
||||
|
||||
- Allow multiple service drivers to run simultaneously on
|
||||
a PCI-PCI Bridge Port device.
|
||||
|
||||
- Allow service drivers implemented in an independent
|
||||
staged approach.
|
||||
|
||||
- Allow one service driver to run on multiple PCI-PCI Bridge
|
||||
Port devices.
|
||||
|
||||
- Manage and distribute resources of a PCI-PCI Bridge Port
|
||||
device to requested service drivers.
|
||||
|
||||
Configuring the PCI Express Port Bus Driver vs. Service Drivers
|
||||
===============================================================
|
||||
|
||||
Including the PCI Express Port Bus Driver Support into the Kernel
|
||||
-----------------------------------------------------------------
|
||||
|
||||
Including the PCI Express Port Bus driver depends on whether the PCI
|
||||
Express support is included in the kernel config. The kernel will
|
||||
automatically include the PCI Express Port Bus driver as a kernel
|
||||
driver when the PCI Express support is enabled in the kernel.
|
||||
|
||||
Enabling Service Driver Support
|
||||
-------------------------------
|
||||
|
||||
PCI device drivers are implemented based on Linux Device Driver Model.
|
||||
All service drivers are PCI device drivers. As discussed above, it is
|
||||
impossible to load any service driver once the kernel has loaded the
|
||||
PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
|
||||
Model requires some minimal changes on existing service drivers that
|
||||
imposes no impact on the functionality of existing service drivers.
|
||||
|
||||
A service driver is required to use the two APIs shown below to
|
||||
register its service with the PCI Express Port Bus driver (see
|
||||
section 5.2.1 & 5.2.2). It is important that a service driver
|
||||
initializes the pcie_port_service_driver data structure, included in
|
||||
header file /include/linux/pcieport_if.h, before calling these APIs.
|
||||
Failure to do so will result an identity mismatch, which prevents
|
||||
the PCI Express Port Bus driver from loading a service driver.
|
||||
|
||||
pcie_port_service_register
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
::
|
||||
|
||||
int pcie_port_service_register(struct pcie_port_service_driver *new)
|
||||
|
||||
This API replaces the Linux Driver Model's pci_register_driver API. A
|
||||
service driver should always calls pcie_port_service_register at
|
||||
module init. Note that after service driver being loaded, calls
|
||||
such as pci_enable_device(dev) and pci_set_master(dev) are no longer
|
||||
necessary since these calls are executed by the PCI Port Bus driver.
|
||||
|
||||
pcie_port_service_unregister
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
::
|
||||
|
||||
void pcie_port_service_unregister(struct pcie_port_service_driver *new)
|
||||
|
||||
pcie_port_service_unregister replaces the Linux Driver Model's
|
||||
pci_unregister_driver. It's always called by service driver when a
|
||||
module exits.
|
||||
|
||||
Sample Code
|
||||
~~~~~~~~~~~
|
||||
|
||||
Below is sample service driver code to initialize the port service
|
||||
driver data structure.
|
||||
::
|
||||
|
||||
static struct pcie_port_service_id service_id[] = { {
|
||||
.vendor = PCI_ANY_ID,
|
||||
.device = PCI_ANY_ID,
|
||||
.port_type = PCIE_RC_PORT,
|
||||
.service_type = PCIE_PORT_SERVICE_AER,
|
||||
}, { /* end: all zeroes */ }
|
||||
};
|
||||
|
||||
static struct pcie_port_service_driver root_aerdrv = {
|
||||
.name = (char *)device_name,
|
||||
.id_table = &service_id[0],
|
||||
|
||||
.probe = aerdrv_load,
|
||||
.remove = aerdrv_unload,
|
||||
|
||||
.suspend = aerdrv_suspend,
|
||||
.resume = aerdrv_resume,
|
||||
};
|
||||
|
||||
Below is a sample code for registering/unregistering a service
|
||||
driver.
|
||||
::
|
||||
|
||||
static int __init aerdrv_service_init(void)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
retval = pcie_port_service_register(&root_aerdrv);
|
||||
if (!retval) {
|
||||
/*
|
||||
* FIX ME
|
||||
*/
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __exit aerdrv_service_exit(void)
|
||||
{
|
||||
pcie_port_service_unregister(&root_aerdrv);
|
||||
}
|
||||
|
||||
module_init(aerdrv_service_init);
|
||||
module_exit(aerdrv_service_exit);
|
||||
|
||||
Possible Resource Conflicts
|
||||
===========================
|
||||
|
||||
Since all service drivers of a PCI-PCI Bridge Port device are
|
||||
allowed to run simultaneously, below lists a few of possible resource
|
||||
conflicts with proposed solutions.
|
||||
|
||||
MSI and MSI-X Vector Resource
|
||||
-----------------------------
|
||||
|
||||
Once MSI or MSI-X interrupts are enabled on a device, it stays in this
|
||||
mode until they are disabled again. Since service drivers of the same
|
||||
PCI-PCI Bridge port share the same physical device, if an individual
|
||||
service driver enables or disables MSI/MSI-X mode it may result
|
||||
unpredictable behavior.
|
||||
|
||||
To avoid this situation all service drivers are not permitted to
|
||||
switch interrupt mode on its device. The PCI Express Port Bus driver
|
||||
is responsible for determining the interrupt mode and this should be
|
||||
transparent to service drivers. Service drivers need to know only
|
||||
the vector IRQ assigned to the field irq of struct pcie_device, which
|
||||
is passed in when the PCI Express Port Bus driver probes each service
|
||||
driver. Service drivers should use (struct pcie_device*)dev->irq to
|
||||
call request_irq/free_irq. In addition, the interrupt mode is stored
|
||||
in the field interrupt_mode of struct pcie_device.
|
||||
|
||||
PCI Memory/IO Mapped Regions
|
||||
----------------------------
|
||||
|
||||
Service drivers for PCI Express Power Management (PME), Advanced
|
||||
Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
|
||||
PCI configuration space on the PCI Express port. In all cases the
|
||||
registers accessed are independent of each other. This patch assumes
|
||||
that all service drivers will be well behaved and not overwrite
|
||||
other service driver's configuration settings.
|
||||
|
||||
PCI Config Registers
|
||||
--------------------
|
||||
|
||||
Each service driver runs its PCI config operations on its own
|
||||
capability structure except the PCI Express capability structure, in
|
||||
which Root Control register and Device Control register are shared
|
||||
between PME and AER. This patch assumes that all service drivers
|
||||
will be well behaved and not overwrite other service driver's
|
||||
configuration settings.
|
138
Documentation/PCI/sysfs-pci.rst
Normal file
@ -0,0 +1,138 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
============================================
|
||||
Accessing PCI device resources through sysfs
|
||||
============================================
|
||||
|
||||
sysfs, usually mounted at /sys, provides access to PCI resources on platforms
|
||||
that support it. For example, a given bus might look like this::
|
||||
|
||||
/sys/devices/pci0000:17
|
||||
|-- 0000:17:00.0
|
||||
| |-- class
|
||||
| |-- config
|
||||
| |-- device
|
||||
| |-- enable
|
||||
| |-- irq
|
||||
| |-- local_cpus
|
||||
| |-- remove
|
||||
| |-- resource
|
||||
| |-- resource0
|
||||
| |-- resource1
|
||||
| |-- resource2
|
||||
| |-- revision
|
||||
| |-- rom
|
||||
| |-- subsystem_device
|
||||
| |-- subsystem_vendor
|
||||
| `-- vendor
|
||||
`-- ...
|
||||
|
||||
The topmost element describes the PCI domain and bus number. In this case,
|
||||
the domain number is 0000 and the bus number is 17 (both values are in hex).
|
||||
This bus contains a single function device in slot 0. The domain and bus
|
||||
numbers are reproduced for convenience. Under the device directory are several
|
||||
files, each with their own function.
|
||||
|
||||
=================== =====================================================
|
||||
file function
|
||||
=================== =====================================================
|
||||
class PCI class (ascii, ro)
|
||||
config PCI config space (binary, rw)
|
||||
device PCI device (ascii, ro)
|
||||
enable Whether the device is enabled (ascii, rw)
|
||||
irq IRQ number (ascii, ro)
|
||||
local_cpus nearby CPU mask (cpumask, ro)
|
||||
remove remove device from kernel's list (ascii, wo)
|
||||
resource PCI resource host addresses (ascii, ro)
|
||||
resource0..N PCI resource N, if present (binary, mmap, rw\ [1]_)
|
||||
resource0_wc..N_wc PCI WC map resource N, if prefetchable (binary, mmap)
|
||||
revision PCI revision (ascii, ro)
|
||||
rom PCI ROM resource, if present (binary, ro)
|
||||
subsystem_device PCI subsystem device (ascii, ro)
|
||||
subsystem_vendor PCI subsystem vendor (ascii, ro)
|
||||
vendor PCI vendor (ascii, ro)
|
||||
=================== =====================================================
|
||||
|
||||
::
|
||||
|
||||
ro - read only file
|
||||
rw - file is readable and writable
|
||||
wo - write only file
|
||||
mmap - file is mmapable
|
||||
ascii - file contains ascii text
|
||||
binary - file contains binary data
|
||||
cpumask - file contains a cpumask type
|
||||
|
||||
.. [1] rw for IORESOURCE_IO (I/O port) regions only
|
||||
|
||||
The read only files are informational, writes to them will be ignored, with
|
||||
the exception of the 'rom' file. Writable files can be used to perform
|
||||
actions on the device (e.g. changing config space, detaching a device).
|
||||
mmapable files are available via an mmap of the file at offset 0 and can be
|
||||
used to do actual device programming from userspace. Note that some platforms
|
||||
don't support mmapping of certain resources, so be sure to check the return
|
||||
value from any attempted mmap. The most notable of these are I/O port
|
||||
resources, which also provide read/write access.
|
||||
|
||||
The 'enable' file provides a counter that indicates how many times the device
|
||||
has been enabled. If the 'enable' file currently returns '4', and a '1' is
|
||||
echoed into it, it will then return '5'. Echoing a '0' into it will decrease
|
||||
the count. Even when it returns to 0, though, some of the initialisation
|
||||
may not be reversed.
|
||||
|
||||
The 'rom' file is special in that it provides read-only access to the device's
|
||||
ROM file, if available. It's disabled by default, however, so applications
|
||||
should write the string "1" to the file to enable it before attempting a read
|
||||
call, and disable it following the access by writing "0" to the file. Note
|
||||
that the device must be enabled for a rom read to return data successfully.
|
||||
In the event a driver is not bound to the device, it can be enabled using the
|
||||
'enable' file, documented above.
|
||||
|
||||
The 'remove' file is used to remove the PCI device, by writing a non-zero
|
||||
integer to the file. This does not involve any kind of hot-plug functionality,
|
||||
e.g. powering off the device. The device is removed from the kernel's list of
|
||||
PCI devices, the sysfs directory for it is removed, and the device will be
|
||||
removed from any drivers attached to it. Removal of PCI root buses is
|
||||
disallowed.
|
||||
|
||||
Accessing legacy resources through sysfs
|
||||
----------------------------------------
|
||||
|
||||
Legacy I/O port and ISA memory resources are also provided in sysfs if the
|
||||
underlying platform supports them. They're located in the PCI class hierarchy,
|
||||
e.g.::
|
||||
|
||||
/sys/class/pci_bus/0000:17/
|
||||
|-- bridge -> ../../../devices/pci0000:17
|
||||
|-- cpuaffinity
|
||||
|-- legacy_io
|
||||
`-- legacy_mem
|
||||
|
||||
The legacy_io file is a read/write file that can be used by applications to
|
||||
do legacy port I/O. The application should open the file, seek to the desired
|
||||
port (e.g. 0x3e8) and do a read or a write of 1, 2 or 4 bytes. The legacy_mem
|
||||
file should be mmapped with an offset corresponding to the memory offset
|
||||
desired, e.g. 0xa0000 for the VGA frame buffer. The application can then
|
||||
simply dereference the returned pointer (after checking for errors of course)
|
||||
to access legacy memory space.
|
||||
|
||||
Supporting PCI access on new platforms
|
||||
--------------------------------------
|
||||
|
||||
In order to support PCI resource mapping as described above, Linux platform
|
||||
code should ideally define ARCH_GENERIC_PCI_MMAP_RESOURCE and use the generic
|
||||
implementation of that functionality. To support the historical interface of
|
||||
mmap() through files in /proc/bus/pci, platforms may also set HAVE_PCI_MMAP.
|
||||
|
||||
Alternatively, platforms which set HAVE_PCI_MMAP may provide their own
|
||||
implementation of pci_mmap_page_range() instead of defining
|
||||
ARCH_GENERIC_PCI_MMAP_RESOURCE.
|
||||
|
||||
Platforms which support write-combining maps of PCI resources must define
|
||||
arch_can_pci_mmap_wc() which shall evaluate to non-zero at runtime when
|
||||
write-combining is permitted. Platforms which support maps of I/O resources
|
||||
define arch_can_pci_mmap_io() similarly.
|
||||
|
||||
Legacy resources are protected by the HAVE_PCI_LEGACY define. Platforms
|
||||
wishing to support legacy functionality should define it and provide
|
||||
pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
|
474
Documentation/RCU/Design/Data-Structures/BigTreeClassicRCU.svg
Normal file
@ -0,0 +1,474 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:28:20 2015 -->
|
||||
|
||||
<!-- Magnification: 3.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="9.1in"
|
||||
height="8.9in"
|
||||
viewBox="-66 -66 10932 10707"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="BigTreeClassicRCU.fig">
|
||||
<metadata
|
||||
id="metadata106">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs104">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3864"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="973"
|
||||
inkscape:window-height="1137"
|
||||
id="namedview102"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.9743589"
|
||||
inkscape:cx="409.50003"
|
||||
inkscape:cy="400.49997"
|
||||
inkscape:window-x="915"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4" />
|
||||
<g
|
||||
style="stroke-width:.025in; fill:none"
|
||||
id="g4">
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="10800"
|
||||
height="5625"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
|
||||
id="rect6" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="1125"
|
||||
y="3600"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect8" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="3825"
|
||||
y="900"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect10" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="6525"
|
||||
y="3600"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect12" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="3375,6525 3375,5046 "
|
||||
style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline14" />
|
||||
<!-- Arrowhead on XXXpoint 3375 6525 - 3375 4860-->
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="7425"
|
||||
cy="6075"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle18" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="7875"
|
||||
cy="6075"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle20" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="8325"
|
||||
cy="6075"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle22" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="2025"
|
||||
cy="6075"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle24" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="2475"
|
||||
cy="6075"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle26" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="2925"
|
||||
cy="6075"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle28" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="4725"
|
||||
cy="4275"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle30" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="5175"
|
||||
cy="4275"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle32" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="5625"
|
||||
cy="4275"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle34" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="2025"
|
||||
y="6525"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect36" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="2475,3600 3975,2310 "
|
||||
style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline38" />
|
||||
<!-- Arrowhead on XXXpoint 2475 3600 - 4116 2190-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="7875,3600 6372,2310 "
|
||||
style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline42" />
|
||||
<!-- Arrowhead on XXXpoint 7875 3600 - 6231 2190-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="6975,8775 6975,5046 "
|
||||
style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline46" />
|
||||
<!-- Arrowhead on XXXpoint 6975 8775 - 6975 4860-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1575,8775 1575,5046 "
|
||||
style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline50" />
|
||||
<!-- Arrowhead on XXXpoint 1575 8775 - 1575 4860-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="8775,6525 8775,5046 "
|
||||
style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline54" />
|
||||
<!-- Arrowhead on XXXpoint 8775 6525 - 8775 4860-->
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1575"
|
||||
y="9225"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text58">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1575"
|
||||
y="9675"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text60">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1575"
|
||||
y="10350"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text62">CPU 0</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3375"
|
||||
y="6975"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text64">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3375"
|
||||
y="7425"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text66">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3375"
|
||||
y="8100"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text68">CPU 15</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6975"
|
||||
y="9225"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text70">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6975"
|
||||
y="9675"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text72">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6975"
|
||||
y="10350"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text74">CPU 1007</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8730"
|
||||
y="6930"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text76">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8730"
|
||||
y="7380"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text78">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8730"
|
||||
y="8055"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text80">CPU 1023</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="225"
|
||||
y="450"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="start"
|
||||
id="text82">struct rcu_state</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2475"
|
||||
y="4050"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text84">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2475"
|
||||
y="4500"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text86">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7875"
|
||||
y="4500"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text88">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7875"
|
||||
y="4050"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text90">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5175"
|
||||
y="1350"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text92">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5175"
|
||||
y="1800"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text94">rcu_node</text>
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="225"
|
||||
y="8775"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect96" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="5625"
|
||||
y="8775"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect98" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="7380"
|
||||
y="6480"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect100" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,662 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:29:48 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="7.4000001in"
|
||||
height="7.9000001in"
|
||||
viewBox="-44 -44 8938 9526.283"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2pre0 (973e216, 2017-07-25)"
|
||||
sodipodi:docname="BigTreePreemptRCUBHdyntickCB.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker1177"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path897"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path891"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1019"
|
||||
id="namedview208"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.0195195"
|
||||
inkscape:cx="166.25478"
|
||||
inkscape:cy="362.18693"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g4" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4"
|
||||
transform="translate(0,-2415.6743)">
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8550 - 5710 6240-->
|
||||
<polyline
|
||||
points="5714 6518 5704 6272 5598 6494 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline20"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9750 - 4512 7590-->
|
||||
<polyline
|
||||
points="4514 7868 4506 7622 4396 7844 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline24"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1040 9750 - 1502 7590-->
|
||||
<polyline
|
||||
points="1504 7868 1496 7622 1386 7844 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline28"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2240 8550 - 2702 6390-->
|
||||
<polyline
|
||||
points="2704 6668 2696 6422 2586 6644 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline32"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9600 - 5744 5948-->
|
||||
<polyline
|
||||
points="5682 6220 5730 5978 5574 6170 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline36"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1086 9600 - 2780 5948-->
|
||||
<polyline
|
||||
points="2718 6220 2766 5978 2610 6170 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline40"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="12.340758"
|
||||
y="2442.5947"
|
||||
width="6300"
|
||||
height="7045.3135"
|
||||
rx="0"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect42" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="312.34076"
|
||||
y="3017.7224"
|
||||
width="5700"
|
||||
height="3594.5476"
|
||||
rx="0"
|
||||
style="fill:#ffff00;stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect44" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1350,3900 2350,3040 "
|
||||
style="stroke:#00d1d1;stroke-width:29.99464035;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline46"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Arrowhead on XXXpoint 1350 3900 - 2444 2960-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="4950,3900 3948,3040 "
|
||||
style="stroke:#00d1d1;stroke-width:29.99464035;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline50"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Arrowhead on XXXpoint 4950 3900 - 3854 2960-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="4050,7050 4050,4864 "
|
||||
style="stroke:#00d1d1;stroke-width:29.99464035;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline54"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Arrowhead on XXXpoint 4050 7050 - 4050 4740-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1050,7050 1050,4864 "
|
||||
style="stroke:#00d1d1;stroke-width:29.99464035;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline58"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Arrowhead on XXXpoint 1050 7050 - 1050 4740-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="2250,5850 2250,4864 "
|
||||
style="stroke:#00d1d1;stroke-width:29.99464035;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline62"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Arrowhead on XXXpoint 2250 5850 - 2250 4740-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2250 8550 - 2250 6690-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1050 9750 - 1050 7890-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9750 - 4050 7890-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8550 - 5250 6690-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 6000 6300 - 8146 7986-->
|
||||
<!-- Circle -->
|
||||
<ellipse
|
||||
cx="2862.3408"
|
||||
cy="5749.5786"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:13.70675087"
|
||||
id="circle86"
|
||||
rx="76"
|
||||
ry="72.849495" />
|
||||
<!-- Circle -->
|
||||
<ellipse
|
||||
cx="3162.3408"
|
||||
cy="5749.5786"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:13.70675087"
|
||||
id="circle88"
|
||||
rx="76"
|
||||
ry="72.849495" />
|
||||
<!-- Circle -->
|
||||
<ellipse
|
||||
cx="3462.3408"
|
||||
cy="5749.5786"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:13.70675087"
|
||||
id="circle90"
|
||||
rx="76"
|
||||
ry="72.849495" />
|
||||
<!-- Circle -->
|
||||
<ellipse
|
||||
cx="1362.3407"
|
||||
cy="6899.834"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:13.70675087"
|
||||
id="circle92"
|
||||
rx="76"
|
||||
ry="72.849495" />
|
||||
<!-- Circle -->
|
||||
<ellipse
|
||||
cx="1662.3407"
|
||||
cy="6899.834"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:13.70675087"
|
||||
id="circle94"
|
||||
rx="76"
|
||||
ry="72.849495" />
|
||||
<!-- Circle -->
|
||||
<ellipse
|
||||
cx="1962.3407"
|
||||
cy="6899.834"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:13.70675087"
|
||||
id="circle96"
|
||||
rx="76"
|
||||
ry="72.849495" />
|
||||
<!-- Circle -->
|
||||
<ellipse
|
||||
cx="4362.3408"
|
||||
cy="6899.834"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:13.70675087"
|
||||
id="circle98"
|
||||
rx="76"
|
||||
ry="72.849495" />
|
||||
<!-- Circle -->
|
||||
<ellipse
|
||||
cx="4662.3408"
|
||||
cy="6899.834"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:13.70675087"
|
||||
id="circle100"
|
||||
rx="76"
|
||||
ry="72.849495" />
|
||||
<!-- Circle -->
|
||||
<ellipse
|
||||
cx="4962.3408"
|
||||
cy="6899.834"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:13.70675087"
|
||||
id="circle102"
|
||||
rx="76"
|
||||
ry="72.849495" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="6745.3027"
|
||||
y="8146.0654"
|
||||
width="1500"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect104" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="6745.3027"
|
||||
y="9583.8857"
|
||||
width="1500"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect106" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="8100,8850 8100,9384 "
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline108"
|
||||
transform="matrix(1,0,0,0.95854605,-604.69715,525.62477)" />
|
||||
<!-- Arrowhead on XXXpoint 8100 8850 - 8100 9510-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="6745.3027"
|
||||
y="11021.704"
|
||||
width="1500"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect112" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="8100,10350 8100,10884 "
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline114"
|
||||
transform="matrix(1,0,0,0.95854605,-604.69715,525.62477)" />
|
||||
<!-- Arrowhead on XXXpoint 8100 10350 - 8100 11010-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="762.34076"
|
||||
y="5318.2324"
|
||||
width="1800"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect118" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="312.34076"
|
||||
y="8337.6533"
|
||||
width="1500"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect120" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="3762.3408"
|
||||
y="5318.2324"
|
||||
width="1800"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect122" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="4512.3408"
|
||||
y="7187.3975"
|
||||
width="1500"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect124" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="3312.3408"
|
||||
y="8337.6533"
|
||||
width="1500"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect126" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="2262.3408"
|
||||
y="3592.8503"
|
||||
width="1800"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect128" />
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="1512.3407"
|
||||
y="7187.3975"
|
||||
width="1500"
|
||||
height="862.69141"
|
||||
rx="0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:29.37160873;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect138" />
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7338.3037"
|
||||
y="8614.0625"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text140"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7338.3037"
|
||||
y="8907.7783"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text142"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_head</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7338.3037"
|
||||
y="10082.644"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text144"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7338.3037"
|
||||
y="10376.36"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text146"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_head</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7338.3037"
|
||||
y="11551.224"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text148"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7338.3037"
|
||||
y="11844.94"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text150"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_head</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5886.4043"
|
||||
y="2788.5688"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="192"
|
||||
id="text152"
|
||||
style="font-style:normal;font-weight:normal;font-size:187.978302px;font-family:Helvetica;text-anchor:end;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_state</text>
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3096.1016"
|
||||
y="3963.4336"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text156"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3096.1016"
|
||||
y="4257.1494"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text158"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1627.5209"
|
||||
y="5725.7305"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text160"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1627.5209"
|
||||
y="6019.4463"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text162"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4564.6821"
|
||||
y="6019.4463"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text164"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4564.6821"
|
||||
y="5725.7305"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text166"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2214.9531"
|
||||
y="7634.8848"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text168"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2214.9531"
|
||||
y="7928.6011"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text170"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1040.0886"
|
||||
y="8809.749"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text172"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1040.0886"
|
||||
y="9103.4648"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text174"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5152.1138"
|
||||
y="7634.8848"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text176"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5152.1138"
|
||||
y="7928.6011"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text178"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3977.2495"
|
||||
y="8809.749"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text180"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3977.2495"
|
||||
y="9103.4648"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text182"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:middle;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="452.6564"
|
||||
y="3376.0012"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text184"
|
||||
style="font-style:normal;font-weight:bold;font-size:187.978302px;font-family:Courier;text-anchor:start;fill:#000000;stroke-width:0.02447634in"
|
||||
transform="scale(1.0213945,0.97905363)">struct rcu_state</text>
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="5250,5850 5250,4864 "
|
||||
style="stroke:#00d1d1;stroke-width:29.99464035;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline204"
|
||||
transform="matrix(1,0,0,0.95854605,12.340758,1579.9033)" />
|
||||
<!-- Arrowhead on XXXpoint 5250 5850 - 5250 4740-->
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:34.24744034;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker1177)"
|
||||
d="m 6000.1472,7564.2558 c 1498.5508,0 1498.5508,0 1498.5508,0 v 520.0252"
|
||||
id="path886"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 22 KiB |
1163
Documentation/RCU/Design/Data-Structures/Data-Structures.rst
Normal file
939
Documentation/RCU/Design/Data-Structures/HugeTreeClassicRCU.svg
Normal file
@ -0,0 +1,939 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:37:22 2015 -->
|
||||
|
||||
<!-- Magnification: 3.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="15.1in"
|
||||
height="11.2in"
|
||||
viewBox="-66 -66 18087 13407"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="HugeTreeClassicRCU.fig">
|
||||
<metadata
|
||||
id="metadata224">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs222">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3982"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1134"
|
||||
inkscape:window-height="789"
|
||||
id="namedview220"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.60515873"
|
||||
inkscape:cx="679.5"
|
||||
inkscape:cy="504"
|
||||
inkscape:window-x="786"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4" />
|
||||
<g
|
||||
style="stroke-width:.025in; fill:none"
|
||||
id="g4">
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="450"
|
||||
y="0"
|
||||
width="17100"
|
||||
height="8325"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
|
||||
id="rect6" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="11025"
|
||||
y="3600"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect8" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="4275"
|
||||
y="3600"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect10" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="5400"
|
||||
y="6300"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect12" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="9900"
|
||||
y="6300"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect14" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="14400"
|
||||
y="6300"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect16" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="900"
|
||||
y="6300"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect18" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="7650"
|
||||
y="900"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect20" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="3150,9225 3150,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline22" />
|
||||
<!-- Arrowhead on XXXpoint 3150 9225 - 3150 7560-->
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="8550"
|
||||
cy="4275"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle26" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="9000"
|
||||
cy="4275"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle28" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="9450"
|
||||
cy="4275"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle30" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="6750,6300 8250,5010 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline32" />
|
||||
<!-- Arrowhead on XXXpoint 6750 6300 - 8391 4890-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="11250,6300 9747,5010 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline36" />
|
||||
<!-- Arrowhead on XXXpoint 11250 6300 - 9606 4890-->
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="13950"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle40" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="13500"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle42" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="13050"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle44" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="9450"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle46" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="9000"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle48" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="8550"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle50" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="4950"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle52" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="4500"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle54" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="4050"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle56" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="1800"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle58" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="2250"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle60" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="2700"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle62" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="15300"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle64" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="15750"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle66" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="16200"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle68" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="10800"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle70" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="11250"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle72" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="11700"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle74" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="6300"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle76" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="6750"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle78" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="7200"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle80" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="11475"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect82" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="1800"
|
||||
y="9225"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect84" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="4500"
|
||||
y="11475"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect86" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="6300"
|
||||
y="9270"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect88" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="8955"
|
||||
y="11475"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect90" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10755"
|
||||
y="9270"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect92" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="13455"
|
||||
y="11475"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect94" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="15255"
|
||||
y="9270"
|
||||
width="2700"
|
||||
height="1800"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect96" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="11700,3600 10197,2310 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline98" />
|
||||
<!-- Arrowhead on XXXpoint 11700 3600 - 10056 2190-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="6300,3600 7800,2310 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline102" />
|
||||
<!-- Arrowhead on XXXpoint 6300 3600 - 7941 2190-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="3150,6300 4650,5010 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline106" />
|
||||
<!-- Arrowhead on XXXpoint 3150 6300 - 4791 4890-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="14850,6300 13347,5010 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline110" />
|
||||
<!-- Arrowhead on XXXpoint 14850 6300 - 13206 4890-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1350,11475 1350,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline114" />
|
||||
<!-- Arrowhead on XXXpoint 1350 11475 - 1350 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="16650,9225 16650,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline118" />
|
||||
<!-- Arrowhead on XXXpoint 16650 9225 - 16650 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="14850,11475 14850,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline122" />
|
||||
<!-- Arrowhead on XXXpoint 14850 11475 - 14850 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="12150,9225 12150,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline126" />
|
||||
<!-- Arrowhead on XXXpoint 12150 9225 - 12150 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="10350,11475 10350,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline130" />
|
||||
<!-- Arrowhead on XXXpoint 10350 11475 - 10350 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="7650,9225 7650,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline134" />
|
||||
<!-- Arrowhead on XXXpoint 7650 9225 - 7650 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="5850,11475 5850,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline138" />
|
||||
<!-- Arrowhead on XXXpoint 5850 11475 - 5850 7560-->
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="12375"
|
||||
y="4500"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text142">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="12375"
|
||||
y="4050"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text144">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5625"
|
||||
y="4050"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text146">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5625"
|
||||
y="4500"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text148">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6750"
|
||||
y="6750"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text150">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6750"
|
||||
y="7200"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text152">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11250"
|
||||
y="7200"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text154">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11250"
|
||||
y="6750"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text156">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="15750"
|
||||
y="7200"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text158">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="15750"
|
||||
y="6750"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text160">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2250"
|
||||
y="6750"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text162">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2250"
|
||||
y="7200"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text164">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1350"
|
||||
y="13050"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text166">CPU 0</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1350"
|
||||
y="11925"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text168">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1350"
|
||||
y="12375"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text170">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3150"
|
||||
y="10800"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text172">CPU 15</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3150"
|
||||
y="9675"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text174">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3150"
|
||||
y="10125"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text176">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5850"
|
||||
y="11925"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text178">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5850"
|
||||
y="12375"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text180">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5850"
|
||||
y="13050"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text182">CPU 21823</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7650"
|
||||
y="10845"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text184">CPU 21839</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7650"
|
||||
y="10170"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text186">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7650"
|
||||
y="9720"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text188">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="10305"
|
||||
y="11925"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text190">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="10305"
|
||||
y="12375"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text192">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="10305"
|
||||
y="13050"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text194">CPU 43679</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="12105"
|
||||
y="10845"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text196">CPU 43695</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="12105"
|
||||
y="10170"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text198">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="12105"
|
||||
y="9720"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text200">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="14805"
|
||||
y="11925"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text202">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="14805"
|
||||
y="12375"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text204">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="14805"
|
||||
y="13050"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text206">CPU 65519</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="16605"
|
||||
y="10845"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text208">CPU 65535</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="16605"
|
||||
y="10170"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text210">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="16605"
|
||||
y="9720"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text212">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="675"
|
||||
y="450"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="start"
|
||||
id="text214">struct rcu_state</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9000"
|
||||
y="1350"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text216">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9000"
|
||||
y="1800"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text218">rcu_node</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 25 KiB |
828
Documentation/RCU/Design/Data-Structures/TreeLevel.svg
Normal file
@ -0,0 +1,828 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:41:29 2015 -->
|
||||
|
||||
<!-- Magnification: 3.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="17.7in"
|
||||
height="10.4in"
|
||||
viewBox="-66 -66 21237 12507"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeLevel.fig">
|
||||
<metadata
|
||||
id="metadata216">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs214">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3974"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1023"
|
||||
inkscape:window-height="1148"
|
||||
id="namedview212"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.55869424"
|
||||
inkscape:cx="796.50006"
|
||||
inkscape:cy="467.99997"
|
||||
inkscape:window-x="897"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4" />
|
||||
<g
|
||||
style="stroke-width:.025in; fill:none"
|
||||
id="g4">
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="20655"
|
||||
height="8325"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
|
||||
id="rect6" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="14130"
|
||||
y="3600"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect8" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="7380"
|
||||
y="3600"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect10" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="8505"
|
||||
y="6300"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect12" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="13005"
|
||||
y="6300"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect14" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="17505"
|
||||
y="6300"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect16" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="4005"
|
||||
y="6300"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect18" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10755"
|
||||
y="900"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect20" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="6255,9225 6255,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline22" />
|
||||
<!-- Arrowhead on XXXpoint 6255 9225 - 6255 7560-->
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="11655"
|
||||
cy="4275"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle26" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="12105"
|
||||
cy="4275"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle28" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="12555"
|
||||
cy="4275"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle30" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="9855,6300 11355,5010 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline32" />
|
||||
<!-- Arrowhead on XXXpoint 9855 6300 - 11496 4890-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="14355,6300 12852,5010 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline36" />
|
||||
<!-- Arrowhead on XXXpoint 14355 6300 - 12711 4890-->
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="17055"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle40" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="16605"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle42" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="16155"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle44" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="12555"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle46" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="12105"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle48" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="11655"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle50" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="8055"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle52" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="7605"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle54" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="7155"
|
||||
cy="6975"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle56" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="4905"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle58" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="5355"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle60" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="5805"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle62" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="18405"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle64" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="18855"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle66" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="19305"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle68" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="13905"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle70" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="14355"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle72" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="14805"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle74" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="9405"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle76" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="9855"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle78" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="10305"
|
||||
cy="8775"
|
||||
r="114"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:21;"
|
||||
id="circle80" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="225"
|
||||
y="1125"
|
||||
width="3150"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:21; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
|
||||
id="rect82" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="225"
|
||||
y="2250"
|
||||
width="3150"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:21; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
|
||||
id="rect84" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="225"
|
||||
y="3375"
|
||||
width="3150"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:21; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
|
||||
id="rect86" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="14805,3600 13302,2310 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline88" />
|
||||
<!-- Arrowhead on XXXpoint 14805 3600 - 13161 2190-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="9405,3600 10905,2310 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline92" />
|
||||
<!-- Arrowhead on XXXpoint 9405 3600 - 11046 2190-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="6255,6300 7755,5010 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline96" />
|
||||
<!-- Arrowhead on XXXpoint 6255 6300 - 7896 4890-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="17955,6300 16452,5010 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline100" />
|
||||
<!-- Arrowhead on XXXpoint 17955 6300 - 16311 4890-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="4455,11025 4455,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline104" />
|
||||
<!-- Arrowhead on XXXpoint 4455 11025 - 4455 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="19755,9225 19755,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline108" />
|
||||
<!-- Arrowhead on XXXpoint 19755 9225 - 19755 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="17955,11025 17955,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline112" />
|
||||
<!-- Arrowhead on XXXpoint 17955 11025 - 17955 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="15255,9225 15255,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline116" />
|
||||
<!-- Arrowhead on XXXpoint 15255 9225 - 15255 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="13455,11025 13455,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline120" />
|
||||
<!-- Arrowhead on XXXpoint 13455 11025 - 13455 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="10755,9225 10755,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline124" />
|
||||
<!-- Arrowhead on XXXpoint 10755 9225 - 10755 7560-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="8955,11025 8955,7746 "
|
||||
style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline128" />
|
||||
<!-- Arrowhead on XXXpoint 8955 11025 - 8955 7560-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="12105"
|
||||
y="11025"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect132" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="13905"
|
||||
y="9225"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect134" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="16605"
|
||||
y="11025"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect136" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="18405"
|
||||
y="9225"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect138" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="9405"
|
||||
y="9225"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect140" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="7605"
|
||||
y="11025"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect142" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="4905"
|
||||
y="9225"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect144" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="3105"
|
||||
y="11025"
|
||||
width="2700"
|
||||
height="1350"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect146" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="3375,1575 10701,1575 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline148" />
|
||||
<!-- Arrowhead on XXXpoint 3375 1575 - 10890 1575-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="3375,3825 4050,3825 4050,5400 2700,5400 2700,6975 3951,6975 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline152" />
|
||||
<!-- Arrowhead on XXXpoint 2700 6975 - 4140 6975-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="3375,2700 5175,2700 5175,4275 7326,4275 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline156" />
|
||||
<!-- Arrowhead on XXXpoint 5175 4275 - 7515 4275-->
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="15480"
|
||||
y="4500"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text160">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="15480"
|
||||
y="4050"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text162">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8730"
|
||||
y="4050"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text164">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8730"
|
||||
y="4500"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text166">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9855"
|
||||
y="6750"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text168">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9855"
|
||||
y="7200"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text170">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="14355"
|
||||
y="7200"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text172">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="14355"
|
||||
y="6750"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text174">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="18855"
|
||||
y="7200"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text176">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="18855"
|
||||
y="6750"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text178">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5355"
|
||||
y="6750"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text180">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5355"
|
||||
y="7200"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text182">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="450"
|
||||
y="1800"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="324"
|
||||
text-anchor="start"
|
||||
id="text184">->level[0]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="450"
|
||||
y="2925"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="324"
|
||||
text-anchor="start"
|
||||
id="text186">->level[1]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="450"
|
||||
y="4050"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="324"
|
||||
text-anchor="start"
|
||||
id="text188">->level[2]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="12105"
|
||||
y="1350"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text190">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="12105"
|
||||
y="1800"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="middle"
|
||||
id="text192">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6255"
|
||||
y="10125"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text194">CPU 15</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4455"
|
||||
y="11925"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text196">CPU 0</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="19755"
|
||||
y="10125"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text198">CPU 65535</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="17955"
|
||||
y="11925"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text200">CPU 65519</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="15255"
|
||||
y="10125"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text202">CPU 43695</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="13455"
|
||||
y="11925"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text204">CPU 43679</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="10755"
|
||||
y="10125"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text206">CPU 21839</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8955"
|
||||
y="11925"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text208">CPU 21823</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="225"
|
||||
y="450"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="288"
|
||||
text-anchor="start"
|
||||
id="text210">struct rcu_state</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 23 KiB |
305
Documentation/RCU/Design/Data-Structures/TreeMapping.svg
Normal file
@ -0,0 +1,305 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:43:22 2015 -->
|
||||
|
||||
<!-- Magnification: 1.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="3.1in"
|
||||
height="0.9in"
|
||||
viewBox="-12 -12 3699 1074"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeMapping.fig">
|
||||
<metadata
|
||||
id="metadata66">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs64">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3836"
|
||||
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(1.1) rotate(180) translate(1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3842"
|
||||
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(0.6) rotate(180) translate(0,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3824"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="991"
|
||||
inkscape:window-height="606"
|
||||
id="namedview62"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.0752688"
|
||||
inkscape:cx="139.5"
|
||||
inkscape:cy="40.5"
|
||||
inkscape:window-x="891"
|
||||
inkscape:window-y="177"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4" />
|
||||
<g
|
||||
style="stroke-width:.025in; fill:none"
|
||||
id="g4">
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="3675"
|
||||
height="1050"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
|
||||
id="rect6" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="75"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect8" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="600"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect10" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="1125"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect12" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="1650"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect14" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="2175"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect16" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="3225"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect18" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="675,375 675,150 300,150 300,358 "
|
||||
style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline20" />
|
||||
<!-- Arrowhead on XXXpoint 300 150 - 300 390-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1200,675 1200,900 300,900 300,691 "
|
||||
style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline24" />
|
||||
<!-- Arrowhead on XXXpoint 300 900 - 300 660-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1725,375 1725,150 900,150 900,358 "
|
||||
style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline28" />
|
||||
<!-- Arrowhead on XXXpoint 900 150 - 900 390-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="2250,375 2250,75 825,75 825,358 "
|
||||
style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline32" />
|
||||
<!-- Arrowhead on XXXpoint 825 75 - 825 390-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="2775,675 2775,900 1425,900 1425,691 "
|
||||
style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline36" />
|
||||
<!-- Arrowhead on XXXpoint 1425 900 - 1425 660-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="3300,675 3300,975 1350,975 1350,691 "
|
||||
style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline40" />
|
||||
<!-- Arrowhead on XXXpoint 1350 975 - 1350 660-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="2700"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect44" />
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="300"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text46">0:7 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1350"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text48">4:7 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1875"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text50">0:1 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2400"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text52">2:3 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2925"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text54">4:5 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3450"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text56">6:7 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="825"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text58">0:3 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3600"
|
||||
y="150"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="end"
|
||||
id="text60">struct rcu_state</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.0 KiB |
380
Documentation/RCU/Design/Data-Structures/TreeMappingLevel.svg
Normal file
@ -0,0 +1,380 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:45:19 2015 -->
|
||||
|
||||
<!-- Magnification: 1.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="3.1in"
|
||||
height="1.8in"
|
||||
viewBox="-12 -12 3699 2124"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeMappingLevel.svg">
|
||||
<metadata
|
||||
id="metadata98">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs96">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3868"
|
||||
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(1.1) rotate(180) translate(1,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1598"
|
||||
inkscape:window-height="1211"
|
||||
id="namedview94"
|
||||
showgrid="false"
|
||||
inkscape:zoom="5.2508961"
|
||||
inkscape:cx="139.5"
|
||||
inkscape:cy="81"
|
||||
inkscape:window-x="840"
|
||||
inkscape:window-y="122"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4" />
|
||||
<g
|
||||
style="stroke-width:.025in; fill:none"
|
||||
id="g4">
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="3675"
|
||||
height="2100"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
|
||||
id="rect6" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="75"
|
||||
y="1350"
|
||||
width="750"
|
||||
height="225"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect8" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="75"
|
||||
y="1575"
|
||||
width="750"
|
||||
height="225"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect10" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="75"
|
||||
y="1800"
|
||||
width="750"
|
||||
height="225"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect12" />
|
||||
<!-- Arc -->
|
||||
<path
|
||||
style="stroke:#000000;stroke-width:7;stroke-linecap:butt;"
|
||||
d="M 1800,900 A 118 118 0 0 0 1800 1125 "
|
||||
id="path14" />
|
||||
<!-- Arc -->
|
||||
<path
|
||||
style="stroke:#000000;stroke-width:7;stroke-linecap:butt;"
|
||||
d="M 750,900 A 75 75 0 0 0 750 1050 "
|
||||
id="path16" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="750,900 750,691 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline18" />
|
||||
<!-- Arrowhead on XXXpoint 750 900 - 750 660-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="75"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect22" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="600"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect24" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="1650"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect26" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="2175"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect28" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="3225"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect30" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="675,375 675,150 300,150 300,358 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline32" />
|
||||
<!-- Arrowhead on XXXpoint 300 150 - 300 390-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1725,375 1725,150 900,150 900,358 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline36" />
|
||||
<!-- Arrowhead on XXXpoint 900 150 - 900 390-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="2250,375 2250,75 825,75 825,358 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline40" />
|
||||
<!-- Arrowhead on XXXpoint 825 75 - 825 390-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="2775,675 2775,975 1425,975 1425,691 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline44" />
|
||||
<!-- Arrowhead on XXXpoint 1425 975 - 1425 660-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="2700"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect48" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="1125"
|
||||
y="375"
|
||||
width="375"
|
||||
height="300"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
|
||||
id="rect50" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="3300,675 3300,1050 1350,1050 1350,691 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline52" />
|
||||
<!-- Arrowhead on XXXpoint 1350 1050 - 1350 660-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="825,1425 975,1425 975,1200 225,1200 225,691 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline56" />
|
||||
<!-- Arrowhead on XXXpoint 225 1200 - 225 660-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1200,675 1200,975 300,975 300,691 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline60" />
|
||||
<!-- Arrowhead on XXXpoint 300 975 - 300 660-->
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="150"
|
||||
y="1500"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="108"
|
||||
text-anchor="start"
|
||||
id="text64">->level[0]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="150"
|
||||
y="1725"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="108"
|
||||
text-anchor="start"
|
||||
id="text66">->level[1]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="150"
|
||||
y="1950"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="108"
|
||||
text-anchor="start"
|
||||
id="text68">->level[2]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="300"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text70">0:7 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1350"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text72">4:7 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1875"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text74">0:1 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2400"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text76">2:3 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2925"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text78">4:5 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3450"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text80">6:7 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="825"
|
||||
y="525"
|
||||
fill="#000000"
|
||||
font-family="Times"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="middle"
|
||||
id="text82">0:3 </text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3600"
|
||||
y="150"
|
||||
fill="#000000"
|
||||
font-family="Courier"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="96"
|
||||
text-anchor="end"
|
||||
id="text84">struct rcu_state</text>
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="825,1875 1800,1875 1800,1125 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:none"
|
||||
id="polyline86" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1800,900 1800,691 "
|
||||
style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
id="polyline88" />
|
||||
<!-- Arrowhead on XXXpoint 1800 900 - 1800 660-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="825,1650 1200,1650 1200,1125 750,1125 750,1050 "
|
||||
style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="polyline92" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
631
Documentation/RCU/Design/Data-Structures/blkd_task.svg
Normal file
@ -0,0 +1,631 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:35:03 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="10.1in"
|
||||
height="6.5999999in"
|
||||
viewBox="-44 -44 12088 7895.4414"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2pre0 (973e216, 2017-07-25)"
|
||||
sodipodi:docname="blkd_task.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1019"
|
||||
id="namedview208"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.0495049"
|
||||
inkscape:cx="456.40569"
|
||||
inkscape:cy="348.88682"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g4"
|
||||
showguides="false" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4"
|
||||
transform="translate(0,-2393.6637)">
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8100 - 5710 5790-->
|
||||
<polyline
|
||||
points="5714 6068 5704 5822 5598 6044 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline14"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9300 - 4512 7140-->
|
||||
<polyline
|
||||
points="4514 7418 4506 7172 4396 7394 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline18"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1040 9300 - 1502 7140-->
|
||||
<polyline
|
||||
points="1504 7418 1496 7172 1386 7394 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline22"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2240 8100 - 2702 5940-->
|
||||
<polyline
|
||||
points="2704 6218 2696 5972 2586 6194 "
|
||||
style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8"
|
||||
id="polyline26"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="23.757858"
|
||||
y="2635.7231"
|
||||
width="6300"
|
||||
height="7350"
|
||||
rx="0"
|
||||
style="fill:#ffffff;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect28" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="323.75787"
|
||||
y="3235.7231"
|
||||
width="5700"
|
||||
height="3750"
|
||||
rx="0"
|
||||
style="fill:#ffff00;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect30" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1350,3450 2350,2590 "
|
||||
style="stroke:#00d1d1;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline32"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 1350 3450 - 2444 2510-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="4950,3450 3948,2590 "
|
||||
style="stroke:#00d1d1;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline36"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 4950 3450 - 3854 2510-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="4050,6600 4050,4414 "
|
||||
style="stroke:#00d1d1;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline40"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 4050 6600 - 4050 4290-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="1050,6600 1050,4414 "
|
||||
style="stroke:#00d1d1;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline44"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 1050 6600 - 1050 4290-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="2250,5400 2250,4414 "
|
||||
style="stroke:#00d1d1;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline48"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 2250 5400 - 2250 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2250 8100 - 2250 6240-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1050 9300 - 1050 7440-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9300 - 4050 7440-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8100 - 5250 6240-->
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="2873.7581"
|
||||
cy="6085.7236"
|
||||
r="76"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:14"
|
||||
id="circle68" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="3173.7581"
|
||||
cy="6085.7236"
|
||||
r="76"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:14"
|
||||
id="circle70" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="3473.7581"
|
||||
cy="6085.7236"
|
||||
r="76"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:14"
|
||||
id="circle72" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="1373.7578"
|
||||
cy="7285.7236"
|
||||
r="76"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:14"
|
||||
id="circle74" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="1673.7578"
|
||||
cy="7285.7236"
|
||||
r="76"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:14"
|
||||
id="circle76" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="1973.7578"
|
||||
cy="7285.7236"
|
||||
r="76"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:14"
|
||||
id="circle78" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="4373.7578"
|
||||
cy="7285.7236"
|
||||
r="76"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:14"
|
||||
id="circle80" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="4673.7578"
|
||||
cy="7285.7236"
|
||||
r="76"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:14"
|
||||
id="circle82" />
|
||||
<!-- Circle -->
|
||||
<circle
|
||||
cx="4973.7578"
|
||||
cy="7285.7236"
|
||||
r="76"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:14"
|
||||
id="circle84" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="773.75781"
|
||||
y="5635.7236"
|
||||
width="1800"
|
||||
height="900"
|
||||
rx="0"
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect86" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="323.75787"
|
||||
y="8785.7227"
|
||||
width="1500"
|
||||
height="900"
|
||||
rx="0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect88" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="4523.7578"
|
||||
y="7585.7236"
|
||||
width="1500"
|
||||
height="900"
|
||||
rx="0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect90" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="3323.7581"
|
||||
y="8785.7227"
|
||||
width="1500"
|
||||
height="900"
|
||||
rx="0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect92" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="2273.7581"
|
||||
y="3835.7231"
|
||||
width="1800"
|
||||
height="900"
|
||||
rx="0"
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect94" />
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="1523.7578"
|
||||
y="7585.7236"
|
||||
width="1500"
|
||||
height="900"
|
||||
rx="0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect104" />
|
||||
<!-- Line -->
|
||||
<polygon
|
||||
points="7350,2850 7350,5100 5550,4350 5550,3450 "
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:14;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:120, 120"
|
||||
id="polygon106"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="9300,3150 10734,3150 "
|
||||
style="stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline108"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 9300 3150 - 10860 3150-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10823.758"
|
||||
y="5035.7236"
|
||||
width="1200"
|
||||
height="750"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect112" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="11400,3600 11400,4284 "
|
||||
style="stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline114"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 11400 3600 - 11400 4410-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10823.758"
|
||||
y="6535.7236"
|
||||
width="1200"
|
||||
height="750"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect118" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="11400,5100 11400,5784 "
|
||||
style="stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline120"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 11400 5100 - 11400 5910-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10823.758"
|
||||
y="8035.7236"
|
||||
width="1200"
|
||||
height="750"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect124" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="9300,3900 9900,3900 9900,4650 10734,4650 "
|
||||
style="stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline126"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 9900 4650 - 10860 4650-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="9300,4650 9600,4650 9600,6150 10734,6150 "
|
||||
style="stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline130"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 9600 6150 - 10860 6150-->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3173.7581"
|
||||
y="4135.7231"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text136"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3173.7581"
|
||||
y="4435.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text138"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1673.7578"
|
||||
y="5935.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text140"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1673.7578"
|
||||
y="6235.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text142"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2273.7581"
|
||||
y="7885.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text144"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2273.7581"
|
||||
y="8185.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text146"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1073.7578"
|
||||
y="9085.7227"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text148"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1073.7578"
|
||||
y="9385.7227"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text150"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5273.7578"
|
||||
y="7885.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text152"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5273.7578"
|
||||
y="8185.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text154"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4073.7578"
|
||||
y="9085.7227"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text156"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4073.7578"
|
||||
y="9385.7227"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text158"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">rcu_data</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="473.75784"
|
||||
y="3535.7231"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text160"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:start;fill:#000000">struct rcu_state</text>
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6023.7578"
|
||||
y="2935.7231"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="192"
|
||||
id="text178"
|
||||
style="font-style:normal;font-weight:normal;font-size:192px;font-family:Helvetica;text-anchor:end;fill:#000000">rcu_state</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11423.758"
|
||||
y="5485.7236"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="216"
|
||||
id="text180"
|
||||
style="font-style:normal;font-weight:normal;font-size:216px;font-family:Helvetica;text-anchor:middle;fill:#000000">T3</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11423.758"
|
||||
y="6985.7236"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="216"
|
||||
id="text182"
|
||||
style="font-style:normal;font-weight:normal;font-size:216px;font-family:Helvetica;text-anchor:middle;fill:#000000">T2</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11423.758"
|
||||
y="8485.7227"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="216"
|
||||
id="text184"
|
||||
style="font-style:normal;font-weight:normal;font-size:216px;font-family:Helvetica;text-anchor:middle;fill:#000000">T1</text>
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="5250,5400 5250,4414 "
|
||||
style="stroke:#00d1d1;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline186"
|
||||
transform="translate(23.757862,2185.7233)" />
|
||||
<!-- Arrowhead on XXXpoint 5250 5400 - 5250 4290-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="3773.7581"
|
||||
y="5635.7236"
|
||||
width="1800"
|
||||
height="900"
|
||||
rx="0"
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect190" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="7373.7578"
|
||||
y="5035.7236"
|
||||
width="1950"
|
||||
height="750"
|
||||
rx="0"
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect192" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="7373.7578"
|
||||
y="5785.7236"
|
||||
width="1950"
|
||||
height="750"
|
||||
rx="0"
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect194" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="7373.7578"
|
||||
y="6535.7236"
|
||||
width="1950"
|
||||
height="750"
|
||||
rx="0"
|
||||
style="fill:#ffbfbf;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect196" />
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4673.7578"
|
||||
y="6235.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text198"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">rcu_node</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4673.7578"
|
||||
y="5935.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text200"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:middle;fill:#000000">struct</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7523.7578"
|
||||
y="5485.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:start;fill:#000000">blkd_tasks</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7523.7578"
|
||||
y="6235.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text204"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:start;fill:#000000">gp_tasks</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7523.7578"
|
||||
y="6985.7236"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text206"
|
||||
style="font-style:normal;font-weight:bold;font-size:192px;font-family:Courier;text-anchor:start;fill:#000000">exp_tasks</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 20 KiB |
386
Documentation/RCU/Design/Data-Structures/nxtlist.svg
Normal file
@ -0,0 +1,386 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:39:46 2015 -->
|
||||
|
||||
<!-- Magnification: 3.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="10.4in"
|
||||
height="10.4in"
|
||||
viewBox="-66 -66 12507 12507"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="segcblist.svg">
|
||||
<metadata
|
||||
id="metadata94">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs92">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3852"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="925"
|
||||
inkscape:window-height="928"
|
||||
id="namedview90"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.80021373"
|
||||
inkscape:cx="467.99997"
|
||||
inkscape:cy="467.99997"
|
||||
inkscape:window-x="948"
|
||||
inkscape:window-y="73"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4" />
|
||||
<g
|
||||
style="stroke-width:.025in; fill:none"
|
||||
id="g4">
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="7875"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
|
||||
id="rect6" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="1125"
|
||||
width="7875"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
|
||||
id="rect8" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="2250"
|
||||
width="7875"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
|
||||
id="rect10" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="3375"
|
||||
width="7875"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
|
||||
id="rect12" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="0"
|
||||
y="4500"
|
||||
width="7875"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
|
||||
id="rect14" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10575"
|
||||
y="0"
|
||||
width="1800"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect16" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10575"
|
||||
y="1125"
|
||||
width="1800"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect18" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="11475,2250 11475,3276 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline20" />
|
||||
<!-- Arrowhead on XXXpoint 11475 2250 - 11475 3465-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10575"
|
||||
y="6750"
|
||||
width="1800"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect24" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10575"
|
||||
y="7875"
|
||||
width="1800"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect26" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10575"
|
||||
y="10125"
|
||||
width="1800"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect28" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10575"
|
||||
y="11250"
|
||||
width="1800"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect30" />
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10575"
|
||||
y="3375"
|
||||
width="1800"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect32" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="11475,5625 11475,6651 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline34" />
|
||||
<!-- Arrowhead on XXXpoint 11475 5625 - 11475 6840-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="7875,225 10476,225 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline38" />
|
||||
<!-- Arrowhead on XXXpoint 7875 225 - 10665 225-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="7875,1350 9675,1350 9675,675 7971,675 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline42" />
|
||||
<!-- Arrowhead on XXXpoint 9675 675 - 7785 675-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="7875,2475 9675,2475 9675,4725 10476,4725 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline46" />
|
||||
<!-- Arrowhead on XXXpoint 9675 4725 - 10665 4725-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="7875,3600 9225,3600 9225,5175 10476,5175 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline50" />
|
||||
<!-- Arrowhead on XXXpoint 9225 5175 - 10665 5175-->
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="7875,4725 8775,4725 8775,11475 10476,11475 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline54" />
|
||||
<!-- Arrowhead on XXXpoint 8775 11475 - 10665 11475-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="10575"
|
||||
y="4500"
|
||||
width="1800"
|
||||
height="1125"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
|
||||
id="rect58" />
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points="11475,9000 11475,10026 "
|
||||
style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
|
||||
id="polyline60" />
|
||||
<!-- Arrowhead on XXXpoint 11475 9000 - 11475 10215-->
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="225"
|
||||
y="675"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="324"
|
||||
id="text64"
|
||||
style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">->head</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="225"
|
||||
y="1800"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="324"
|
||||
id="text66"
|
||||
style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">->tails[RCU_DONE_TAIL]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="225"
|
||||
y="2925"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="324"
|
||||
id="text68"
|
||||
style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">->tails[RCU_WAIT_TAIL]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="225"
|
||||
y="4050"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="324"
|
||||
id="text70"
|
||||
style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">->tails[RCU_NEXT_READY_TAIL]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="225"
|
||||
y="5175"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="324"
|
||||
id="text72"
|
||||
style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">->tails[RCU_NEXT_TAIL]</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11475"
|
||||
y="675"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text74">CB 1</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11475"
|
||||
y="1800"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text76">next</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11475"
|
||||
y="7425"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text78">CB 3</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11475"
|
||||
y="8550"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text80">next</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11475"
|
||||
y="10800"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text82">CB 4</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11475"
|
||||
y="11925"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text84">next</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11475"
|
||||
y="4050"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text86">CB 2</text>
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="11475"
|
||||
y="5175"
|
||||
fill="#000000"
|
||||
font-family="Helvetica"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="324"
|
||||
text-anchor="middle"
|
||||
id="text88">next</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
830
Documentation/RCU/Design/Expedited-Grace-Periods/ExpRCUFlow.svg
Normal file
@ -0,0 +1,830 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:39:46 2015 -->
|
||||
|
||||
<!-- Magnification: 3.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="952.6817"
|
||||
height="1219.6219"
|
||||
viewBox="-66 -66 12729.905 16296.808"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="ExpRCUFlow.svg">
|
||||
<metadata
|
||||
id="metadata94">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs92">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4146"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3852"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend-9"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3852-7"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-6"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-16"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-8"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-160"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-5"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-78"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-66"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-8"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-56"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-19"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-89"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-85"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-3"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-73"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-55"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-5"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-88"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-198"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-2"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-22"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker5072"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5074"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-87"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-63"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-26"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-51"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1090"
|
||||
inkscape:window-height="1148"
|
||||
id="namedview90"
|
||||
showgrid="true"
|
||||
inkscape:zoom="0.80021373"
|
||||
inkscape:cx="462.49289"
|
||||
inkscape:cy="623.19585"
|
||||
inkscape:window-x="557"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4"
|
||||
inkscape:snap-grids="false"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5"
|
||||
fit-margin-left="5" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4"
|
||||
transform="translate(23.312813,523.41305)">
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11475 2250 - 11475 3465-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11475 5625 - 11475 6840-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 7875 225 - 10665 225-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9675 675 - 7785 675-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9675 4725 - 10665 4725-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9225 5175 - 10665 5175-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 8775 11475 - 10665 11475-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11475 9000 - 11475 10215-->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<g
|
||||
id="g4104"
|
||||
transform="translate(-1068.9745,0)">
|
||||
<rect
|
||||
transform="matrix(-0.70710678,0.70710678,-0.70710678,-0.70710678,0,0)"
|
||||
y="-7383.8755"
|
||||
x="-6124.8989"
|
||||
height="1966.2251"
|
||||
width="1953.6969"
|
||||
id="rect3032-1-0"
|
||||
style="fill:#96ff96;fill-opacity:1;stroke:#000000;stroke-width:45.00382233;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4098"
|
||||
y="818.40338"
|
||||
x="8168.2671"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="818.40338"
|
||||
x="8168.2671"
|
||||
id="tspan4100"
|
||||
sodipodi:role="line">Idle or</tspan><tspan
|
||||
id="tspan4102"
|
||||
y="1152.4579"
|
||||
x="8168.2671"
|
||||
sodipodi:role="line">offline?</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4114"
|
||||
transform="translate(0,147.96969)">
|
||||
<rect
|
||||
id="rect6"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1475.6636"
|
||||
width="4401.7612"
|
||||
y="0"
|
||||
x="0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110"
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
id="tspan4112"
|
||||
sodipodi:role="line">CPU N Start</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="M 4432.5052,897.4924 5684.8749,880.79414"
|
||||
id="path4119"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="M 8503.0006,874.12161 9755.3703,857.42334"
|
||||
id="path4119-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="8617.0977"
|
||||
y="705.50983"
|
||||
id="text4593"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4595"
|
||||
x="8617.0977"
|
||||
y="705.50983">Y</tspan></text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9"
|
||||
transform="translate(9722.4732,131.27105)">
|
||||
<rect
|
||||
id="rect6-0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="0"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5"
|
||||
y="835.11212"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="835.11212"
|
||||
x="1460.1007"
|
||||
id="tspan4112-9"
|
||||
sodipodi:role="line">Done</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-5"
|
||||
transform="translate(0,3705.3456)">
|
||||
<rect
|
||||
id="rect6-1"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1475.6636"
|
||||
width="4401.7612"
|
||||
y="0"
|
||||
x="0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-9"
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
sodipodi:role="line"
|
||||
id="tspan4776">Send IPI to CPU N</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="M 7102.5627,2263.5171 4430.8404,3682.8694"
|
||||
id="path4119-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4104-1"
|
||||
transform="translate(-1065.3349,6403.5782)">
|
||||
<rect
|
||||
transform="matrix(-0.70710678,0.70710678,-0.70710678,-0.70710678,0,0)"
|
||||
y="-7383.8755"
|
||||
x="-6124.8989"
|
||||
height="1966.2251"
|
||||
width="1953.6969"
|
||||
id="rect3032-1-0-6"
|
||||
style="fill:#96ff96;fill-opacity:1;stroke:#000000;stroke-width:45.00382233;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4098-3"
|
||||
y="482.00006"
|
||||
x="8168.2671"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4102-8"
|
||||
y="482.00006"
|
||||
x="8168.2671"
|
||||
sodipodi:role="line">In RCU</tspan><tspan
|
||||
y="816.05457"
|
||||
x="8168.2671"
|
||||
sodipodi:role="line"
|
||||
id="tspan4833">read-side</tspan><tspan
|
||||
y="1150.109"
|
||||
x="8168.2671"
|
||||
sodipodi:role="line"
|
||||
id="tspan4835">critical</tspan><tspan
|
||||
y="1484.1636"
|
||||
x="8168.2671"
|
||||
sodipodi:role="line"
|
||||
id="tspan4837">section?</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:267.24362183px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="6463.0864"
|
||||
y="2285.6765"
|
||||
id="text4593-0"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4595-6"
|
||||
x="6463.0864"
|
||||
y="2285.6765">N</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654108, 80.17308215;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 2189.1897,5219.361 16.6983,1252.3697"
|
||||
id="path4119-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-5-2"
|
||||
transform="translate(0,6551.5479)">
|
||||
<rect
|
||||
id="rect6-1-7"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1475.6636"
|
||||
width="4401.7612"
|
||||
y="0"
|
||||
x="0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-9-5"
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
sodipodi:role="line"
|
||||
id="tspan4776-5">IPI Handler</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="m 4432.5052,7297.9678 1252.3697,-16.6982"
|
||||
id="path4119-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="m 8503.0013,7278.6595 1252.369,-16.6982"
|
||||
id="path4119-8-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:267.24362183px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="8617.0977"
|
||||
y="7110.0186"
|
||||
id="text4593-4"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4595-0"
|
||||
x="8617.0977"
|
||||
y="7110.0186">N</tspan></text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3"
|
||||
transform="translate(9722.4732,6535.809)">
|
||||
<rect
|
||||
id="rect6-0-7"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7"
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
id="tspan4112-9-0"
|
||||
sodipodi:role="line">Report CPU</tspan><tspan
|
||||
y="837.77039"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4923">Quiescent</tspan><tspan
|
||||
y="1171.825"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925">State</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654335, 80.17308669;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 7102.5627,8725.7454 16.6983,1252.3697"
|
||||
id="path4119-0-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:267.24362183px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="6797.0522"
|
||||
y="9018.6807"
|
||||
id="text4593-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4595-2"
|
||||
x="6797.0522"
|
||||
y="9018.6807">Y</tspan></text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-8"
|
||||
transform="translate(-80.17308,11381.108)">
|
||||
<rect
|
||||
id="rect6-0-7-5"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-6"
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-1">rcu_read_unlock()</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654562, 80.17309124;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 1362.6256,10071.26 16.6983,1252.369"
|
||||
id="path4119-0-0-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 1362.6256,12883.919 16.6983,1252.369"
|
||||
id="path4119-0-0-7-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-8-1"
|
||||
transform="translate(9722.4732,11389.458)">
|
||||
<rect
|
||||
id="rect6-0-7-5-1"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-6-2"
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-1-2">Context Switch</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654789, 80.17309578;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 11165.272,10071.26 16.698,1252.369"
|
||||
id="path4119-0-0-7-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-9"
|
||||
transform="translate(-80.17308,14163.046)">
|
||||
<rect
|
||||
id="rect6-0-7-1"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-3"
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
id="tspan4112-9-0-4"
|
||||
sodipodi:role="line">Report CPU</tspan><tspan
|
||||
y="837.77039"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4923-3">and Task</tspan><tspan
|
||||
y="1171.825"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-9">Quiescent States</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-8-1-8"
|
||||
transform="translate(5663.2978,11389.458)">
|
||||
<rect
|
||||
id="rect6-0-7-5-1-1"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-6-2-4"
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-1-2-4">Enqueue Task</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="M 9827.612,12141.988 8575.243,12125.29"
|
||||
id="path4119-8-7-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 7106.0965,12818.962 16.6983,1252.369"
|
||||
id="path4119-0-0-7-7-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-9-2"
|
||||
transform="translate(5663.2978,14098.088)">
|
||||
<rect
|
||||
id="rect6-0-7-1-8"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-3-4"
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4923-3-2">Report CPU</tspan><tspan
|
||||
y="837.77039"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-9-9">Quiescent</tspan><tspan
|
||||
y="1171.825"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan5239">State</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654562, 80.17309124;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="M 5733.305,14095.542 2761.014,12809.774"
|
||||
id="path4119-0-0-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654107, 80.17308214;stroke-dashoffset:0"
|
||||
d="m 1353.3524,10079.499 9701.6916,0 100.189,-16.698"
|
||||
id="path5265"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 32 KiB |
@ -0,0 +1,830 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:39:46 2015 -->
|
||||
|
||||
<!-- Magnification: 3.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="952.6817"
|
||||
height="1425.6191"
|
||||
viewBox="-66 -66 12729.905 19049.38"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="ExpSchedFlow.svg">
|
||||
<metadata
|
||||
id="metadata94">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs92">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4146"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3852"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend-9"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3852-7"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-6"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-16"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-8"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-160"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-5"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-78"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-66"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-8"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-56"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-19"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-89"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-85"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-3"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-73"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-55"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-5"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-88"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-198"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-2"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-22"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker5072"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5074"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-87"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-63"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-26"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4146-51"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-58"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4146-61"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1090"
|
||||
inkscape:window-height="1148"
|
||||
id="namedview90"
|
||||
showgrid="true"
|
||||
inkscape:zoom="0.69092787"
|
||||
inkscape:cx="476.34085"
|
||||
inkscape:cy="712.80957"
|
||||
inkscape:window-x="770"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4"
|
||||
inkscape:snap-grids="false"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5"
|
||||
fit-margin-left="5" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4"
|
||||
transform="translate(23.312814,523.41265)">
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11475 2250 - 11475 3465-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11475 5625 - 11475 6840-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 7875 225 - 10665 225-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9675 675 - 7785 675-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9675 4725 - 10665 4725-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9225 5175 - 10665 5175-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 8775 11475 - 10665 11475-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11475 9000 - 11475 10215-->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<g
|
||||
id="g4104"
|
||||
transform="translate(-1068.9745,0)">
|
||||
<rect
|
||||
transform="matrix(-0.70710678,0.70710678,-0.70710678,-0.70710678,0,0)"
|
||||
y="-7383.8755"
|
||||
x="-6124.8989"
|
||||
height="1966.2251"
|
||||
width="1953.6969"
|
||||
id="rect3032-1-0"
|
||||
style="fill:#96ff96;fill-opacity:1;stroke:#000000;stroke-width:45.00382233;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4098"
|
||||
y="818.40338"
|
||||
x="8168.2671"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="818.40338"
|
||||
x="8168.2671"
|
||||
id="tspan4100"
|
||||
sodipodi:role="line">Idle or</tspan><tspan
|
||||
id="tspan4102"
|
||||
y="1152.4579"
|
||||
x="8168.2671"
|
||||
sodipodi:role="line">offline?</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4114"
|
||||
transform="translate(0,147.96969)">
|
||||
<rect
|
||||
id="rect6"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1475.6636"
|
||||
width="4401.7612"
|
||||
y="0"
|
||||
x="0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110"
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
id="tspan4112"
|
||||
sodipodi:role="line">CPU N Start</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="M 4432.5052,897.4924 5684.8749,880.79414"
|
||||
id="path4119"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="M 8503.0006,874.12161 9755.3703,857.42334"
|
||||
id="path4119-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="8617.0977"
|
||||
y="705.50983"
|
||||
id="text4593"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4595"
|
||||
x="8617.0977"
|
||||
y="705.50983">Y</tspan></text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9"
|
||||
transform="translate(9722.4732,131.27105)">
|
||||
<rect
|
||||
id="rect6-0"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="0"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5"
|
||||
y="835.11212"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="835.11212"
|
||||
x="1460.1007"
|
||||
id="tspan4112-9"
|
||||
sodipodi:role="line">Done</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-5"
|
||||
transform="translate(0,3705.3456)">
|
||||
<rect
|
||||
id="rect6-1"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1475.6636"
|
||||
width="4401.7612"
|
||||
y="0"
|
||||
x="0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-9"
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
sodipodi:role="line"
|
||||
id="tspan4776">Send IPI to CPU N</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="M 7102.5627,2263.5171 4430.8404,3682.8694"
|
||||
id="path4119-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4104-1"
|
||||
transform="translate(-1065.3349,6403.5782)">
|
||||
<rect
|
||||
transform="matrix(-0.70710678,0.70710678,-0.70710678,-0.70710678,0,0)"
|
||||
y="-7383.8755"
|
||||
x="-6124.8989"
|
||||
height="1966.2251"
|
||||
width="1953.6969"
|
||||
id="rect3032-1-0-6"
|
||||
style="fill:#96ff96;fill-opacity:1;stroke:#000000;stroke-width:45.00382233;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4098-3"
|
||||
y="985.4306"
|
||||
x="8168.2671"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="985.4306"
|
||||
x="8168.2671"
|
||||
sodipodi:role="line"
|
||||
id="tspan3109">CPU idle?</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:267.24362183px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="6463.0864"
|
||||
y="2285.6765"
|
||||
id="text4593-0"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4595-6"
|
||||
x="6463.0864"
|
||||
y="2285.6765">N</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654108, 80.17308215;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 2189.1897,5219.361 16.6983,1252.3697"
|
||||
id="path4119-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-5-2"
|
||||
transform="translate(0,6551.5479)">
|
||||
<rect
|
||||
id="rect6-1-7"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1475.6636"
|
||||
width="4401.7612"
|
||||
y="0"
|
||||
x="0" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-9-5"
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="835.11212"
|
||||
x="2206.4917"
|
||||
sodipodi:role="line"
|
||||
id="tspan4776-5">IPI Handler</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="m 4432.5052,7297.9678 1252.3697,-16.6982"
|
||||
id="path4119-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
|
||||
d="m 8503.0013,7278.6595 1252.369,-16.6982"
|
||||
id="path4119-8-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:267.24362183px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="8617.0977"
|
||||
y="7110.0186"
|
||||
id="text4593-4"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4595-0"
|
||||
x="8617.0977"
|
||||
y="7110.0186">Y</tspan></text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3"
|
||||
transform="translate(9722.4732,6535.809)">
|
||||
<rect
|
||||
id="rect6-0-7"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7"
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
id="tspan4112-9-0"
|
||||
sodipodi:role="line">Report CPU</tspan><tspan
|
||||
y="837.77039"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4923">Quiescent</tspan><tspan
|
||||
y="1171.825"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925">State</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654335, 80.17308669;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 7102.5627,11478.337 16.6983,1252.35"
|
||||
id="path4119-0-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:267.24362183px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="6797.0522"
|
||||
y="9018.6807"
|
||||
id="text4593-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4595-2"
|
||||
x="6797.0522"
|
||||
y="9018.6807">N</tspan></text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-8"
|
||||
transform="translate(-80.17308,14133.68)">
|
||||
<rect
|
||||
id="rect6-0-7-5"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-6"
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-1">Context Switch</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654562, 80.17309124;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 1362.6256,12823.832 16.6983,1252.369"
|
||||
id="path4119-0-0-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 1362.6256,15636.491 16.6983,1252.369"
|
||||
id="path4119-0-0-7-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-8-1"
|
||||
transform="translate(9722.4732,14142.03)">
|
||||
<rect
|
||||
id="rect6-0-7-5-1"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-6-2"
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="841.88086"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-1-2">CPU Offline</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654789, 80.17309578;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 11165.272,12823.832 16.698,1252.369"
|
||||
id="path4119-0-0-7-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-9"
|
||||
transform="translate(-80.17308,16915.618)">
|
||||
<rect
|
||||
id="rect6-0-7-1"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-3"
|
||||
y="505.47754"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="505.47754"
|
||||
x="1460.1007"
|
||||
id="tspan4112-9-0-4"
|
||||
sodipodi:role="line">Report CPU</tspan><tspan
|
||||
y="839.53204"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-9">Quiescent</tspan><tspan
|
||||
y="1173.5865"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan3168">State</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 11165.272,15571.534 16.698,1252.369"
|
||||
id="path4119-0-0-7-7-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-9-2"
|
||||
transform="translate(9722.4732,16850.66)">
|
||||
<rect
|
||||
id="rect6-0-7-1-8"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-3-4"
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="503.71591"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4923-3-2">Report CPU</tspan><tspan
|
||||
y="837.77039"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-9-9">Quiescent</tspan><tspan
|
||||
y="1171.825"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan5239">State</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:40.08654107, 80.17308214;stroke-dashoffset:0"
|
||||
d="m 1353.3524,12832.071 9701.6916,0 100.189,-16.698"
|
||||
id="path5265"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:40.08654022;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-end:url(#Arrow2Lend)"
|
||||
d="m 7112.6465,8669.1867 16.6983,1252.369"
|
||||
id="path4119-0-0-7-7-5-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4114-9-3-8-1-8-3"
|
||||
transform="translate(5663.1399,9972.3627)">
|
||||
<rect
|
||||
id="rect6-0-7-5-1-1-9"
|
||||
style="fill:#87cfff;stroke:#000000;stroke-width:45.00382233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
rx="0"
|
||||
height="1425.5687"
|
||||
width="2748.6331"
|
||||
y="29.467337"
|
||||
x="80.17308" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4110-5-7-6-2-4-0"
|
||||
y="670.74316"
|
||||
x="1460.1007"
|
||||
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="670.74316"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan4925-1-2-4-5">Request</tspan><tspan
|
||||
y="1004.7976"
|
||||
x="1460.1007"
|
||||
sodipodi:role="line"
|
||||
id="tspan3100">context switch</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 32 KiB |
@ -0,0 +1,521 @@
|
||||
=================================================
|
||||
A Tour Through TREE_RCU's Expedited Grace Periods
|
||||
=================================================
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document describes RCU's expedited grace periods.
|
||||
Unlike RCU's normal grace periods, which accept long latencies to attain
|
||||
high efficiency and minimal disturbance, expedited grace periods accept
|
||||
lower efficiency and significant disturbance to attain shorter latencies.
|
||||
|
||||
There are two flavors of RCU (RCU-preempt and RCU-sched), with an earlier
|
||||
third RCU-bh flavor having been implemented in terms of the other two.
|
||||
Each of the two implementations is covered in its own section.
|
||||
|
||||
Expedited Grace Period Design
|
||||
=============================
|
||||
|
||||
The expedited RCU grace periods cannot be accused of being subtle,
|
||||
given that they for all intents and purposes hammer every CPU that
|
||||
has not yet provided a quiescent state for the current expedited
|
||||
grace period.
|
||||
The one saving grace is that the hammer has grown a bit smaller
|
||||
over time: The old call to ``try_stop_cpus()`` has been
|
||||
replaced with a set of calls to ``smp_call_function_single()``,
|
||||
each of which results in an IPI to the target CPU.
|
||||
The corresponding handler function checks the CPU's state, motivating
|
||||
a faster quiescent state where possible, and triggering a report
|
||||
of that quiescent state.
|
||||
As always for RCU, once everything has spent some time in a quiescent
|
||||
state, the expedited grace period has completed.
|
||||
|
||||
The details of the ``smp_call_function_single()`` handler's
|
||||
operation depend on the RCU flavor, as described in the following
|
||||
sections.
|
||||
|
||||
RCU-preempt Expedited Grace Periods
|
||||
===================================
|
||||
|
||||
``CONFIG_PREEMPTION=y`` kernels implement RCU-preempt.
|
||||
The overall flow of the handling of a given CPU by an RCU-preempt
|
||||
expedited grace period is shown in the following diagram:
|
||||
|
||||
.. kernel-figure:: ExpRCUFlow.svg
|
||||
|
||||
The solid arrows denote direct action, for example, a function call.
|
||||
The dotted arrows denote indirect action, for example, an IPI
|
||||
or a state that is reached after some time.
|
||||
|
||||
If a given CPU is offline or idle, ``synchronize_rcu_expedited()``
|
||||
will ignore it because idle and offline CPUs are already residing
|
||||
in quiescent states.
|
||||
Otherwise, the expedited grace period will use
|
||||
``smp_call_function_single()`` to send the CPU an IPI, which
|
||||
is handled by ``rcu_exp_handler()``.
|
||||
|
||||
However, because this is preemptible RCU, ``rcu_exp_handler()``
|
||||
can check to see if the CPU is currently running in an RCU read-side
|
||||
critical section.
|
||||
If not, the handler can immediately report a quiescent state.
|
||||
Otherwise, it sets flags so that the outermost ``rcu_read_unlock()``
|
||||
invocation will provide the needed quiescent-state report.
|
||||
This flag-setting avoids the previous forced preemption of all
|
||||
CPUs that might have RCU read-side critical sections.
|
||||
In addition, this flag-setting is done so as to avoid increasing
|
||||
the overhead of the common-case fastpath through the scheduler.
|
||||
|
||||
Again because this is preemptible RCU, an RCU read-side critical section
|
||||
can be preempted.
|
||||
When that happens, RCU will enqueue the task, which will the continue to
|
||||
block the current expedited grace period until it resumes and finds its
|
||||
outermost ``rcu_read_unlock()``.
|
||||
The CPU will report a quiescent state just after enqueuing the task because
|
||||
the CPU is no longer blocking the grace period.
|
||||
It is instead the preempted task doing the blocking.
|
||||
The list of blocked tasks is managed by ``rcu_preempt_ctxt_queue()``,
|
||||
which is called from ``rcu_preempt_note_context_switch()``, which
|
||||
in turn is called from ``rcu_note_context_switch()``, which in
|
||||
turn is called from the scheduler.
|
||||
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Why not just have the expedited grace period check the state of all |
|
||||
| the CPUs? After all, that would avoid all those real-time-unfriendly |
|
||||
| IPIs. |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Because we want the RCU read-side critical sections to run fast, |
|
||||
| which means no memory barriers. Therefore, it is not possible to |
|
||||
| safely check the state from some other CPU. And even if it was |
|
||||
| possible to safely check the state, it would still be necessary to |
|
||||
| IPI the CPU to safely interact with the upcoming |
|
||||
| ``rcu_read_unlock()`` invocation, which means that the remote state |
|
||||
| testing would not help the worst-case latency that real-time |
|
||||
| applications care about. |
|
||||
| |
|
||||
| One way to prevent your real-time application from getting hit with |
|
||||
| these IPIs is to build your kernel with ``CONFIG_NO_HZ_FULL=y``. RCU |
|
||||
| would then perceive the CPU running your application as being idle, |
|
||||
| and it would be able to safely detect that state without needing to |
|
||||
| IPI the CPU. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
Please note that this is just the overall flow: Additional complications
|
||||
can arise due to races with CPUs going idle or offline, among other
|
||||
things.
|
||||
|
||||
RCU-sched Expedited Grace Periods
|
||||
---------------------------------
|
||||
|
||||
``CONFIG_PREEMPTION=n`` kernels implement RCU-sched. The overall flow of
|
||||
the handling of a given CPU by an RCU-sched expedited grace period is
|
||||
shown in the following diagram:
|
||||
|
||||
.. kernel-figure:: ExpSchedFlow.svg
|
||||
|
||||
As with RCU-preempt, RCU-sched's ``synchronize_rcu_expedited()`` ignores
|
||||
offline and idle CPUs, again because they are in remotely detectable
|
||||
quiescent states. However, because the ``rcu_read_lock_sched()`` and
|
||||
``rcu_read_unlock_sched()`` leave no trace of their invocation, in
|
||||
general it is not possible to tell whether or not the current CPU is in
|
||||
an RCU read-side critical section. The best that RCU-sched's
|
||||
``rcu_exp_handler()`` can do is to check for idle, on the off-chance
|
||||
that the CPU went idle while the IPI was in flight. If the CPU is idle,
|
||||
then ``rcu_exp_handler()`` reports the quiescent state.
|
||||
|
||||
Otherwise, the handler forces a future context switch by setting the
|
||||
NEED_RESCHED flag of the current task's thread flag and the CPU preempt
|
||||
counter. At the time of the context switch, the CPU reports the
|
||||
quiescent state. Should the CPU go offline first, it will report the
|
||||
quiescent state at that time.
|
||||
|
||||
Expedited Grace Period and CPU Hotplug
|
||||
--------------------------------------
|
||||
|
||||
The expedited nature of expedited grace periods require a much tighter
|
||||
interaction with CPU hotplug operations than is required for normal
|
||||
grace periods. In addition, attempting to IPI offline CPUs will result
|
||||
in splats, but failing to IPI online CPUs can result in too-short grace
|
||||
periods. Neither option is acceptable in production kernels.
|
||||
|
||||
The interaction between expedited grace periods and CPU hotplug
|
||||
operations is carried out at several levels:
|
||||
|
||||
#. The number of CPUs that have ever been online is tracked by the
|
||||
``rcu_state`` structure's ``->ncpus`` field. The ``rcu_state``
|
||||
structure's ``->ncpus_snap`` field tracks the number of CPUs that
|
||||
have ever been online at the beginning of an RCU expedited grace
|
||||
period. Note that this number never decreases, at least in the
|
||||
absence of a time machine.
|
||||
#. The identities of the CPUs that have ever been online is tracked by
|
||||
the ``rcu_node`` structure's ``->expmaskinitnext`` field. The
|
||||
``rcu_node`` structure's ``->expmaskinit`` field tracks the
|
||||
identities of the CPUs that were online at least once at the
|
||||
beginning of the most recent RCU expedited grace period. The
|
||||
``rcu_state`` structure's ``->ncpus`` and ``->ncpus_snap`` fields are
|
||||
used to detect when new CPUs have come online for the first time,
|
||||
that is, when the ``rcu_node`` structure's ``->expmaskinitnext``
|
||||
field has changed since the beginning of the last RCU expedited grace
|
||||
period, which triggers an update of each ``rcu_node`` structure's
|
||||
``->expmaskinit`` field from its ``->expmaskinitnext`` field.
|
||||
#. Each ``rcu_node`` structure's ``->expmaskinit`` field is used to
|
||||
initialize that structure's ``->expmask`` at the beginning of each
|
||||
RCU expedited grace period. This means that only those CPUs that have
|
||||
been online at least once will be considered for a given grace
|
||||
period.
|
||||
#. Any CPU that goes offline will clear its bit in its leaf ``rcu_node``
|
||||
structure's ``->qsmaskinitnext`` field, so any CPU with that bit
|
||||
clear can safely be ignored. However, it is possible for a CPU coming
|
||||
online or going offline to have this bit set for some time while
|
||||
``cpu_online`` returns ``false``.
|
||||
#. For each non-idle CPU that RCU believes is currently online, the
|
||||
grace period invokes ``smp_call_function_single()``. If this
|
||||
succeeds, the CPU was fully online. Failure indicates that the CPU is
|
||||
in the process of coming online or going offline, in which case it is
|
||||
necessary to wait for a short time period and try again. The purpose
|
||||
of this wait (or series of waits, as the case may be) is to permit a
|
||||
concurrent CPU-hotplug operation to complete.
|
||||
#. In the case of RCU-sched, one of the last acts of an outgoing CPU is
|
||||
to invoke ``rcu_report_dead()``, which reports a quiescent state for
|
||||
that CPU. However, this is likely paranoia-induced redundancy.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Why all the dancing around with multiple counters and masks tracking |
|
||||
| CPUs that were once online? Why not just have a single set of masks |
|
||||
| tracking the currently online CPUs and be done with it? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Maintaining single set of masks tracking the online CPUs *sounds* |
|
||||
| easier, at least until you try working out all the race conditions |
|
||||
| between grace-period initialization and CPU-hotplug operations. For |
|
||||
| example, suppose initialization is progressing down the tree while a |
|
||||
| CPU-offline operation is progressing up the tree. This situation can |
|
||||
| result in bits set at the top of the tree that have no counterparts |
|
||||
| at the bottom of the tree. Those bits will never be cleared, which |
|
||||
| will result in grace-period hangs. In short, that way lies madness, |
|
||||
| to say nothing of a great many bugs, hangs, and deadlocks. |
|
||||
| In contrast, the current multi-mask multi-counter scheme ensures that |
|
||||
| grace-period initialization will always see consistent masks up and |
|
||||
| down the tree, which brings significant simplifications over the |
|
||||
| single-mask method. |
|
||||
| |
|
||||
| This is an instance of `deferring work in order to avoid |
|
||||
| synchronization <http://www.cs.columbia.edu/~library/TR-repository/re |
|
||||
| ports/reports-1992/cucs-039-92.ps.gz>`__. |
|
||||
| Lazily recording CPU-hotplug events at the beginning of the next |
|
||||
| grace period greatly simplifies maintenance of the CPU-tracking |
|
||||
| bitmasks in the ``rcu_node`` tree. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
Expedited Grace Period Refinements
|
||||
----------------------------------
|
||||
|
||||
Idle-CPU Checks
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Each expedited grace period checks for idle CPUs when initially forming
|
||||
the mask of CPUs to be IPIed and again just before IPIing a CPU (both
|
||||
checks are carried out by ``sync_rcu_exp_select_cpus()``). If the CPU is
|
||||
idle at any time between those two times, the CPU will not be IPIed.
|
||||
Instead, the task pushing the grace period forward will include the idle
|
||||
CPUs in the mask passed to ``rcu_report_exp_cpu_mult()``.
|
||||
|
||||
For RCU-sched, there is an additional check: If the IPI has interrupted
|
||||
the idle loop, then ``rcu_exp_handler()`` invokes
|
||||
``rcu_report_exp_rdp()`` to report the corresponding quiescent state.
|
||||
|
||||
For RCU-preempt, there is no specific check for idle in the IPI handler
|
||||
(``rcu_exp_handler()``), but because RCU read-side critical sections are
|
||||
not permitted within the idle loop, if ``rcu_exp_handler()`` sees that
|
||||
the CPU is within RCU read-side critical section, the CPU cannot
|
||||
possibly be idle. Otherwise, ``rcu_exp_handler()`` invokes
|
||||
``rcu_report_exp_rdp()`` to report the corresponding quiescent state,
|
||||
regardless of whether or not that quiescent state was due to the CPU
|
||||
being idle.
|
||||
|
||||
In summary, RCU expedited grace periods check for idle when building the
|
||||
bitmask of CPUs that must be IPIed, just before sending each IPI, and
|
||||
(either explicitly or implicitly) within the IPI handler.
|
||||
|
||||
Batching via Sequence Counter
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If each grace-period request was carried out separately, expedited grace
|
||||
periods would have abysmal scalability and problematic high-load
|
||||
characteristics. Because each grace-period operation can serve an
|
||||
unlimited number of updates, it is important to *batch* requests, so
|
||||
that a single expedited grace-period operation will cover all requests
|
||||
in the corresponding batch.
|
||||
|
||||
This batching is controlled by a sequence counter named
|
||||
``->expedited_sequence`` in the ``rcu_state`` structure. This counter
|
||||
has an odd value when there is an expedited grace period in progress and
|
||||
an even value otherwise, so that dividing the counter value by two gives
|
||||
the number of completed grace periods. During any given update request,
|
||||
the counter must transition from even to odd and then back to even, thus
|
||||
indicating that a grace period has elapsed. Therefore, if the initial
|
||||
value of the counter is ``s``, the updater must wait until the counter
|
||||
reaches at least the value ``(s+3)&~0x1``. This counter is managed by
|
||||
the following access functions:
|
||||
|
||||
#. ``rcu_exp_gp_seq_start()``, which marks the start of an expedited
|
||||
grace period.
|
||||
#. ``rcu_exp_gp_seq_end()``, which marks the end of an expedited grace
|
||||
period.
|
||||
#. ``rcu_exp_gp_seq_snap()``, which obtains a snapshot of the counter.
|
||||
#. ``rcu_exp_gp_seq_done()``, which returns ``true`` if a full expedited
|
||||
grace period has elapsed since the corresponding call to
|
||||
``rcu_exp_gp_seq_snap()``.
|
||||
|
||||
Again, only one request in a given batch need actually carry out a
|
||||
grace-period operation, which means there must be an efficient way to
|
||||
identify which of many concurrent reqeusts will initiate the grace
|
||||
period, and that there be an efficient way for the remaining requests to
|
||||
wait for that grace period to complete. However, that is the topic of
|
||||
the next section.
|
||||
|
||||
Funnel Locking and Wait/Wakeup
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The natural way to sort out which of a batch of updaters will initiate
|
||||
the expedited grace period is to use the ``rcu_node`` combining tree, as
|
||||
implemented by the ``exp_funnel_lock()`` function. The first updater
|
||||
corresponding to a given grace period arriving at a given ``rcu_node``
|
||||
structure records its desired grace-period sequence number in the
|
||||
``->exp_seq_rq`` field and moves up to the next level in the tree.
|
||||
Otherwise, if the ``->exp_seq_rq`` field already contains the sequence
|
||||
number for the desired grace period or some later one, the updater
|
||||
blocks on one of four wait queues in the ``->exp_wq[]`` array, using the
|
||||
second-from-bottom and third-from bottom bits as an index. An
|
||||
``->exp_lock`` field in the ``rcu_node`` structure synchronizes access
|
||||
to these fields.
|
||||
|
||||
An empty ``rcu_node`` tree is shown in the following diagram, with the
|
||||
white cells representing the ``->exp_seq_rq`` field and the red cells
|
||||
representing the elements of the ``->exp_wq[]`` array.
|
||||
|
||||
.. kernel-figure:: Funnel0.svg
|
||||
|
||||
The next diagram shows the situation after the arrival of Task A and
|
||||
Task B at the leftmost and rightmost leaf ``rcu_node`` structures,
|
||||
respectively. The current value of the ``rcu_state`` structure's
|
||||
``->expedited_sequence`` field is zero, so adding three and clearing the
|
||||
bottom bit results in the value two, which both tasks record in the
|
||||
``->exp_seq_rq`` field of their respective ``rcu_node`` structures:
|
||||
|
||||
.. kernel-figure:: Funnel1.svg
|
||||
|
||||
Each of Tasks A and B will move up to the root ``rcu_node`` structure.
|
||||
Suppose that Task A wins, recording its desired grace-period sequence
|
||||
number and resulting in the state shown below:
|
||||
|
||||
.. kernel-figure:: Funnel2.svg
|
||||
|
||||
Task A now advances to initiate a new grace period, while Task B moves
|
||||
up to the root ``rcu_node`` structure, and, seeing that its desired
|
||||
sequence number is already recorded, blocks on ``->exp_wq[1]``.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Why ``->exp_wq[1]``? Given that the value of these tasks' desired |
|
||||
| sequence number is two, so shouldn't they instead block on |
|
||||
| ``->exp_wq[2]``? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| No. |
|
||||
| Recall that the bottom bit of the desired sequence number indicates |
|
||||
| whether or not a grace period is currently in progress. It is |
|
||||
| therefore necessary to shift the sequence number right one bit |
|
||||
| position to obtain the number of the grace period. This results in |
|
||||
| ``->exp_wq[1]``. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
If Tasks C and D also arrive at this point, they will compute the same
|
||||
desired grace-period sequence number, and see that both leaf
|
||||
``rcu_node`` structures already have that value recorded. They will
|
||||
therefore block on their respective ``rcu_node`` structures'
|
||||
``->exp_wq[1]`` fields, as shown below:
|
||||
|
||||
.. kernel-figure:: Funnel3.svg
|
||||
|
||||
Task A now acquires the ``rcu_state`` structure's ``->exp_mutex`` and
|
||||
initiates the grace period, which increments ``->expedited_sequence``.
|
||||
Therefore, if Tasks E and F arrive, they will compute a desired sequence
|
||||
number of 4 and will record this value as shown below:
|
||||
|
||||
.. kernel-figure:: Funnel4.svg
|
||||
|
||||
Tasks E and F will propagate up the ``rcu_node`` combining tree, with
|
||||
Task F blocking on the root ``rcu_node`` structure and Task E wait for
|
||||
Task A to finish so that it can start the next grace period. The
|
||||
resulting state is as shown below:
|
||||
|
||||
.. kernel-figure:: Funnel5.svg
|
||||
|
||||
Once the grace period completes, Task A starts waking up the tasks
|
||||
waiting for this grace period to complete, increments the
|
||||
``->expedited_sequence``, acquires the ``->exp_wake_mutex`` and then
|
||||
releases the ``->exp_mutex``. This results in the following state:
|
||||
|
||||
.. kernel-figure:: Funnel6.svg
|
||||
|
||||
Task E can then acquire ``->exp_mutex`` and increment
|
||||
``->expedited_sequence`` to the value three. If new tasks G and H arrive
|
||||
and moves up the combining tree at the same time, the state will be as
|
||||
follows:
|
||||
|
||||
.. kernel-figure:: Funnel7.svg
|
||||
|
||||
Note that three of the root ``rcu_node`` structure's waitqueues are now
|
||||
occupied. However, at some point, Task A will wake up the tasks blocked
|
||||
on the ``->exp_wq`` waitqueues, resulting in the following state:
|
||||
|
||||
.. kernel-figure:: Funnel8.svg
|
||||
|
||||
Execution will continue with Tasks E and H completing their grace
|
||||
periods and carrying out their wakeups.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| What happens if Task A takes so long to do its wakeups that Task E's |
|
||||
| grace period completes? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Then Task E will block on the ``->exp_wake_mutex``, which will also |
|
||||
| prevent it from releasing ``->exp_mutex``, which in turn will prevent |
|
||||
| the next grace period from starting. This last is important in |
|
||||
| preventing overflow of the ``->exp_wq[]`` array. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
Use of Workqueues
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
In earlier implementations, the task requesting the expedited grace
|
||||
period also drove it to completion. This straightforward approach had
|
||||
the disadvantage of needing to account for POSIX signals sent to user
|
||||
tasks, so more recent implemementations use the Linux kernel's
|
||||
`workqueues <https://www.kernel.org/doc/Documentation/core-api/workqueue.rst>`__.
|
||||
|
||||
The requesting task still does counter snapshotting and funnel-lock
|
||||
processing, but the task reaching the top of the funnel lock does a
|
||||
``schedule_work()`` (from ``_synchronize_rcu_expedited()`` so that a
|
||||
workqueue kthread does the actual grace-period processing. Because
|
||||
workqueue kthreads do not accept POSIX signals, grace-period-wait
|
||||
processing need not allow for POSIX signals. In addition, this approach
|
||||
allows wakeups for the previous expedited grace period to be overlapped
|
||||
with processing for the next expedited grace period. Because there are
|
||||
only four sets of waitqueues, it is necessary to ensure that the
|
||||
previous grace period's wakeups complete before the next grace period's
|
||||
wakeups start. This is handled by having the ``->exp_mutex`` guard
|
||||
expedited grace-period processing and the ``->exp_wake_mutex`` guard
|
||||
wakeups. The key point is that the ``->exp_mutex`` is not released until
|
||||
the first wakeup is complete, which means that the ``->exp_wake_mutex``
|
||||
has already been acquired at that point. This approach ensures that the
|
||||
previous grace period's wakeups can be carried out while the current
|
||||
grace period is in process, but that these wakeups will complete before
|
||||
the next grace period starts. This means that only three waitqueues are
|
||||
required, guaranteeing that the four that are provided are sufficient.
|
||||
|
||||
Stall Warnings
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Expediting grace periods does nothing to speed things up when RCU
|
||||
readers take too long, and therefore expedited grace periods check for
|
||||
stalls just as normal grace periods do.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| But why not just let the normal grace-period machinery detect the |
|
||||
| stalls, given that a given reader must block both normal and |
|
||||
| expedited grace periods? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Because it is quite possible that at a given time there is no normal |
|
||||
| grace period in progress, in which case the normal grace period |
|
||||
| cannot emit a stall warning. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
The ``synchronize_sched_expedited_wait()`` function loops waiting for
|
||||
the expedited grace period to end, but with a timeout set to the current
|
||||
RCU CPU stall-warning time. If this time is exceeded, any CPUs or
|
||||
``rcu_node`` structures blocking the current grace period are printed.
|
||||
Each stall warning results in another pass through the loop, but the
|
||||
second and subsequent passes use longer stall times.
|
||||
|
||||
Mid-boot operation
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The use of workqueues has the advantage that the expedited grace-period
|
||||
code need not worry about POSIX signals. Unfortunately, it has the
|
||||
corresponding disadvantage that workqueues cannot be used until they are
|
||||
initialized, which does not happen until some time after the scheduler
|
||||
spawns the first task. Given that there are parts of the kernel that
|
||||
really do want to execute grace periods during this mid-boot “dead
|
||||
zone”, expedited grace periods must do something else during thie time.
|
||||
|
||||
What they do is to fall back to the old practice of requiring that the
|
||||
requesting task drive the expedited grace period, as was the case before
|
||||
the use of workqueues. However, the requesting task is only required to
|
||||
drive the grace period during the mid-boot dead zone. Before mid-boot, a
|
||||
synchronous grace period is a no-op. Some time after mid-boot,
|
||||
workqueues are used.
|
||||
|
||||
Non-expedited non-SRCU synchronous grace periods must also operate
|
||||
normally during mid-boot. This is handled by causing non-expedited grace
|
||||
periods to take the expedited code path during mid-boot.
|
||||
|
||||
The current code assumes that there are no POSIX signals during the
|
||||
mid-boot dead zone. However, if an overwhelming need for POSIX signals
|
||||
somehow arises, appropriate adjustments can be made to the expedited
|
||||
stall-warning code. One such adjustment would reinstate the
|
||||
pre-workqueue stall-warning checks, but only during the mid-boot dead
|
||||
zone.
|
||||
|
||||
With this refinement, synchronous grace periods can now be used from
|
||||
task context pretty much any time during the life of the kernel. That
|
||||
is, aside from some points in the suspend, hibernate, or shutdown code
|
||||
path.
|
||||
|
||||
Summary
|
||||
~~~~~~~
|
||||
|
||||
Expedited grace periods use a sequence-number approach to promote
|
||||
batching, so that a single grace-period operation can serve numerous
|
||||
requests. A funnel lock is used to efficiently identify the one task out
|
||||
of a concurrent group that will request the grace period. All members of
|
||||
the group will block on waitqueues provided in the ``rcu_node``
|
||||
structure. The actual grace-period processing is carried out by a
|
||||
workqueue.
|
||||
|
||||
CPU-hotplug operations are noted lazily in order to prevent the need for
|
||||
tight synchronization between expedited grace periods and CPU-hotplug
|
||||
operations. The dyntick-idle counters are used to avoid sending IPIs to
|
||||
idle CPUs, at least in the common case. RCU-preempt and RCU-sched use
|
||||
different IPI handlers and different code to respond to the state
|
||||
changes carried out by those handlers, but otherwise use common code.
|
||||
|
||||
Quiescent states are tracked using the ``rcu_node`` tree, and once all
|
||||
necessary quiescent states have been reported, all tasks waiting on this
|
||||
expedited grace period are awakened. A pair of mutexes are used to allow
|
||||
one grace period's wakeups to proceed concurrently with the next grace
|
||||
period's processing.
|
||||
|
||||
This combination of mechanisms allows expedited grace periods to run
|
||||
reasonably efficiently. However, for non-time-critical tasks, normal
|
||||
grace periods should be used instead because their longer duration
|
||||
permits much higher degrees of batching, and thus much lower per-request
|
||||
overheads.
|
275
Documentation/RCU/Design/Expedited-Grace-Periods/Funnel0.svg
Normal file
@ -0,0 +1,275 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490.05093"
|
||||
height="125.78741"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Funnel0.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="201.06495"
|
||||
inkscape:cy="-86.548414"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="171"
|
||||
inkscape:window-y="279"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-117.08462,-249.92053)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="362.371"
|
||||
y="262.51819"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="362.371"
|
||||
y="262.51819">->expedited_sequence: 0</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="253.55223"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="297.04141"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="427.509"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="384.01981"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7-5"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="340.53061"
|
||||
y="275.07489" />
|
||||
<g
|
||||
id="g3997"
|
||||
transform="translate(-0.87295532,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.45404"
|
||||
y="360.25174"
|
||||
id="text3013"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015"
|
||||
x="145.45404"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:0</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3997-7"
|
||||
transform="translate(260.06223,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9-3"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1-6"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2-0"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.45404"
|
||||
y="360.25174"
|
||||
id="text3013-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6"
|
||||
x="145.45404"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:0</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
275
Documentation/RCU/Design/Expedited-Grace-Periods/Funnel1.svg
Normal file
@ -0,0 +1,275 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490.05093"
|
||||
height="125.78741"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Funnel1.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="201.06495"
|
||||
inkscape:cy="-86.548414"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g3997-7"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="363"
|
||||
inkscape:window-y="336"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-117.08462,-249.92053)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="362.371"
|
||||
y="262.51819"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="362.371"
|
||||
y="262.51819">->expedited_sequence: 0</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="253.55223"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="297.04141"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="427.509"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="384.01981"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7-5"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="340.53061"
|
||||
y="275.07489" />
|
||||
<g
|
||||
id="g3997"
|
||||
transform="translate(-0.87295532,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
id="text3013"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
style="font-size:10px">A:2</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3997-7"
|
||||
transform="translate(260.06223,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9-3"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1-6"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2-0"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
id="text3013-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
style="font-size:10px">B:2</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
287
Documentation/RCU/Design/Expedited-Grace-Periods/Funnel2.svg
Normal file
@ -0,0 +1,287 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490.05093"
|
||||
height="125.78741"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Funnel2.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="114.01552"
|
||||
inkscape:cy="-86.548414"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g3997-7"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="363"
|
||||
inkscape:window-y="336"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-117.08462,-249.92053)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="362.371"
|
||||
y="262.51819"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="362.371"
|
||||
y="262.51819">->expedited_sequence: 0</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="253.55223"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="297.04141"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="427.509"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="384.01981"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7-5"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="340.53061"
|
||||
y="275.07489" />
|
||||
<g
|
||||
id="g3997"
|
||||
transform="translate(-0.87295532,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
id="text3013"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:2</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3997-7"
|
||||
transform="translate(260.06223,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9-3"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1-6"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2-0"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
id="text3013-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
style="font-size:10px">B:2</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
id="text3013-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-7"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
style="font-size:10px">A:2</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
323
Documentation/RCU/Design/Expedited-Grace-Periods/Funnel3.svg
Normal file
@ -0,0 +1,323 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490.05093"
|
||||
height="125.78741"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Funnel3.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="114.01552"
|
||||
inkscape:cy="-86.548414"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="68"
|
||||
inkscape:window-y="180"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-117.08462,-249.92053)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="362.371"
|
||||
y="262.51819"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="362.371"
|
||||
y="262.51819">->expedited_sequence: 0 GP: A</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="253.55223"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="297.04141"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="427.509"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="384.01981"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7-5"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="340.53061"
|
||||
y="275.07489" />
|
||||
<g
|
||||
id="g3997"
|
||||
transform="translate(-0.87295532,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
id="text3013"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:2</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
id="text3013-3-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
style="font-size:10px">C</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3019"
|
||||
transform="translate(260.06223,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62-9"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9-3"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1-6"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2-0"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
id="text3013-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:2</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
id="text3013-3-3-7"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6-5"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
style="font-size:10px">D</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
id="text3013-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-7"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
style="font-size:10px">:2</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
id="text3013-3-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
style="font-size:10px">B</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
323
Documentation/RCU/Design/Expedited-Grace-Periods/Funnel4.svg
Normal file
@ -0,0 +1,323 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490.05093"
|
||||
height="125.78741"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Funnel4.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="114.01552"
|
||||
inkscape:cy="-86.548414"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="68"
|
||||
inkscape:window-y="180"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-117.08462,-249.92053)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="362.371"
|
||||
y="262.51819"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="362.371"
|
||||
y="262.51819">->expedited_sequence: 1 GP: A</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="253.55223"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="297.04141"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="427.509"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="384.01981"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7-5"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="340.53061"
|
||||
y="275.07489" />
|
||||
<g
|
||||
id="g3997"
|
||||
transform="translate(-0.87295532,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
id="text3013"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
style="font-size:10px">E:4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
id="text3013-3-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
style="font-size:10px">C</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3019"
|
||||
transform="translate(260.06223,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62-9"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9-3"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1-6"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2-0"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
id="text3013-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
style="font-size:10px">F:4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
id="text3013-3-3-7"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6-5"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
style="font-size:10px">D</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
id="text3013-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-7"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
style="font-size:10px">:2</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
id="text3013-3-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
style="font-size:10px">B</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
335
Documentation/RCU/Design/Expedited-Grace-Periods/Funnel5.svg
Normal file
@ -0,0 +1,335 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490.05093"
|
||||
height="125.78741"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Funnel5.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="114.01552"
|
||||
inkscape:cy="-86.548414"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="68"
|
||||
inkscape:window-y="180"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-117.08462,-249.92053)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="362.371"
|
||||
y="262.51819"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="362.371"
|
||||
y="262.51819">->expedited_sequence: 1 GP: A,E</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="253.55223"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="297.04141"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="427.509"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="384.01981"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7-5"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="340.53061"
|
||||
y="275.07489" />
|
||||
<g
|
||||
id="g3997"
|
||||
transform="translate(-0.87295532,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
id="text3013"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
id="text3013-3-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
style="font-size:10px">C</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3019"
|
||||
transform="translate(260.06223,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62-9"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9-3"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1-6"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2-0"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
id="text3013-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
id="text3013-3-3-7"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6-5"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
style="font-size:10px">D</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
id="text3013-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-7"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
style="font-size:10px">:4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
id="text3013-3-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
style="font-size:10px">B</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="405.40396"
|
||||
y="291.88705"
|
||||
id="text3013-3-36-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7-6"
|
||||
x="405.40396"
|
||||
y="291.88705"
|
||||
style="font-size:10px">F</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
335
Documentation/RCU/Design/Expedited-Grace-Periods/Funnel6.svg
Normal file
@ -0,0 +1,335 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490.05093"
|
||||
height="125.78741"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Funnel6.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="114.01552"
|
||||
inkscape:cy="-86.548414"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="68"
|
||||
inkscape:window-y="180"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-117.08462,-249.92053)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="362.371"
|
||||
y="262.51819"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="362.371"
|
||||
y="262.51819">->expedited_sequence: 2 GP: E Wakeup: A</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="253.55223"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="297.04141"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="427.509"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="384.01981"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7-5"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="340.53061"
|
||||
y="275.07489" />
|
||||
<g
|
||||
id="g3997"
|
||||
transform="translate(-0.87295532,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
id="text3013"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
id="text3013-3-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
style="font-size:10px">C</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3019"
|
||||
transform="translate(260.06223,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62-9"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9-3"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1-6"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2-0"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
id="text3013-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
id="text3013-3-3-7"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6-5"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
style="font-size:10px">D</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
id="text3013-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-7"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
style="font-size:10px">:4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
id="text3013-3-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
style="font-size:10px">B</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="405.40396"
|
||||
y="291.88705"
|
||||
id="text3013-3-36-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7-6"
|
||||
x="405.40396"
|
||||
y="291.88705"
|
||||
style="font-size:10px">F</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
347
Documentation/RCU/Design/Expedited-Grace-Periods/Funnel7.svg
Normal file
@ -0,0 +1,347 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490.05093"
|
||||
height="125.78741"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Funnel7.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="114.01552"
|
||||
inkscape:cy="-86.548414"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="68"
|
||||
inkscape:window-y="180"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-117.08462,-249.92053)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="362.371"
|
||||
y="262.51819"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="362.371"
|
||||
y="262.51819">->expedited_sequence: 3 GP: E,H Wakeup: A</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="253.55223"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="297.04141"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101-3-6"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="427.509"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="384.01981"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7-5"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="340.53061"
|
||||
y="275.07489" />
|
||||
<g
|
||||
id="g3997"
|
||||
transform="translate(-0.87295532,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
id="text3013"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
id="text3013-3-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6"
|
||||
x="232.51051"
|
||||
y="360.18094"
|
||||
style="font-size:10px">C</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3019"
|
||||
transform="translate(260.06223,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62-9"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9-3"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1-6"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2-0"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
id="text3013-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:6</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
id="text3013-3-3-7"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-6-5"
|
||||
x="232.31764"
|
||||
y="360.18582"
|
||||
style="font-size:10px">D</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
id="text3013-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-7"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
style="font-size:10px">:6</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
id="text3013-3-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7"
|
||||
x="361.97092"
|
||||
y="291.88705"
|
||||
style="font-size:10px">B</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="405.40396"
|
||||
y="291.88705"
|
||||
id="text3013-3-36-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7-6"
|
||||
x="405.40396"
|
||||
y="291.88705"
|
||||
style="font-size:10px">F</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="449.22031"
|
||||
y="291.88217"
|
||||
id="text3013-3-36-3-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7-6-6"
|
||||
x="449.22031"
|
||||
y="291.88217"
|
||||
style="font-size:10px">G</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
311
Documentation/RCU/Design/Expedited-Grace-Periods/Funnel8.svg
Normal file
@ -0,0 +1,311 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490.05093"
|
||||
height="125.78741"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="Funnel8.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="114.01552"
|
||||
inkscape:cy="-86.548414"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="68"
|
||||
inkscape:window-y="180"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-117.08462,-249.92053)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="362.371"
|
||||
y="262.51819"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="362.371"
|
||||
y="262.51819">->expedited_sequence: 3 GP: E,H</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="253.55223"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="297.04141"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect3101-3-6"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="427.509"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="384.01981"
|
||||
y="275.07489" />
|
||||
<rect
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||
id="rect3101-3-6-7-5"
|
||||
width="43.158947"
|
||||
height="26.33428"
|
||||
x="340.53061"
|
||||
y="275.07489" />
|
||||
<g
|
||||
id="g3997"
|
||||
transform="translate(-0.87295532,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2"
|
||||
style="fill:#ff8282;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
id="text3013"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015"
|
||||
x="146.00092"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:4</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3019"
|
||||
transform="translate(260.06223,0)">
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="123.95757"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-35-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="167.44673"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-62-9"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="297.91437"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-9-3"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="254.42516"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-1-6"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="343.37366"
|
||||
x="210.93593"
|
||||
height="26.33428"
|
||||
width="43.158947"
|
||||
id="rect3101-3-6-7-5-2-0"
|
||||
style="fill:#ff8282;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
id="text3013-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6"
|
||||
x="145.54926"
|
||||
y="360.25174"
|
||||
style="font-size:10px">:6</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
id="text3013-36"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-7"
|
||||
x="275.59558"
|
||||
y="291.95297"
|
||||
style="font-size:10px">:6</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="405.40396"
|
||||
y="291.88705"
|
||||
id="text3013-3-36-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7-6"
|
||||
x="405.40396"
|
||||
y="291.88705"
|
||||
style="font-size:10px">F</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="449.22031"
|
||||
y="291.88217"
|
||||
id="text3013-3-36-3-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3015-6-7-6-6"
|
||||
x="449.22031"
|
||||
y="291.88217"
|
||||
style="font-size:10px">G</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,653 @@
|
||||
======================================================
|
||||
A Tour Through TREE_RCU's Grace-Period Memory Ordering
|
||||
======================================================
|
||||
|
||||
August 8, 2017
|
||||
|
||||
This article was contributed by Paul E. McKenney
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document gives a rough visual overview of how Tree RCU's
|
||||
grace-period memory ordering guarantee is provided.
|
||||
|
||||
What Is Tree RCU's Grace Period Memory Ordering Guarantee?
|
||||
==========================================================
|
||||
|
||||
RCU grace periods provide extremely strong memory-ordering guarantees
|
||||
for non-idle non-offline code.
|
||||
Any code that happens after the end of a given RCU grace period is guaranteed
|
||||
to see the effects of all accesses prior to the beginning of that grace
|
||||
period that are within RCU read-side critical sections.
|
||||
Similarly, any code that happens before the beginning of a given RCU grace
|
||||
period is guaranteed to not see the effects of all accesses following the end
|
||||
of that grace period that are within RCU read-side critical sections.
|
||||
|
||||
Note well that RCU-sched read-side critical sections include any region
|
||||
of code for which preemption is disabled.
|
||||
Given that each individual machine instruction can be thought of as
|
||||
an extremely small region of preemption-disabled code, one can think of
|
||||
``synchronize_rcu()`` as ``smp_mb()`` on steroids.
|
||||
|
||||
RCU updaters use this guarantee by splitting their updates into
|
||||
two phases, one of which is executed before the grace period and
|
||||
the other of which is executed after the grace period.
|
||||
In the most common use case, phase one removes an element from
|
||||
a linked RCU-protected data structure, and phase two frees that element.
|
||||
For this to work, any readers that have witnessed state prior to the
|
||||
phase-one update (in the common case, removal) must not witness state
|
||||
following the phase-two update (in the common case, freeing).
|
||||
|
||||
The RCU implementation provides this guarantee using a network
|
||||
of lock-based critical sections, memory barriers, and per-CPU
|
||||
processing, as is described in the following sections.
|
||||
|
||||
Tree RCU Grace Period Memory Ordering Building Blocks
|
||||
=====================================================
|
||||
|
||||
The workhorse for RCU's grace-period memory ordering is the
|
||||
critical section for the ``rcu_node`` structure's
|
||||
``->lock``. These critical sections use helper functions for lock
|
||||
acquisition, including ``raw_spin_lock_rcu_node()``,
|
||||
``raw_spin_lock_irq_rcu_node()``, and ``raw_spin_lock_irqsave_rcu_node()``.
|
||||
Their lock-release counterparts are ``raw_spin_unlock_rcu_node()``,
|
||||
``raw_spin_unlock_irq_rcu_node()``, and
|
||||
``raw_spin_unlock_irqrestore_rcu_node()``, respectively.
|
||||
For completeness, a ``raw_spin_trylock_rcu_node()`` is also provided.
|
||||
The key point is that the lock-acquisition functions, including
|
||||
``raw_spin_trylock_rcu_node()``, all invoke ``smp_mb__after_unlock_lock()``
|
||||
immediately after successful acquisition of the lock.
|
||||
|
||||
Therefore, for any given ``rcu_node`` structure, any access
|
||||
happening before one of the above lock-release functions will be seen
|
||||
by all CPUs as happening before any access happening after a later
|
||||
one of the above lock-acquisition functions.
|
||||
Furthermore, any access happening before one of the
|
||||
above lock-release function on any given CPU will be seen by all
|
||||
CPUs as happening before any access happening after a later one
|
||||
of the above lock-acquisition functions executing on that same CPU,
|
||||
even if the lock-release and lock-acquisition functions are operating
|
||||
on different ``rcu_node`` structures.
|
||||
Tree RCU uses these two ordering guarantees to form an ordering
|
||||
network among all CPUs that were in any way involved in the grace
|
||||
period, including any CPUs that came online or went offline during
|
||||
the grace period in question.
|
||||
|
||||
The following litmus test exhibits the ordering effects of these
|
||||
lock-acquisition and lock-release functions::
|
||||
|
||||
1 int x, y, z;
|
||||
2
|
||||
3 void task0(void)
|
||||
4 {
|
||||
5 raw_spin_lock_rcu_node(rnp);
|
||||
6 WRITE_ONCE(x, 1);
|
||||
7 r1 = READ_ONCE(y);
|
||||
8 raw_spin_unlock_rcu_node(rnp);
|
||||
9 }
|
||||
10
|
||||
11 void task1(void)
|
||||
12 {
|
||||
13 raw_spin_lock_rcu_node(rnp);
|
||||
14 WRITE_ONCE(y, 1);
|
||||
15 r2 = READ_ONCE(z);
|
||||
16 raw_spin_unlock_rcu_node(rnp);
|
||||
17 }
|
||||
18
|
||||
19 void task2(void)
|
||||
20 {
|
||||
21 WRITE_ONCE(z, 1);
|
||||
22 smp_mb();
|
||||
23 r3 = READ_ONCE(x);
|
||||
24 }
|
||||
25
|
||||
26 WARN_ON(r1 == 0 && r2 == 0 && r3 == 0);
|
||||
|
||||
The ``WARN_ON()`` is evaluated at "the end of time",
|
||||
after all changes have propagated throughout the system.
|
||||
Without the ``smp_mb__after_unlock_lock()`` provided by the
|
||||
acquisition functions, this ``WARN_ON()`` could trigger, for example
|
||||
on PowerPC.
|
||||
The ``smp_mb__after_unlock_lock()`` invocations prevent this
|
||||
``WARN_ON()`` from triggering.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| But the chain of rcu_node-structure lock acquisitions guarantees |
|
||||
| that new readers will see all of the updater's pre-grace-period |
|
||||
| accesses and also guarantees that the updater's post-grace-period |
|
||||
| accesses will see all of the old reader's accesses. So why do we |
|
||||
| need all of those calls to smp_mb__after_unlock_lock()? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Because we must provide ordering for RCU's polling grace-period |
|
||||
| primitives, for example, get_state_synchronize_rcu() and |
|
||||
| poll_state_synchronize_rcu(). Consider this code:: |
|
||||
| |
|
||||
| CPU 0 CPU 1 |
|
||||
| ---- ---- |
|
||||
| WRITE_ONCE(X, 1) WRITE_ONCE(Y, 1) |
|
||||
| g = get_state_synchronize_rcu() smp_mb() |
|
||||
| while (!poll_state_synchronize_rcu(g)) r1 = READ_ONCE(X) |
|
||||
| continue; |
|
||||
| r0 = READ_ONCE(Y) |
|
||||
| |
|
||||
| RCU guarantees that the outcome r0 == 0 && r1 == 0 will not |
|
||||
| happen, even if CPU 1 is in an RCU extended quiescent state |
|
||||
| (idle or offline) and thus won't interact directly with the RCU |
|
||||
| core processing at all. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
This approach must be extended to include idle CPUs, which need
|
||||
RCU's grace-period memory ordering guarantee to extend to any
|
||||
RCU read-side critical sections preceding and following the current
|
||||
idle sojourn.
|
||||
This case is handled by calls to the strongly ordered
|
||||
``atomic_add_return()`` read-modify-write atomic operation that
|
||||
is invoked within ``rcu_dynticks_eqs_enter()`` at idle-entry
|
||||
time and within ``rcu_dynticks_eqs_exit()`` at idle-exit time.
|
||||
The grace-period kthread invokes ``rcu_dynticks_snap()`` and
|
||||
``rcu_dynticks_in_eqs_since()`` (both of which invoke
|
||||
an ``atomic_add_return()`` of zero) to detect idle CPUs.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| But what about CPUs that remain offline for the entire grace period? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Such CPUs will be offline at the beginning of the grace period, so |
|
||||
| the grace period won't expect quiescent states from them. Races |
|
||||
| between grace-period start and CPU-hotplug operations are mediated |
|
||||
| by the CPU's leaf ``rcu_node`` structure's ``->lock`` as described |
|
||||
| above. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
The approach must be extended to handle one final case, that of waking a
|
||||
task blocked in ``synchronize_rcu()``. This task might be affinitied to
|
||||
a CPU that is not yet aware that the grace period has ended, and thus
|
||||
might not yet be subject to the grace period's memory ordering.
|
||||
Therefore, there is an ``smp_mb()`` after the return from
|
||||
``wait_for_completion()`` in the ``synchronize_rcu()`` code path.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| What? Where??? I don't see any ``smp_mb()`` after the return from |
|
||||
| ``wait_for_completion()``!!! |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| That would be because I spotted the need for that ``smp_mb()`` during |
|
||||
| the creation of this documentation, and it is therefore unlikely to |
|
||||
| hit mainline before v4.14. Kudos to Lance Roy, Will Deacon, Peter |
|
||||
| Zijlstra, and Jonathan Cameron for asking questions that sensitized |
|
||||
| me to the rather elaborate sequence of events that demonstrate the |
|
||||
| need for this memory barrier. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
Tree RCU's grace--period memory-ordering guarantees rely most heavily on
|
||||
the ``rcu_node`` structure's ``->lock`` field, so much so that it is
|
||||
necessary to abbreviate this pattern in the diagrams in the next
|
||||
section. For example, consider the ``rcu_prepare_for_idle()`` function
|
||||
shown below, which is one of several functions that enforce ordering of
|
||||
newly arrived RCU callbacks against future grace periods:
|
||||
|
||||
::
|
||||
|
||||
1 static void rcu_prepare_for_idle(void)
|
||||
2 {
|
||||
3 bool needwake;
|
||||
4 struct rcu_data *rdp;
|
||||
5 struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
|
||||
6 struct rcu_node *rnp;
|
||||
7 struct rcu_state *rsp;
|
||||
8 int tne;
|
||||
9
|
||||
10 if (IS_ENABLED(CONFIG_RCU_NOCB_CPU_ALL) ||
|
||||
11 rcu_is_nocb_cpu(smp_processor_id()))
|
||||
12 return;
|
||||
13 tne = READ_ONCE(tick_nohz_active);
|
||||
14 if (tne != rdtp->tick_nohz_enabled_snap) {
|
||||
15 if (rcu_cpu_has_callbacks(NULL))
|
||||
16 invoke_rcu_core();
|
||||
17 rdtp->tick_nohz_enabled_snap = tne;
|
||||
18 return;
|
||||
19 }
|
||||
20 if (!tne)
|
||||
21 return;
|
||||
22 if (rdtp->all_lazy &&
|
||||
23 rdtp->nonlazy_posted != rdtp->nonlazy_posted_snap) {
|
||||
24 rdtp->all_lazy = false;
|
||||
25 rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted;
|
||||
26 invoke_rcu_core();
|
||||
27 return;
|
||||
28 }
|
||||
29 if (rdtp->last_accelerate == jiffies)
|
||||
30 return;
|
||||
31 rdtp->last_accelerate = jiffies;
|
||||
32 for_each_rcu_flavor(rsp) {
|
||||
33 rdp = this_cpu_ptr(rsp->rda);
|
||||
34 if (rcu_segcblist_pend_cbs(&rdp->cblist))
|
||||
35 continue;
|
||||
36 rnp = rdp->mynode;
|
||||
37 raw_spin_lock_rcu_node(rnp);
|
||||
38 needwake = rcu_accelerate_cbs(rsp, rnp, rdp);
|
||||
39 raw_spin_unlock_rcu_node(rnp);
|
||||
40 if (needwake)
|
||||
41 rcu_gp_kthread_wake(rsp);
|
||||
42 }
|
||||
43 }
|
||||
|
||||
But the only part of ``rcu_prepare_for_idle()`` that really matters for
|
||||
this discussion are lines 37–39. We will therefore abbreviate this
|
||||
function as follows:
|
||||
|
||||
.. kernel-figure:: rcu_node-lock.svg
|
||||
|
||||
The box represents the ``rcu_node`` structure's ``->lock`` critical
|
||||
section, with the double line on top representing the additional
|
||||
``smp_mb__after_unlock_lock()``.
|
||||
|
||||
Tree RCU Grace Period Memory Ordering Components
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Tree RCU's grace-period memory-ordering guarantee is provided by a
|
||||
number of RCU components:
|
||||
|
||||
#. `Callback Registry`_
|
||||
#. `Grace-Period Initialization`_
|
||||
#. `Self-Reported Quiescent States`_
|
||||
#. `Dynamic Tick Interface`_
|
||||
#. `CPU-Hotplug Interface`_
|
||||
#. `Forcing Quiescent States`_
|
||||
#. `Grace-Period Cleanup`_
|
||||
#. `Callback Invocation`_
|
||||
|
||||
Each of the following section looks at the corresponding component in
|
||||
detail.
|
||||
|
||||
Callback Registry
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
If RCU's grace-period guarantee is to mean anything at all, any access
|
||||
that happens before a given invocation of ``call_rcu()`` must also
|
||||
happen before the corresponding grace period. The implementation of this
|
||||
portion of RCU's grace period guarantee is shown in the following
|
||||
figure:
|
||||
|
||||
.. kernel-figure:: TreeRCU-callback-registry.svg
|
||||
|
||||
Because ``call_rcu()`` normally acts only on CPU-local state, it
|
||||
provides no ordering guarantees, either for itself or for phase one of
|
||||
the update (which again will usually be removal of an element from an
|
||||
RCU-protected data structure). It simply enqueues the ``rcu_head``
|
||||
structure on a per-CPU list, which cannot become associated with a grace
|
||||
period until a later call to ``rcu_accelerate_cbs()``, as shown in the
|
||||
diagram above.
|
||||
|
||||
One set of code paths shown on the left invokes ``rcu_accelerate_cbs()``
|
||||
via ``note_gp_changes()``, either directly from ``call_rcu()`` (if the
|
||||
current CPU is inundated with queued ``rcu_head`` structures) or more
|
||||
likely from an ``RCU_SOFTIRQ`` handler. Another code path in the middle
|
||||
is taken only in kernels built with ``CONFIG_RCU_FAST_NO_HZ=y``, which
|
||||
invokes ``rcu_accelerate_cbs()`` via ``rcu_prepare_for_idle()``. The
|
||||
final code path on the right is taken only in kernels built with
|
||||
``CONFIG_HOTPLUG_CPU=y``, which invokes ``rcu_accelerate_cbs()`` via
|
||||
``rcu_advance_cbs()``, ``rcu_migrate_callbacks``,
|
||||
``rcutree_migrate_callbacks()``, and ``takedown_cpu()``, which in turn
|
||||
is invoked on a surviving CPU after the outgoing CPU has been completely
|
||||
offlined.
|
||||
|
||||
There are a few other code paths within grace-period processing that
|
||||
opportunistically invoke ``rcu_accelerate_cbs()``. However, either way,
|
||||
all of the CPU's recently queued ``rcu_head`` structures are associated
|
||||
with a future grace-period number under the protection of the CPU's lead
|
||||
``rcu_node`` structure's ``->lock``. In all cases, there is full
|
||||
ordering against any prior critical section for that same ``rcu_node``
|
||||
structure's ``->lock``, and also full ordering against any of the
|
||||
current task's or CPU's prior critical sections for any ``rcu_node``
|
||||
structure's ``->lock``.
|
||||
|
||||
The next section will show how this ordering ensures that any accesses
|
||||
prior to the ``call_rcu()`` (particularly including phase one of the
|
||||
update) happen before the start of the corresponding grace period.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| But what about ``synchronize_rcu()``? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| The ``synchronize_rcu()`` passes ``call_rcu()`` to ``wait_rcu_gp()``, |
|
||||
| which invokes it. So either way, it eventually comes down to |
|
||||
| ``call_rcu()``. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
Grace-Period Initialization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Grace-period initialization is carried out by the grace-period kernel
|
||||
thread, which makes several passes over the ``rcu_node`` tree within the
|
||||
``rcu_gp_init()`` function. This means that showing the full flow of
|
||||
ordering through the grace-period computation will require duplicating
|
||||
this tree. If you find this confusing, please note that the state of the
|
||||
``rcu_node`` changes over time, just like Heraclitus's river. However,
|
||||
to keep the ``rcu_node`` river tractable, the grace-period kernel
|
||||
thread's traversals are presented in multiple parts, starting in this
|
||||
section with the various phases of grace-period initialization.
|
||||
|
||||
The first ordering-related grace-period initialization action is to
|
||||
advance the ``rcu_state`` structure's ``->gp_seq`` grace-period-number
|
||||
counter, as shown below:
|
||||
|
||||
.. kernel-figure:: TreeRCU-gp-init-1.svg
|
||||
|
||||
The actual increment is carried out using ``smp_store_release()``, which
|
||||
helps reject false-positive RCU CPU stall detection. Note that only the
|
||||
root ``rcu_node`` structure is touched.
|
||||
|
||||
The first pass through the ``rcu_node`` tree updates bitmasks based on
|
||||
CPUs having come online or gone offline since the start of the previous
|
||||
grace period. In the common case where the number of online CPUs for
|
||||
this ``rcu_node`` structure has not transitioned to or from zero, this
|
||||
pass will scan only the leaf ``rcu_node`` structures. However, if the
|
||||
number of online CPUs for a given leaf ``rcu_node`` structure has
|
||||
transitioned from zero, ``rcu_init_new_rnp()`` will be invoked for the
|
||||
first incoming CPU. Similarly, if the number of online CPUs for a given
|
||||
leaf ``rcu_node`` structure has transitioned to zero,
|
||||
``rcu_cleanup_dead_rnp()`` will be invoked for the last outgoing CPU.
|
||||
The diagram below shows the path of ordering if the leftmost
|
||||
``rcu_node`` structure onlines its first CPU and if the next
|
||||
``rcu_node`` structure has no online CPUs (or, alternatively if the
|
||||
leftmost ``rcu_node`` structure offlines its last CPU and if the next
|
||||
``rcu_node`` structure has no online CPUs).
|
||||
|
||||
.. kernel-figure:: TreeRCU-gp-init-2.svg
|
||||
|
||||
The final ``rcu_gp_init()`` pass through the ``rcu_node`` tree traverses
|
||||
breadth-first, setting each ``rcu_node`` structure's ``->gp_seq`` field
|
||||
to the newly advanced value from the ``rcu_state`` structure, as shown
|
||||
in the following diagram.
|
||||
|
||||
.. kernel-figure:: TreeRCU-gp-init-3.svg
|
||||
|
||||
This change will also cause each CPU's next call to
|
||||
``__note_gp_changes()`` to notice that a new grace period has started,
|
||||
as described in the next section. But because the grace-period kthread
|
||||
started the grace period at the root (with the advancing of the
|
||||
``rcu_state`` structure's ``->gp_seq`` field) before setting each leaf
|
||||
``rcu_node`` structure's ``->gp_seq`` field, each CPU's observation of
|
||||
the start of the grace period will happen after the actual start of the
|
||||
grace period.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| But what about the CPU that started the grace period? Why wouldn't it |
|
||||
| see the start of the grace period right when it started that grace |
|
||||
| period? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| In some deep philosophical and overly anthromorphized sense, yes, the |
|
||||
| CPU starting the grace period is immediately aware of having done so. |
|
||||
| However, if we instead assume that RCU is not self-aware, then even |
|
||||
| the CPU starting the grace period does not really become aware of the |
|
||||
| start of this grace period until its first call to |
|
||||
| ``__note_gp_changes()``. On the other hand, this CPU potentially gets |
|
||||
| early notification because it invokes ``__note_gp_changes()`` during |
|
||||
| its last ``rcu_gp_init()`` pass through its leaf ``rcu_node`` |
|
||||
| structure. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
Self-Reported Quiescent States
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When all entities that might block the grace period have reported
|
||||
quiescent states (or as described in a later section, had quiescent
|
||||
states reported on their behalf), the grace period can end. Online
|
||||
non-idle CPUs report their own quiescent states, as shown in the
|
||||
following diagram:
|
||||
|
||||
.. kernel-figure:: TreeRCU-qs.svg
|
||||
|
||||
This is for the last CPU to report a quiescent state, which signals the
|
||||
end of the grace period. Earlier quiescent states would push up the
|
||||
``rcu_node`` tree only until they encountered an ``rcu_node`` structure
|
||||
that is waiting for additional quiescent states. However, ordering is
|
||||
nevertheless preserved because some later quiescent state will acquire
|
||||
that ``rcu_node`` structure's ``->lock``.
|
||||
|
||||
Any number of events can lead up to a CPU invoking ``note_gp_changes``
|
||||
(or alternatively, directly invoking ``__note_gp_changes()``), at which
|
||||
point that CPU will notice the start of a new grace period while holding
|
||||
its leaf ``rcu_node`` lock. Therefore, all execution shown in this
|
||||
diagram happens after the start of the grace period. In addition, this
|
||||
CPU will consider any RCU read-side critical section that started before
|
||||
the invocation of ``__note_gp_changes()`` to have started before the
|
||||
grace period, and thus a critical section that the grace period must
|
||||
wait on.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| But a RCU read-side critical section might have started after the |
|
||||
| beginning of the grace period (the advancing of ``->gp_seq`` from |
|
||||
| earlier), so why should the grace period wait on such a critical |
|
||||
| section? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| It is indeed not necessary for the grace period to wait on such a |
|
||||
| critical section. However, it is permissible to wait on it. And it is |
|
||||
| furthermore important to wait on it, as this lazy approach is far |
|
||||
| more scalable than a “big bang” all-at-once grace-period start could |
|
||||
| possibly be. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
If the CPU does a context switch, a quiescent state will be noted by
|
||||
``rcu_note_context_switch()`` on the left. On the other hand, if the CPU
|
||||
takes a scheduler-clock interrupt while executing in usermode, a
|
||||
quiescent state will be noted by ``rcu_sched_clock_irq()`` on the right.
|
||||
Either way, the passage through a quiescent state will be noted in a
|
||||
per-CPU variable.
|
||||
|
||||
The next time an ``RCU_SOFTIRQ`` handler executes on this CPU (for
|
||||
example, after the next scheduler-clock interrupt), ``rcu_core()`` will
|
||||
invoke ``rcu_check_quiescent_state()``, which will notice the recorded
|
||||
quiescent state, and invoke ``rcu_report_qs_rdp()``. If
|
||||
``rcu_report_qs_rdp()`` verifies that the quiescent state really does
|
||||
apply to the current grace period, it invokes ``rcu_report_rnp()`` which
|
||||
traverses up the ``rcu_node`` tree as shown at the bottom of the
|
||||
diagram, clearing bits from each ``rcu_node`` structure's ``->qsmask``
|
||||
field, and propagating up the tree when the result is zero.
|
||||
|
||||
Note that traversal passes upwards out of a given ``rcu_node`` structure
|
||||
only if the current CPU is reporting the last quiescent state for the
|
||||
subtree headed by that ``rcu_node`` structure. A key point is that if a
|
||||
CPU's traversal stops at a given ``rcu_node`` structure, then there will
|
||||
be a later traversal by another CPU (or perhaps the same one) that
|
||||
proceeds upwards from that point, and the ``rcu_node`` ``->lock``
|
||||
guarantees that the first CPU's quiescent state happens before the
|
||||
remainder of the second CPU's traversal. Applying this line of thought
|
||||
repeatedly shows that all CPUs' quiescent states happen before the last
|
||||
CPU traverses through the root ``rcu_node`` structure, the “last CPU”
|
||||
being the one that clears the last bit in the root ``rcu_node``
|
||||
structure's ``->qsmask`` field.
|
||||
|
||||
Dynamic Tick Interface
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Due to energy-efficiency considerations, RCU is forbidden from
|
||||
disturbing idle CPUs. CPUs are therefore required to notify RCU when
|
||||
entering or leaving idle state, which they do via fully ordered
|
||||
value-returning atomic operations on a per-CPU variable. The ordering
|
||||
effects are as shown below:
|
||||
|
||||
.. kernel-figure:: TreeRCU-dyntick.svg
|
||||
|
||||
The RCU grace-period kernel thread samples the per-CPU idleness variable
|
||||
while holding the corresponding CPU's leaf ``rcu_node`` structure's
|
||||
``->lock``. This means that any RCU read-side critical sections that
|
||||
precede the idle period (the oval near the top of the diagram above)
|
||||
will happen before the end of the current grace period. Similarly, the
|
||||
beginning of the current grace period will happen before any RCU
|
||||
read-side critical sections that follow the idle period (the oval near
|
||||
the bottom of the diagram above).
|
||||
|
||||
Plumbing this into the full grace-period execution is described
|
||||
`below <Forcing Quiescent States_>`__.
|
||||
|
||||
CPU-Hotplug Interface
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
RCU is also forbidden from disturbing offline CPUs, which might well be
|
||||
powered off and removed from the system completely. CPUs are therefore
|
||||
required to notify RCU of their comings and goings as part of the
|
||||
corresponding CPU hotplug operations. The ordering effects are shown
|
||||
below:
|
||||
|
||||
.. kernel-figure:: TreeRCU-hotplug.svg
|
||||
|
||||
Because CPU hotplug operations are much less frequent than idle
|
||||
transitions, they are heavier weight, and thus acquire the CPU's leaf
|
||||
``rcu_node`` structure's ``->lock`` and update this structure's
|
||||
``->qsmaskinitnext``. The RCU grace-period kernel thread samples this
|
||||
mask to detect CPUs having gone offline since the beginning of this
|
||||
grace period.
|
||||
|
||||
Plumbing this into the full grace-period execution is described
|
||||
`below <Forcing Quiescent States_>`__.
|
||||
|
||||
Forcing Quiescent States
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As noted above, idle and offline CPUs cannot report their own quiescent
|
||||
states, and therefore the grace-period kernel thread must do the
|
||||
reporting on their behalf. This process is called “forcing quiescent
|
||||
states”, it is repeated every few jiffies, and its ordering effects are
|
||||
shown below:
|
||||
|
||||
.. kernel-figure:: TreeRCU-gp-fqs.svg
|
||||
|
||||
Each pass of quiescent state forcing is guaranteed to traverse the leaf
|
||||
``rcu_node`` structures, and if there are no new quiescent states due to
|
||||
recently idled and/or offlined CPUs, then only the leaves are traversed.
|
||||
However, if there is a newly offlined CPU as illustrated on the left or
|
||||
a newly idled CPU as illustrated on the right, the corresponding
|
||||
quiescent state will be driven up towards the root. As with
|
||||
self-reported quiescent states, the upwards driving stops once it
|
||||
reaches an ``rcu_node`` structure that has quiescent states outstanding
|
||||
from other CPUs.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| The leftmost drive to root stopped before it reached the root |
|
||||
| ``rcu_node`` structure, which means that there are still CPUs |
|
||||
| subordinate to that structure on which the current grace period is |
|
||||
| waiting. Given that, how is it possible that the rightmost drive to |
|
||||
| root ended the grace period? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Good analysis! It is in fact impossible in the absence of bugs in |
|
||||
| RCU. But this diagram is complex enough as it is, so simplicity |
|
||||
| overrode accuracy. You can think of it as poetic license, or you can |
|
||||
| think of it as misdirection that is resolved in the |
|
||||
| `stitched-together diagram <Putting It All Together_>`__. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
Grace-Period Cleanup
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Grace-period cleanup first scans the ``rcu_node`` tree breadth-first
|
||||
advancing all the ``->gp_seq`` fields, then it advances the
|
||||
``rcu_state`` structure's ``->gp_seq`` field. The ordering effects are
|
||||
shown below:
|
||||
|
||||
.. kernel-figure:: TreeRCU-gp-cleanup.svg
|
||||
|
||||
As indicated by the oval at the bottom of the diagram, once grace-period
|
||||
cleanup is complete, the next grace period can begin.
|
||||
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Quick Quiz**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| But when precisely does the grace period end? |
|
||||
+-----------------------------------------------------------------------+
|
||||
| **Answer**: |
|
||||
+-----------------------------------------------------------------------+
|
||||
| There is no useful single point at which the grace period can be said |
|
||||
| to end. The earliest reasonable candidate is as soon as the last CPU |
|
||||
| has reported its quiescent state, but it may be some milliseconds |
|
||||
| before RCU becomes aware of this. The latest reasonable candidate is |
|
||||
| once the ``rcu_state`` structure's ``->gp_seq`` field has been |
|
||||
| updated, but it is quite possible that some CPUs have already |
|
||||
| completed phase two of their updates by that time. In short, if you |
|
||||
| are going to work with RCU, you need to learn to embrace uncertainty. |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
Callback Invocation
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Once a given CPU's leaf ``rcu_node`` structure's ``->gp_seq`` field has
|
||||
been updated, that CPU can begin invoking its RCU callbacks that were
|
||||
waiting for this grace period to end. These callbacks are identified by
|
||||
``rcu_advance_cbs()``, which is usually invoked by
|
||||
``__note_gp_changes()``. As shown in the diagram below, this invocation
|
||||
can be triggered by the scheduling-clock interrupt
|
||||
(``rcu_sched_clock_irq()`` on the left) or by idle entry
|
||||
(``rcu_cleanup_after_idle()`` on the right, but only for kernels build
|
||||
with ``CONFIG_RCU_FAST_NO_HZ=y``). Either way, ``RCU_SOFTIRQ`` is
|
||||
raised, which results in ``rcu_do_batch()`` invoking the callbacks,
|
||||
which in turn allows those callbacks to carry out (either directly or
|
||||
indirectly via wakeup) the needed phase-two processing for each update.
|
||||
|
||||
.. kernel-figure:: TreeRCU-callback-invocation.svg
|
||||
|
||||
Please note that callback invocation can also be prompted by any number
|
||||
of corner-case code paths, for example, when a CPU notes that it has
|
||||
excessive numbers of callbacks queued. In all cases, the CPU acquires
|
||||
its leaf ``rcu_node`` structure's ``->lock`` before invoking callbacks,
|
||||
which preserves the required ordering against the newly completed grace
|
||||
period.
|
||||
|
||||
However, if the callback function communicates to other CPUs, for
|
||||
example, doing a wakeup, then it is that function's responsibility to
|
||||
maintain ordering. For example, if the callback function wakes up a task
|
||||
that runs on some other CPU, proper ordering must in place in both the
|
||||
callback function and the task being awakened. To see why this is
|
||||
important, consider the top half of the `grace-period
|
||||
cleanup`_ diagram. The callback might be
|
||||
running on a CPU corresponding to the leftmost leaf ``rcu_node``
|
||||
structure, and awaken a task that is to run on a CPU corresponding to
|
||||
the rightmost leaf ``rcu_node`` structure, and the grace-period kernel
|
||||
thread might not yet have reached the rightmost leaf. In this case, the
|
||||
grace period's memory ordering might not yet have reached that CPU, so
|
||||
again the callback function and the awakened task must supply proper
|
||||
ordering.
|
||||
|
||||
Putting It All Together
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A stitched-together diagram is here:
|
||||
|
||||
.. kernel-figure:: TreeRCU-gp.svg
|
||||
|
||||
Legal Statement
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
This work represents the view of the author and does not necessarily
|
||||
represent the view of IBM.
|
||||
|
||||
Linux is a registered trademark of Linus Torvalds.
|
||||
|
||||
Other company, product, and service names may be trademarks or service
|
||||
marks of others.
|
@ -0,0 +1,486 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:35:03 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="592.12805"
|
||||
height="469.83038"
|
||||
viewBox="-44 -44 7874.1949 6244.9802"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeRCU-callback-invocation.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutS"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutS"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4073"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.2,0.2)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutM"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4070"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.4,0.4)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3952"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3952-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-9"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1087"
|
||||
inkscape:window-height="1144"
|
||||
id="namedview208"
|
||||
showgrid="true"
|
||||
inkscape:zoom="1.2009216"
|
||||
inkscape:cx="289.88715"
|
||||
inkscape:cy="219.06265"
|
||||
inkscape:window-x="713"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g3058"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-bottom="5">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3079"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true"
|
||||
originx="-116.00011px"
|
||||
originy="-87.2081px" />
|
||||
</sodipodi:namedview>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4"
|
||||
transform="translate(-2296.0293,-2364.1166)">
|
||||
<path
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
|
||||
d="m 6161.6776,2411.7612 0,4920.3076"
|
||||
id="path3134-9-0-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
|
||||
d="m 6161.6776,4672.443 -2393.6631,0.5116 0,1196.8316 2393.6631,-0.5116"
|
||||
id="path3134-9-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
|
||||
d="m 6161.6776,4672.443 2393.6631,0.5116 0,1196.8316 -2393.6631,-0.5116"
|
||||
id="path3134-9-0-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8100 - 5710 5790-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9300 - 4512 7140-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1040 9300 - 1502 7140-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2240 8100 - 2702 5940-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1350 3450 - 2444 2510-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4950 3450 - 3854 2510-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 6600 - 4050 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1050 6600 - 1050 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2250 5400 - 2250 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2250 8100 - 2250 6240-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1050 9300 - 1050 7440-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9300 - 4050 7440-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8100 - 5250 6240-->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9300 3150 - 10860 3150-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11400 3600 - 11400 4410-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11400 5100 - 11400 5910-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9900 4650 - 10860 4650-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9600 6150 - 10860 6150-->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 5400 - 5250 4290-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<rect
|
||||
x="2333.5203"
|
||||
y="5109.5566"
|
||||
width="2844.0974"
|
||||
height="360.77411"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.0005789, 60.00115781;stroke-dashoffset:0"
|
||||
id="rect118-3"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2562.135"
|
||||
y="5357.9937"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_sched_clock_irq()</text>
|
||||
<rect
|
||||
x="7069.6187"
|
||||
y="5087.4678"
|
||||
width="2975.115"
|
||||
height="382.86298"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057902, 60.00115804;stroke-dashoffset:0"
|
||||
id="rect118-36"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7165.2524"
|
||||
y="5333.4927"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-9-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_cleanup_after_idle()</text>
|
||||
<g
|
||||
id="g3058"
|
||||
transform="translate(-53.192514,-2819.2063)">
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier"
|
||||
id="text202"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="6532.0293"
|
||||
x="5073.3374"
|
||||
xml:space="preserve">rcu_advance_cbs()</text>
|
||||
<rect
|
||||
id="rect112"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="5650.2598"
|
||||
x="4800.2563" />
|
||||
<rect
|
||||
id="rect112-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="5726.2852"
|
||||
x="4800.2563" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2-3-7"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="6961.395"
|
||||
x="7220.106"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104-6-5"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">Leaf</tspan></text>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-3"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="6321.9248"
|
||||
x="5073.3374"
|
||||
xml:space="preserve">__note_gp_changes()</text>
|
||||
</g>
|
||||
<g
|
||||
id="g3049"
|
||||
transform="translate(26.596257,6090.5512)">
|
||||
<path
|
||||
transform="matrix(13.298129,0,0,13.298129,1872.6808,-2726.4833)"
|
||||
d="m 385.2961,345.54001 c 0,21.84301 -29.51209,39.55026 -65.9171,39.55026 -36.40501,0 -65.91711,-17.70725 -65.91711,-39.55026 0,-21.84301 29.5121,-39.55026 65.91711,-39.55026 36.40501,0 65.9171,17.70725 65.9171,39.55026 z"
|
||||
sodipodi:ry="39.550262"
|
||||
sodipodi:rx="65.917107"
|
||||
sodipodi:cy="345.54001"
|
||||
sodipodi:cx="319.379"
|
||||
id="path3084-3"
|
||||
style="fill:#ffffa1;fill-opacity:0;stroke:#000000;stroke-width:2.25600004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.256, 4.512;stroke-dashoffset:0"
|
||||
sodipodi:type="arc" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2-6"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="1785.2073"
|
||||
x="5717.4517"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104-7"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">Phase Two</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3110-5"
|
||||
y="2005.6624"
|
||||
x="6119.668"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="2005.6624"
|
||||
x="6119.668"
|
||||
id="tspan3112-3"
|
||||
sodipodi:role="line">of Update</tspan></text>
|
||||
</g>
|
||||
<rect
|
||||
x="5097.8271"
|
||||
y="6268.2183"
|
||||
width="1994.7195"
|
||||
height="664.90662"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057858, 60.00115716;stroke-dashoffset:0"
|
||||
id="rect118-36-3"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5363.7886"
|
||||
y="6534.1812"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-9-6-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">RCU_SOFTIRQ</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5363.7886"
|
||||
y="6800.1436"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-9-6-6-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_do_batch()</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,655 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:35:03 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="816.04761"
|
||||
height="636.55627"
|
||||
viewBox="-44 -44 10851.906 8461.0989"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeRCU-callback-registry.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutS"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutS"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4073"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.2,0.2)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutM"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4070"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.4,0.4)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3952"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3952-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-9"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1087"
|
||||
inkscape:window-height="1144"
|
||||
id="namedview208"
|
||||
showgrid="true"
|
||||
inkscape:zoom="1.2009216"
|
||||
inkscape:cx="408.02381"
|
||||
inkscape:cy="254.38856"
|
||||
inkscape:window-x="713"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-bottom="5">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3079"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true"
|
||||
originx="5.2596966e-08px"
|
||||
originy="-4.5963961e-06px" />
|
||||
</sodipodi:namedview>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4"
|
||||
transform="translate(-753.44492,-1306.6788)">
|
||||
<path
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
|
||||
d="m 6161.6776,2411.7612 0,6117.1391"
|
||||
id="path3134-9-0-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
|
||||
d="m 6161.6776,3342.6302 -3856.4573,0 10.6979,5757.1962 2918.1436,-2e-4"
|
||||
id="path3134-9-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
|
||||
d="m 6161.6776,3342.6302 3856.4574,0 -12.188,5757.1963 -2918.1436,-3e-4"
|
||||
id="path3134-9-0-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8100 - 5710 5790-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9300 - 4512 7140-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1040 9300 - 1502 7140-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2240 8100 - 2702 5940-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1350 3450 - 2444 2510-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4950 3450 - 3854 2510-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 6600 - 4050 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1050 6600 - 1050 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2250 5400 - 2250 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2250 8100 - 2250 6240-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1050 9300 - 1050 7440-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9300 - 4050 7440-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8100 - 5250 6240-->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9300 3150 - 10860 3150-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11400 3600 - 11400 4410-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11400 5100 - 11400 5910-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9900 4650 - 10860 4650-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9600 6150 - 10860 6150-->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 5400 - 5250 4290-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<rect
|
||||
x="4544.7305"
|
||||
y="4603.417"
|
||||
width="3240.0088"
|
||||
height="2650.6289"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057884, 60.00115769;stroke-dashoffset:0"
|
||||
id="rect118"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5073.3374"
|
||||
y="6372.4521"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">rcu_accelerate_cbs()</text>
|
||||
<g
|
||||
id="g3107"
|
||||
transform="translate(2715.7065,4700.8888)">
|
||||
<rect
|
||||
id="rect112"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4773.3452"
|
||||
y="4825.2578"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_prepare_for_idle()</text>
|
||||
<rect
|
||||
x="790.93585"
|
||||
y="4630.8252"
|
||||
width="3240.0088"
|
||||
height="2650.6289"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.0005789, 60.00115781;stroke-dashoffset:0"
|
||||
id="rect118-3"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1319.5447"
|
||||
y="6639.2261"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_accelerate_cbs()</text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-7"
|
||||
transform="translate(-1038.0776,4728.2971)">
|
||||
<rect
|
||||
id="rect112-5"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1019.5512"
|
||||
y="4852.666"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">note_gp_changes()</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1319.5447"
|
||||
y="6376.6328"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-6-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_advance_cbs()</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="1340.6649"
|
||||
y="6111.4473"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-6-6-2"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">__note_gp_changes()</text>
|
||||
<rect
|
||||
x="5422.6279"
|
||||
y="3041.8311"
|
||||
width="1480.4871"
|
||||
height="379.24637"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.0005789, 60.00115794;stroke-dashoffset:0"
|
||||
id="rect118-3-9"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5607.2734"
|
||||
y="3283.3892"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">call_rcu()</text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#ffffa1;fill-opacity:0;stroke:#000000;stroke-width:2.25600004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.256, 4.512;stroke-dashoffset:0"
|
||||
id="path3084"
|
||||
sodipodi:cx="319.379"
|
||||
sodipodi:cy="345.54001"
|
||||
sodipodi:rx="65.917107"
|
||||
sodipodi:ry="39.550262"
|
||||
d="m 385.2961,345.54001 c 0,21.84301 -29.51209,39.55026 -65.9171,39.55026 -36.40501,0 -65.91711,-17.70725 -65.91711,-39.55026 0,-21.84301 29.5121,-39.55026 65.91711,-39.55026 36.40501,0 65.9171,17.70725 65.9171,39.55026 z"
|
||||
transform="matrix(13.298129,0,0,13.298129,1915.7286,4523.6528)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5853.9238"
|
||||
y="8902.3623"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104">Wake up</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="6165.7158"
|
||||
y="9122.8174"
|
||||
id="text3110"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3112"
|
||||
x="6165.7158"
|
||||
y="9122.8174">grace-period</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="6162.8716"
|
||||
y="9364.3564"
|
||||
id="text3114"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3116"
|
||||
x="6162.8716"
|
||||
y="9364.3564">kernel thread</tspan></text>
|
||||
<rect
|
||||
x="8239.8516"
|
||||
y="4608.7363"
|
||||
width="3240.0088"
|
||||
height="2650.6289"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057902, 60.00115804;stroke-dashoffset:0"
|
||||
id="rect118-36"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8768.4678"
|
||||
y="6484.1562"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-75"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_accelerate_cbs()</text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-3"
|
||||
transform="translate(6410.833,4706.2127)">
|
||||
<rect
|
||||
id="rect112-56"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-2"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8329.5352"
|
||||
y="4830.5771"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-9"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">takedown_cpu()</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8335.4873"
|
||||
y="5094.127"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-9-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcutree_migrate_callbacks()</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8335.4873"
|
||||
y="5357.1006"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-9-6-0"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_migrate_callbacks()</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="8768.4678"
|
||||
y="6224.9038"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-6-6-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_advance_cbs()</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3467.9963"
|
||||
y="6987.9912"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6">Leaf</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7220.106"
|
||||
y="6961.395"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5">Leaf</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="10905.331"
|
||||
y="6961.395"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-3"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-5">Leaf</tspan></text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#ffffa1;fill-opacity:0;stroke:#000000;stroke-width:2.25600004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.256, 4.512;stroke-dashoffset:0"
|
||||
id="path3084-3"
|
||||
sodipodi:cx="319.379"
|
||||
sodipodi:cy="345.54001"
|
||||
sodipodi:rx="65.917107"
|
||||
sodipodi:ry="39.550262"
|
||||
d="m 385.2961,345.54001 c 0,21.84301 -29.51209,39.55026 -65.9171,39.55026 -36.40501,0 -65.91711,-17.70725 -65.91711,-39.55026 0,-21.84301 29.5121,-39.55026 65.91711,-39.55026 36.40501,0 65.9171,17.70725 65.9171,39.55026 z"
|
||||
transform="matrix(13.298129,0,0,13.298129,1872.6808,-2726.4833)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5717.4517"
|
||||
y="1785.2073"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-7">Phase One</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="6119.668"
|
||||
y="2005.6624"
|
||||
id="text3110-5"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3112-3"
|
||||
x="6119.668"
|
||||
y="2005.6624">of Update</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 23 KiB |
700
Documentation/RCU/Design/Memory-Ordering/TreeRCU-dyntick.svg
Normal file
@ -0,0 +1,700 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:35:03 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="670.61804"
|
||||
height="557.16394"
|
||||
viewBox="-44 -44 8917.9652 7405.8166"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeRCU-dyntick.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutS"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutS"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4073"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.2,0.2)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutM"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4070"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.4,0.4)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3952"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3952-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-9"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-1"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-7"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker4880"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4882"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-5"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-10"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-36"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-0"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-26"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-8"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-7"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-367"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-5"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-56"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-2"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3081"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3083"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3085"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3087"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3089"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3091"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3093"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3095"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3097"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3099"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-9"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-1"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-3675"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-3"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1087"
|
||||
inkscape:window-height="1148"
|
||||
id="namedview208"
|
||||
showgrid="true"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="381.32663"
|
||||
inkscape:cy="239.67141"
|
||||
inkscape:window-x="833"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-bottom="5"
|
||||
inkscape:snap-global="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3154"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true"
|
||||
originx="-235.14935px"
|
||||
originy="-709.25071px" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3-1-3-5"
|
||||
d="m 3754.1051,47.378296 -2.828,7173.860804"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3-1-3"
|
||||
d="m 6681.1176,1435.1734 -2.828,1578.9586 -2861.3912,7.7159"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3-1"
|
||||
d="m 3748.8929,3772.1176 2904.1747,-0.8434 26.8008,1842.1825"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" />
|
||||
<g
|
||||
id="g3115"
|
||||
transform="translate(-2341.8794,10827.399)">
|
||||
<rect
|
||||
ry="0"
|
||||
id="rect118-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057923, 60.00115859;stroke-dashoffset:0"
|
||||
rx="0"
|
||||
height="2349.7295"
|
||||
width="5308.7119"
|
||||
y="-8909.5498"
|
||||
x="2379.3704" />
|
||||
<g
|
||||
transform="translate(2576.8841,-9085.2783)"
|
||||
id="g3107-7"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<rect
|
||||
x="2084.55"
|
||||
y="949.37109"
|
||||
width="2809.1992"
|
||||
height="1370.8721"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect112-5" />
|
||||
<rect
|
||||
x="2084.55"
|
||||
y="1025.3964"
|
||||
width="2809.1992"
|
||||
height="1294.8468"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect112-3-3" />
|
||||
</g>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-6-6-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-7356.375"
|
||||
x="4769.4536"
|
||||
xml:space="preserve">->qsmask &= ~->grpmask</text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2-3"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-6825.5815"
|
||||
x="7082.9585"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104-6"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">Leaf</tspan></text>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-2-7-7"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-8652.5312"
|
||||
x="2466.7822"
|
||||
xml:space="preserve">dyntick_save_progress_counter()</text>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-2-7-2-0"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-8368.1475"
|
||||
x="2463.3262"
|
||||
xml:space="preserve">rcu_implicit_dynticks_qs()</text>
|
||||
</g>
|
||||
<g
|
||||
id="g4504"
|
||||
transform="translate(2063.5184,-16111.739)">
|
||||
<path
|
||||
transform="matrix(13.298129,0,0,13.298129,335.22989,12456.379)"
|
||||
d="m 385.2961,345.54001 c 0,21.84301 -29.51209,39.55026 -65.9171,39.55026 -36.40501,0 -65.91711,-17.70725 -65.91711,-39.55026 0,-21.84301 29.5121,-39.55026 65.91711,-39.55026 36.40501,0 65.9171,17.70725 65.9171,39.55026 z"
|
||||
sodipodi:ry="39.550262"
|
||||
sodipodi:rx="65.917107"
|
||||
sodipodi:cy="345.54001"
|
||||
sodipodi:cx="319.379"
|
||||
id="path3084"
|
||||
style="fill:#ffffa1;fill-opacity:0;stroke:#000000;stroke-width:2.25600004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.256, 4.512;stroke-dashoffset:0"
|
||||
sodipodi:type="arc" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="16835.086"
|
||||
x="4409.043"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">RCU</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3110"
|
||||
y="17055.541"
|
||||
x="4579.373"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17055.541"
|
||||
x="4579.373"
|
||||
id="tspan3112"
|
||||
sodipodi:role="line">read-side</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3114"
|
||||
y="17297.08"
|
||||
x="4584.8276"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17297.08"
|
||||
x="4584.8276"
|
||||
id="tspan3116"
|
||||
sodipodi:role="line">critical section</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3148-9-9"
|
||||
transform="translate(2035.3087,6370.5796)">
|
||||
<rect
|
||||
x="3592.3828"
|
||||
y="-4715.7246"
|
||||
width="3164.783"
|
||||
height="769.99048"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057963, 60.00115926;stroke-dashoffset:0"
|
||||
id="rect118-3-5-1-3"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3745.7725"
|
||||
y="-4418.6582"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-3-27-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_dynticks_eqs_enter()</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3745.7725"
|
||||
y="-4165.7954"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-3-27-0-0"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">atomic_add_return()</text>
|
||||
</g>
|
||||
<g
|
||||
id="g3148-9-9-2"
|
||||
transform="translate(2035.3089,9031.6839)">
|
||||
<rect
|
||||
x="3592.3828"
|
||||
y="-4715.7246"
|
||||
width="3164.783"
|
||||
height="769.99048"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057963, 60.00115926;stroke-dashoffset:0"
|
||||
id="rect118-3-5-1-3-6"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3745.7725"
|
||||
y="-4418.6582"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-3-27-6-1"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_dynticks_eqs_exit()</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3745.7725"
|
||||
y="-4165.7954"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-3-27-0-0-8"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">atomic_add_return()</text>
|
||||
</g>
|
||||
<g
|
||||
id="g4504-7"
|
||||
transform="translate(2082.3248,-10883.562)">
|
||||
<path
|
||||
transform="matrix(13.298129,0,0,13.298129,335.22989,12456.379)"
|
||||
d="m 385.2961,345.54001 c 0,21.84301 -29.51209,39.55026 -65.9171,39.55026 -36.40501,0 -65.91711,-17.70725 -65.91711,-39.55026 0,-21.84301 29.5121,-39.55026 65.91711,-39.55026 36.40501,0 65.9171,17.70725 65.9171,39.55026 z"
|
||||
sodipodi:ry="39.550262"
|
||||
sodipodi:rx="65.917107"
|
||||
sodipodi:cy="345.54001"
|
||||
sodipodi:cx="319.379"
|
||||
id="path3084-9"
|
||||
style="fill:#ffffa1;fill-opacity:0;stroke:#000000;stroke-width:2.25600004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.256, 4.512;stroke-dashoffset:0"
|
||||
sodipodi:type="arc" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="16835.086"
|
||||
x="4409.043"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104-0"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">RCU</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3110-2"
|
||||
y="17055.541"
|
||||
x="4579.373"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17055.541"
|
||||
x="4579.373"
|
||||
id="tspan3112-3"
|
||||
sodipodi:role="line">read-side</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3114-7"
|
||||
y="17297.08"
|
||||
x="4584.8276"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17297.08"
|
||||
x="4584.8276"
|
||||
id="tspan3116-5"
|
||||
sodipodi:role="line">critical section</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 25 KiB |
1133
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-cleanup.svg
Normal file
After Width: | Height: | Size: 42 KiB |
1309
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg
Normal file
After Width: | Height: | Size: 50 KiB |
658
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-1.svg
Normal file
@ -0,0 +1,658 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:35:03 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1039.3743"
|
||||
height="677.72852"
|
||||
viewBox="-44 -44 13821.733 9008.3597"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeRCU-gp-init-1.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutS"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutS"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4073"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.2,0.2)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutM"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4070"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.4,0.4)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3952"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3952-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-9"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-1"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-7"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker4880"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4882"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-5"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-10"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-36"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-7"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1087"
|
||||
inkscape:window-height="1144"
|
||||
id="namedview208"
|
||||
showgrid="true"
|
||||
inkscape:zoom="2.6330492"
|
||||
inkscape:cx="524.82797"
|
||||
inkscape:cy="519.31194"
|
||||
inkscape:window-x="79"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g3188"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-bottom="5">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3059"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true"
|
||||
originx="1.6062488e-07px"
|
||||
originy="10.7285px" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3"
|
||||
d="m 6871.027,46.883461 0,8777.144039"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
transform="translate(2450.4075,-10679.115)"
|
||||
id="g3188">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3119.363"
|
||||
y="13255.592"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier"><tspan
|
||||
style="font-size:172.87567139px"
|
||||
id="tspan3071">rcu_seq_start(rsp->gp_seq)</tspan></text>
|
||||
<g
|
||||
id="g3107"
|
||||
transform="translate(947.90548,11584.029)">
|
||||
<rect
|
||||
id="rect112"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5452.3052"
|
||||
y="13844.535"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5">Root</tspan></text>
|
||||
</g>
|
||||
<rect
|
||||
ry="0"
|
||||
id="rect118"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057884, 60.00115769;stroke-dashoffset:0"
|
||||
rx="0"
|
||||
height="6844.4546"
|
||||
width="13658.751"
|
||||
y="1371.6335"
|
||||
x="37.490932" />
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="1631.0878"
|
||||
x="153.26733"
|
||||
xml:space="preserve">rcu_gp_init()</text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
transform="translate(2329.9439,-10642.748)"
|
||||
id="g3147">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6"
|
||||
transform="translate(3054.6101,13760.052)">
|
||||
<rect
|
||||
id="rect112-7"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
transform="translate(3181.0246,-10679.115)"
|
||||
id="g3153">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0">Leaf</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-1642.5375,-10642.748)"
|
||||
id="g3147-3"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-6"
|
||||
transform="translate(3054.6101,13760.052)">
|
||||
<rect
|
||||
id="rect112-7-0"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-151.71726,-10679.115)"
|
||||
id="g3153-2"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9-6"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1-1"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2-8"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0-9">Leaf</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-3484.4587,-10679.115)"
|
||||
id="g3153-20"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9-2"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1-3"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2-7"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7-5"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0-92">Leaf</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-6817.1998,-10679.115)"
|
||||
id="g3153-28"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9-9"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1-7"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0-1">Leaf</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812908px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 5473.7572,3203.2219 -582.9982,865.094"
|
||||
id="path3414"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812813px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 8282.5391,3203.4839 582.9982,865.094"
|
||||
id="path3414-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812813px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 3523.1241,5416.3989 -582.9982,865.094"
|
||||
id="path3414-8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812717px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 10268.171,5416.6609 583,865.094"
|
||||
id="path3414-9-4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812717px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 4939.6205,5416.3989 0,846.288"
|
||||
id="path3414-8-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812717px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 8816.5958,5442.9949 0,846.288"
|
||||
id="path3414-8-3-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
id="g4504-3-9"
|
||||
transform="translate(4866.0367,-16425.339)">
|
||||
<path
|
||||
transform="matrix(13.298129,0,0,13.298129,335.22989,12456.379)"
|
||||
d="m 385.2961,345.54001 c 0,21.84301 -29.51209,39.55026 -65.9171,39.55026 -36.40501,0 -65.91711,-17.70725 -65.91711,-39.55026 0,-21.84301 29.5121,-39.55026 65.91711,-39.55026 36.40501,0 65.9171,17.70725 65.9171,39.55026 z"
|
||||
sodipodi:ry="39.550262"
|
||||
sodipodi:rx="65.917107"
|
||||
sodipodi:cy="345.54001"
|
||||
sodipodi:cx="319.379"
|
||||
id="path3084-6-1"
|
||||
style="fill:#ffffa1;fill-opacity:0;stroke:#000000;stroke-width:2.25600004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.256, 4.512;stroke-dashoffset:0"
|
||||
sodipodi:type="arc" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2-7-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="16888.277"
|
||||
x="4344.877"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104-5-7"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">End of</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3110-3-0"
|
||||
y="17119.1"
|
||||
x="4578.7886"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17119.1"
|
||||
x="4578.7886"
|
||||
id="tspan3112-5-9"
|
||||
sodipodi:role="line">Last Grace</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3114-6-3"
|
||||
y="17350.271"
|
||||
x="4581.7886"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17350.271"
|
||||
x="4581.7886"
|
||||
id="tspan3116-2-6"
|
||||
sodipodi:role="line">Period</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3-5"
|
||||
d="m 8546.5914,605.78414 -1595.7755,0"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send-36)" />
|
||||
</svg>
|
After Width: | Height: | Size: 24 KiB |
656
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-2.svg
Normal file
@ -0,0 +1,656 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:35:03 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1037.9602"
|
||||
height="666.38184"
|
||||
viewBox="-44 -44 13802.928 8857.5401"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeRCU-gp-init-2.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutS"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutS"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4073"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.2,0.2)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutM"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4070"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.4,0.4)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3952"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3952-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-9"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-1"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-7"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker4880"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4882"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-5"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-10"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1087"
|
||||
inkscape:window-height="1144"
|
||||
id="namedview208"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.79710462"
|
||||
inkscape:cx="564.27119"
|
||||
inkscape:cy="397.32188"
|
||||
inkscape:window-x="833"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-bottom="5" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3"
|
||||
d="m 6861.6904,46.438525 -2.8276,1315.668775 -5343.8436,17.1194 -2.8276,6561.7446 2039.0799,17.963 -2.7042,-2144.1399 -491.6705,-0.2109 -2.7042,-1993.6887 1487.7179,-4.7279 -17.8,1812.453 2017.2374,-7.6434 4.9532,-2151.5723 -1405.5264,11.163 -10.919,-1891.1468 1739.2164,-2.7175 -13.2006,4234.2295 -1701.3595,1.3953 -8.7841,2107.7116 1702.6392,-4.8334 33.4144,-1867.7167 1312.2492,12.9229 14.608,1818.3367 2000.0063,20.4217 -12.279,-1841.4113 1304.168,1.6154 -12.279,2032.7059 -4638.6515,1.6154 19.5828,569.0378"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" />
|
||||
<rect
|
||||
ry="0"
|
||||
id="rect118"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057884, 60.00115769;stroke-dashoffset:0"
|
||||
rx="0"
|
||||
height="7653.1299"
|
||||
width="13639.945"
|
||||
y="555.69745"
|
||||
x="37.490929" />
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="799.34259"
|
||||
x="134.46091"
|
||||
xml:space="preserve">rcu_gp_init()</text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
transform="translate(2311.1375,-10650.009)"
|
||||
id="g3147">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6"
|
||||
transform="translate(3054.6101,13760.052)">
|
||||
<rect
|
||||
id="rect112-7"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
transform="translate(3162.2182,-10686.376)"
|
||||
id="g3153">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0">Leaf</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-1661.3439,-10650.009)"
|
||||
id="g3147-3"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-6"
|
||||
transform="translate(3054.6101,13760.052)">
|
||||
<rect
|
||||
id="rect112-7-0"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5398.415"
|
||||
y="15310.093"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-8"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->qsmaskinit</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5398.415"
|
||||
y="15545.01"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-5-8"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->qsmaskinitnext</text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-170.52359,-10686.376)"
|
||||
id="g3153-2"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9-6"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1-1"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2-8"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0-9">Leaf</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-3503.2651,-10686.376)"
|
||||
id="g3153-20"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9-2"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1-3"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2-7"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7-5"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0-92">Leaf</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-6836.0062,-10686.376)"
|
||||
id="g3153-28"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9-9"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1-7"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0-1">Leaf</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7699.7246"
|
||||
y="17734.791"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-4"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->qsmaskinit</text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812908px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 5454.9508,3195.9607 -582.9982,865.094"
|
||||
id="path3414"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812813px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 8263.7327,3196.2227 582.9982,865.094"
|
||||
id="path3414-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812813px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 3504.3177,5409.1377 -582.9982,865.094"
|
||||
id="path3414-8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812717px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 10249.365,5409.3997 583,865.094"
|
||||
id="path3414-9-4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812717px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 4920.8141,5409.1377 0,846.288"
|
||||
id="path3414-8-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812717px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 8797.7894,5435.7337 0,846.288"
|
||||
id="path3414-8-3-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<rect
|
||||
ry="0"
|
||||
id="rect118-1"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057923, 60.00115846;stroke-dashoffset:0"
|
||||
rx="0"
|
||||
height="4418.4302"
|
||||
width="4932.5845"
|
||||
y="1492.2119"
|
||||
x="2087.8708" />
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="1690.4336"
|
||||
x="2223.3145"
|
||||
xml:space="preserve"
|
||||
sodipodi:linespacing="125%">rcu_init_new_rnp()<tspan
|
||||
style="font-size:192px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3307"> or</tspan></text>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-2-7"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="1958.5066"
|
||||
x="2223.3145"
|
||||
xml:space="preserve">rcu_cleanup_dead_rnp()</text>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-2-7-6"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="2227.4531"
|
||||
x="2226.1592"
|
||||
xml:space="preserve"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:192px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3327">(optional)</tspan></text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
transform="translate(2431.6011,-10686.376)"
|
||||
id="g3188">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3305.5364"
|
||||
y="13255.592"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">->qsmaskinit</text>
|
||||
<g
|
||||
id="g3107"
|
||||
transform="translate(947.90548,11584.029)">
|
||||
<rect
|
||||
id="rect112"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5452.3052"
|
||||
y="13844.535"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5">Root</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3305.5364"
|
||||
y="13490.509"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-5"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->qsmaskinitnext</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 24 KiB |
636
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-3.svg
Normal file
@ -0,0 +1,636 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:35:03 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1039.3743"
|
||||
height="594.19171"
|
||||
viewBox="-44 -44 13821.733 7897.9895"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeRCU-gp-init-3.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutS"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutS"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4073"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.2,0.2)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutM"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4070"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.4,0.4)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3952"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3952-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-9"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-1"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-7"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker4880"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4882"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-5"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-10"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1087"
|
||||
inkscape:window-height="1144"
|
||||
id="namedview208"
|
||||
showgrid="true"
|
||||
inkscape:zoom="0.68224756"
|
||||
inkscape:cx="617.89019"
|
||||
inkscape:cy="625.84293"
|
||||
inkscape:window-x="54"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g3153"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-bottom="5">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3090" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3"
|
||||
d="m 6899.3032,45.520244 -2.8276,2480.757056 -2316.0141,-1.687 -2.8276,2179.8547 2321.1758,-0.8434 -2.7042,-1843.2376 2404.5142,-0.2109 16.1022,1993.2669 -7783.8345,-4.7279 -16.7936,2120.3946 2033.1033,-23.5344 2.0128,-1866.561 2051.9097,14.0785 2.0128,1838.2987 1280.8475,-4.728 14.608,-1830.1039 1312.2492,12.9229 14.608,1818.3367 2000.0059,20.4217 -12.279,-1841.4113 1304.168,1.6154 -12.279,2032.7059 -4638.6511,1.6154 19.5828,569.0378"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
transform="translate(2450.4075,-11647.329)"
|
||||
id="g3188">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3145.9592"
|
||||
y="13255.592"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">->gp_seq = rsp->gp_seq</text>
|
||||
<g
|
||||
id="g3107"
|
||||
transform="translate(947.90548,11584.029)">
|
||||
<rect
|
||||
id="rect112"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5452.3052"
|
||||
y="13844.535"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5">Root</tspan></text>
|
||||
</g>
|
||||
<rect
|
||||
ry="0"
|
||||
id="rect118"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057884, 60.00115769;stroke-dashoffset:0"
|
||||
rx="0"
|
||||
height="6844.4546"
|
||||
width="13658.751"
|
||||
y="403.41983"
|
||||
x="37.490932" />
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="662.8739"
|
||||
x="153.26733"
|
||||
xml:space="preserve">rcu_gp_init()</text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
transform="translate(2329.9439,-11610.962)"
|
||||
id="g3147">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6"
|
||||
transform="translate(3054.6101,13760.052)">
|
||||
<rect
|
||||
id="rect112-7"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5253.6904"
|
||||
y="15407.032"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->gp_seq = rsp->gp_seq</text>
|
||||
</g>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
transform="translate(3181.0246,-11647.329)"
|
||||
id="g3153">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0">Leaf</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7415.4365"
|
||||
y="17670.572"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-9"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->gp_seq = rsp->gp_seq</text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-1642.5375,-11610.962)"
|
||||
id="g3147-3"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-6"
|
||||
transform="translate(3054.6101,13760.052)">
|
||||
<rect
|
||||
id="rect112-7-0"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5258.0688"
|
||||
y="15412.313"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-3"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->gp_seq = rsp->gp_seq</text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-151.71726,-11647.329)"
|
||||
id="g3153-2"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9-6"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1-1"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2-8"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0-9">Leaf</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-3484.4587,-11647.329)"
|
||||
id="g3153-20"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9-2"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1-3"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2-7"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7-5"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0-92">Leaf</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7405.2607"
|
||||
y="17670.572"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-35"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->gp_seq = rsp->gp_seq</text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-6817.1998,-11647.329)"
|
||||
id="g3153-28"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-6-9-9"
|
||||
transform="translate(5213.0126,16008.808)">
|
||||
<rect
|
||||
id="rect112-7-1-7"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-5-2-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9717.4141"
|
||||
y="18269.314"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-7-35-7-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-5-6-0-1">Leaf</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7413.4688"
|
||||
y="17670.566"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-75"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->gp_seq = rsp->gp_seq</text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812908px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 5473.7572,2235.0081 -582.9982,865.094"
|
||||
id="path3414"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812813px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 8282.5391,2235.2701 582.9982,865.094"
|
||||
id="path3414-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812813px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 3523.1241,4448.1851 -582.9982,865.094"
|
||||
id="path3414-8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812717px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 10268.171,4448.4471 583,865.094"
|
||||
id="path3414-9-4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812717px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 4939.6205,4448.1851 0,846.288"
|
||||
id="path3414-8-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:13.29812717px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 8816.5958,4474.7811 0,846.288"
|
||||
id="path3414-8-3-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7271.9297"
|
||||
y="6023.2412"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-62"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->gp_seq = rsp->gp_seq</text>
|
||||
</svg>
|
After Width: | Height: | Size: 23 KiB |
5144
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg
Normal file
After Width: | Height: | Size: 209 KiB |
775
Documentation/RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg
Normal file
@ -0,0 +1,775 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:35:03 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="613.22784"
|
||||
height="707.07056"
|
||||
viewBox="-44 -44 8154.7829 9398.3736"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="TreeRCU-hotplug.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutS"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutS"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4073"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.2,0.2)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutM"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4070"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="scale(0.4,0.4)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3952"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3952-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6,-0.6)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-6"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-2"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3940-9"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-1"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-7"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker4880"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path4882"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-5"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-0"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-10"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-36"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-0"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-26"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-8"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-7"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-367"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-5"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-56"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3946-2"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3081"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3083"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3085"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3087"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3089"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3091"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3093"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3095"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3097"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3099"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-9"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-1"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Send"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Send-3675"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3940-3"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1087"
|
||||
inkscape:window-height="1148"
|
||||
id="namedview208"
|
||||
showgrid="true"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="325.41695"
|
||||
inkscape:cy="364.94502"
|
||||
inkscape:window-x="833"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-bottom="5"
|
||||
inkscape:snap-global="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3154"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true"
|
||||
originx="65.610033px"
|
||||
originy="-659.12429px" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3-1-3-5"
|
||||
d="m 5749.1555,47.151064 2.828,9167.338436"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3-1"
|
||||
d="m 5746.8844,5080.2018 -4107.7813,-0.8434 20.2152,2632.0511"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3134-9-0-3-1-3"
|
||||
d="m 1629.8595,1633.6804 12.2312,2669.7294 4055.5945,7.7159"
|
||||
style="fill:none;stroke:#969696;stroke-width:53.19251633;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" />
|
||||
<g
|
||||
id="g3115"
|
||||
transform="translate(1657.6576,12154.29)">
|
||||
<rect
|
||||
ry="0"
|
||||
id="rect118-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057923, 60.00115859;stroke-dashoffset:0"
|
||||
rx="0"
|
||||
height="2349.7295"
|
||||
width="3992.2642"
|
||||
y="-8909.5498"
|
||||
x="2379.3704" />
|
||||
<g
|
||||
transform="translate(582.16224,-9085.2783)"
|
||||
id="g3107-7"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<rect
|
||||
x="2084.55"
|
||||
y="949.37109"
|
||||
width="2809.1992"
|
||||
height="1370.8721"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect112-5" />
|
||||
<rect
|
||||
x="2084.55"
|
||||
y="1025.3964"
|
||||
width="2809.1992"
|
||||
height="1294.8468"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect112-3-3" />
|
||||
</g>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-6-6-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-7356.375"
|
||||
x="2774.7393"
|
||||
xml:space="preserve">->qsmask &= ~->grpmask</text>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-2-7-7"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-8652.5312"
|
||||
x="2466.7822"
|
||||
xml:space="preserve">dyntick_save_progress_counter()</text>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-2-7-2-0"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-8368.1475"
|
||||
x="2463.3262"
|
||||
xml:space="preserve">rcu_implicit_dynticks_qs()</text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2-3"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-6817.3472"
|
||||
x="5103.9922"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104-6"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">Leaf</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4504"
|
||||
transform="translate(-2953.0872,-15955.072)">
|
||||
<path
|
||||
transform="matrix(13.298129,0,0,13.298129,335.22989,12456.379)"
|
||||
d="m 385.2961,345.54001 c 0,21.84301 -29.51209,39.55026 -65.9171,39.55026 -36.40501,0 -65.91711,-17.70725 -65.91711,-39.55026 0,-21.84301 29.5121,-39.55026 65.91711,-39.55026 36.40501,0 65.9171,17.70725 65.9171,39.55026 z"
|
||||
sodipodi:ry="39.550262"
|
||||
sodipodi:rx="65.917107"
|
||||
sodipodi:cy="345.54001"
|
||||
sodipodi:cx="319.379"
|
||||
id="path3084"
|
||||
style="fill:#ffffa1;fill-opacity:0;stroke:#000000;stroke-width:2.25600004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.256, 4.512;stroke-dashoffset:0"
|
||||
sodipodi:type="arc" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="16835.086"
|
||||
x="4409.043"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">RCU</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3110"
|
||||
y="17055.541"
|
||||
x="4579.373"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17055.541"
|
||||
x="4579.373"
|
||||
id="tspan3112"
|
||||
sodipodi:role="line">read-side</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3114"
|
||||
y="17297.08"
|
||||
x="4584.8276"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17297.08"
|
||||
x="4584.8276"
|
||||
id="tspan3116"
|
||||
sodipodi:role="line">critical section</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3148-9-9"
|
||||
transform="translate(-3554.8919,7020.44)">
|
||||
<rect
|
||||
x="3592.3828"
|
||||
y="-4981.6865"
|
||||
width="3728.9751"
|
||||
height="2265.0989"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057963, 60.00115926;stroke-dashoffset:0"
|
||||
id="rect118-3-5-1-3"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3745.7725"
|
||||
y="-4684.6201"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-3-27-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_report_dead()</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3745.7725"
|
||||
y="-4431.7573"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-3-27-0-0"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_cleanup_dying_idle_cpu()</text>
|
||||
<g
|
||||
transform="translate(1783.3183,-5255.3491)"
|
||||
id="g3107-7-5"
|
||||
style="fill:none;stroke-width:0.025in">
|
||||
<rect
|
||||
x="2084.55"
|
||||
y="949.37109"
|
||||
width="2809.1992"
|
||||
height="1370.8721"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect112-5-3" />
|
||||
<rect
|
||||
x="2084.55"
|
||||
y="1025.3964"
|
||||
width="2809.1992"
|
||||
height="1294.8468"
|
||||
rx="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect112-3-3-5" />
|
||||
</g>
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-6-6-2-6"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-3526.4448"
|
||||
x="4241.8574"
|
||||
xml:space="preserve">->qsmaskinitnext</text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2-3-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="-2987.4167"
|
||||
x="6305.1484"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104-6-9"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">Leaf</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4504-7"
|
||||
transform="translate(-2934.2808,-8785.3871)">
|
||||
<path
|
||||
transform="matrix(13.298129,0,0,13.298129,335.22989,12456.379)"
|
||||
d="m 385.2961,345.54001 c 0,21.84301 -29.51209,39.55026 -65.9171,39.55026 -36.40501,0 -65.91711,-17.70725 -65.91711,-39.55026 0,-21.84301 29.5121,-39.55026 65.91711,-39.55026 36.40501,0 65.9171,17.70725 65.9171,39.55026 z"
|
||||
sodipodi:ry="39.550262"
|
||||
sodipodi:rx="65.917107"
|
||||
sodipodi:cy="345.54001"
|
||||
sodipodi:cx="319.379"
|
||||
id="path3084-9"
|
||||
style="fill:#ffffa1;fill-opacity:0;stroke:#000000;stroke-width:2.25600004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.256, 4.512;stroke-dashoffset:0"
|
||||
sodipodi:type="arc" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-1-2-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="16835.086"
|
||||
x="4409.043"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3104-0"
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">RCU</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3110-2"
|
||||
y="17055.541"
|
||||
x="4579.373"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17055.541"
|
||||
x="4579.373"
|
||||
id="tspan3112-3"
|
||||
sodipodi:role="line">read-side</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3114-7"
|
||||
y="17297.08"
|
||||
x="4584.8276"
|
||||
style="font-size:159.57754517px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="17297.08"
|
||||
x="4584.8276"
|
||||
id="tspan3116-5"
|
||||
sodipodi:role="line">critical section</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3206"
|
||||
transform="translate(3999.537,1706.6099)">
|
||||
<rect
|
||||
ry="0"
|
||||
id="rect118-3-5-1-3-1"
|
||||
style="fill:none;stroke:#000000;stroke-width:30.00057983;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00058007, 60.00116001;stroke-dashoffset:0"
|
||||
rx="0"
|
||||
height="2265.0989"
|
||||
width="3728.9751"
|
||||
y="3382.2036"
|
||||
x="-3958.3845" />
|
||||
<text
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
id="text202-7-5-3-27-6-2"
|
||||
font-size="192"
|
||||
font-weight="bold"
|
||||
font-style="normal"
|
||||
y="3679.27"
|
||||
x="-3804.9949"
|
||||
xml:space="preserve">rcu_cpu_starting()</text>
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g3107-7-5-0"
|
||||
transform="translate(-5767.4491,3108.5424)">
|
||||
<rect
|
||||
id="rect112-5-3-9"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3-3-5-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-3308.9099"
|
||||
y="4837.4453"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-6-6-2-6-6"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">->qsmaskinitnext</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-1245.6189"
|
||||
y="5376.4731"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7-5-1-2-3-2-0"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;line-height:125%;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-size:159.57754517px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
|
||||
id="tspan3104-6-9-6">Leaf</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 28 KiB |
1095
Documentation/RCU/Design/Memory-Ordering/TreeRCU-qs.svg
Normal file
After Width: | Height: | Size: 43 KiB |
229
Documentation/RCU/Design/Memory-Ordering/rcu_node-lock.svg
Normal file
@ -0,0 +1,229 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
|
||||
|
||||
<!-- CreationDate: Wed Dec 9 17:35:03 2015 -->
|
||||
|
||||
<!-- Magnification: 2.000 -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="303.54147"
|
||||
height="211.57945"
|
||||
viewBox="-44 -44 4036.5336 2812.3117"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="rcu_node-lock.svg">
|
||||
<metadata
|
||||
id="metadata212">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs210">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3970"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1087"
|
||||
inkscape:window-height="1144"
|
||||
id="namedview208"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.0495049"
|
||||
inkscape:cx="311.2033"
|
||||
inkscape:cy="168.10913"
|
||||
inkscape:window-x="833"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g4"
|
||||
fit-margin-top="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-bottom="5" />
|
||||
<g
|
||||
style="fill:none;stroke-width:0.025in"
|
||||
id="g4"
|
||||
transform="translate(-1905.5784,-4568.3024)">
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8100 - 5710 5790-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9300 - 4512 7140-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1040 9300 - 1502 7140-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2240 8100 - 2702 5940-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1350 3450 - 2444 2510-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4950 3450 - 3854 2510-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 6600 - 4050 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1050 6600 - 1050 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2250 5400 - 2250 4290-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 2250 8100 - 2250 6240-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 1050 9300 - 1050 7440-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 4050 9300 - 4050 7440-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 8100 - 5250 6240-->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Circle -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9300 3150 - 10860 3150-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11400 3600 - 11400 4410-->
|
||||
<!-- Line: box -->
|
||||
<rect
|
||||
x="1943.0693"
|
||||
y="4603.417"
|
||||
width="3873.5518"
|
||||
height="2650.6289"
|
||||
rx="0"
|
||||
style="stroke:#000000;stroke-width:30.00057793;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:30.00057884, 60.00115769;stroke-dashoffset:0"
|
||||
id="rect118"
|
||||
ry="0" />
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 11400 5100 - 11400 5910-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9900 4650 - 10860 4650-->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 9600 6150 - 10860 6150-->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Line -->
|
||||
<!-- Arrowhead on XXXpoint 5250 5400 - 5250 4290-->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Line: box -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3105.219"
|
||||
y="6425.6445"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">rcu_accelerate_cbs()</text>
|
||||
<!-- Text -->
|
||||
<!-- Text -->
|
||||
<g
|
||||
id="g3107"
|
||||
transform="translate(747.5807,4700.8888)">
|
||||
<rect
|
||||
id="rect112"
|
||||
style="stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1370.8721"
|
||||
width="2809.1992"
|
||||
y="949.37109"
|
||||
x="2084.55" />
|
||||
<rect
|
||||
id="rect112-3"
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
rx="0"
|
||||
height="1294.8468"
|
||||
width="2809.1992"
|
||||
y="1025.3964"
|
||||
x="2084.55" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2025.5763"
|
||||
y="4825.2578"
|
||||
font-style="normal"
|
||||
font-weight="bold"
|
||||
font-size="192"
|
||||
id="text202-7"
|
||||
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_prepare_for_idle()</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.4 KiB |
374
Documentation/RCU/Design/Requirements/GPpartitionReaders1.svg
Normal file
@ -0,0 +1,374 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="447.99197"
|
||||
height="428.19299"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="GPpartitionReaders1.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.6184291"
|
||||
inkscape:cx="223.99599"
|
||||
inkscape:cy="214.0965"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="979"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="571"
|
||||
inkscape:window-y="335"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-28.441125,-185.60612)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991"></flowPara></flowRoot> <g
|
||||
id="g4433"
|
||||
transform="translate(2,0)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text2993"
|
||||
y="-261.66608"
|
||||
x="412.12299"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,1,-1,0,0,0)"><tspan
|
||||
y="-261.66608"
|
||||
x="412.12299"
|
||||
id="tspan2995"
|
||||
sodipodi:role="line">synchronize_rcu()</tspan></text>
|
||||
<g
|
||||
id="g4417"
|
||||
transform="matrix(0,1,-1,0,730.90257,222.4928)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-end:url(#Arrow2Lend)"
|
||||
d="m 97.580736,477.4048 183.140664,0"
|
||||
id="path2997"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 96.752718,465.38398 0,22.62742"
|
||||
id="path4397"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 281.54942,465.38397 0,22.62742"
|
||||
id="path4397-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="112.04738"
|
||||
y="268.18076"
|
||||
id="text4429"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431"
|
||||
x="112.04738"
|
||||
y="268.18076">WRITE_ONCE(a, 1);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="112.04738"
|
||||
y="439.13766"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="112.04738"
|
||||
y="439.13766">WRITE_ONCE(b, 1);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="255.60869"
|
||||
y="309.29346"
|
||||
id="text4445"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4447"
|
||||
x="255.60869"
|
||||
y="309.29346">r1 = READ_ONCE(a);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="255.14423"
|
||||
y="520.61786"
|
||||
id="text4449"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4451"
|
||||
x="255.14423"
|
||||
y="520.61786">WRITE_ONCE(c, 1);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.10254"
|
||||
y="384.71124"
|
||||
id="text4453"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4455"
|
||||
x="396.10254"
|
||||
y="384.71124">r2 = READ_ONCE(b);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.10254"
|
||||
y="582.13617"
|
||||
id="text4457"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4459"
|
||||
x="396.10254"
|
||||
y="582.13617">r3 = READ_ONCE(c);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="112.08231"
|
||||
y="213.91006"
|
||||
id="text4461"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4463"
|
||||
x="112.08231"
|
||||
y="213.91006">thread0()</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="252.34512"
|
||||
y="213.91006"
|
||||
id="text4461-6"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4463-0"
|
||||
x="252.34512"
|
||||
y="213.91006">thread1()</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.42557"
|
||||
y="213.91006"
|
||||
id="text4461-2"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4463-2"
|
||||
x="396.42557"
|
||||
y="213.91006">thread2()</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect4495"
|
||||
width="436.28488"
|
||||
height="416.4859"
|
||||
x="34.648232"
|
||||
y="191.10612" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 183.14066,191.10612 0,417.193 -0.70711,0"
|
||||
id="path4497"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 325.13867,191.10612 0,417.193 -0.70711,0"
|
||||
id="path4497-5"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="111.75929"
|
||||
y="251.53981"
|
||||
id="text4429-8"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9"
|
||||
x="111.75929"
|
||||
y="251.53981">rcu_read_lock();</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.10254"
|
||||
y="367.91556"
|
||||
id="text4429-8-9"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9-4"
|
||||
x="396.10254"
|
||||
y="367.91556">rcu_read_lock();</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.10254"
|
||||
y="597.40289"
|
||||
id="text4429-8-9-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9-4-4"
|
||||
x="396.10254"
|
||||
y="597.40289">rcu_read_unlock();</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="111.75929"
|
||||
y="453.15311"
|
||||
id="text4429-8-9-3-1"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9-4-4-6"
|
||||
x="111.75929"
|
||||
y="453.15311">rcu_read_unlock();</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 33.941125,227.87568 436.284885,0 0,0.7071"
|
||||
id="path4608"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="394.94427"
|
||||
y="345.66351"
|
||||
id="text4648"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650"
|
||||
x="394.94427"
|
||||
y="345.66351">QS</tspan></text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(36.441125,199.60612)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="112.11968"
|
||||
y="475.77856"
|
||||
id="text4648-4"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650-4"
|
||||
x="112.11968"
|
||||
y="475.77856">QS</tspan></text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652-7"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(-246.38346,329.72117)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652-7-7"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(-103.65246,202.90878)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="254.85066"
|
||||
y="348.96619"
|
||||
id="text4648-4-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650-4-5"
|
||||
x="254.85066"
|
||||
y="348.96619">QS</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 17 KiB |
639
Documentation/RCU/Design/Requirements/ReadersPartitionGP1.svg
Normal file
@ -0,0 +1,639 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="735.25"
|
||||
height="516.21875"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="ReadersPartitionGP1.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3789-9"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path3792-4"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3670394"
|
||||
inkscape:cx="367.26465"
|
||||
inkscape:cy="258.46182"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g4433-6"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="438"
|
||||
inkscape:window-y="335"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-29.15625,-185.59375)">
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2985"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion
|
||||
id="flowRegion2987"><rect
|
||||
id="rect2989"
|
||||
width="82.85714"
|
||||
height="11.428572"
|
||||
x="240"
|
||||
y="492.36218" /></flowRegion><flowPara
|
||||
id="flowPara2991" /></flowRoot> <g
|
||||
id="g4433"
|
||||
transform="translate(2,-12)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text2993"
|
||||
y="-261.66608"
|
||||
x="436.12299"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,1,-1,0,0,0)"><tspan
|
||||
y="-261.66608"
|
||||
x="436.12299"
|
||||
id="tspan2995"
|
||||
sodipodi:role="line">synchronize_rcu()</tspan></text>
|
||||
<g
|
||||
id="g4417"
|
||||
transform="matrix(0,1,-1,0,730.90257,222.4928)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-end:url(#Arrow2Lend)"
|
||||
d="M 97.580736,477.4048 327.57913,476.09759"
|
||||
id="path2997"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 96.752718,465.38398 0,22.62742"
|
||||
id="path4397"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 328.40703,465.38397 0,22.62742"
|
||||
id="path4397-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="112.04738"
|
||||
y="268.18076"
|
||||
id="text4429"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431"
|
||||
x="112.04738"
|
||||
y="268.18076">WRITE_ONCE(a, 1);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="112.04738"
|
||||
y="487.13766"
|
||||
id="text4441"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4443"
|
||||
x="112.04738"
|
||||
y="487.13766">WRITE_ONCE(b, 1);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="255.60869"
|
||||
y="297.29346"
|
||||
id="text4445"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4447"
|
||||
x="255.60869"
|
||||
y="297.29346">r1 = READ_ONCE(a);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="255.14423"
|
||||
y="554.61786"
|
||||
id="text4449"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4451"
|
||||
x="255.14423"
|
||||
y="554.61786">WRITE_ONCE(c, 1);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.10254"
|
||||
y="370.71124"
|
||||
id="text4453"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4455"
|
||||
x="396.10254"
|
||||
y="370.71124">WRITE_ONCE(d, 1);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.10254"
|
||||
y="572.13617"
|
||||
id="text4457"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4459"
|
||||
x="396.10254"
|
||||
y="572.13617">r2 = READ_ONCE(c);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="112.08231"
|
||||
y="213.91006"
|
||||
id="text4461"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4463"
|
||||
x="112.08231"
|
||||
y="213.91006">thread0()</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="252.34512"
|
||||
y="213.91006"
|
||||
id="text4461-6"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4463-0"
|
||||
x="252.34512"
|
||||
y="213.91006">thread1()</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.42557"
|
||||
y="213.91006"
|
||||
id="text4461-2"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4463-2"
|
||||
x="396.42557"
|
||||
y="213.91006">thread2()</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect4495"
|
||||
width="724.25244"
|
||||
height="505.21201"
|
||||
x="34.648232"
|
||||
y="191.10612" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 183.14066,191.10612 0,504.24243"
|
||||
id="path4497"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 325.13867,191.10612 0,504.24243"
|
||||
id="path4497-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="111.75929"
|
||||
y="251.53981"
|
||||
id="text4429-8"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9"
|
||||
x="111.75929"
|
||||
y="251.53981">rcu_read_lock();</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.10254"
|
||||
y="353.91556"
|
||||
id="text4429-8-9"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9-4"
|
||||
x="396.10254"
|
||||
y="353.91556">rcu_read_lock();</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="396.10254"
|
||||
y="587.40289"
|
||||
id="text4429-8-9-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9-4-4"
|
||||
x="396.10254"
|
||||
y="587.40289">rcu_read_unlock();</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="111.75929"
|
||||
y="501.15311"
|
||||
id="text4429-8-9-3-1"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9-4-4-6"
|
||||
x="111.75929"
|
||||
y="501.15311">rcu_read_unlock();</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 33.941125,227.87568 724.941765,0"
|
||||
id="path4608"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="394.94427"
|
||||
y="331.66351"
|
||||
id="text4648"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650"
|
||||
x="394.94427"
|
||||
y="331.66351">QS</tspan></text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(36.441125,185.60612)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="112.11968"
|
||||
y="523.77856"
|
||||
id="text4648-4"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650-4"
|
||||
x="112.11968"
|
||||
y="523.77856">QS</tspan></text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652-7"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(-246.38346,377.72117)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652-7-7"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(-103.65246,190.90878)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="254.85066"
|
||||
y="336.96619"
|
||||
id="text4648-4-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650-4-5"
|
||||
x="254.85066"
|
||||
y="336.96619">QS</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 470.93311,190.39903 0,504.24243"
|
||||
id="path4497-5-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 616.22755,190.38323 0,504.24243"
|
||||
id="path4497-5-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
id="g4433-6"
|
||||
transform="translate(288.0964,78.32827)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text2993-7"
|
||||
y="-261.66608"
|
||||
x="440.12299"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,1,-1,0,0,0)"><tspan
|
||||
y="-261.66608"
|
||||
x="440.12299"
|
||||
id="tspan2995-1"
|
||||
sodipodi:role="line">synchronize_rcu()</tspan></text>
|
||||
<g
|
||||
id="g4417-1"
|
||||
transform="matrix(0,1,-1,0,730.90257,222.4928)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-end:url(#Arrow2Lend)"
|
||||
d="M 97.580736,477.4048 328.5624,477.07246"
|
||||
id="path2997-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 96.752718,465.38398 0,22.62742"
|
||||
id="path4397-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 329.39039,465.38397 0,22.62742"
|
||||
id="path4397-5-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="541.70508"
|
||||
y="387.6217"
|
||||
id="text4445-0"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4447-5"
|
||||
x="541.70508"
|
||||
y="387.6217">r3 = READ_ONCE(d);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="541.2406"
|
||||
y="646.94611"
|
||||
id="text4449-6"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4451-6"
|
||||
x="541.2406"
|
||||
y="646.94611">WRITE_ONCE(e, 1);</tspan></text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652-7-7-5"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(182.44393,281.23704)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="540.94702"
|
||||
y="427.29443"
|
||||
id="text4648-4-3-1"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650-4-5-7"
|
||||
x="540.94702"
|
||||
y="427.29443">QS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="686.27747"
|
||||
y="461.83929"
|
||||
id="text4453-7"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4455-1"
|
||||
x="686.27747"
|
||||
y="461.83929">r4 = READ_ONCE(b);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="686.27747"
|
||||
y="669.26422"
|
||||
id="text4457-9"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4459-2"
|
||||
x="686.27747"
|
||||
y="669.26422">r5 = READ_ONCE(e);</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="686.27747"
|
||||
y="445.04358"
|
||||
id="text4429-8-9-33"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9-4-2"
|
||||
x="686.27747"
|
||||
y="445.04358">rcu_read_lock();</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="686.27747"
|
||||
y="684.53094"
|
||||
id="text4429-8-9-3-8"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4431-9-4-4-5"
|
||||
x="686.27747"
|
||||
y="684.53094">rcu_read_unlock();</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="685.11914"
|
||||
y="422.79153"
|
||||
id="text4648-9"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650-7"
|
||||
x="685.11914"
|
||||
y="422.79153">QS</tspan></text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652-8"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(326.61602,276.73415)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="397.85934"
|
||||
y="609.59003"
|
||||
id="text4648-5"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650-77"
|
||||
x="397.85934"
|
||||
y="609.59003">QS</tspan></text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652-80"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(39.356201,463.53264)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="256.75986"
|
||||
y="586.99133"
|
||||
id="text4648-5-2"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4650-77-7"
|
||||
x="256.75986"
|
||||
y="586.99133">QS</tspan></text>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path4652-80-5"
|
||||
sodipodi:cx="358.85669"
|
||||
sodipodi:cy="142.87541"
|
||||
sodipodi:rx="10.960155"
|
||||
sodipodi:ry="10.253048"
|
||||
d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0"
|
||||
transform="translate(-101.74328,440.93395)"
|
||||
sodipodi:start="4.7135481"
|
||||
sodipodi:end="10.994651"
|
||||
sodipodi:open="true" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="546.22791"
|
||||
y="213.91006"
|
||||
id="text4461-2-5"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4463-2-6"
|
||||
x="546.22791"
|
||||
y="213.91006">thread3()</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"
|
||||
x="684.00067"
|
||||
y="213.91006"
|
||||
id="text4461-2-1"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4463-2-0"
|
||||
x="684.00067"
|
||||
y="213.91006">thread4()</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 29 KiB |
2728
Documentation/RCU/Design/Requirements/Requirements.rst
Normal file
123
Documentation/RCU/NMI-RCU.rst
Normal file
@ -0,0 +1,123 @@
|
||||
.. _NMI_rcu_doc:
|
||||
|
||||
Using RCU to Protect Dynamic NMI Handlers
|
||||
=========================================
|
||||
|
||||
|
||||
Although RCU is usually used to protect read-mostly data structures,
|
||||
it is possible to use RCU to provide dynamic non-maskable interrupt
|
||||
handlers, as well as dynamic irq handlers. This document describes
|
||||
how to do this, drawing loosely from Zwane Mwaikambo's NMI-timer
|
||||
work in "arch/x86/kernel/traps.c".
|
||||
|
||||
The relevant pieces of code are listed below, each followed by a
|
||||
brief explanation::
|
||||
|
||||
static int dummy_nmi_callback(struct pt_regs *regs, int cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
The dummy_nmi_callback() function is a "dummy" NMI handler that does
|
||||
nothing, but returns zero, thus saying that it did nothing, allowing
|
||||
the NMI handler to take the default machine-specific action::
|
||||
|
||||
static nmi_callback_t nmi_callback = dummy_nmi_callback;
|
||||
|
||||
This nmi_callback variable is a global function pointer to the current
|
||||
NMI handler::
|
||||
|
||||
void do_nmi(struct pt_regs * regs, long error_code)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
nmi_enter();
|
||||
|
||||
cpu = smp_processor_id();
|
||||
++nmi_count(cpu);
|
||||
|
||||
if (!rcu_dereference_sched(nmi_callback)(regs, cpu))
|
||||
default_do_nmi(regs);
|
||||
|
||||
nmi_exit();
|
||||
}
|
||||
|
||||
The do_nmi() function processes each NMI. It first disables preemption
|
||||
in the same way that a hardware irq would, then increments the per-CPU
|
||||
count of NMIs. It then invokes the NMI handler stored in the nmi_callback
|
||||
function pointer. If this handler returns zero, do_nmi() invokes the
|
||||
default_do_nmi() function to handle a machine-specific NMI. Finally,
|
||||
preemption is restored.
|
||||
|
||||
In theory, rcu_dereference_sched() is not needed, since this code runs
|
||||
only on i386, which in theory does not need rcu_dereference_sched()
|
||||
anyway. However, in practice it is a good documentation aid, particularly
|
||||
for anyone attempting to do something similar on Alpha or on systems
|
||||
with aggressive optimizing compilers.
|
||||
|
||||
Quick Quiz:
|
||||
Why might the rcu_dereference_sched() be necessary on Alpha, given that the code referenced by the pointer is read-only?
|
||||
|
||||
:ref:`Answer to Quick Quiz <answer_quick_quiz_NMI>`
|
||||
|
||||
Back to the discussion of NMI and RCU::
|
||||
|
||||
void set_nmi_callback(nmi_callback_t callback)
|
||||
{
|
||||
rcu_assign_pointer(nmi_callback, callback);
|
||||
}
|
||||
|
||||
The set_nmi_callback() function registers an NMI handler. Note that any
|
||||
data that is to be used by the callback must be initialized up -before-
|
||||
the call to set_nmi_callback(). On architectures that do not order
|
||||
writes, the rcu_assign_pointer() ensures that the NMI handler sees the
|
||||
initialized values::
|
||||
|
||||
void unset_nmi_callback(void)
|
||||
{
|
||||
rcu_assign_pointer(nmi_callback, dummy_nmi_callback);
|
||||
}
|
||||
|
||||
This function unregisters an NMI handler, restoring the original
|
||||
dummy_nmi_handler(). However, there may well be an NMI handler
|
||||
currently executing on some other CPU. We therefore cannot free
|
||||
up any data structures used by the old NMI handler until execution
|
||||
of it completes on all other CPUs.
|
||||
|
||||
One way to accomplish this is via synchronize_rcu(), perhaps as
|
||||
follows::
|
||||
|
||||
unset_nmi_callback();
|
||||
synchronize_rcu();
|
||||
kfree(my_nmi_data);
|
||||
|
||||
This works because (as of v4.20) synchronize_rcu() blocks until all
|
||||
CPUs complete any preemption-disabled segments of code that they were
|
||||
executing.
|
||||
Since NMI handlers disable preemption, synchronize_rcu() is guaranteed
|
||||
not to return until all ongoing NMI handlers exit. It is therefore safe
|
||||
to free up the handler's data as soon as synchronize_rcu() returns.
|
||||
|
||||
Important note: for this to work, the architecture in question must
|
||||
invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively.
|
||||
|
||||
.. _answer_quick_quiz_NMI:
|
||||
|
||||
Answer to Quick Quiz:
|
||||
Why might the rcu_dereference_sched() be necessary on Alpha, given that the code referenced by the pointer is read-only?
|
||||
|
||||
The caller to set_nmi_callback() might well have
|
||||
initialized some data that is to be used by the new NMI
|
||||
handler. In this case, the rcu_dereference_sched() would
|
||||
be needed, because otherwise a CPU that received an NMI
|
||||
just after the new handler was set might see the pointer
|
||||
to the new NMI handler, but the old pre-initialized
|
||||
version of the handler's data.
|
||||
|
||||
This same sad story can happen on other CPUs when using
|
||||
a compiler with aggressive pointer-value speculation
|
||||
optimizations.
|
||||
|
||||
More important, the rcu_dereference_sched() makes it
|
||||
clear to someone reading the code that the pointer is
|
||||
being protected by RCU-sched.
|
2812
Documentation/RCU/RTFP.txt
Normal file
143
Documentation/RCU/UP.rst
Normal file
@ -0,0 +1,143 @@
|
||||
.. _up_doc:
|
||||
|
||||
RCU on Uniprocessor Systems
|
||||
===========================
|
||||
|
||||
A common misconception is that, on UP systems, the call_rcu() primitive
|
||||
may immediately invoke its function. The basis of this misconception
|
||||
is that since there is only one CPU, it should not be necessary to
|
||||
wait for anything else to get done, since there are no other CPUs for
|
||||
anything else to be happening on. Although this approach will *sort of*
|
||||
work a surprising amount of the time, it is a very bad idea in general.
|
||||
This document presents three examples that demonstrate exactly how bad
|
||||
an idea this is.
|
||||
|
||||
Example 1: softirq Suicide
|
||||
--------------------------
|
||||
|
||||
Suppose that an RCU-based algorithm scans a linked list containing
|
||||
elements A, B, and C in process context, and can delete elements from
|
||||
this same list in softirq context. Suppose that the process-context scan
|
||||
is referencing element B when it is interrupted by softirq processing,
|
||||
which deletes element B, and then invokes call_rcu() to free element B
|
||||
after a grace period.
|
||||
|
||||
Now, if call_rcu() were to directly invoke its arguments, then upon return
|
||||
from softirq, the list scan would find itself referencing a newly freed
|
||||
element B. This situation can greatly decrease the life expectancy of
|
||||
your kernel.
|
||||
|
||||
This same problem can occur if call_rcu() is invoked from a hardware
|
||||
interrupt handler.
|
||||
|
||||
Example 2: Function-Call Fatality
|
||||
---------------------------------
|
||||
|
||||
Of course, one could avert the suicide described in the preceding example
|
||||
by having call_rcu() directly invoke its arguments only if it was called
|
||||
from process context. However, this can fail in a similar manner.
|
||||
|
||||
Suppose that an RCU-based algorithm again scans a linked list containing
|
||||
elements A, B, and C in process contexts, but that it invokes a function
|
||||
on each element as it is scanned. Suppose further that this function
|
||||
deletes element B from the list, then passes it to call_rcu() for deferred
|
||||
freeing. This may be a bit unconventional, but it is perfectly legal
|
||||
RCU usage, since call_rcu() must wait for a grace period to elapse.
|
||||
Therefore, in this case, allowing call_rcu() to immediately invoke
|
||||
its arguments would cause it to fail to make the fundamental guarantee
|
||||
underlying RCU, namely that call_rcu() defers invoking its arguments until
|
||||
all RCU read-side critical sections currently executing have completed.
|
||||
|
||||
Quick Quiz #1:
|
||||
Why is it *not* legal to invoke synchronize_rcu() in this case?
|
||||
|
||||
:ref:`Answers to Quick Quiz <answer_quick_quiz_up>`
|
||||
|
||||
Example 3: Death by Deadlock
|
||||
----------------------------
|
||||
|
||||
Suppose that call_rcu() is invoked while holding a lock, and that the
|
||||
callback function must acquire this same lock. In this case, if
|
||||
call_rcu() were to directly invoke the callback, the result would
|
||||
be self-deadlock.
|
||||
|
||||
In some cases, it would possible to restructure to code so that
|
||||
the call_rcu() is delayed until after the lock is released. However,
|
||||
there are cases where this can be quite ugly:
|
||||
|
||||
1. If a number of items need to be passed to call_rcu() within
|
||||
the same critical section, then the code would need to create
|
||||
a list of them, then traverse the list once the lock was
|
||||
released.
|
||||
|
||||
2. In some cases, the lock will be held across some kernel API,
|
||||
so that delaying the call_rcu() until the lock is released
|
||||
requires that the data item be passed up via a common API.
|
||||
It is far better to guarantee that callbacks are invoked
|
||||
with no locks held than to have to modify such APIs to allow
|
||||
arbitrary data items to be passed back up through them.
|
||||
|
||||
If call_rcu() directly invokes the callback, painful locking restrictions
|
||||
or API changes would be required.
|
||||
|
||||
Quick Quiz #2:
|
||||
What locking restriction must RCU callbacks respect?
|
||||
|
||||
:ref:`Answers to Quick Quiz <answer_quick_quiz_up>`
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
Permitting call_rcu() to immediately invoke its arguments breaks RCU,
|
||||
even on a UP system. So do not do it! Even on a UP system, the RCU
|
||||
infrastructure *must* respect grace periods, and *must* invoke callbacks
|
||||
from a known environment in which no locks are held.
|
||||
|
||||
Note that it *is* safe for synchronize_rcu() to return immediately on
|
||||
UP systems, including PREEMPT SMP builds running on UP systems.
|
||||
|
||||
Quick Quiz #3:
|
||||
Why can't synchronize_rcu() return immediately on UP systems running
|
||||
preemptable RCU?
|
||||
|
||||
.. _answer_quick_quiz_up:
|
||||
|
||||
Answer to Quick Quiz #1:
|
||||
Why is it *not* legal to invoke synchronize_rcu() in this case?
|
||||
|
||||
Because the calling function is scanning an RCU-protected linked
|
||||
list, and is therefore within an RCU read-side critical section.
|
||||
Therefore, the called function has been invoked within an RCU
|
||||
read-side critical section, and is not permitted to block.
|
||||
|
||||
Answer to Quick Quiz #2:
|
||||
What locking restriction must RCU callbacks respect?
|
||||
|
||||
Any lock that is acquired within an RCU callback must be acquired
|
||||
elsewhere using an _bh variant of the spinlock primitive.
|
||||
For example, if "mylock" is acquired by an RCU callback, then
|
||||
a process-context acquisition of this lock must use something
|
||||
like spin_lock_bh() to acquire the lock. Please note that
|
||||
it is also OK to use _irq variants of spinlocks, for example,
|
||||
spin_lock_irqsave().
|
||||
|
||||
If the process-context code were to simply use spin_lock(),
|
||||
then, since RCU callbacks can be invoked from softirq context,
|
||||
the callback might be called from a softirq that interrupted
|
||||
the process-context critical section. This would result in
|
||||
self-deadlock.
|
||||
|
||||
This restriction might seem gratuitous, since very few RCU
|
||||
callbacks acquire locks directly. However, a great many RCU
|
||||
callbacks do acquire locks *indirectly*, for example, via
|
||||
the kfree() primitive.
|
||||
|
||||
Answer to Quick Quiz #3:
|
||||
Why can't synchronize_rcu() return immediately on UP systems
|
||||
running preemptable RCU?
|
||||
|
||||
Because some other task might have been preempted in the middle
|
||||
of an RCU read-side critical section. If synchronize_rcu()
|
||||
simply immediately returned, it would prematurely signal the
|
||||
end of the grace period, which would come as a nasty shock to
|
||||
that other thread when it started running again.
|
165
Documentation/RCU/arrayRCU.rst
Normal file
@ -0,0 +1,165 @@
|
||||
.. _array_rcu_doc:
|
||||
|
||||
Using RCU to Protect Read-Mostly Arrays
|
||||
=======================================
|
||||
|
||||
Although RCU is more commonly used to protect linked lists, it can
|
||||
also be used to protect arrays. Three situations are as follows:
|
||||
|
||||
1. :ref:`Hash Tables <hash_tables>`
|
||||
|
||||
2. :ref:`Static Arrays <static_arrays>`
|
||||
|
||||
3. :ref:`Resizable Arrays <resizable_arrays>`
|
||||
|
||||
Each of these three situations involves an RCU-protected pointer to an
|
||||
array that is separately indexed. It might be tempting to consider use
|
||||
of RCU to instead protect the index into an array, however, this use
|
||||
case is **not** supported. The problem with RCU-protected indexes into
|
||||
arrays is that compilers can play way too many optimization games with
|
||||
integers, which means that the rules governing handling of these indexes
|
||||
are far more trouble than they are worth. If RCU-protected indexes into
|
||||
arrays prove to be particularly valuable (which they have not thus far),
|
||||
explicit cooperation from the compiler will be required to permit them
|
||||
to be safely used.
|
||||
|
||||
That aside, each of the three RCU-protected pointer situations are
|
||||
described in the following sections.
|
||||
|
||||
.. _hash_tables:
|
||||
|
||||
Situation 1: Hash Tables
|
||||
------------------------
|
||||
|
||||
Hash tables are often implemented as an array, where each array entry
|
||||
has a linked-list hash chain. Each hash chain can be protected by RCU
|
||||
as described in the listRCU.txt document. This approach also applies
|
||||
to other array-of-list situations, such as radix trees.
|
||||
|
||||
.. _static_arrays:
|
||||
|
||||
Situation 2: Static Arrays
|
||||
--------------------------
|
||||
|
||||
Static arrays, where the data (rather than a pointer to the data) is
|
||||
located in each array element, and where the array is never resized,
|
||||
have not been used with RCU. Rik van Riel recommends using seqlock in
|
||||
this situation, which would also have minimal read-side overhead as long
|
||||
as updates are rare.
|
||||
|
||||
Quick Quiz:
|
||||
Why is it so important that updates be rare when using seqlock?
|
||||
|
||||
:ref:`Answer to Quick Quiz <answer_quick_quiz_seqlock>`
|
||||
|
||||
.. _resizable_arrays:
|
||||
|
||||
Situation 3: Resizable Arrays
|
||||
------------------------------
|
||||
|
||||
Use of RCU for resizable arrays is demonstrated by the grow_ary()
|
||||
function formerly used by the System V IPC code. The array is used
|
||||
to map from semaphore, message-queue, and shared-memory IDs to the data
|
||||
structure that represents the corresponding IPC construct. The grow_ary()
|
||||
function does not acquire any locks; instead its caller must hold the
|
||||
ids->sem semaphore.
|
||||
|
||||
The grow_ary() function, shown below, does some limit checks, allocates a
|
||||
new ipc_id_ary, copies the old to the new portion of the new, initializes
|
||||
the remainder of the new, updates the ids->entries pointer to point to
|
||||
the new array, and invokes ipc_rcu_putref() to free up the old array.
|
||||
Note that rcu_assign_pointer() is used to update the ids->entries pointer,
|
||||
which includes any memory barriers required on whatever architecture
|
||||
you are running on::
|
||||
|
||||
static int grow_ary(struct ipc_ids* ids, int newsize)
|
||||
{
|
||||
struct ipc_id_ary* new;
|
||||
struct ipc_id_ary* old;
|
||||
int i;
|
||||
int size = ids->entries->size;
|
||||
|
||||
if(newsize > IPCMNI)
|
||||
newsize = IPCMNI;
|
||||
if(newsize <= size)
|
||||
return newsize;
|
||||
|
||||
new = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*newsize +
|
||||
sizeof(struct ipc_id_ary));
|
||||
if(new == NULL)
|
||||
return size;
|
||||
new->size = newsize;
|
||||
memcpy(new->p, ids->entries->p,
|
||||
sizeof(struct kern_ipc_perm *)*size +
|
||||
sizeof(struct ipc_id_ary));
|
||||
for(i=size;i<newsize;i++) {
|
||||
new->p[i] = NULL;
|
||||
}
|
||||
old = ids->entries;
|
||||
|
||||
/*
|
||||
* Use rcu_assign_pointer() to make sure the memcpyed
|
||||
* contents of the new array are visible before the new
|
||||
* array becomes visible.
|
||||
*/
|
||||
rcu_assign_pointer(ids->entries, new);
|
||||
|
||||
ipc_rcu_putref(old);
|
||||
return newsize;
|
||||
}
|
||||
|
||||
The ipc_rcu_putref() function decrements the array's reference count
|
||||
and then, if the reference count has dropped to zero, uses call_rcu()
|
||||
to free the array after a grace period has elapsed.
|
||||
|
||||
The array is traversed by the ipc_lock() function. This function
|
||||
indexes into the array under the protection of rcu_read_lock(),
|
||||
using rcu_dereference() to pick up the pointer to the array so
|
||||
that it may later safely be dereferenced -- memory barriers are
|
||||
required on the Alpha CPU. Since the size of the array is stored
|
||||
with the array itself, there can be no array-size mismatches, so
|
||||
a simple check suffices. The pointer to the structure corresponding
|
||||
to the desired IPC object is placed in "out", with NULL indicating
|
||||
a non-existent entry. After acquiring "out->lock", the "out->deleted"
|
||||
flag indicates whether the IPC object is in the process of being
|
||||
deleted, and, if not, the pointer is returned::
|
||||
|
||||
struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
|
||||
{
|
||||
struct kern_ipc_perm* out;
|
||||
int lid = id % SEQ_MULTIPLIER;
|
||||
struct ipc_id_ary* entries;
|
||||
|
||||
rcu_read_lock();
|
||||
entries = rcu_dereference(ids->entries);
|
||||
if(lid >= entries->size) {
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
out = entries->p[lid];
|
||||
if(out == NULL) {
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
spin_lock(&out->lock);
|
||||
|
||||
/* ipc_rmid() may have already freed the ID while ipc_lock
|
||||
* was spinning: here verify that the structure is still valid
|
||||
*/
|
||||
if (out->deleted) {
|
||||
spin_unlock(&out->lock);
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
.. _answer_quick_quiz_seqlock:
|
||||
|
||||
Answer to Quick Quiz:
|
||||
Why is it so important that updates be rare when using seqlock?
|
||||
|
||||
The reason that it is important that updates be rare when
|
||||
using seqlock is that frequent updates can livelock readers.
|
||||
One way to avoid this problem is to assign a seqlock for
|
||||
each array entry rather than to the entire array.
|
483
Documentation/RCU/checklist.rst
Normal file
@ -0,0 +1,483 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
================================
|
||||
Review Checklist for RCU Patches
|
||||
================================
|
||||
|
||||
|
||||
This document contains a checklist for producing and reviewing patches
|
||||
that make use of RCU. Violating any of the rules listed below will
|
||||
result in the same sorts of problems that leaving out a locking primitive
|
||||
would cause. This list is based on experiences reviewing such patches
|
||||
over a rather long period of time, but improvements are always welcome!
|
||||
|
||||
0. Is RCU being applied to a read-mostly situation? If the data
|
||||
structure is updated more than about 10% of the time, then you
|
||||
should strongly consider some other approach, unless detailed
|
||||
performance measurements show that RCU is nonetheless the right
|
||||
tool for the job. Yes, RCU does reduce read-side overhead by
|
||||
increasing write-side overhead, which is exactly why normal uses
|
||||
of RCU will do much more reading than updating.
|
||||
|
||||
Another exception is where performance is not an issue, and RCU
|
||||
provides a simpler implementation. An example of this situation
|
||||
is the dynamic NMI code in the Linux 2.6 kernel, at least on
|
||||
architectures where NMIs are rare.
|
||||
|
||||
Yet another exception is where the low real-time latency of RCU's
|
||||
read-side primitives is critically important.
|
||||
|
||||
One final exception is where RCU readers are used to prevent
|
||||
the ABA problem (https://en.wikipedia.org/wiki/ABA_problem)
|
||||
for lockless updates. This does result in the mildly
|
||||
counter-intuitive situation where rcu_read_lock() and
|
||||
rcu_read_unlock() are used to protect updates, however, this
|
||||
approach provides the same potential simplifications that garbage
|
||||
collectors do.
|
||||
|
||||
1. Does the update code have proper mutual exclusion?
|
||||
|
||||
RCU does allow *readers* to run (almost) naked, but *writers* must
|
||||
still use some sort of mutual exclusion, such as:
|
||||
|
||||
a. locking,
|
||||
b. atomic operations, or
|
||||
c. restricting updates to a single task.
|
||||
|
||||
If you choose #b, be prepared to describe how you have handled
|
||||
memory barriers on weakly ordered machines (pretty much all of
|
||||
them -- even x86 allows later loads to be reordered to precede
|
||||
earlier stores), and be prepared to explain why this added
|
||||
complexity is worthwhile. If you choose #c, be prepared to
|
||||
explain how this single task does not become a major bottleneck on
|
||||
big multiprocessor machines (for example, if the task is updating
|
||||
information relating to itself that other tasks can read, there
|
||||
by definition can be no bottleneck). Note that the definition
|
||||
of "large" has changed significantly: Eight CPUs was "large"
|
||||
in the year 2000, but a hundred CPUs was unremarkable in 2017.
|
||||
|
||||
2. Do the RCU read-side critical sections make proper use of
|
||||
rcu_read_lock() and friends? These primitives are needed
|
||||
to prevent grace periods from ending prematurely, which
|
||||
could result in data being unceremoniously freed out from
|
||||
under your read-side code, which can greatly increase the
|
||||
actuarial risk of your kernel.
|
||||
|
||||
As a rough rule of thumb, any dereference of an RCU-protected
|
||||
pointer must be covered by rcu_read_lock(), rcu_read_lock_bh(),
|
||||
rcu_read_lock_sched(), or by the appropriate update-side lock.
|
||||
Disabling of preemption can serve as rcu_read_lock_sched(), but
|
||||
is less readable and prevents lockdep from detecting locking issues.
|
||||
|
||||
Letting RCU-protected pointers "leak" out of an RCU read-side
|
||||
critical section is every bit as bad as letting them leak out
|
||||
from under a lock. Unless, of course, you have arranged some
|
||||
other means of protection, such as a lock or a reference count
|
||||
*before* letting them out of the RCU read-side critical section.
|
||||
|
||||
3. Does the update code tolerate concurrent accesses?
|
||||
|
||||
The whole point of RCU is to permit readers to run without
|
||||
any locks or atomic operations. This means that readers will
|
||||
be running while updates are in progress. There are a number
|
||||
of ways to handle this concurrency, depending on the situation:
|
||||
|
||||
a. Use the RCU variants of the list and hlist update
|
||||
primitives to add, remove, and replace elements on
|
||||
an RCU-protected list. Alternatively, use the other
|
||||
RCU-protected data structures that have been added to
|
||||
the Linux kernel.
|
||||
|
||||
This is almost always the best approach.
|
||||
|
||||
b. Proceed as in (a) above, but also maintain per-element
|
||||
locks (that are acquired by both readers and writers)
|
||||
that guard per-element state. Of course, fields that
|
||||
the readers refrain from accessing can be guarded by
|
||||
some other lock acquired only by updaters, if desired.
|
||||
|
||||
This works quite well, also.
|
||||
|
||||
c. Make updates appear atomic to readers. For example,
|
||||
pointer updates to properly aligned fields will
|
||||
appear atomic, as will individual atomic primitives.
|
||||
Sequences of operations performed under a lock will *not*
|
||||
appear to be atomic to RCU readers, nor will sequences
|
||||
of multiple atomic primitives.
|
||||
|
||||
This can work, but is starting to get a bit tricky.
|
||||
|
||||
d. Carefully order the updates and the reads so that
|
||||
readers see valid data at all phases of the update.
|
||||
This is often more difficult than it sounds, especially
|
||||
given modern CPUs' tendency to reorder memory references.
|
||||
One must usually liberally sprinkle memory barriers
|
||||
(smp_wmb(), smp_rmb(), smp_mb()) through the code,
|
||||
making it difficult to understand and to test.
|
||||
|
||||
It is usually better to group the changing data into
|
||||
a separate structure, so that the change may be made
|
||||
to appear atomic by updating a pointer to reference
|
||||
a new structure containing updated values.
|
||||
|
||||
4. Weakly ordered CPUs pose special challenges. Almost all CPUs
|
||||
are weakly ordered -- even x86 CPUs allow later loads to be
|
||||
reordered to precede earlier stores. RCU code must take all of
|
||||
the following measures to prevent memory-corruption problems:
|
||||
|
||||
a. Readers must maintain proper ordering of their memory
|
||||
accesses. The rcu_dereference() primitive ensures that
|
||||
the CPU picks up the pointer before it picks up the data
|
||||
that the pointer points to. This really is necessary
|
||||
on Alpha CPUs.
|
||||
|
||||
The rcu_dereference() primitive is also an excellent
|
||||
documentation aid, letting the person reading the
|
||||
code know exactly which pointers are protected by RCU.
|
||||
Please note that compilers can also reorder code, and
|
||||
they are becoming increasingly aggressive about doing
|
||||
just that. The rcu_dereference() primitive therefore also
|
||||
prevents destructive compiler optimizations. However,
|
||||
with a bit of devious creativity, it is possible to
|
||||
mishandle the return value from rcu_dereference().
|
||||
Please see rcu_dereference.txt in this directory for
|
||||
more information.
|
||||
|
||||
The rcu_dereference() primitive is used by the
|
||||
various "_rcu()" list-traversal primitives, such
|
||||
as the list_for_each_entry_rcu(). Note that it is
|
||||
perfectly legal (if redundant) for update-side code to
|
||||
use rcu_dereference() and the "_rcu()" list-traversal
|
||||
primitives. This is particularly useful in code that
|
||||
is common to readers and updaters. However, lockdep
|
||||
will complain if you access rcu_dereference() outside
|
||||
of an RCU read-side critical section. See lockdep.txt
|
||||
to learn what to do about this.
|
||||
|
||||
Of course, neither rcu_dereference() nor the "_rcu()"
|
||||
list-traversal primitives can substitute for a good
|
||||
concurrency design coordinating among multiple updaters.
|
||||
|
||||
b. If the list macros are being used, the list_add_tail_rcu()
|
||||
and list_add_rcu() primitives must be used in order
|
||||
to prevent weakly ordered machines from misordering
|
||||
structure initialization and pointer planting.
|
||||
Similarly, if the hlist macros are being used, the
|
||||
hlist_add_head_rcu() primitive is required.
|
||||
|
||||
c. If the list macros are being used, the list_del_rcu()
|
||||
primitive must be used to keep list_del()'s pointer
|
||||
poisoning from inflicting toxic effects on concurrent
|
||||
readers. Similarly, if the hlist macros are being used,
|
||||
the hlist_del_rcu() primitive is required.
|
||||
|
||||
The list_replace_rcu() and hlist_replace_rcu() primitives
|
||||
may be used to replace an old structure with a new one
|
||||
in their respective types of RCU-protected lists.
|
||||
|
||||
d. Rules similar to (4b) and (4c) apply to the "hlist_nulls"
|
||||
type of RCU-protected linked lists.
|
||||
|
||||
e. Updates must ensure that initialization of a given
|
||||
structure happens before pointers to that structure are
|
||||
publicized. Use the rcu_assign_pointer() primitive
|
||||
when publicizing a pointer to a structure that can
|
||||
be traversed by an RCU read-side critical section.
|
||||
|
||||
5. If call_rcu() or call_srcu() is used, the callback function will
|
||||
be called from softirq context. In particular, it cannot block.
|
||||
|
||||
6. Since synchronize_rcu() can block, it cannot be called
|
||||
from any sort of irq context. The same rule applies
|
||||
for synchronize_srcu(), synchronize_rcu_expedited(), and
|
||||
synchronize_srcu_expedited().
|
||||
|
||||
The expedited forms of these primitives have the same semantics
|
||||
as the non-expedited forms, but expediting is both expensive and
|
||||
(with the exception of synchronize_srcu_expedited()) unfriendly
|
||||
to real-time workloads. Use of the expedited primitives should
|
||||
be restricted to rare configuration-change operations that would
|
||||
not normally be undertaken while a real-time workload is running.
|
||||
However, real-time workloads can use rcupdate.rcu_normal kernel
|
||||
boot parameter to completely disable expedited grace periods,
|
||||
though this might have performance implications.
|
||||
|
||||
In particular, if you find yourself invoking one of the expedited
|
||||
primitives repeatedly in a loop, please do everyone a favor:
|
||||
Restructure your code so that it batches the updates, allowing
|
||||
a single non-expedited primitive to cover the entire batch.
|
||||
This will very likely be faster than the loop containing the
|
||||
expedited primitive, and will be much much easier on the rest
|
||||
of the system, especially to real-time workloads running on
|
||||
the rest of the system.
|
||||
|
||||
7. As of v4.20, a given kernel implements only one RCU flavor, which
|
||||
is RCU-sched for PREEMPTION=n and RCU-preempt for PREEMPTION=y.
|
||||
If the updater uses call_rcu() or synchronize_rcu(), then
|
||||
the corresponding readers may use: (1) rcu_read_lock() and
|
||||
rcu_read_unlock(), (2) any pair of primitives that disables
|
||||
and re-enables softirq, for example, rcu_read_lock_bh() and
|
||||
rcu_read_unlock_bh(), or (3) any pair of primitives that disables
|
||||
and re-enables preemption, for example, rcu_read_lock_sched() and
|
||||
rcu_read_unlock_sched(). If the updater uses synchronize_srcu()
|
||||
or call_srcu(), then the corresponding readers must use
|
||||
srcu_read_lock() and srcu_read_unlock(), and with the same
|
||||
srcu_struct. The rules for the expedited RCU grace-period-wait
|
||||
primitives are the same as for their non-expedited counterparts.
|
||||
|
||||
If the updater uses call_rcu_tasks() or synchronize_rcu_tasks(),
|
||||
then the readers must refrain from executing voluntary
|
||||
context switches, that is, from blocking. If the updater uses
|
||||
call_rcu_tasks_trace() or synchronize_rcu_tasks_trace(), then
|
||||
the corresponding readers must use rcu_read_lock_trace() and
|
||||
rcu_read_unlock_trace(). If an updater uses call_rcu_tasks_rude()
|
||||
or synchronize_rcu_tasks_rude(), then the corresponding readers
|
||||
must use anything that disables interrupts.
|
||||
|
||||
Mixing things up will result in confusion and broken kernels, and
|
||||
has even resulted in an exploitable security issue. Therefore,
|
||||
when using non-obvious pairs of primitives, commenting is
|
||||
of course a must. One example of non-obvious pairing is
|
||||
the XDP feature in networking, which calls BPF programs from
|
||||
network-driver NAPI (softirq) context. BPF relies heavily on RCU
|
||||
protection for its data structures, but because the BPF program
|
||||
invocation happens entirely within a single local_bh_disable()
|
||||
section in a NAPI poll cycle, this usage is safe. The reason
|
||||
that this usage is safe is that readers can use anything that
|
||||
disables BH when updaters use call_rcu() or synchronize_rcu().
|
||||
|
||||
8. Although synchronize_rcu() is slower than is call_rcu(), it
|
||||
usually results in simpler code. So, unless update performance is
|
||||
critically important, the updaters cannot block, or the latency of
|
||||
synchronize_rcu() is visible from userspace, synchronize_rcu()
|
||||
should be used in preference to call_rcu(). Furthermore,
|
||||
kfree_rcu() usually results in even simpler code than does
|
||||
synchronize_rcu() without synchronize_rcu()'s multi-millisecond
|
||||
latency. So please take advantage of kfree_rcu()'s "fire and
|
||||
forget" memory-freeing capabilities where it applies.
|
||||
|
||||
An especially important property of the synchronize_rcu()
|
||||
primitive is that it automatically self-limits: if grace periods
|
||||
are delayed for whatever reason, then the synchronize_rcu()
|
||||
primitive will correspondingly delay updates. In contrast,
|
||||
code using call_rcu() should explicitly limit update rate in
|
||||
cases where grace periods are delayed, as failing to do so can
|
||||
result in excessive realtime latencies or even OOM conditions.
|
||||
|
||||
Ways of gaining this self-limiting property when using call_rcu()
|
||||
include:
|
||||
|
||||
a. Keeping a count of the number of data-structure elements
|
||||
used by the RCU-protected data structure, including
|
||||
those waiting for a grace period to elapse. Enforce a
|
||||
limit on this number, stalling updates as needed to allow
|
||||
previously deferred frees to complete. Alternatively,
|
||||
limit only the number awaiting deferred free rather than
|
||||
the total number of elements.
|
||||
|
||||
One way to stall the updates is to acquire the update-side
|
||||
mutex. (Don't try this with a spinlock -- other CPUs
|
||||
spinning on the lock could prevent the grace period
|
||||
from ever ending.) Another way to stall the updates
|
||||
is for the updates to use a wrapper function around
|
||||
the memory allocator, so that this wrapper function
|
||||
simulates OOM when there is too much memory awaiting an
|
||||
RCU grace period. There are of course many other
|
||||
variations on this theme.
|
||||
|
||||
b. Limiting update rate. For example, if updates occur only
|
||||
once per hour, then no explicit rate limiting is
|
||||
required, unless your system is already badly broken.
|
||||
Older versions of the dcache subsystem take this approach,
|
||||
guarding updates with a global lock, limiting their rate.
|
||||
|
||||
c. Trusted update -- if updates can only be done manually by
|
||||
superuser or some other trusted user, then it might not
|
||||
be necessary to automatically limit them. The theory
|
||||
here is that superuser already has lots of ways to crash
|
||||
the machine.
|
||||
|
||||
d. Periodically invoke synchronize_rcu(), permitting a limited
|
||||
number of updates per grace period.
|
||||
|
||||
The same cautions apply to call_srcu() and kfree_rcu().
|
||||
|
||||
Note that although these primitives do take action to avoid memory
|
||||
exhaustion when any given CPU has too many callbacks, a determined
|
||||
user could still exhaust memory. This is especially the case
|
||||
if a system with a large number of CPUs has been configured to
|
||||
offload all of its RCU callbacks onto a single CPU, or if the
|
||||
system has relatively little free memory.
|
||||
|
||||
9. All RCU list-traversal primitives, which include
|
||||
rcu_dereference(), list_for_each_entry_rcu(), and
|
||||
list_for_each_safe_rcu(), must be either within an RCU read-side
|
||||
critical section or must be protected by appropriate update-side
|
||||
locks. RCU read-side critical sections are delimited by
|
||||
rcu_read_lock() and rcu_read_unlock(), or by similar primitives
|
||||
such as rcu_read_lock_bh() and rcu_read_unlock_bh(), in which
|
||||
case the matching rcu_dereference() primitive must be used in
|
||||
order to keep lockdep happy, in this case, rcu_dereference_bh().
|
||||
|
||||
The reason that it is permissible to use RCU list-traversal
|
||||
primitives when the update-side lock is held is that doing so
|
||||
can be quite helpful in reducing code bloat when common code is
|
||||
shared between readers and updaters. Additional primitives
|
||||
are provided for this case, as discussed in lockdep.txt.
|
||||
|
||||
One exception to this rule is when data is only ever added to
|
||||
the linked data structure, and is never removed during any
|
||||
time that readers might be accessing that structure. In such
|
||||
cases, READ_ONCE() may be used in place of rcu_dereference()
|
||||
and the read-side markers (rcu_read_lock() and rcu_read_unlock(),
|
||||
for example) may be omitted.
|
||||
|
||||
10. Conversely, if you are in an RCU read-side critical section,
|
||||
and you don't hold the appropriate update-side lock, you *must*
|
||||
use the "_rcu()" variants of the list macros. Failing to do so
|
||||
will break Alpha, cause aggressive compilers to generate bad code,
|
||||
and confuse people trying to read your code.
|
||||
|
||||
11. Any lock acquired by an RCU callback must be acquired elsewhere
|
||||
with softirq disabled, e.g., via spin_lock_irqsave(),
|
||||
spin_lock_bh(), etc. Failing to disable softirq on a given
|
||||
acquisition of that lock will result in deadlock as soon as
|
||||
the RCU softirq handler happens to run your RCU callback while
|
||||
interrupting that acquisition's critical section.
|
||||
|
||||
12. RCU callbacks can be and are executed in parallel. In many cases,
|
||||
the callback code simply wrappers around kfree(), so that this
|
||||
is not an issue (or, more accurately, to the extent that it is
|
||||
an issue, the memory-allocator locking handles it). However,
|
||||
if the callbacks do manipulate a shared data structure, they
|
||||
must use whatever locking or other synchronization is required
|
||||
to safely access and/or modify that data structure.
|
||||
|
||||
Do not assume that RCU callbacks will be executed on the same
|
||||
CPU that executed the corresponding call_rcu() or call_srcu().
|
||||
For example, if a given CPU goes offline while having an RCU
|
||||
callback pending, then that RCU callback will execute on some
|
||||
surviving CPU. (If this was not the case, a self-spawning RCU
|
||||
callback would prevent the victim CPU from ever going offline.)
|
||||
Furthermore, CPUs designated by rcu_nocbs= might well *always*
|
||||
have their RCU callbacks executed on some other CPUs, in fact,
|
||||
for some real-time workloads, this is the whole point of using
|
||||
the rcu_nocbs= kernel boot parameter.
|
||||
|
||||
13. Unlike other forms of RCU, it *is* permissible to block in an
|
||||
SRCU read-side critical section (demarked by srcu_read_lock()
|
||||
and srcu_read_unlock()), hence the "SRCU": "sleepable RCU".
|
||||
Please note that if you don't need to sleep in read-side critical
|
||||
sections, you should be using RCU rather than SRCU, because RCU
|
||||
is almost always faster and easier to use than is SRCU.
|
||||
|
||||
Also unlike other forms of RCU, explicit initialization and
|
||||
cleanup is required either at build time via DEFINE_SRCU()
|
||||
or DEFINE_STATIC_SRCU() or at runtime via init_srcu_struct()
|
||||
and cleanup_srcu_struct(). These last two are passed a
|
||||
"struct srcu_struct" that defines the scope of a given
|
||||
SRCU domain. Once initialized, the srcu_struct is passed
|
||||
to srcu_read_lock(), srcu_read_unlock() synchronize_srcu(),
|
||||
synchronize_srcu_expedited(), and call_srcu(). A given
|
||||
synchronize_srcu() waits only for SRCU read-side critical
|
||||
sections governed by srcu_read_lock() and srcu_read_unlock()
|
||||
calls that have been passed the same srcu_struct. This property
|
||||
is what makes sleeping read-side critical sections tolerable --
|
||||
a given subsystem delays only its own updates, not those of other
|
||||
subsystems using SRCU. Therefore, SRCU is less prone to OOM the
|
||||
system than RCU would be if RCU's read-side critical sections
|
||||
were permitted to sleep.
|
||||
|
||||
The ability to sleep in read-side critical sections does not
|
||||
come for free. First, corresponding srcu_read_lock() and
|
||||
srcu_read_unlock() calls must be passed the same srcu_struct.
|
||||
Second, grace-period-detection overhead is amortized only
|
||||
over those updates sharing a given srcu_struct, rather than
|
||||
being globally amortized as they are for other forms of RCU.
|
||||
Therefore, SRCU should be used in preference to rw_semaphore
|
||||
only in extremely read-intensive situations, or in situations
|
||||
requiring SRCU's read-side deadlock immunity or low read-side
|
||||
realtime latency. You should also consider percpu_rw_semaphore
|
||||
when you need lightweight readers.
|
||||
|
||||
SRCU's expedited primitive (synchronize_srcu_expedited())
|
||||
never sends IPIs to other CPUs, so it is easier on
|
||||
real-time workloads than is synchronize_rcu_expedited().
|
||||
|
||||
Note that rcu_assign_pointer() relates to SRCU just as it does to
|
||||
other forms of RCU, but instead of rcu_dereference() you should
|
||||
use srcu_dereference() in order to avoid lockdep splats.
|
||||
|
||||
14. The whole point of call_rcu(), synchronize_rcu(), and friends
|
||||
is to wait until all pre-existing readers have finished before
|
||||
carrying out some otherwise-destructive operation. It is
|
||||
therefore critically important to *first* remove any path
|
||||
that readers can follow that could be affected by the
|
||||
destructive operation, and *only then* invoke call_rcu(),
|
||||
synchronize_rcu(), or friends.
|
||||
|
||||
Because these primitives only wait for pre-existing readers, it
|
||||
is the caller's responsibility to guarantee that any subsequent
|
||||
readers will execute safely.
|
||||
|
||||
15. The various RCU read-side primitives do *not* necessarily contain
|
||||
memory barriers. You should therefore plan for the CPU
|
||||
and the compiler to freely reorder code into and out of RCU
|
||||
read-side critical sections. It is the responsibility of the
|
||||
RCU update-side primitives to deal with this.
|
||||
|
||||
For SRCU readers, you can use smp_mb__after_srcu_read_unlock()
|
||||
immediately after an srcu_read_unlock() to get a full barrier.
|
||||
|
||||
16. Use CONFIG_PROVE_LOCKING, CONFIG_DEBUG_OBJECTS_RCU_HEAD, and the
|
||||
__rcu sparse checks to validate your RCU code. These can help
|
||||
find problems as follows:
|
||||
|
||||
CONFIG_PROVE_LOCKING:
|
||||
check that accesses to RCU-protected data
|
||||
structures are carried out under the proper RCU
|
||||
read-side critical section, while holding the right
|
||||
combination of locks, or whatever other conditions
|
||||
are appropriate.
|
||||
|
||||
CONFIG_DEBUG_OBJECTS_RCU_HEAD:
|
||||
check that you don't pass the
|
||||
same object to call_rcu() (or friends) before an RCU
|
||||
grace period has elapsed since the last time that you
|
||||
passed that same object to call_rcu() (or friends).
|
||||
|
||||
__rcu sparse checks:
|
||||
tag the pointer to the RCU-protected data
|
||||
structure with __rcu, and sparse will warn you if you
|
||||
access that pointer without the services of one of the
|
||||
variants of rcu_dereference().
|
||||
|
||||
These debugging aids can help you find problems that are
|
||||
otherwise extremely difficult to spot.
|
||||
|
||||
17. If you register a callback using call_rcu() or call_srcu(), and
|
||||
pass in a function defined within a loadable module, then it in
|
||||
necessary to wait for all pending callbacks to be invoked after
|
||||
the last invocation and before unloading that module. Note that
|
||||
it is absolutely *not* sufficient to wait for a grace period!
|
||||
The current (say) synchronize_rcu() implementation is *not*
|
||||
guaranteed to wait for callbacks registered on other CPUs.
|
||||
Or even on the current CPU if that CPU recently went offline
|
||||
and came back online.
|
||||
|
||||
You instead need to use one of the barrier functions:
|
||||
|
||||
- call_rcu() -> rcu_barrier()
|
||||
- call_srcu() -> srcu_barrier()
|
||||
|
||||
However, these barrier functions are absolutely *not* guaranteed
|
||||
to wait for a grace period. In fact, if there are no call_rcu()
|
||||
callbacks waiting anywhere in the system, rcu_barrier() is within
|
||||
its rights to return immediately.
|
||||
|
||||
So if you need to wait for both an RCU grace period and for
|
||||
all pre-existing call_rcu() callbacks, you will need to execute
|
||||
both rcu_barrier() and synchronize_rcu(), if necessary, using
|
||||
something like workqueues to to execute them concurrently.
|
||||
|
||||
See rcubarrier.txt for more information.
|
38
Documentation/RCU/index.rst
Normal file
@ -0,0 +1,38 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. _rcu_concepts:
|
||||
|
||||
============
|
||||
RCU concepts
|
||||
============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
arrayRCU
|
||||
checklist
|
||||
lockdep
|
||||
lockdep-splat
|
||||
rcubarrier
|
||||
rcu_dereference
|
||||
whatisRCU
|
||||
rcu
|
||||
rculist_nulls
|
||||
rcuref
|
||||
torture
|
||||
stallwarn
|
||||
listRCU
|
||||
NMI-RCU
|
||||
UP
|
||||
|
||||
Design/Memory-Ordering/Tree-RCU-Memory-Ordering
|
||||
Design/Expedited-Grace-Periods/Expedited-Grace-Periods
|
||||
Design/Requirements/Requirements
|
||||
Design/Data-Structures/Data-Structures
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
Indices
|
||||
=======
|
||||
|
||||
* :ref:`genindex`
|
468
Documentation/RCU/listRCU.rst
Normal file
@ -0,0 +1,468 @@
|
||||
.. _list_rcu_doc:
|
||||
|
||||
Using RCU to Protect Read-Mostly Linked Lists
|
||||
=============================================
|
||||
|
||||
One of the best applications of RCU is to protect read-mostly linked lists
|
||||
(``struct list_head`` in list.h). One big advantage of this approach
|
||||
is that all of the required memory barriers are included for you in
|
||||
the list macros. This document describes several applications of RCU,
|
||||
with the best fits first.
|
||||
|
||||
|
||||
Example 1: Read-mostly list: Deferred Destruction
|
||||
-------------------------------------------------
|
||||
|
||||
A widely used usecase for RCU lists in the kernel is lockless iteration over
|
||||
all processes in the system. ``task_struct::tasks`` represents the list node that
|
||||
links all the processes. The list can be traversed in parallel to any list
|
||||
additions or removals.
|
||||
|
||||
The traversal of the list is done using ``for_each_process()`` which is defined
|
||||
by the 2 macros::
|
||||
|
||||
#define next_task(p) \
|
||||
list_entry_rcu((p)->tasks.next, struct task_struct, tasks)
|
||||
|
||||
#define for_each_process(p) \
|
||||
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
|
||||
|
||||
The code traversing the list of all processes typically looks like::
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_process(p) {
|
||||
/* Do something with p */
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
The simplified code for removing a process from a task list is::
|
||||
|
||||
void release_task(struct task_struct *p)
|
||||
{
|
||||
write_lock(&tasklist_lock);
|
||||
list_del_rcu(&p->tasks);
|
||||
write_unlock(&tasklist_lock);
|
||||
call_rcu(&p->rcu, delayed_put_task_struct);
|
||||
}
|
||||
|
||||
When a process exits, ``release_task()`` calls ``list_del_rcu(&p->tasks)`` under
|
||||
``tasklist_lock`` writer lock protection, to remove the task from the list of
|
||||
all tasks. The ``tasklist_lock`` prevents concurrent list additions/removals
|
||||
from corrupting the list. Readers using ``for_each_process()`` are not protected
|
||||
with the ``tasklist_lock``. To prevent readers from noticing changes in the list
|
||||
pointers, the ``task_struct`` object is freed only after one or more grace
|
||||
periods elapse (with the help of call_rcu()). This deferring of destruction
|
||||
ensures that any readers traversing the list will see valid ``p->tasks.next``
|
||||
pointers and deletion/freeing can happen in parallel with traversal of the list.
|
||||
This pattern is also called an **existence lock**, since RCU pins the object in
|
||||
memory until all existing readers finish.
|
||||
|
||||
|
||||
Example 2: Read-Side Action Taken Outside of Lock: No In-Place Updates
|
||||
----------------------------------------------------------------------
|
||||
|
||||
The best applications are cases where, if reader-writer locking were
|
||||
used, the read-side lock would be dropped before taking any action
|
||||
based on the results of the search. The most celebrated example is
|
||||
the routing table. Because the routing table is tracking the state of
|
||||
equipment outside of the computer, it will at times contain stale data.
|
||||
Therefore, once the route has been computed, there is no need to hold
|
||||
the routing table static during transmission of the packet. After all,
|
||||
you can hold the routing table static all you want, but that won't keep
|
||||
the external Internet from changing, and it is the state of the external
|
||||
Internet that really matters. In addition, routing entries are typically
|
||||
added or deleted, rather than being modified in place.
|
||||
|
||||
A straightforward example of this use of RCU may be found in the
|
||||
system-call auditing support. For example, a reader-writer locked
|
||||
implementation of ``audit_filter_task()`` might be as follows::
|
||||
|
||||
static enum audit_state audit_filter_task(struct task_struct *tsk)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
enum audit_state state;
|
||||
|
||||
read_lock(&auditsc_lock);
|
||||
/* Note: audit_filter_mutex held by caller. */
|
||||
list_for_each_entry(e, &audit_tsklist, list) {
|
||||
if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
|
||||
read_unlock(&auditsc_lock);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
read_unlock(&auditsc_lock);
|
||||
return AUDIT_BUILD_CONTEXT;
|
||||
}
|
||||
|
||||
Here the list is searched under the lock, but the lock is dropped before
|
||||
the corresponding value is returned. By the time that this value is acted
|
||||
on, the list may well have been modified. This makes sense, since if
|
||||
you are turning auditing off, it is OK to audit a few extra system calls.
|
||||
|
||||
This means that RCU can be easily applied to the read side, as follows::
|
||||
|
||||
static enum audit_state audit_filter_task(struct task_struct *tsk)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
enum audit_state state;
|
||||
|
||||
rcu_read_lock();
|
||||
/* Note: audit_filter_mutex held by caller. */
|
||||
list_for_each_entry_rcu(e, &audit_tsklist, list) {
|
||||
if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
|
||||
rcu_read_unlock();
|
||||
return state;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return AUDIT_BUILD_CONTEXT;
|
||||
}
|
||||
|
||||
The ``read_lock()`` and ``read_unlock()`` calls have become rcu_read_lock()
|
||||
and rcu_read_unlock(), respectively, and the list_for_each_entry() has
|
||||
become list_for_each_entry_rcu(). The **_rcu()** list-traversal primitives
|
||||
insert the read-side memory barriers that are required on DEC Alpha CPUs.
|
||||
|
||||
The changes to the update side are also straightforward. A reader-writer lock
|
||||
might be used as follows for deletion and insertion::
|
||||
|
||||
static inline int audit_del_rule(struct audit_rule *rule,
|
||||
struct list_head *list)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
|
||||
write_lock(&auditsc_lock);
|
||||
list_for_each_entry(e, list, list) {
|
||||
if (!audit_compare_rule(rule, &e->rule)) {
|
||||
list_del(&e->list);
|
||||
write_unlock(&auditsc_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
write_unlock(&auditsc_lock);
|
||||
return -EFAULT; /* No matching rule */
|
||||
}
|
||||
|
||||
static inline int audit_add_rule(struct audit_entry *entry,
|
||||
struct list_head *list)
|
||||
{
|
||||
write_lock(&auditsc_lock);
|
||||
if (entry->rule.flags & AUDIT_PREPEND) {
|
||||
entry->rule.flags &= ~AUDIT_PREPEND;
|
||||
list_add(&entry->list, list);
|
||||
} else {
|
||||
list_add_tail(&entry->list, list);
|
||||
}
|
||||
write_unlock(&auditsc_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Following are the RCU equivalents for these two functions::
|
||||
|
||||
static inline int audit_del_rule(struct audit_rule *rule,
|
||||
struct list_head *list)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
|
||||
/* No need to use the _rcu iterator here, since this is the only
|
||||
* deletion routine. */
|
||||
list_for_each_entry(e, list, list) {
|
||||
if (!audit_compare_rule(rule, &e->rule)) {
|
||||
list_del_rcu(&e->list);
|
||||
call_rcu(&e->rcu, audit_free_rule);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EFAULT; /* No matching rule */
|
||||
}
|
||||
|
||||
static inline int audit_add_rule(struct audit_entry *entry,
|
||||
struct list_head *list)
|
||||
{
|
||||
if (entry->rule.flags & AUDIT_PREPEND) {
|
||||
entry->rule.flags &= ~AUDIT_PREPEND;
|
||||
list_add_rcu(&entry->list, list);
|
||||
} else {
|
||||
list_add_tail_rcu(&entry->list, list);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Normally, the ``write_lock()`` and ``write_unlock()`` would be replaced by a
|
||||
spin_lock() and a spin_unlock(). But in this case, all callers hold
|
||||
``audit_filter_mutex``, so no additional locking is required. The
|
||||
``auditsc_lock`` can therefore be eliminated, since use of RCU eliminates the
|
||||
need for writers to exclude readers.
|
||||
|
||||
The list_del(), list_add(), and list_add_tail() primitives have been
|
||||
replaced by list_del_rcu(), list_add_rcu(), and list_add_tail_rcu().
|
||||
The **_rcu()** list-manipulation primitives add memory barriers that are needed on
|
||||
weakly ordered CPUs (most of them!). The list_del_rcu() primitive omits the
|
||||
pointer poisoning debug-assist code that would otherwise cause concurrent
|
||||
readers to fail spectacularly.
|
||||
|
||||
So, when readers can tolerate stale data and when entries are either added or
|
||||
deleted, without in-place modification, it is very easy to use RCU!
|
||||
|
||||
|
||||
Example 3: Handling In-Place Updates
|
||||
------------------------------------
|
||||
|
||||
The system-call auditing code does not update auditing rules in place. However,
|
||||
if it did, the reader-writer-locked code to do so might look as follows
|
||||
(assuming only ``field_count`` is updated, otherwise, the added fields would
|
||||
need to be filled in)::
|
||||
|
||||
static inline int audit_upd_rule(struct audit_rule *rule,
|
||||
struct list_head *list,
|
||||
__u32 newaction,
|
||||
__u32 newfield_count)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
struct audit_entry *ne;
|
||||
|
||||
write_lock(&auditsc_lock);
|
||||
/* Note: audit_filter_mutex held by caller. */
|
||||
list_for_each_entry(e, list, list) {
|
||||
if (!audit_compare_rule(rule, &e->rule)) {
|
||||
e->rule.action = newaction;
|
||||
e->rule.field_count = newfield_count;
|
||||
write_unlock(&auditsc_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
write_unlock(&auditsc_lock);
|
||||
return -EFAULT; /* No matching rule */
|
||||
}
|
||||
|
||||
The RCU version creates a copy, updates the copy, then replaces the old
|
||||
entry with the newly updated entry. This sequence of actions, allowing
|
||||
concurrent reads while making a copy to perform an update, is what gives
|
||||
RCU (*read-copy update*) its name. The RCU code is as follows::
|
||||
|
||||
static inline int audit_upd_rule(struct audit_rule *rule,
|
||||
struct list_head *list,
|
||||
__u32 newaction,
|
||||
__u32 newfield_count)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
struct audit_entry *ne;
|
||||
|
||||
list_for_each_entry(e, list, list) {
|
||||
if (!audit_compare_rule(rule, &e->rule)) {
|
||||
ne = kmalloc(sizeof(*entry), GFP_ATOMIC);
|
||||
if (ne == NULL)
|
||||
return -ENOMEM;
|
||||
audit_copy_rule(&ne->rule, &e->rule);
|
||||
ne->rule.action = newaction;
|
||||
ne->rule.field_count = newfield_count;
|
||||
list_replace_rcu(&e->list, &ne->list);
|
||||
call_rcu(&e->rcu, audit_free_rule);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EFAULT; /* No matching rule */
|
||||
}
|
||||
|
||||
Again, this assumes that the caller holds ``audit_filter_mutex``. Normally, the
|
||||
writer lock would become a spinlock in this sort of code.
|
||||
|
||||
Another use of this pattern can be found in the openswitch driver's *connection
|
||||
tracking table* code in ``ct_limit_set()``. The table holds connection tracking
|
||||
entries and has a limit on the maximum entries. There is one such table
|
||||
per-zone and hence one *limit* per zone. The zones are mapped to their limits
|
||||
through a hashtable using an RCU-managed hlist for the hash chains. When a new
|
||||
limit is set, a new limit object is allocated and ``ct_limit_set()`` is called
|
||||
to replace the old limit object with the new one using list_replace_rcu().
|
||||
The old limit object is then freed after a grace period using kfree_rcu().
|
||||
|
||||
|
||||
Example 4: Eliminating Stale Data
|
||||
---------------------------------
|
||||
|
||||
The auditing example above tolerates stale data, as do most algorithms
|
||||
that are tracking external state. Because there is a delay from the
|
||||
time the external state changes before Linux becomes aware of the change,
|
||||
additional RCU-induced staleness is generally not a problem.
|
||||
|
||||
However, there are many examples where stale data cannot be tolerated.
|
||||
One example in the Linux kernel is the System V IPC (see the shm_lock()
|
||||
function in ipc/shm.c). This code checks a *deleted* flag under a
|
||||
per-entry spinlock, and, if the *deleted* flag is set, pretends that the
|
||||
entry does not exist. For this to be helpful, the search function must
|
||||
return holding the per-entry spinlock, as shm_lock() does in fact do.
|
||||
|
||||
.. _quick_quiz:
|
||||
|
||||
Quick Quiz:
|
||||
For the deleted-flag technique to be helpful, why is it necessary
|
||||
to hold the per-entry lock while returning from the search function?
|
||||
|
||||
:ref:`Answer to Quick Quiz <quick_quiz_answer>`
|
||||
|
||||
If the system-call audit module were to ever need to reject stale data, one way
|
||||
to accomplish this would be to add a ``deleted`` flag and a ``lock`` spinlock to the
|
||||
audit_entry structure, and modify ``audit_filter_task()`` as follows::
|
||||
|
||||
static enum audit_state audit_filter_task(struct task_struct *tsk)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
enum audit_state state;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(e, &audit_tsklist, list) {
|
||||
if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
|
||||
spin_lock(&e->lock);
|
||||
if (e->deleted) {
|
||||
spin_unlock(&e->lock);
|
||||
rcu_read_unlock();
|
||||
return AUDIT_BUILD_CONTEXT;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return state;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return AUDIT_BUILD_CONTEXT;
|
||||
}
|
||||
|
||||
Note that this example assumes that entries are only added and deleted.
|
||||
Additional mechanism is required to deal correctly with the update-in-place
|
||||
performed by ``audit_upd_rule()``. For one thing, ``audit_upd_rule()`` would
|
||||
need additional memory barriers to ensure that the list_add_rcu() was really
|
||||
executed before the list_del_rcu().
|
||||
|
||||
The ``audit_del_rule()`` function would need to set the ``deleted`` flag under the
|
||||
spinlock as follows::
|
||||
|
||||
static inline int audit_del_rule(struct audit_rule *rule,
|
||||
struct list_head *list)
|
||||
{
|
||||
struct audit_entry *e;
|
||||
|
||||
/* No need to use the _rcu iterator here, since this
|
||||
* is the only deletion routine. */
|
||||
list_for_each_entry(e, list, list) {
|
||||
if (!audit_compare_rule(rule, &e->rule)) {
|
||||
spin_lock(&e->lock);
|
||||
list_del_rcu(&e->list);
|
||||
e->deleted = 1;
|
||||
spin_unlock(&e->lock);
|
||||
call_rcu(&e->rcu, audit_free_rule);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EFAULT; /* No matching rule */
|
||||
}
|
||||
|
||||
This too assumes that the caller holds ``audit_filter_mutex``.
|
||||
|
||||
|
||||
Example 5: Skipping Stale Objects
|
||||
---------------------------------
|
||||
|
||||
For some usecases, reader performance can be improved by skipping stale objects
|
||||
during read-side list traversal if the object in concern is pending destruction
|
||||
after one or more grace periods. One such example can be found in the timerfd
|
||||
subsystem. When a ``CLOCK_REALTIME`` clock is reprogrammed - for example due to
|
||||
setting of the system time, then all programmed timerfds that depend on this
|
||||
clock get triggered and processes waiting on them to expire are woken up in
|
||||
advance of their scheduled expiry. To facilitate this, all such timers are added
|
||||
to an RCU-managed ``cancel_list`` when they are setup in
|
||||
``timerfd_setup_cancel()``::
|
||||
|
||||
static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
|
||||
{
|
||||
spin_lock(&ctx->cancel_lock);
|
||||
if ((ctx->clockid == CLOCK_REALTIME &&
|
||||
(flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
|
||||
if (!ctx->might_cancel) {
|
||||
ctx->might_cancel = true;
|
||||
spin_lock(&cancel_lock);
|
||||
list_add_rcu(&ctx->clist, &cancel_list);
|
||||
spin_unlock(&cancel_lock);
|
||||
}
|
||||
}
|
||||
spin_unlock(&ctx->cancel_lock);
|
||||
}
|
||||
|
||||
When a timerfd is freed (fd is closed), then the ``might_cancel`` flag of the
|
||||
timerfd object is cleared, the object removed from the ``cancel_list`` and
|
||||
destroyed::
|
||||
|
||||
int timerfd_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct timerfd_ctx *ctx = file->private_data;
|
||||
|
||||
spin_lock(&ctx->cancel_lock);
|
||||
if (ctx->might_cancel) {
|
||||
ctx->might_cancel = false;
|
||||
spin_lock(&cancel_lock);
|
||||
list_del_rcu(&ctx->clist);
|
||||
spin_unlock(&cancel_lock);
|
||||
}
|
||||
spin_unlock(&ctx->cancel_lock);
|
||||
|
||||
hrtimer_cancel(&ctx->t.tmr);
|
||||
kfree_rcu(ctx, rcu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
If the ``CLOCK_REALTIME`` clock is set, for example by a time server, the
|
||||
hrtimer framework calls ``timerfd_clock_was_set()`` which walks the
|
||||
``cancel_list`` and wakes up processes waiting on the timerfd. While iterating
|
||||
the ``cancel_list``, the ``might_cancel`` flag is consulted to skip stale
|
||||
objects::
|
||||
|
||||
void timerfd_clock_was_set(void)
|
||||
{
|
||||
struct timerfd_ctx *ctx;
|
||||
unsigned long flags;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(ctx, &cancel_list, clist) {
|
||||
if (!ctx->might_cancel)
|
||||
continue;
|
||||
spin_lock_irqsave(&ctx->wqh.lock, flags);
|
||||
if (ctx->moffs != ktime_mono_to_real(0)) {
|
||||
ctx->moffs = KTIME_MAX;
|
||||
ctx->ticks++;
|
||||
wake_up_locked_poll(&ctx->wqh, EPOLLIN);
|
||||
}
|
||||
spin_unlock_irqrestore(&ctx->wqh.lock, flags);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
The key point here is, because RCU-traversal of the ``cancel_list`` happens
|
||||
while objects are being added and removed to the list, sometimes the traversal
|
||||
can step on an object that has been removed from the list. In this example, it
|
||||
is seen that it is better to skip such objects using a flag.
|
||||
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
Read-mostly list-based data structures that can tolerate stale data are
|
||||
the most amenable to use of RCU. The simplest case is where entries are
|
||||
either added or deleted from the data structure (or atomically modified
|
||||
in place), but non-atomic in-place modifications can be handled by making
|
||||
a copy, updating the copy, then replacing the original with the copy.
|
||||
If stale data cannot be tolerated, then a *deleted* flag may be used
|
||||
in conjunction with a per-entry spinlock in order to allow the search
|
||||
function to reject newly deleted data.
|
||||
|
||||
.. _quick_quiz_answer:
|
||||
|
||||
Answer to Quick Quiz:
|
||||
For the deleted-flag technique to be helpful, why is it necessary
|
||||
to hold the per-entry lock while returning from the search function?
|
||||
|
||||
If the search function drops the per-entry lock before returning,
|
||||
then the caller will be processing stale data in any case. If it
|
||||
is really OK to be processing stale data, then you don't need a
|
||||
*deleted* flag. If processing stale data really is a problem,
|
||||
then you need to hold the per-entry lock across all of the code
|
||||
that uses the value that was returned.
|
||||
|
||||
:ref:`Back to Quick Quiz <quick_quiz>`
|
115
Documentation/RCU/lockdep-splat.rst
Normal file
@ -0,0 +1,115 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=================
|
||||
Lockdep-RCU Splat
|
||||
=================
|
||||
|
||||
Lockdep-RCU was added to the Linux kernel in early 2010
|
||||
(http://lwn.net/Articles/371986/). This facility checks for some common
|
||||
misuses of the RCU API, most notably using one of the rcu_dereference()
|
||||
family to access an RCU-protected pointer without the proper protection.
|
||||
When such misuse is detected, an lockdep-RCU splat is emitted.
|
||||
|
||||
The usual cause of a lockdep-RCU slat is someone accessing an
|
||||
RCU-protected data structure without either (1) being in the right kind of
|
||||
RCU read-side critical section or (2) holding the right update-side lock.
|
||||
This problem can therefore be serious: it might result in random memory
|
||||
overwriting or worse. There can of course be false positives, this
|
||||
being the real world and all that.
|
||||
|
||||
So let's look at an example RCU lockdep splat from 3.0-rc5, one that
|
||||
has long since been fixed::
|
||||
|
||||
=============================
|
||||
WARNING: suspicious RCU usage
|
||||
-----------------------------
|
||||
block/cfq-iosched.c:2776 suspicious rcu_dereference_protected() usage!
|
||||
|
||||
other info that might help us debug this::
|
||||
|
||||
rcu_scheduler_active = 1, debug_locks = 0
|
||||
3 locks held by scsi_scan_6/1552:
|
||||
#0: (&shost->scan_mutex){+.+.}, at: [<ffffffff8145efca>]
|
||||
scsi_scan_host_selected+0x5a/0x150
|
||||
#1: (&eq->sysfs_lock){+.+.}, at: [<ffffffff812a5032>]
|
||||
elevator_exit+0x22/0x60
|
||||
#2: (&(&q->__queue_lock)->rlock){-.-.}, at: [<ffffffff812b6233>]
|
||||
cfq_exit_queue+0x43/0x190
|
||||
|
||||
stack backtrace:
|
||||
Pid: 1552, comm: scsi_scan_6 Not tainted 3.0.0-rc5 #17
|
||||
Call Trace:
|
||||
[<ffffffff810abb9b>] lockdep_rcu_dereference+0xbb/0xc0
|
||||
[<ffffffff812b6139>] __cfq_exit_single_io_context+0xe9/0x120
|
||||
[<ffffffff812b626c>] cfq_exit_queue+0x7c/0x190
|
||||
[<ffffffff812a5046>] elevator_exit+0x36/0x60
|
||||
[<ffffffff812a802a>] blk_cleanup_queue+0x4a/0x60
|
||||
[<ffffffff8145cc09>] scsi_free_queue+0x9/0x10
|
||||
[<ffffffff81460944>] __scsi_remove_device+0x84/0xd0
|
||||
[<ffffffff8145dca3>] scsi_probe_and_add_lun+0x353/0xb10
|
||||
[<ffffffff817da069>] ? error_exit+0x29/0xb0
|
||||
[<ffffffff817d98ed>] ? _raw_spin_unlock_irqrestore+0x3d/0x80
|
||||
[<ffffffff8145e722>] __scsi_scan_target+0x112/0x680
|
||||
[<ffffffff812c690d>] ? trace_hardirqs_off_thunk+0x3a/0x3c
|
||||
[<ffffffff817da069>] ? error_exit+0x29/0xb0
|
||||
[<ffffffff812bcc60>] ? kobject_del+0x40/0x40
|
||||
[<ffffffff8145ed16>] scsi_scan_channel+0x86/0xb0
|
||||
[<ffffffff8145f0b0>] scsi_scan_host_selected+0x140/0x150
|
||||
[<ffffffff8145f149>] do_scsi_scan_host+0x89/0x90
|
||||
[<ffffffff8145f170>] do_scan_async+0x20/0x160
|
||||
[<ffffffff8145f150>] ? do_scsi_scan_host+0x90/0x90
|
||||
[<ffffffff810975b6>] kthread+0xa6/0xb0
|
||||
[<ffffffff817db154>] kernel_thread_helper+0x4/0x10
|
||||
[<ffffffff81066430>] ? finish_task_switch+0x80/0x110
|
||||
[<ffffffff817d9c04>] ? retint_restore_args+0xe/0xe
|
||||
[<ffffffff81097510>] ? __kthread_init_worker+0x70/0x70
|
||||
[<ffffffff817db150>] ? gs_change+0xb/0xb
|
||||
|
||||
Line 2776 of block/cfq-iosched.c in v3.0-rc5 is as follows::
|
||||
|
||||
if (rcu_dereference(ioc->ioc_data) == cic) {
|
||||
|
||||
This form says that it must be in a plain vanilla RCU read-side critical
|
||||
section, but the "other info" list above shows that this is not the
|
||||
case. Instead, we hold three locks, one of which might be RCU related.
|
||||
And maybe that lock really does protect this reference. If so, the fix
|
||||
is to inform RCU, perhaps by changing __cfq_exit_single_io_context() to
|
||||
take the struct request_queue "q" from cfq_exit_queue() as an argument,
|
||||
which would permit us to invoke rcu_dereference_protected as follows::
|
||||
|
||||
if (rcu_dereference_protected(ioc->ioc_data,
|
||||
lockdep_is_held(&q->queue_lock)) == cic) {
|
||||
|
||||
With this change, there would be no lockdep-RCU splat emitted if this
|
||||
code was invoked either from within an RCU read-side critical section
|
||||
or with the ->queue_lock held. In particular, this would have suppressed
|
||||
the above lockdep-RCU splat because ->queue_lock is held (see #2 in the
|
||||
list above).
|
||||
|
||||
On the other hand, perhaps we really do need an RCU read-side critical
|
||||
section. In this case, the critical section must span the use of the
|
||||
return value from rcu_dereference(), or at least until there is some
|
||||
reference count incremented or some such. One way to handle this is to
|
||||
add rcu_read_lock() and rcu_read_unlock() as follows::
|
||||
|
||||
rcu_read_lock();
|
||||
if (rcu_dereference(ioc->ioc_data) == cic) {
|
||||
spin_lock(&ioc->lock);
|
||||
rcu_assign_pointer(ioc->ioc_data, NULL);
|
||||
spin_unlock(&ioc->lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
With this change, the rcu_dereference() is always within an RCU
|
||||
read-side critical section, which again would have suppressed the
|
||||
above lockdep-RCU splat.
|
||||
|
||||
But in this particular case, we don't actually dereference the pointer
|
||||
returned from rcu_dereference(). Instead, that pointer is just compared
|
||||
to the cic pointer, which means that the rcu_dereference() can be replaced
|
||||
by rcu_access_pointer() as follows::
|
||||
|
||||
if (rcu_access_pointer(ioc->ioc_data) == cic) {
|
||||
|
||||
Because it is legal to invoke rcu_access_pointer() without protection,
|
||||
this change would also suppress the above lockdep-RCU splat.
|
116
Documentation/RCU/lockdep.rst
Normal file
@ -0,0 +1,116 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
========================
|
||||
RCU and lockdep checking
|
||||
========================
|
||||
|
||||
All flavors of RCU have lockdep checking available, so that lockdep is
|
||||
aware of when each task enters and leaves any flavor of RCU read-side
|
||||
critical section. Each flavor of RCU is tracked separately (but note
|
||||
that this is not the case in 2.6.32 and earlier). This allows lockdep's
|
||||
tracking to include RCU state, which can sometimes help when debugging
|
||||
deadlocks and the like.
|
||||
|
||||
In addition, RCU provides the following primitives that check lockdep's
|
||||
state::
|
||||
|
||||
rcu_read_lock_held() for normal RCU.
|
||||
rcu_read_lock_bh_held() for RCU-bh.
|
||||
rcu_read_lock_sched_held() for RCU-sched.
|
||||
srcu_read_lock_held() for SRCU.
|
||||
|
||||
These functions are conservative, and will therefore return 1 if they
|
||||
aren't certain (for example, if CONFIG_DEBUG_LOCK_ALLOC is not set).
|
||||
This prevents things like WARN_ON(!rcu_read_lock_held()) from giving false
|
||||
positives when lockdep is disabled.
|
||||
|
||||
In addition, a separate kernel config parameter CONFIG_PROVE_RCU enables
|
||||
checking of rcu_dereference() primitives:
|
||||
|
||||
rcu_dereference(p):
|
||||
Check for RCU read-side critical section.
|
||||
rcu_dereference_bh(p):
|
||||
Check for RCU-bh read-side critical section.
|
||||
rcu_dereference_sched(p):
|
||||
Check for RCU-sched read-side critical section.
|
||||
srcu_dereference(p, sp):
|
||||
Check for SRCU read-side critical section.
|
||||
rcu_dereference_check(p, c):
|
||||
Use explicit check expression "c" along with
|
||||
rcu_read_lock_held(). This is useful in code that is
|
||||
invoked by both RCU readers and updaters.
|
||||
rcu_dereference_bh_check(p, c):
|
||||
Use explicit check expression "c" along with
|
||||
rcu_read_lock_bh_held(). This is useful in code that
|
||||
is invoked by both RCU-bh readers and updaters.
|
||||
rcu_dereference_sched_check(p, c):
|
||||
Use explicit check expression "c" along with
|
||||
rcu_read_lock_sched_held(). This is useful in code that
|
||||
is invoked by both RCU-sched readers and updaters.
|
||||
srcu_dereference_check(p, c):
|
||||
Use explicit check expression "c" along with
|
||||
srcu_read_lock_held(). This is useful in code that
|
||||
is invoked by both SRCU readers and updaters.
|
||||
rcu_dereference_raw(p):
|
||||
Don't check. (Use sparingly, if at all.)
|
||||
rcu_dereference_protected(p, c):
|
||||
Use explicit check expression "c", and omit all barriers
|
||||
and compiler constraints. This is useful when the data
|
||||
structure cannot change, for example, in code that is
|
||||
invoked only by updaters.
|
||||
rcu_access_pointer(p):
|
||||
Return the value of the pointer and omit all barriers,
|
||||
but retain the compiler constraints that prevent duplicating
|
||||
or coalescsing. This is useful when when testing the
|
||||
value of the pointer itself, for example, against NULL.
|
||||
|
||||
The rcu_dereference_check() check expression can be any boolean
|
||||
expression, but would normally include a lockdep expression. However,
|
||||
any boolean expression can be used. For a moderately ornate example,
|
||||
consider the following::
|
||||
|
||||
file = rcu_dereference_check(fdt->fd[fd],
|
||||
lockdep_is_held(&files->file_lock) ||
|
||||
atomic_read(&files->count) == 1);
|
||||
|
||||
This expression picks up the pointer "fdt->fd[fd]" in an RCU-safe manner,
|
||||
and, if CONFIG_PROVE_RCU is configured, verifies that this expression
|
||||
is used in:
|
||||
|
||||
1. An RCU read-side critical section (implicit), or
|
||||
2. with files->file_lock held, or
|
||||
3. on an unshared files_struct.
|
||||
|
||||
In case (1), the pointer is picked up in an RCU-safe manner for vanilla
|
||||
RCU read-side critical sections, in case (2) the ->file_lock prevents
|
||||
any change from taking place, and finally, in case (3) the current task
|
||||
is the only task accessing the file_struct, again preventing any change
|
||||
from taking place. If the above statement was invoked only from updater
|
||||
code, it could instead be written as follows::
|
||||
|
||||
file = rcu_dereference_protected(fdt->fd[fd],
|
||||
lockdep_is_held(&files->file_lock) ||
|
||||
atomic_read(&files->count) == 1);
|
||||
|
||||
This would verify cases #2 and #3 above, and furthermore lockdep would
|
||||
complain if this was used in an RCU read-side critical section unless one
|
||||
of these two cases held. Because rcu_dereference_protected() omits all
|
||||
barriers and compiler constraints, it generates better code than do the
|
||||
other flavors of rcu_dereference(). On the other hand, it is illegal
|
||||
to use rcu_dereference_protected() if either the RCU-protected pointer
|
||||
or the RCU-protected data that it points to can change concurrently.
|
||||
|
||||
Like rcu_dereference(), when lockdep is enabled, RCU list and hlist
|
||||
traversal primitives check for being called from within an RCU read-side
|
||||
critical section. However, a lockdep expression can be passed to them
|
||||
as a additional optional argument. With this lockdep expression, these
|
||||
traversal primitives will complain only if the lockdep expression is
|
||||
false and they are called from outside any RCU read-side critical section.
|
||||
|
||||
For example, the workqueue for_each_pwq() macro is intended to be used
|
||||
either within an RCU read-side critical section or with wq->mutex held.
|
||||
It is thus implemented as follows::
|
||||
|
||||
#define for_each_pwq(pwq, wq)
|
||||
list_for_each_entry_rcu((pwq), &(wq)->pwqs, pwqs_node,
|
||||
lock_is_held(&(wq->mutex).dep_map))
|
92
Documentation/RCU/rcu.rst
Normal file
@ -0,0 +1,92 @@
|
||||
.. _rcu_doc:
|
||||
|
||||
RCU Concepts
|
||||
============
|
||||
|
||||
The basic idea behind RCU (read-copy update) is to split destructive
|
||||
operations into two parts, one that prevents anyone from seeing the data
|
||||
item being destroyed, and one that actually carries out the destruction.
|
||||
A "grace period" must elapse between the two parts, and this grace period
|
||||
must be long enough that any readers accessing the item being deleted have
|
||||
since dropped their references. For example, an RCU-protected deletion
|
||||
from a linked list would first remove the item from the list, wait for
|
||||
a grace period to elapse, then free the element. See the
|
||||
:ref:`Documentation/RCU/listRCU.rst <list_rcu_doc>` for more information on
|
||||
using RCU with linked lists.
|
||||
|
||||
Frequently Asked Questions
|
||||
--------------------------
|
||||
|
||||
- Why would anyone want to use RCU?
|
||||
|
||||
The advantage of RCU's two-part approach is that RCU readers need
|
||||
not acquire any locks, perform any atomic instructions, write to
|
||||
shared memory, or (on CPUs other than Alpha) execute any memory
|
||||
barriers. The fact that these operations are quite expensive
|
||||
on modern CPUs is what gives RCU its performance advantages
|
||||
in read-mostly situations. The fact that RCU readers need not
|
||||
acquire locks can also greatly simplify deadlock-avoidance code.
|
||||
|
||||
- How can the updater tell when a grace period has completed
|
||||
if the RCU readers give no indication when they are done?
|
||||
|
||||
Just as with spinlocks, RCU readers are not permitted to
|
||||
block, switch to user-mode execution, or enter the idle loop.
|
||||
Therefore, as soon as a CPU is seen passing through any of these
|
||||
three states, we know that that CPU has exited any previous RCU
|
||||
read-side critical sections. So, if we remove an item from a
|
||||
linked list, and then wait until all CPUs have switched context,
|
||||
executed in user mode, or executed in the idle loop, we can
|
||||
safely free up that item.
|
||||
|
||||
Preemptible variants of RCU (CONFIG_PREEMPT_RCU) get the
|
||||
same effect, but require that the readers manipulate CPU-local
|
||||
counters. These counters allow limited types of blocking within
|
||||
RCU read-side critical sections. SRCU also uses CPU-local
|
||||
counters, and permits general blocking within RCU read-side
|
||||
critical sections. These variants of RCU detect grace periods
|
||||
by sampling these counters.
|
||||
|
||||
- If I am running on a uniprocessor kernel, which can only do one
|
||||
thing at a time, why should I wait for a grace period?
|
||||
|
||||
See :ref:`Documentation/RCU/UP.rst <up_doc>` for more information.
|
||||
|
||||
- How can I see where RCU is currently used in the Linux kernel?
|
||||
|
||||
Search for "rcu_read_lock", "rcu_read_unlock", "call_rcu",
|
||||
"rcu_read_lock_bh", "rcu_read_unlock_bh", "srcu_read_lock",
|
||||
"srcu_read_unlock", "synchronize_rcu", "synchronize_net",
|
||||
"synchronize_srcu", and the other RCU primitives. Or grab one
|
||||
of the cscope databases from:
|
||||
|
||||
(http://www.rdrop.com/users/paulmck/RCU/linuxusage/rculocktab.html).
|
||||
|
||||
- What guidelines should I follow when writing code that uses RCU?
|
||||
|
||||
See the checklist.txt file in this directory.
|
||||
|
||||
- Why the name "RCU"?
|
||||
|
||||
"RCU" stands for "read-copy update".
|
||||
:ref:`Documentation/RCU/listRCU.rst <list_rcu_doc>` has more information on where
|
||||
this name came from, search for "read-copy update" to find it.
|
||||
|
||||
- I hear that RCU is patented? What is with that?
|
||||
|
||||
Yes, it is. There are several known patents related to RCU,
|
||||
search for the string "Patent" in Documentation/RCU/RTFP.txt to find them.
|
||||
Of these, one was allowed to lapse by the assignee, and the
|
||||
others have been contributed to the Linux kernel under GPL.
|
||||
There are now also LGPL implementations of user-level RCU
|
||||
available (https://liburcu.org/).
|
||||
|
||||
- I hear that RCU needs work in order to support realtime kernels?
|
||||
|
||||
Realtime-friendly RCU can be enabled via the CONFIG_PREEMPT_RCU
|
||||
kernel configuration parameter.
|
||||
|
||||
- Where can I find more information on RCU?
|
||||
|
||||
See the Documentation/RCU/RTFP.txt file.
|
||||
Or point your browser at (http://www.rdrop.com/users/paulmck/RCU/).
|
469
Documentation/RCU/rcu_dereference.rst
Normal file
@ -0,0 +1,469 @@
|
||||
.. _rcu_dereference_doc:
|
||||
|
||||
PROPER CARE AND FEEDING OF RETURN VALUES FROM rcu_dereference()
|
||||
===============================================================
|
||||
|
||||
Most of the time, you can use values from rcu_dereference() or one of
|
||||
the similar primitives without worries. Dereferencing (prefix "*"),
|
||||
field selection ("->"), assignment ("="), address-of ("&"), addition and
|
||||
subtraction of constants, and casts all work quite naturally and safely.
|
||||
|
||||
It is nevertheless possible to get into trouble with other operations.
|
||||
Follow these rules to keep your RCU code working properly:
|
||||
|
||||
- You must use one of the rcu_dereference() family of primitives
|
||||
to load an RCU-protected pointer, otherwise CONFIG_PROVE_RCU
|
||||
will complain. Worse yet, your code can see random memory-corruption
|
||||
bugs due to games that compilers and DEC Alpha can play.
|
||||
Without one of the rcu_dereference() primitives, compilers
|
||||
can reload the value, and won't your code have fun with two
|
||||
different values for a single pointer! Without rcu_dereference(),
|
||||
DEC Alpha can load a pointer, dereference that pointer, and
|
||||
return data preceding initialization that preceded the store of
|
||||
the pointer.
|
||||
|
||||
In addition, the volatile cast in rcu_dereference() prevents the
|
||||
compiler from deducing the resulting pointer value. Please see
|
||||
the section entitled "EXAMPLE WHERE THE COMPILER KNOWS TOO MUCH"
|
||||
for an example where the compiler can in fact deduce the exact
|
||||
value of the pointer, and thus cause misordering.
|
||||
|
||||
- In the special case where data is added but is never removed
|
||||
while readers are accessing the structure, READ_ONCE() may be used
|
||||
instead of rcu_dereference(). In this case, use of READ_ONCE()
|
||||
takes on the role of the lockless_dereference() primitive that
|
||||
was removed in v4.15.
|
||||
|
||||
- You are only permitted to use rcu_dereference on pointer values.
|
||||
The compiler simply knows too much about integral values to
|
||||
trust it to carry dependencies through integer operations.
|
||||
There are a very few exceptions, namely that you can temporarily
|
||||
cast the pointer to uintptr_t in order to:
|
||||
|
||||
- Set bits and clear bits down in the must-be-zero low-order
|
||||
bits of that pointer. This clearly means that the pointer
|
||||
must have alignment constraints, for example, this does
|
||||
*not* work in general for char* pointers.
|
||||
|
||||
- XOR bits to translate pointers, as is done in some
|
||||
classic buddy-allocator algorithms.
|
||||
|
||||
It is important to cast the value back to pointer before
|
||||
doing much of anything else with it.
|
||||
|
||||
- Avoid cancellation when using the "+" and "-" infix arithmetic
|
||||
operators. For example, for a given variable "x", avoid
|
||||
"(x-(uintptr_t)x)" for char* pointers. The compiler is within its
|
||||
rights to substitute zero for this sort of expression, so that
|
||||
subsequent accesses no longer depend on the rcu_dereference(),
|
||||
again possibly resulting in bugs due to misordering.
|
||||
|
||||
Of course, if "p" is a pointer from rcu_dereference(), and "a"
|
||||
and "b" are integers that happen to be equal, the expression
|
||||
"p+a-b" is safe because its value still necessarily depends on
|
||||
the rcu_dereference(), thus maintaining proper ordering.
|
||||
|
||||
- If you are using RCU to protect JITed functions, so that the
|
||||
"()" function-invocation operator is applied to a value obtained
|
||||
(directly or indirectly) from rcu_dereference(), you may need to
|
||||
interact directly with the hardware to flush instruction caches.
|
||||
This issue arises on some systems when a newly JITed function is
|
||||
using the same memory that was used by an earlier JITed function.
|
||||
|
||||
- Do not use the results from relational operators ("==", "!=",
|
||||
">", ">=", "<", or "<=") when dereferencing. For example,
|
||||
the following (quite strange) code is buggy::
|
||||
|
||||
int *p;
|
||||
int *q;
|
||||
|
||||
...
|
||||
|
||||
p = rcu_dereference(gp)
|
||||
q = &global_q;
|
||||
q += p > &oom_p;
|
||||
r1 = *q; /* BUGGY!!! */
|
||||
|
||||
As before, the reason this is buggy is that relational operators
|
||||
are often compiled using branches. And as before, although
|
||||
weak-memory machines such as ARM or PowerPC do order stores
|
||||
after such branches, but can speculate loads, which can again
|
||||
result in misordering bugs.
|
||||
|
||||
- Be very careful about comparing pointers obtained from
|
||||
rcu_dereference() against non-NULL values. As Linus Torvalds
|
||||
explained, if the two pointers are equal, the compiler could
|
||||
substitute the pointer you are comparing against for the pointer
|
||||
obtained from rcu_dereference(). For example::
|
||||
|
||||
p = rcu_dereference(gp);
|
||||
if (p == &default_struct)
|
||||
do_default(p->a);
|
||||
|
||||
Because the compiler now knows that the value of "p" is exactly
|
||||
the address of the variable "default_struct", it is free to
|
||||
transform this code into the following::
|
||||
|
||||
p = rcu_dereference(gp);
|
||||
if (p == &default_struct)
|
||||
do_default(default_struct.a);
|
||||
|
||||
On ARM and Power hardware, the load from "default_struct.a"
|
||||
can now be speculated, such that it might happen before the
|
||||
rcu_dereference(). This could result in bugs due to misordering.
|
||||
|
||||
However, comparisons are OK in the following cases:
|
||||
|
||||
- The comparison was against the NULL pointer. If the
|
||||
compiler knows that the pointer is NULL, you had better
|
||||
not be dereferencing it anyway. If the comparison is
|
||||
non-equal, the compiler is none the wiser. Therefore,
|
||||
it is safe to compare pointers from rcu_dereference()
|
||||
against NULL pointers.
|
||||
|
||||
- The pointer is never dereferenced after being compared.
|
||||
Since there are no subsequent dereferences, the compiler
|
||||
cannot use anything it learned from the comparison
|
||||
to reorder the non-existent subsequent dereferences.
|
||||
This sort of comparison occurs frequently when scanning
|
||||
RCU-protected circular linked lists.
|
||||
|
||||
Note that if checks for being within an RCU read-side
|
||||
critical section are not required and the pointer is never
|
||||
dereferenced, rcu_access_pointer() should be used in place
|
||||
of rcu_dereference().
|
||||
|
||||
- The comparison is against a pointer that references memory
|
||||
that was initialized "a long time ago." The reason
|
||||
this is safe is that even if misordering occurs, the
|
||||
misordering will not affect the accesses that follow
|
||||
the comparison. So exactly how long ago is "a long
|
||||
time ago"? Here are some possibilities:
|
||||
|
||||
- Compile time.
|
||||
|
||||
- Boot time.
|
||||
|
||||
- Module-init time for module code.
|
||||
|
||||
- Prior to kthread creation for kthread code.
|
||||
|
||||
- During some prior acquisition of the lock that
|
||||
we now hold.
|
||||
|
||||
- Before mod_timer() time for a timer handler.
|
||||
|
||||
There are many other possibilities involving the Linux
|
||||
kernel's wide array of primitives that cause code to
|
||||
be invoked at a later time.
|
||||
|
||||
- The pointer being compared against also came from
|
||||
rcu_dereference(). In this case, both pointers depend
|
||||
on one rcu_dereference() or another, so you get proper
|
||||
ordering either way.
|
||||
|
||||
That said, this situation can make certain RCU usage
|
||||
bugs more likely to happen. Which can be a good thing,
|
||||
at least if they happen during testing. An example
|
||||
of such an RCU usage bug is shown in the section titled
|
||||
"EXAMPLE OF AMPLIFIED RCU-USAGE BUG".
|
||||
|
||||
- All of the accesses following the comparison are stores,
|
||||
so that a control dependency preserves the needed ordering.
|
||||
That said, it is easy to get control dependencies wrong.
|
||||
Please see the "CONTROL DEPENDENCIES" section of
|
||||
Documentation/memory-barriers.txt for more details.
|
||||
|
||||
- The pointers are not equal *and* the compiler does
|
||||
not have enough information to deduce the value of the
|
||||
pointer. Note that the volatile cast in rcu_dereference()
|
||||
will normally prevent the compiler from knowing too much.
|
||||
|
||||
However, please note that if the compiler knows that the
|
||||
pointer takes on only one of two values, a not-equal
|
||||
comparison will provide exactly the information that the
|
||||
compiler needs to deduce the value of the pointer.
|
||||
|
||||
- Disable any value-speculation optimizations that your compiler
|
||||
might provide, especially if you are making use of feedback-based
|
||||
optimizations that take data collected from prior runs. Such
|
||||
value-speculation optimizations reorder operations by design.
|
||||
|
||||
There is one exception to this rule: Value-speculation
|
||||
optimizations that leverage the branch-prediction hardware are
|
||||
safe on strongly ordered systems (such as x86), but not on weakly
|
||||
ordered systems (such as ARM or Power). Choose your compiler
|
||||
command-line options wisely!
|
||||
|
||||
|
||||
EXAMPLE OF AMPLIFIED RCU-USAGE BUG
|
||||
----------------------------------
|
||||
|
||||
Because updaters can run concurrently with RCU readers, RCU readers can
|
||||
see stale and/or inconsistent values. If RCU readers need fresh or
|
||||
consistent values, which they sometimes do, they need to take proper
|
||||
precautions. To see this, consider the following code fragment::
|
||||
|
||||
struct foo {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
struct foo *gp1;
|
||||
struct foo *gp2;
|
||||
|
||||
void updater(void)
|
||||
{
|
||||
struct foo *p;
|
||||
|
||||
p = kmalloc(...);
|
||||
if (p == NULL)
|
||||
deal_with_it();
|
||||
p->a = 42; /* Each field in its own cache line. */
|
||||
p->b = 43;
|
||||
p->c = 44;
|
||||
rcu_assign_pointer(gp1, p);
|
||||
p->b = 143;
|
||||
p->c = 144;
|
||||
rcu_assign_pointer(gp2, p);
|
||||
}
|
||||
|
||||
void reader(void)
|
||||
{
|
||||
struct foo *p;
|
||||
struct foo *q;
|
||||
int r1, r2;
|
||||
|
||||
p = rcu_dereference(gp2);
|
||||
if (p == NULL)
|
||||
return;
|
||||
r1 = p->b; /* Guaranteed to get 143. */
|
||||
q = rcu_dereference(gp1); /* Guaranteed non-NULL. */
|
||||
if (p == q) {
|
||||
/* The compiler decides that q->c is same as p->c. */
|
||||
r2 = p->c; /* Could get 44 on weakly order system. */
|
||||
}
|
||||
do_something_with(r1, r2);
|
||||
}
|
||||
|
||||
You might be surprised that the outcome (r1 == 143 && r2 == 44) is possible,
|
||||
but you should not be. After all, the updater might have been invoked
|
||||
a second time between the time reader() loaded into "r1" and the time
|
||||
that it loaded into "r2". The fact that this same result can occur due
|
||||
to some reordering from the compiler and CPUs is beside the point.
|
||||
|
||||
But suppose that the reader needs a consistent view?
|
||||
|
||||
Then one approach is to use locking, for example, as follows::
|
||||
|
||||
struct foo {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
spinlock_t lock;
|
||||
};
|
||||
struct foo *gp1;
|
||||
struct foo *gp2;
|
||||
|
||||
void updater(void)
|
||||
{
|
||||
struct foo *p;
|
||||
|
||||
p = kmalloc(...);
|
||||
if (p == NULL)
|
||||
deal_with_it();
|
||||
spin_lock(&p->lock);
|
||||
p->a = 42; /* Each field in its own cache line. */
|
||||
p->b = 43;
|
||||
p->c = 44;
|
||||
spin_unlock(&p->lock);
|
||||
rcu_assign_pointer(gp1, p);
|
||||
spin_lock(&p->lock);
|
||||
p->b = 143;
|
||||
p->c = 144;
|
||||
spin_unlock(&p->lock);
|
||||
rcu_assign_pointer(gp2, p);
|
||||
}
|
||||
|
||||
void reader(void)
|
||||
{
|
||||
struct foo *p;
|
||||
struct foo *q;
|
||||
int r1, r2;
|
||||
|
||||
p = rcu_dereference(gp2);
|
||||
if (p == NULL)
|
||||
return;
|
||||
spin_lock(&p->lock);
|
||||
r1 = p->b; /* Guaranteed to get 143. */
|
||||
q = rcu_dereference(gp1); /* Guaranteed non-NULL. */
|
||||
if (p == q) {
|
||||
/* The compiler decides that q->c is same as p->c. */
|
||||
r2 = p->c; /* Locking guarantees r2 == 144. */
|
||||
}
|
||||
spin_unlock(&p->lock);
|
||||
do_something_with(r1, r2);
|
||||
}
|
||||
|
||||
As always, use the right tool for the job!
|
||||
|
||||
|
||||
EXAMPLE WHERE THE COMPILER KNOWS TOO MUCH
|
||||
-----------------------------------------
|
||||
|
||||
If a pointer obtained from rcu_dereference() compares not-equal to some
|
||||
other pointer, the compiler normally has no clue what the value of the
|
||||
first pointer might be. This lack of knowledge prevents the compiler
|
||||
from carrying out optimizations that otherwise might destroy the ordering
|
||||
guarantees that RCU depends on. And the volatile cast in rcu_dereference()
|
||||
should prevent the compiler from guessing the value.
|
||||
|
||||
But without rcu_dereference(), the compiler knows more than you might
|
||||
expect. Consider the following code fragment::
|
||||
|
||||
struct foo {
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
static struct foo variable1;
|
||||
static struct foo variable2;
|
||||
static struct foo *gp = &variable1;
|
||||
|
||||
void updater(void)
|
||||
{
|
||||
initialize_foo(&variable2);
|
||||
rcu_assign_pointer(gp, &variable2);
|
||||
/*
|
||||
* The above is the only store to gp in this translation unit,
|
||||
* and the address of gp is not exported in any way.
|
||||
*/
|
||||
}
|
||||
|
||||
int reader(void)
|
||||
{
|
||||
struct foo *p;
|
||||
|
||||
p = gp;
|
||||
barrier();
|
||||
if (p == &variable1)
|
||||
return p->a; /* Must be variable1.a. */
|
||||
else
|
||||
return p->b; /* Must be variable2.b. */
|
||||
}
|
||||
|
||||
Because the compiler can see all stores to "gp", it knows that the only
|
||||
possible values of "gp" are "variable1" on the one hand and "variable2"
|
||||
on the other. The comparison in reader() therefore tells the compiler
|
||||
the exact value of "p" even in the not-equals case. This allows the
|
||||
compiler to make the return values independent of the load from "gp",
|
||||
in turn destroying the ordering between this load and the loads of the
|
||||
return values. This can result in "p->b" returning pre-initialization
|
||||
garbage values.
|
||||
|
||||
In short, rcu_dereference() is *not* optional when you are going to
|
||||
dereference the resulting pointer.
|
||||
|
||||
|
||||
WHICH MEMBER OF THE rcu_dereference() FAMILY SHOULD YOU USE?
|
||||
------------------------------------------------------------
|
||||
|
||||
First, please avoid using rcu_dereference_raw() and also please avoid
|
||||
using rcu_dereference_check() and rcu_dereference_protected() with a
|
||||
second argument with a constant value of 1 (or true, for that matter).
|
||||
With that caution out of the way, here is some guidance for which
|
||||
member of the rcu_dereference() to use in various situations:
|
||||
|
||||
1. If the access needs to be within an RCU read-side critical
|
||||
section, use rcu_dereference(). With the new consolidated
|
||||
RCU flavors, an RCU read-side critical section is entered
|
||||
using rcu_read_lock(), anything that disables bottom halves,
|
||||
anything that disables interrupts, or anything that disables
|
||||
preemption.
|
||||
|
||||
2. If the access might be within an RCU read-side critical section
|
||||
on the one hand, or protected by (say) my_lock on the other,
|
||||
use rcu_dereference_check(), for example::
|
||||
|
||||
p1 = rcu_dereference_check(p->rcu_protected_pointer,
|
||||
lockdep_is_held(&my_lock));
|
||||
|
||||
|
||||
3. If the access might be within an RCU read-side critical section
|
||||
on the one hand, or protected by either my_lock or your_lock on
|
||||
the other, again use rcu_dereference_check(), for example::
|
||||
|
||||
p1 = rcu_dereference_check(p->rcu_protected_pointer,
|
||||
lockdep_is_held(&my_lock) ||
|
||||
lockdep_is_held(&your_lock));
|
||||
|
||||
4. If the access is on the update side, so that it is always protected
|
||||
by my_lock, use rcu_dereference_protected()::
|
||||
|
||||
p1 = rcu_dereference_protected(p->rcu_protected_pointer,
|
||||
lockdep_is_held(&my_lock));
|
||||
|
||||
This can be extended to handle multiple locks as in #3 above,
|
||||
and both can be extended to check other conditions as well.
|
||||
|
||||
5. If the protection is supplied by the caller, and is thus unknown
|
||||
to this code, that is the rare case when rcu_dereference_raw()
|
||||
is appropriate. In addition, rcu_dereference_raw() might be
|
||||
appropriate when the lockdep expression would be excessively
|
||||
complex, except that a better approach in that case might be to
|
||||
take a long hard look at your synchronization design. Still,
|
||||
there are data-locking cases where any one of a very large number
|
||||
of locks or reference counters suffices to protect the pointer,
|
||||
so rcu_dereference_raw() does have its place.
|
||||
|
||||
However, its place is probably quite a bit smaller than one
|
||||
might expect given the number of uses in the current kernel.
|
||||
Ditto for its synonym, rcu_dereference_check( ... , 1), and
|
||||
its close relative, rcu_dereference_protected(... , 1).
|
||||
|
||||
|
||||
SPARSE CHECKING OF RCU-PROTECTED POINTERS
|
||||
-----------------------------------------
|
||||
|
||||
The sparse static-analysis tool checks for direct access to RCU-protected
|
||||
pointers, which can result in "interesting" bugs due to compiler
|
||||
optimizations involving invented loads and perhaps also load tearing.
|
||||
For example, suppose someone mistakenly does something like this::
|
||||
|
||||
p = q->rcu_protected_pointer;
|
||||
do_something_with(p->a);
|
||||
do_something_else_with(p->b);
|
||||
|
||||
If register pressure is high, the compiler might optimize "p" out
|
||||
of existence, transforming the code to something like this::
|
||||
|
||||
do_something_with(q->rcu_protected_pointer->a);
|
||||
do_something_else_with(q->rcu_protected_pointer->b);
|
||||
|
||||
This could fatally disappoint your code if q->rcu_protected_pointer
|
||||
changed in the meantime. Nor is this a theoretical problem: Exactly
|
||||
this sort of bug cost Paul E. McKenney (and several of his innocent
|
||||
colleagues) a three-day weekend back in the early 1990s.
|
||||
|
||||
Load tearing could of course result in dereferencing a mashup of a pair
|
||||
of pointers, which also might fatally disappoint your code.
|
||||
|
||||
These problems could have been avoided simply by making the code instead
|
||||
read as follows::
|
||||
|
||||
p = rcu_dereference(q->rcu_protected_pointer);
|
||||
do_something_with(p->a);
|
||||
do_something_else_with(p->b);
|
||||
|
||||
Unfortunately, these sorts of bugs can be extremely hard to spot during
|
||||
review. This is where the sparse tool comes into play, along with the
|
||||
"__rcu" marker. If you mark a pointer declaration, whether in a structure
|
||||
or as a formal parameter, with "__rcu", which tells sparse to complain if
|
||||
this pointer is accessed directly. It will also cause sparse to complain
|
||||
if a pointer not marked with "__rcu" is accessed using rcu_dereference()
|
||||
and friends. For example, ->rcu_protected_pointer might be declared as
|
||||
follows::
|
||||
|
||||
struct foo __rcu *rcu_protected_pointer;
|
||||
|
||||
Use of "__rcu" is opt-in. If you choose not to use it, then you should
|
||||
ignore the sparse warnings.
|
353
Documentation/RCU/rcubarrier.rst
Normal file
@ -0,0 +1,353 @@
|
||||
.. _rcu_barrier:
|
||||
|
||||
RCU and Unloadable Modules
|
||||
==========================
|
||||
|
||||
[Originally published in LWN Jan. 14, 2007: http://lwn.net/Articles/217484/]
|
||||
|
||||
RCU (read-copy update) is a synchronization mechanism that can be thought
|
||||
of as a replacement for read-writer locking (among other things), but with
|
||||
very low-overhead readers that are immune to deadlock, priority inversion,
|
||||
and unbounded latency. RCU read-side critical sections are delimited
|
||||
by rcu_read_lock() and rcu_read_unlock(), which, in non-CONFIG_PREEMPTION
|
||||
kernels, generate no code whatsoever.
|
||||
|
||||
This means that RCU writers are unaware of the presence of concurrent
|
||||
readers, so that RCU updates to shared data must be undertaken quite
|
||||
carefully, leaving an old version of the data structure in place until all
|
||||
pre-existing readers have finished. These old versions are needed because
|
||||
such readers might hold a reference to them. RCU updates can therefore be
|
||||
rather expensive, and RCU is thus best suited for read-mostly situations.
|
||||
|
||||
How can an RCU writer possibly determine when all readers are finished,
|
||||
given that readers might well leave absolutely no trace of their
|
||||
presence? There is a synchronize_rcu() primitive that blocks until all
|
||||
pre-existing readers have completed. An updater wishing to delete an
|
||||
element p from a linked list might do the following, while holding an
|
||||
appropriate lock, of course::
|
||||
|
||||
list_del_rcu(p);
|
||||
synchronize_rcu();
|
||||
kfree(p);
|
||||
|
||||
But the above code cannot be used in IRQ context -- the call_rcu()
|
||||
primitive must be used instead. This primitive takes a pointer to an
|
||||
rcu_head struct placed within the RCU-protected data structure and
|
||||
another pointer to a function that may be invoked later to free that
|
||||
structure. Code to delete an element p from the linked list from IRQ
|
||||
context might then be as follows::
|
||||
|
||||
list_del_rcu(p);
|
||||
call_rcu(&p->rcu, p_callback);
|
||||
|
||||
Since call_rcu() never blocks, this code can safely be used from within
|
||||
IRQ context. The function p_callback() might be defined as follows::
|
||||
|
||||
static void p_callback(struct rcu_head *rp)
|
||||
{
|
||||
struct pstruct *p = container_of(rp, struct pstruct, rcu);
|
||||
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
|
||||
Unloading Modules That Use call_rcu()
|
||||
-------------------------------------
|
||||
|
||||
But what if p_callback is defined in an unloadable module?
|
||||
|
||||
If we unload the module while some RCU callbacks are pending,
|
||||
the CPUs executing these callbacks are going to be severely
|
||||
disappointed when they are later invoked, as fancifully depicted at
|
||||
http://lwn.net/images/ns/kernel/rcu-drop.jpg.
|
||||
|
||||
We could try placing a synchronize_rcu() in the module-exit code path,
|
||||
but this is not sufficient. Although synchronize_rcu() does wait for a
|
||||
grace period to elapse, it does not wait for the callbacks to complete.
|
||||
|
||||
One might be tempted to try several back-to-back synchronize_rcu()
|
||||
calls, but this is still not guaranteed to work. If there is a very
|
||||
heavy RCU-callback load, then some of the callbacks might be deferred
|
||||
in order to allow other processing to proceed. Such deferral is required
|
||||
in realtime kernels in order to avoid excessive scheduling latencies.
|
||||
|
||||
|
||||
rcu_barrier()
|
||||
-------------
|
||||
|
||||
We instead need the rcu_barrier() primitive. Rather than waiting for
|
||||
a grace period to elapse, rcu_barrier() waits for all outstanding RCU
|
||||
callbacks to complete. Please note that rcu_barrier() does **not** imply
|
||||
synchronize_rcu(), in particular, if there are no RCU callbacks queued
|
||||
anywhere, rcu_barrier() is within its rights to return immediately,
|
||||
without waiting for a grace period to elapse.
|
||||
|
||||
Pseudo-code using rcu_barrier() is as follows:
|
||||
|
||||
1. Prevent any new RCU callbacks from being posted.
|
||||
2. Execute rcu_barrier().
|
||||
3. Allow the module to be unloaded.
|
||||
|
||||
There is also an srcu_barrier() function for SRCU, and you of course
|
||||
must match the flavor of rcu_barrier() with that of call_rcu(). If your
|
||||
module uses multiple flavors of call_rcu(), then it must also use multiple
|
||||
flavors of rcu_barrier() when unloading that module. For example, if
|
||||
it uses call_rcu(), call_srcu() on srcu_struct_1, and call_srcu() on
|
||||
srcu_struct_2, then the following three lines of code will be required
|
||||
when unloading::
|
||||
|
||||
1 rcu_barrier();
|
||||
2 srcu_barrier(&srcu_struct_1);
|
||||
3 srcu_barrier(&srcu_struct_2);
|
||||
|
||||
The rcutorture module makes use of rcu_barrier() in its exit function
|
||||
as follows::
|
||||
|
||||
1 static void
|
||||
2 rcu_torture_cleanup(void)
|
||||
3 {
|
||||
4 int i;
|
||||
5
|
||||
6 fullstop = 1;
|
||||
7 if (shuffler_task != NULL) {
|
||||
8 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
|
||||
9 kthread_stop(shuffler_task);
|
||||
10 }
|
||||
11 shuffler_task = NULL;
|
||||
12
|
||||
13 if (writer_task != NULL) {
|
||||
14 VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
|
||||
15 kthread_stop(writer_task);
|
||||
16 }
|
||||
17 writer_task = NULL;
|
||||
18
|
||||
19 if (reader_tasks != NULL) {
|
||||
20 for (i = 0; i < nrealreaders; i++) {
|
||||
21 if (reader_tasks[i] != NULL) {
|
||||
22 VERBOSE_PRINTK_STRING(
|
||||
23 "Stopping rcu_torture_reader task");
|
||||
24 kthread_stop(reader_tasks[i]);
|
||||
25 }
|
||||
26 reader_tasks[i] = NULL;
|
||||
27 }
|
||||
28 kfree(reader_tasks);
|
||||
29 reader_tasks = NULL;
|
||||
30 }
|
||||
31 rcu_torture_current = NULL;
|
||||
32
|
||||
33 if (fakewriter_tasks != NULL) {
|
||||
34 for (i = 0; i < nfakewriters; i++) {
|
||||
35 if (fakewriter_tasks[i] != NULL) {
|
||||
36 VERBOSE_PRINTK_STRING(
|
||||
37 "Stopping rcu_torture_fakewriter task");
|
||||
38 kthread_stop(fakewriter_tasks[i]);
|
||||
39 }
|
||||
40 fakewriter_tasks[i] = NULL;
|
||||
41 }
|
||||
42 kfree(fakewriter_tasks);
|
||||
43 fakewriter_tasks = NULL;
|
||||
44 }
|
||||
45
|
||||
46 if (stats_task != NULL) {
|
||||
47 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task");
|
||||
48 kthread_stop(stats_task);
|
||||
49 }
|
||||
50 stats_task = NULL;
|
||||
51
|
||||
52 /* Wait for all RCU callbacks to fire. */
|
||||
53 rcu_barrier();
|
||||
54
|
||||
55 rcu_torture_stats_print(); /* -After- the stats thread is stopped! */
|
||||
56
|
||||
57 if (cur_ops->cleanup != NULL)
|
||||
58 cur_ops->cleanup();
|
||||
59 if (atomic_read(&n_rcu_torture_error))
|
||||
60 rcu_torture_print_module_parms("End of test: FAILURE");
|
||||
61 else
|
||||
62 rcu_torture_print_module_parms("End of test: SUCCESS");
|
||||
63 }
|
||||
|
||||
Line 6 sets a global variable that prevents any RCU callbacks from
|
||||
re-posting themselves. This will not be necessary in most cases, since
|
||||
RCU callbacks rarely include calls to call_rcu(). However, the rcutorture
|
||||
module is an exception to this rule, and therefore needs to set this
|
||||
global variable.
|
||||
|
||||
Lines 7-50 stop all the kernel tasks associated with the rcutorture
|
||||
module. Therefore, once execution reaches line 53, no more rcutorture
|
||||
RCU callbacks will be posted. The rcu_barrier() call on line 53 waits
|
||||
for any pre-existing callbacks to complete.
|
||||
|
||||
Then lines 55-62 print status and do operation-specific cleanup, and
|
||||
then return, permitting the module-unload operation to be completed.
|
||||
|
||||
.. _rcubarrier_quiz_1:
|
||||
|
||||
Quick Quiz #1:
|
||||
Is there any other situation where rcu_barrier() might
|
||||
be required?
|
||||
|
||||
:ref:`Answer to Quick Quiz #1 <answer_rcubarrier_quiz_1>`
|
||||
|
||||
Your module might have additional complications. For example, if your
|
||||
module invokes call_rcu() from timers, you will need to first cancel all
|
||||
the timers, and only then invoke rcu_barrier() to wait for any remaining
|
||||
RCU callbacks to complete.
|
||||
|
||||
Of course, if you module uses call_rcu(), you will need to invoke
|
||||
rcu_barrier() before unloading. Similarly, if your module uses
|
||||
call_srcu(), you will need to invoke srcu_barrier() before unloading,
|
||||
and on the same srcu_struct structure. If your module uses call_rcu()
|
||||
**and** call_srcu(), then you will need to invoke rcu_barrier() **and**
|
||||
srcu_barrier().
|
||||
|
||||
|
||||
Implementing rcu_barrier()
|
||||
--------------------------
|
||||
|
||||
Dipankar Sarma's implementation of rcu_barrier() makes use of the fact
|
||||
that RCU callbacks are never reordered once queued on one of the per-CPU
|
||||
queues. His implementation queues an RCU callback on each of the per-CPU
|
||||
callback queues, and then waits until they have all started executing, at
|
||||
which point, all earlier RCU callbacks are guaranteed to have completed.
|
||||
|
||||
The original code for rcu_barrier() was as follows::
|
||||
|
||||
1 void rcu_barrier(void)
|
||||
2 {
|
||||
3 BUG_ON(in_interrupt());
|
||||
4 /* Take cpucontrol mutex to protect against CPU hotplug */
|
||||
5 mutex_lock(&rcu_barrier_mutex);
|
||||
6 init_completion(&rcu_barrier_completion);
|
||||
7 atomic_set(&rcu_barrier_cpu_count, 0);
|
||||
8 on_each_cpu(rcu_barrier_func, NULL, 0, 1);
|
||||
9 wait_for_completion(&rcu_barrier_completion);
|
||||
10 mutex_unlock(&rcu_barrier_mutex);
|
||||
11 }
|
||||
|
||||
Line 3 verifies that the caller is in process context, and lines 5 and 10
|
||||
use rcu_barrier_mutex to ensure that only one rcu_barrier() is using the
|
||||
global completion and counters at a time, which are initialized on lines
|
||||
6 and 7. Line 8 causes each CPU to invoke rcu_barrier_func(), which is
|
||||
shown below. Note that the final "1" in on_each_cpu()'s argument list
|
||||
ensures that all the calls to rcu_barrier_func() will have completed
|
||||
before on_each_cpu() returns. Line 9 then waits for the completion.
|
||||
|
||||
This code was rewritten in 2008 and several times thereafter, but this
|
||||
still gives the general idea.
|
||||
|
||||
The rcu_barrier_func() runs on each CPU, where it invokes call_rcu()
|
||||
to post an RCU callback, as follows::
|
||||
|
||||
1 static void rcu_barrier_func(void *notused)
|
||||
2 {
|
||||
3 int cpu = smp_processor_id();
|
||||
4 struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
|
||||
5 struct rcu_head *head;
|
||||
6
|
||||
7 head = &rdp->barrier;
|
||||
8 atomic_inc(&rcu_barrier_cpu_count);
|
||||
9 call_rcu(head, rcu_barrier_callback);
|
||||
10 }
|
||||
|
||||
Lines 3 and 4 locate RCU's internal per-CPU rcu_data structure,
|
||||
which contains the struct rcu_head that needed for the later call to
|
||||
call_rcu(). Line 7 picks up a pointer to this struct rcu_head, and line
|
||||
8 increments a global counter. This counter will later be decremented
|
||||
by the callback. Line 9 then registers the rcu_barrier_callback() on
|
||||
the current CPU's queue.
|
||||
|
||||
The rcu_barrier_callback() function simply atomically decrements the
|
||||
rcu_barrier_cpu_count variable and finalizes the completion when it
|
||||
reaches zero, as follows::
|
||||
|
||||
1 static void rcu_barrier_callback(struct rcu_head *notused)
|
||||
2 {
|
||||
3 if (atomic_dec_and_test(&rcu_barrier_cpu_count))
|
||||
4 complete(&rcu_barrier_completion);
|
||||
5 }
|
||||
|
||||
.. _rcubarrier_quiz_2:
|
||||
|
||||
Quick Quiz #2:
|
||||
What happens if CPU 0's rcu_barrier_func() executes
|
||||
immediately (thus incrementing rcu_barrier_cpu_count to the
|
||||
value one), but the other CPU's rcu_barrier_func() invocations
|
||||
are delayed for a full grace period? Couldn't this result in
|
||||
rcu_barrier() returning prematurely?
|
||||
|
||||
:ref:`Answer to Quick Quiz #2 <answer_rcubarrier_quiz_2>`
|
||||
|
||||
The current rcu_barrier() implementation is more complex, due to the need
|
||||
to avoid disturbing idle CPUs (especially on battery-powered systems)
|
||||
and the need to minimally disturb non-idle CPUs in real-time systems.
|
||||
However, the code above illustrates the concepts.
|
||||
|
||||
|
||||
rcu_barrier() Summary
|
||||
---------------------
|
||||
|
||||
The rcu_barrier() primitive has seen relatively little use, since most
|
||||
code using RCU is in the core kernel rather than in modules. However, if
|
||||
you are using RCU from an unloadable module, you need to use rcu_barrier()
|
||||
so that your module may be safely unloaded.
|
||||
|
||||
|
||||
Answers to Quick Quizzes
|
||||
------------------------
|
||||
|
||||
.. _answer_rcubarrier_quiz_1:
|
||||
|
||||
Quick Quiz #1:
|
||||
Is there any other situation where rcu_barrier() might
|
||||
be required?
|
||||
|
||||
Answer: Interestingly enough, rcu_barrier() was not originally
|
||||
implemented for module unloading. Nikita Danilov was using
|
||||
RCU in a filesystem, which resulted in a similar situation at
|
||||
filesystem-unmount time. Dipankar Sarma coded up rcu_barrier()
|
||||
in response, so that Nikita could invoke it during the
|
||||
filesystem-unmount process.
|
||||
|
||||
Much later, yours truly hit the RCU module-unload problem when
|
||||
implementing rcutorture, and found that rcu_barrier() solves
|
||||
this problem as well.
|
||||
|
||||
:ref:`Back to Quick Quiz #1 <rcubarrier_quiz_1>`
|
||||
|
||||
.. _answer_rcubarrier_quiz_2:
|
||||
|
||||
Quick Quiz #2:
|
||||
What happens if CPU 0's rcu_barrier_func() executes
|
||||
immediately (thus incrementing rcu_barrier_cpu_count to the
|
||||
value one), but the other CPU's rcu_barrier_func() invocations
|
||||
are delayed for a full grace period? Couldn't this result in
|
||||
rcu_barrier() returning prematurely?
|
||||
|
||||
Answer: This cannot happen. The reason is that on_each_cpu() has its last
|
||||
argument, the wait flag, set to "1". This flag is passed through
|
||||
to smp_call_function() and further to smp_call_function_on_cpu(),
|
||||
causing this latter to spin until the cross-CPU invocation of
|
||||
rcu_barrier_func() has completed. This by itself would prevent
|
||||
a grace period from completing on non-CONFIG_PREEMPTION kernels,
|
||||
since each CPU must undergo a context switch (or other quiescent
|
||||
state) before the grace period can complete. However, this is
|
||||
of no use in CONFIG_PREEMPTION kernels.
|
||||
|
||||
Therefore, on_each_cpu() disables preemption across its call
|
||||
to smp_call_function() and also across the local call to
|
||||
rcu_barrier_func(). This prevents the local CPU from context
|
||||
switching, again preventing grace periods from completing. This
|
||||
means that all CPUs have executed rcu_barrier_func() before
|
||||
the first rcu_barrier_callback() can possibly execute, in turn
|
||||
preventing rcu_barrier_cpu_count from prematurely reaching zero.
|
||||
|
||||
Currently, -rt implementations of RCU keep but a single global
|
||||
queue for RCU callbacks, and thus do not suffer from this
|
||||
problem. However, when the -rt RCU eventually does have per-CPU
|
||||
callback queues, things will have to change. One simple change
|
||||
is to add an rcu_read_lock() before line 8 of rcu_barrier()
|
||||
and an rcu_read_unlock() after line 8 of this same function. If
|
||||
you can think of a better change, please let me know!
|
||||
|
||||
:ref:`Back to Quick Quiz #2 <rcubarrier_quiz_2>`
|
200
Documentation/RCU/rculist_nulls.rst
Normal file
@ -0,0 +1,200 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=================================================
|
||||
Using RCU hlist_nulls to protect list and objects
|
||||
=================================================
|
||||
|
||||
This section describes how to use hlist_nulls to
|
||||
protect read-mostly linked lists and
|
||||
objects using SLAB_TYPESAFE_BY_RCU allocations.
|
||||
|
||||
Please read the basics in Documentation/RCU/listRCU.rst
|
||||
|
||||
Using 'nulls'
|
||||
=============
|
||||
|
||||
Using special makers (called 'nulls') is a convenient way
|
||||
to solve following problem :
|
||||
|
||||
A typical RCU linked list managing objects which are
|
||||
allocated with SLAB_TYPESAFE_BY_RCU kmem_cache can
|
||||
use following algos :
|
||||
|
||||
1) Lookup algo
|
||||
--------------
|
||||
|
||||
::
|
||||
|
||||
rcu_read_lock()
|
||||
begin:
|
||||
obj = lockless_lookup(key);
|
||||
if (obj) {
|
||||
if (!try_get_ref(obj)) // might fail for free objects
|
||||
goto begin;
|
||||
/*
|
||||
* Because a writer could delete object, and a writer could
|
||||
* reuse these object before the RCU grace period, we
|
||||
* must check key after getting the reference on object
|
||||
*/
|
||||
if (obj->key != key) { // not the object we expected
|
||||
put_ref(obj);
|
||||
goto begin;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
Beware that lockless_lookup(key) cannot use traditional hlist_for_each_entry_rcu()
|
||||
but a version with an additional memory barrier (smp_rmb())
|
||||
|
||||
::
|
||||
|
||||
lockless_lookup(key)
|
||||
{
|
||||
struct hlist_node *node, *next;
|
||||
for (pos = rcu_dereference((head)->first);
|
||||
pos && ({ next = pos->next; smp_rmb(); prefetch(next); 1; }) &&
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; });
|
||||
pos = rcu_dereference(next))
|
||||
if (obj->key == key)
|
||||
return obj;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
And note the traditional hlist_for_each_entry_rcu() misses this smp_rmb()::
|
||||
|
||||
struct hlist_node *node;
|
||||
for (pos = rcu_dereference((head)->first);
|
||||
pos && ({ prefetch(pos->next); 1; }) &&
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; });
|
||||
pos = rcu_dereference(pos->next))
|
||||
if (obj->key == key)
|
||||
return obj;
|
||||
return NULL;
|
||||
|
||||
Quoting Corey Minyard::
|
||||
|
||||
"If the object is moved from one list to another list in-between the
|
||||
time the hash is calculated and the next field is accessed, and the
|
||||
object has moved to the end of a new list, the traversal will not
|
||||
complete properly on the list it should have, since the object will
|
||||
be on the end of the new list and there's not a way to tell it's on a
|
||||
new list and restart the list traversal. I think that this can be
|
||||
solved by pre-fetching the "next" field (with proper barriers) before
|
||||
checking the key."
|
||||
|
||||
2) Insert algo
|
||||
--------------
|
||||
|
||||
We need to make sure a reader cannot read the new 'obj->obj_next' value
|
||||
and previous value of 'obj->key'. Or else, an item could be deleted
|
||||
from a chain, and inserted into another chain. If new chain was empty
|
||||
before the move, 'next' pointer is NULL, and lockless reader can
|
||||
not detect it missed following items in original chain.
|
||||
|
||||
::
|
||||
|
||||
/*
|
||||
* Please note that new inserts are done at the head of list,
|
||||
* not in the middle or end.
|
||||
*/
|
||||
obj = kmem_cache_alloc(...);
|
||||
lock_chain(); // typically a spin_lock()
|
||||
obj->key = key;
|
||||
/*
|
||||
* we need to make sure obj->key is updated before obj->next
|
||||
* or obj->refcnt
|
||||
*/
|
||||
smp_wmb();
|
||||
atomic_set(&obj->refcnt, 1);
|
||||
hlist_add_head_rcu(&obj->obj_node, list);
|
||||
unlock_chain(); // typically a spin_unlock()
|
||||
|
||||
|
||||
3) Remove algo
|
||||
--------------
|
||||
Nothing special here, we can use a standard RCU hlist deletion.
|
||||
But thanks to SLAB_TYPESAFE_BY_RCU, beware a deleted object can be reused
|
||||
very very fast (before the end of RCU grace period)
|
||||
|
||||
::
|
||||
|
||||
if (put_last_reference_on(obj) {
|
||||
lock_chain(); // typically a spin_lock()
|
||||
hlist_del_init_rcu(&obj->obj_node);
|
||||
unlock_chain(); // typically a spin_unlock()
|
||||
kmem_cache_free(cachep, obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Avoiding extra smp_rmb()
|
||||
========================
|
||||
|
||||
With hlist_nulls we can avoid extra smp_rmb() in lockless_lookup()
|
||||
and extra smp_wmb() in insert function.
|
||||
|
||||
For example, if we choose to store the slot number as the 'nulls'
|
||||
end-of-list marker for each slot of the hash table, we can detect
|
||||
a race (some writer did a delete and/or a move of an object
|
||||
to another chain) checking the final 'nulls' value if
|
||||
the lookup met the end of chain. If final 'nulls' value
|
||||
is not the slot number, then we must restart the lookup at
|
||||
the beginning. If the object was moved to the same chain,
|
||||
then the reader doesn't care : It might eventually
|
||||
scan the list again without harm.
|
||||
|
||||
|
||||
1) lookup algo
|
||||
--------------
|
||||
|
||||
::
|
||||
|
||||
head = &table[slot];
|
||||
rcu_read_lock();
|
||||
begin:
|
||||
hlist_nulls_for_each_entry_rcu(obj, node, head, member) {
|
||||
if (obj->key == key) {
|
||||
if (!try_get_ref(obj)) // might fail for free objects
|
||||
goto begin;
|
||||
if (obj->key != key) { // not the object we expected
|
||||
put_ref(obj);
|
||||
goto begin;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* if the nulls value we got at the end of this lookup is
|
||||
* not the expected one, we must restart lookup.
|
||||
* We probably met an item that was moved to another chain.
|
||||
*/
|
||||
if (get_nulls_value(node) != slot)
|
||||
goto begin;
|
||||
obj = NULL;
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
2) Insert function
|
||||
------------------
|
||||
|
||||
::
|
||||
|
||||
/*
|
||||
* Please note that new inserts are done at the head of list,
|
||||
* not in the middle or end.
|
||||
*/
|
||||
obj = kmem_cache_alloc(cachep);
|
||||
lock_chain(); // typically a spin_lock()
|
||||
obj->key = key;
|
||||
/*
|
||||
* changes to obj->key must be visible before refcnt one
|
||||
*/
|
||||
smp_wmb();
|
||||
atomic_set(&obj->refcnt, 1);
|
||||
/*
|
||||
* insert obj in RCU way (readers might be traversing chain)
|
||||
*/
|
||||
hlist_nulls_add_head_rcu(&obj->obj_node, list);
|
||||
unlock_chain(); // typically a spin_unlock()
|
158
Documentation/RCU/rcuref.rst
Normal file
@ -0,0 +1,158 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====================================================================
|
||||
Reference-count design for elements of lists/arrays protected by RCU
|
||||
====================================================================
|
||||
|
||||
|
||||
Please note that the percpu-ref feature is likely your first
|
||||
stop if you need to combine reference counts and RCU. Please see
|
||||
include/linux/percpu-refcount.h for more information. However, in
|
||||
those unusual cases where percpu-ref would consume too much memory,
|
||||
please read on.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Reference counting on elements of lists which are protected by traditional
|
||||
reader/writer spinlocks or semaphores are straightforward:
|
||||
|
||||
CODE LISTING A::
|
||||
|
||||
1. 2.
|
||||
add() search_and_reference()
|
||||
{ {
|
||||
alloc_object read_lock(&list_lock);
|
||||
... search_for_element
|
||||
atomic_set(&el->rc, 1); atomic_inc(&el->rc);
|
||||
write_lock(&list_lock); ...
|
||||
add_element read_unlock(&list_lock);
|
||||
... ...
|
||||
write_unlock(&list_lock); }
|
||||
}
|
||||
|
||||
3. 4.
|
||||
release_referenced() delete()
|
||||
{ {
|
||||
... write_lock(&list_lock);
|
||||
if(atomic_dec_and_test(&el->rc)) ...
|
||||
kfree(el);
|
||||
... remove_element
|
||||
} write_unlock(&list_lock);
|
||||
...
|
||||
if (atomic_dec_and_test(&el->rc))
|
||||
kfree(el);
|
||||
...
|
||||
}
|
||||
|
||||
If this list/array is made lock free using RCU as in changing the
|
||||
write_lock() in add() and delete() to spin_lock() and changing read_lock()
|
||||
in search_and_reference() to rcu_read_lock(), the atomic_inc() in
|
||||
search_and_reference() could potentially hold reference to an element which
|
||||
has already been deleted from the list/array. Use atomic_inc_not_zero()
|
||||
in this scenario as follows:
|
||||
|
||||
CODE LISTING B::
|
||||
|
||||
1. 2.
|
||||
add() search_and_reference()
|
||||
{ {
|
||||
alloc_object rcu_read_lock();
|
||||
... search_for_element
|
||||
atomic_set(&el->rc, 1); if (!atomic_inc_not_zero(&el->rc)) {
|
||||
spin_lock(&list_lock); rcu_read_unlock();
|
||||
return FAIL;
|
||||
add_element }
|
||||
... ...
|
||||
spin_unlock(&list_lock); rcu_read_unlock();
|
||||
} }
|
||||
3. 4.
|
||||
release_referenced() delete()
|
||||
{ {
|
||||
... spin_lock(&list_lock);
|
||||
if (atomic_dec_and_test(&el->rc)) ...
|
||||
call_rcu(&el->head, el_free); remove_element
|
||||
... spin_unlock(&list_lock);
|
||||
} ...
|
||||
if (atomic_dec_and_test(&el->rc))
|
||||
call_rcu(&el->head, el_free);
|
||||
...
|
||||
}
|
||||
|
||||
Sometimes, a reference to the element needs to be obtained in the
|
||||
update (write) stream. In such cases, atomic_inc_not_zero() might be
|
||||
overkill, since we hold the update-side spinlock. One might instead
|
||||
use atomic_inc() in such cases.
|
||||
|
||||
It is not always convenient to deal with "FAIL" in the
|
||||
search_and_reference() code path. In such cases, the
|
||||
atomic_dec_and_test() may be moved from delete() to el_free()
|
||||
as follows:
|
||||
|
||||
CODE LISTING C::
|
||||
|
||||
1. 2.
|
||||
add() search_and_reference()
|
||||
{ {
|
||||
alloc_object rcu_read_lock();
|
||||
... search_for_element
|
||||
atomic_set(&el->rc, 1); atomic_inc(&el->rc);
|
||||
spin_lock(&list_lock); ...
|
||||
|
||||
add_element rcu_read_unlock();
|
||||
... }
|
||||
spin_unlock(&list_lock); 4.
|
||||
} delete()
|
||||
3. {
|
||||
release_referenced() spin_lock(&list_lock);
|
||||
{ ...
|
||||
... remove_element
|
||||
if (atomic_dec_and_test(&el->rc)) spin_unlock(&list_lock);
|
||||
kfree(el); ...
|
||||
... call_rcu(&el->head, el_free);
|
||||
} ...
|
||||
5. }
|
||||
void el_free(struct rcu_head *rhp)
|
||||
{
|
||||
release_referenced();
|
||||
}
|
||||
|
||||
The key point is that the initial reference added by add() is not removed
|
||||
until after a grace period has elapsed following removal. This means that
|
||||
search_and_reference() cannot find this element, which means that the value
|
||||
of el->rc cannot increase. Thus, once it reaches zero, there are no
|
||||
readers that can or ever will be able to reference the element. The
|
||||
element can therefore safely be freed. This in turn guarantees that if
|
||||
any reader finds the element, that reader may safely acquire a reference
|
||||
without checking the value of the reference counter.
|
||||
|
||||
A clear advantage of the RCU-based pattern in listing C over the one
|
||||
in listing B is that any call to search_and_reference() that locates
|
||||
a given object will succeed in obtaining a reference to that object,
|
||||
even given a concurrent invocation of delete() for that same object.
|
||||
Similarly, a clear advantage of both listings B and C over listing A is
|
||||
that a call to delete() is not delayed even if there are an arbitrarily
|
||||
large number of calls to search_and_reference() searching for the same
|
||||
object that delete() was invoked on. Instead, all that is delayed is
|
||||
the eventual invocation of kfree(), which is usually not a problem on
|
||||
modern computer systems, even the small ones.
|
||||
|
||||
In cases where delete() can sleep, synchronize_rcu() can be called from
|
||||
delete(), so that el_free() can be subsumed into delete as follows::
|
||||
|
||||
4.
|
||||
delete()
|
||||
{
|
||||
spin_lock(&list_lock);
|
||||
...
|
||||
remove_element
|
||||
spin_unlock(&list_lock);
|
||||
...
|
||||
synchronize_rcu();
|
||||
if (atomic_dec_and_test(&el->rc))
|
||||
kfree(el);
|
||||
...
|
||||
}
|
||||
|
||||
As additional examples in the kernel, the pattern in listing C is used by
|
||||
reference counting of struct pid, while the pattern in listing B is used by
|
||||
struct posix_acl.
|
366
Documentation/RCU/stallwarn.rst
Normal file
@ -0,0 +1,366 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==============================
|
||||
Using RCU's CPU Stall Detector
|
||||
==============================
|
||||
|
||||
This document first discusses what sorts of issues RCU's CPU stall
|
||||
detector can locate, and then discusses kernel parameters and Kconfig
|
||||
options that can be used to fine-tune the detector's operation. Finally,
|
||||
this document explains the stall detector's "splat" format.
|
||||
|
||||
|
||||
What Causes RCU CPU Stall Warnings?
|
||||
===================================
|
||||
|
||||
So your kernel printed an RCU CPU stall warning. The next question is
|
||||
"What caused it?" The following problems can result in RCU CPU stall
|
||||
warnings:
|
||||
|
||||
- A CPU looping in an RCU read-side critical section.
|
||||
|
||||
- A CPU looping with interrupts disabled.
|
||||
|
||||
- A CPU looping with preemption disabled.
|
||||
|
||||
- A CPU looping with bottom halves disabled.
|
||||
|
||||
- For !CONFIG_PREEMPTION kernels, a CPU looping anywhere in the kernel
|
||||
without invoking schedule(). If the looping in the kernel is
|
||||
really expected and desirable behavior, you might need to add
|
||||
some calls to cond_resched().
|
||||
|
||||
- Booting Linux using a console connection that is too slow to
|
||||
keep up with the boot-time console-message rate. For example,
|
||||
a 115Kbaud serial console can be *way* too slow to keep up
|
||||
with boot-time message rates, and will frequently result in
|
||||
RCU CPU stall warning messages. Especially if you have added
|
||||
debug printk()s.
|
||||
|
||||
- Anything that prevents RCU's grace-period kthreads from running.
|
||||
This can result in the "All QSes seen" console-log message.
|
||||
This message will include information on when the kthread last
|
||||
ran and how often it should be expected to run. It can also
|
||||
result in the ``rcu_.*kthread starved for`` console-log message,
|
||||
which will include additional debugging information.
|
||||
|
||||
- A CPU-bound real-time task in a CONFIG_PREEMPTION kernel, which might
|
||||
happen to preempt a low-priority task in the middle of an RCU
|
||||
read-side critical section. This is especially damaging if
|
||||
that low-priority task is not permitted to run on any other CPU,
|
||||
in which case the next RCU grace period can never complete, which
|
||||
will eventually cause the system to run out of memory and hang.
|
||||
While the system is in the process of running itself out of
|
||||
memory, you might see stall-warning messages.
|
||||
|
||||
- A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that
|
||||
is running at a higher priority than the RCU softirq threads.
|
||||
This will prevent RCU callbacks from ever being invoked,
|
||||
and in a CONFIG_PREEMPT_RCU kernel will further prevent
|
||||
RCU grace periods from ever completing. Either way, the
|
||||
system will eventually run out of memory and hang. In the
|
||||
CONFIG_PREEMPT_RCU case, you might see stall-warning
|
||||
messages.
|
||||
|
||||
You can use the rcutree.kthread_prio kernel boot parameter to
|
||||
increase the scheduling priority of RCU's kthreads, which can
|
||||
help avoid this problem. However, please note that doing this
|
||||
can increase your system's context-switch rate and thus degrade
|
||||
performance.
|
||||
|
||||
- A periodic interrupt whose handler takes longer than the time
|
||||
interval between successive pairs of interrupts. This can
|
||||
prevent RCU's kthreads and softirq handlers from running.
|
||||
Note that certain high-overhead debugging options, for example
|
||||
the function_graph tracer, can result in interrupt handler taking
|
||||
considerably longer than normal, which can in turn result in
|
||||
RCU CPU stall warnings.
|
||||
|
||||
- Testing a workload on a fast system, tuning the stall-warning
|
||||
timeout down to just barely avoid RCU CPU stall warnings, and then
|
||||
running the same workload with the same stall-warning timeout on a
|
||||
slow system. Note that thermal throttling and on-demand governors
|
||||
can cause a single system to be sometimes fast and sometimes slow!
|
||||
|
||||
- A hardware or software issue shuts off the scheduler-clock
|
||||
interrupt on a CPU that is not in dyntick-idle mode. This
|
||||
problem really has happened, and seems to be most likely to
|
||||
result in RCU CPU stall warnings for CONFIG_NO_HZ_COMMON=n kernels.
|
||||
|
||||
- A hardware or software issue that prevents time-based wakeups
|
||||
from occurring. These issues can range from misconfigured or
|
||||
buggy timer hardware through bugs in the interrupt or exception
|
||||
path (whether hardware, firmware, or software) through bugs
|
||||
in Linux's timer subsystem through bugs in the scheduler, and,
|
||||
yes, even including bugs in RCU itself. It can also result in
|
||||
the ``rcu_.*timer wakeup didn't happen for`` console-log message,
|
||||
which will include additional debugging information.
|
||||
|
||||
- A bug in the RCU implementation.
|
||||
|
||||
- A hardware failure. This is quite unlikely, but has occurred
|
||||
at least once in real life. A CPU failed in a running system,
|
||||
becoming unresponsive, but not causing an immediate crash.
|
||||
This resulted in a series of RCU CPU stall warnings, eventually
|
||||
leading the realization that the CPU had failed.
|
||||
|
||||
The RCU, RCU-sched, and RCU-tasks implementations have CPU stall warning.
|
||||
Note that SRCU does *not* have CPU stall warnings. Please note that
|
||||
RCU only detects CPU stalls when there is a grace period in progress.
|
||||
No grace period, no CPU stall warnings.
|
||||
|
||||
To diagnose the cause of the stall, inspect the stack traces.
|
||||
The offending function will usually be near the top of the stack.
|
||||
If you have a series of stall warnings from a single extended stall,
|
||||
comparing the stack traces can often help determine where the stall
|
||||
is occurring, which will usually be in the function nearest the top of
|
||||
that portion of the stack which remains the same from trace to trace.
|
||||
If you can reliably trigger the stall, ftrace can be quite helpful.
|
||||
|
||||
RCU bugs can often be debugged with the help of CONFIG_RCU_TRACE
|
||||
and with RCU's event tracing. For information on RCU's event tracing,
|
||||
see include/trace/events/rcu.h.
|
||||
|
||||
|
||||
Fine-Tuning the RCU CPU Stall Detector
|
||||
======================================
|
||||
|
||||
The rcuupdate.rcu_cpu_stall_suppress module parameter disables RCU's
|
||||
CPU stall detector, which detects conditions that unduly delay RCU grace
|
||||
periods. This module parameter enables CPU stall detection by default,
|
||||
but may be overridden via boot-time parameter or at runtime via sysfs.
|
||||
The stall detector's idea of what constitutes "unduly delayed" is
|
||||
controlled by a set of kernel configuration variables and cpp macros:
|
||||
|
||||
CONFIG_RCU_CPU_STALL_TIMEOUT
|
||||
----------------------------
|
||||
|
||||
This kernel configuration parameter defines the period of time
|
||||
that RCU will wait from the beginning of a grace period until it
|
||||
issues an RCU CPU stall warning. This time period is normally
|
||||
21 seconds.
|
||||
|
||||
This configuration parameter may be changed at runtime via the
|
||||
/sys/module/rcupdate/parameters/rcu_cpu_stall_timeout, however
|
||||
this parameter is checked only at the beginning of a cycle.
|
||||
So if you are 10 seconds into a 40-second stall, setting this
|
||||
sysfs parameter to (say) five will shorten the timeout for the
|
||||
*next* stall, or the following warning for the current stall
|
||||
(assuming the stall lasts long enough). It will not affect the
|
||||
timing of the next warning for the current stall.
|
||||
|
||||
Stall-warning messages may be enabled and disabled completely via
|
||||
/sys/module/rcupdate/parameters/rcu_cpu_stall_suppress.
|
||||
|
||||
RCU_STALL_DELAY_DELTA
|
||||
---------------------
|
||||
|
||||
Although the lockdep facility is extremely useful, it does add
|
||||
some overhead. Therefore, under CONFIG_PROVE_RCU, the
|
||||
RCU_STALL_DELAY_DELTA macro allows five extra seconds before
|
||||
giving an RCU CPU stall warning message. (This is a cpp
|
||||
macro, not a kernel configuration parameter.)
|
||||
|
||||
RCU_STALL_RAT_DELAY
|
||||
-------------------
|
||||
|
||||
The CPU stall detector tries to make the offending CPU print its
|
||||
own warnings, as this often gives better-quality stack traces.
|
||||
However, if the offending CPU does not detect its own stall in
|
||||
the number of jiffies specified by RCU_STALL_RAT_DELAY, then
|
||||
some other CPU will complain. This delay is normally set to
|
||||
two jiffies. (This is a cpp macro, not a kernel configuration
|
||||
parameter.)
|
||||
|
||||
rcupdate.rcu_task_stall_timeout
|
||||
-------------------------------
|
||||
|
||||
This boot/sysfs parameter controls the RCU-tasks stall warning
|
||||
interval. A value of zero or less suppresses RCU-tasks stall
|
||||
warnings. A positive value sets the stall-warning interval
|
||||
in seconds. An RCU-tasks stall warning starts with the line:
|
||||
|
||||
INFO: rcu_tasks detected stalls on tasks:
|
||||
|
||||
And continues with the output of sched_show_task() for each
|
||||
task stalling the current RCU-tasks grace period.
|
||||
|
||||
|
||||
Interpreting RCU's CPU Stall-Detector "Splats"
|
||||
==============================================
|
||||
|
||||
For non-RCU-tasks flavors of RCU, when a CPU detects that some other
|
||||
CPU is stalling, it will print a message similar to the following::
|
||||
|
||||
INFO: rcu_sched detected stalls on CPUs/tasks:
|
||||
2-...: (3 GPs behind) idle=06c/0/0 softirq=1453/1455 fqs=0
|
||||
16-...: (0 ticks this GP) idle=81c/0/0 softirq=764/764 fqs=0
|
||||
(detected by 32, t=2603 jiffies, g=7075, q=625)
|
||||
|
||||
This message indicates that CPU 32 detected that CPUs 2 and 16 were both
|
||||
causing stalls, and that the stall was affecting RCU-sched. This message
|
||||
will normally be followed by stack dumps for each CPU. Please note that
|
||||
PREEMPT_RCU builds can be stalled by tasks as well as by CPUs, and that
|
||||
the tasks will be indicated by PID, for example, "P3421". It is even
|
||||
possible for an rcu_state stall to be caused by both CPUs *and* tasks,
|
||||
in which case the offending CPUs and tasks will all be called out in the list.
|
||||
In some cases, CPUs will detect themselves stalling, which will result
|
||||
in a self-detected stall.
|
||||
|
||||
CPU 2's "(3 GPs behind)" indicates that this CPU has not interacted with
|
||||
the RCU core for the past three grace periods. In contrast, CPU 16's "(0
|
||||
ticks this GP)" indicates that this CPU has not taken any scheduling-clock
|
||||
interrupts during the current stalled grace period.
|
||||
|
||||
The "idle=" portion of the message prints the dyntick-idle state.
|
||||
The hex number before the first "/" is the low-order 12 bits of the
|
||||
dynticks counter, which will have an even-numbered value if the CPU
|
||||
is in dyntick-idle mode and an odd-numbered value otherwise. The hex
|
||||
number between the two "/"s is the value of the nesting, which will be
|
||||
a small non-negative number if in the idle loop (as shown above) and a
|
||||
very large positive number otherwise.
|
||||
|
||||
The "softirq=" portion of the message tracks the number of RCU softirq
|
||||
handlers that the stalled CPU has executed. The number before the "/"
|
||||
is the number that had executed since boot at the time that this CPU
|
||||
last noted the beginning of a grace period, which might be the current
|
||||
(stalled) grace period, or it might be some earlier grace period (for
|
||||
example, if the CPU might have been in dyntick-idle mode for an extended
|
||||
time period). The number after the "/" is the number that have executed
|
||||
since boot until the current time. If this latter number stays constant
|
||||
across repeated stall-warning messages, it is possible that RCU's softirq
|
||||
handlers are no longer able to execute on this CPU. This can happen if
|
||||
the stalled CPU is spinning with interrupts are disabled, or, in -rt
|
||||
kernels, if a high-priority process is starving RCU's softirq handler.
|
||||
|
||||
The "fqs=" shows the number of force-quiescent-state idle/offline
|
||||
detection passes that the grace-period kthread has made across this
|
||||
CPU since the last time that this CPU noted the beginning of a grace
|
||||
period.
|
||||
|
||||
The "detected by" line indicates which CPU detected the stall (in this
|
||||
case, CPU 32), how many jiffies have elapsed since the start of the grace
|
||||
period (in this case 2603), the grace-period sequence number (7075), and
|
||||
an estimate of the total number of RCU callbacks queued across all CPUs
|
||||
(625 in this case).
|
||||
|
||||
In kernels with CONFIG_RCU_FAST_NO_HZ, more information is printed
|
||||
for each CPU::
|
||||
|
||||
0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 softirq=82/543 last_accelerate: a345/d342 dyntick_enabled: 1
|
||||
|
||||
The "last_accelerate:" prints the low-order 16 bits (in hex) of the
|
||||
jiffies counter when this CPU last invoked rcu_try_advance_all_cbs()
|
||||
from rcu_needs_cpu() or last invoked rcu_accelerate_cbs() from
|
||||
rcu_prepare_for_idle(). "dyntick_enabled: 1" indicates that dyntick-idle
|
||||
processing is enabled.
|
||||
|
||||
If the grace period ends just as the stall warning starts printing,
|
||||
there will be a spurious stall-warning message, which will include
|
||||
the following::
|
||||
|
||||
INFO: Stall ended before state dump start
|
||||
|
||||
This is rare, but does happen from time to time in real life. It is also
|
||||
possible for a zero-jiffy stall to be flagged in this case, depending
|
||||
on how the stall warning and the grace-period initialization happen to
|
||||
interact. Please note that it is not possible to entirely eliminate this
|
||||
sort of false positive without resorting to things like stop_machine(),
|
||||
which is overkill for this sort of problem.
|
||||
|
||||
If all CPUs and tasks have passed through quiescent states, but the
|
||||
grace period has nevertheless failed to end, the stall-warning splat
|
||||
will include something like the following::
|
||||
|
||||
All QSes seen, last rcu_preempt kthread activity 23807 (4297905177-4297881370), jiffies_till_next_fqs=3, root ->qsmask 0x0
|
||||
|
||||
The "23807" indicates that it has been more than 23 thousand jiffies
|
||||
since the grace-period kthread ran. The "jiffies_till_next_fqs"
|
||||
indicates how frequently that kthread should run, giving the number
|
||||
of jiffies between force-quiescent-state scans, in this case three,
|
||||
which is way less than 23807. Finally, the root rcu_node structure's
|
||||
->qsmask field is printed, which will normally be zero.
|
||||
|
||||
If the relevant grace-period kthread has been unable to run prior to
|
||||
the stall warning, as was the case in the "All QSes seen" line above,
|
||||
the following additional line is printed::
|
||||
|
||||
rcu_sched kthread starved for 23807 jiffies! g7075 f0x0 RCU_GP_WAIT_FQS(3) ->state=0x1 ->cpu=5
|
||||
Unless rcu_sched kthread gets sufficient CPU time, OOM is now expected behavior.
|
||||
|
||||
Starving the grace-period kthreads of CPU time can of course result
|
||||
in RCU CPU stall warnings even when all CPUs and tasks have passed
|
||||
through the required quiescent states. The "g" number shows the current
|
||||
grace-period sequence number, the "f" precedes the ->gp_flags command
|
||||
to the grace-period kthread, the "RCU_GP_WAIT_FQS" indicates that the
|
||||
kthread is waiting for a short timeout, the "state" precedes value of the
|
||||
task_struct ->state field, and the "cpu" indicates that the grace-period
|
||||
kthread last ran on CPU 5.
|
||||
|
||||
If the relevant grace-period kthread does not wake from FQS wait in a
|
||||
reasonable time, then the following additional line is printed::
|
||||
|
||||
kthread timer wakeup didn't happen for 23804 jiffies! g7076 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402
|
||||
|
||||
The "23804" indicates that kthread's timer expired more than 23 thousand
|
||||
jiffies ago. The rest of the line has meaning similar to the kthread
|
||||
starvation case.
|
||||
|
||||
Additionally, the following line is printed::
|
||||
|
||||
Possible timer handling issue on cpu=4 timer-softirq=11142
|
||||
|
||||
Here "cpu" indicates that the grace-period kthread last ran on CPU 4,
|
||||
where it queued the fqs timer. The number following the "timer-softirq"
|
||||
is the current ``TIMER_SOFTIRQ`` count on cpu 4. If this value does not
|
||||
change on successive RCU CPU stall warnings, there is further reason to
|
||||
suspect a timer problem.
|
||||
|
||||
These messages are usually followed by stack dumps of the CPUs and tasks
|
||||
involved in the stall. These stack traces can help you locate the cause
|
||||
of the stall, keeping in mind that the CPU detecting the stall will have
|
||||
an interrupt frame that is mainly devoted to detecting the stall.
|
||||
|
||||
|
||||
Multiple Warnings From One Stall
|
||||
================================
|
||||
|
||||
If a stall lasts long enough, multiple stall-warning messages will
|
||||
be printed for it. The second and subsequent messages are printed at
|
||||
longer intervals, so that the time between (say) the first and second
|
||||
message will be about three times the interval between the beginning
|
||||
of the stall and the first message. It can be helpful to compare the
|
||||
stack dumps for the different messages for the same stalled grace period.
|
||||
|
||||
|
||||
Stall Warnings for Expedited Grace Periods
|
||||
==========================================
|
||||
|
||||
If an expedited grace period detects a stall, it will place a message
|
||||
like the following in dmesg::
|
||||
|
||||
INFO: rcu_sched detected expedited stalls on CPUs/tasks: { 7-... } 21119 jiffies s: 73 root: 0x2/.
|
||||
|
||||
This indicates that CPU 7 has failed to respond to a reschedule IPI.
|
||||
The three periods (".") following the CPU number indicate that the CPU
|
||||
is online (otherwise the first period would instead have been "O"),
|
||||
that the CPU was online at the beginning of the expedited grace period
|
||||
(otherwise the second period would have instead been "o"), and that
|
||||
the CPU has been online at least once since boot (otherwise, the third
|
||||
period would instead have been "N"). The number before the "jiffies"
|
||||
indicates that the expedited grace period has been going on for 21,119
|
||||
jiffies. The number following the "s:" indicates that the expedited
|
||||
grace-period sequence counter is 73. The fact that this last value is
|
||||
odd indicates that an expedited grace period is in flight. The number
|
||||
following "root:" is a bitmask that indicates which children of the root
|
||||
rcu_node structure correspond to CPUs and/or tasks that are blocking the
|
||||
current expedited grace period. If the tree had more than one level,
|
||||
additional hex numbers would be printed for the states of the other
|
||||
rcu_node structures in the tree.
|
||||
|
||||
As with normal grace periods, PREEMPT_RCU builds can be stalled by
|
||||
tasks as well as by CPUs, and that the tasks will be indicated by PID,
|
||||
for example, "P3421".
|
||||
|
||||
It is entirely possible to see stall warnings from normal and from
|
||||
expedited grace periods at about the same time during the same run.
|
293
Documentation/RCU/torture.rst
Normal file
@ -0,0 +1,293 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==========================
|
||||
RCU Torture Test Operation
|
||||
==========================
|
||||
|
||||
|
||||
CONFIG_RCU_TORTURE_TEST
|
||||
=======================
|
||||
|
||||
The CONFIG_RCU_TORTURE_TEST config option is available for all RCU
|
||||
implementations. It creates an rcutorture kernel module that can
|
||||
be loaded to run a torture test. The test periodically outputs
|
||||
status messages via printk(), which can be examined via the dmesg
|
||||
command (perhaps grepping for "torture"). The test is started
|
||||
when the module is loaded, and stops when the module is unloaded.
|
||||
|
||||
Module parameters are prefixed by "rcutorture." in
|
||||
Documentation/admin-guide/kernel-parameters.txt.
|
||||
|
||||
Output
|
||||
======
|
||||
|
||||
The statistics output is as follows::
|
||||
|
||||
rcu-torture:--- Start of test: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
|
||||
rcu-torture: rtc: (null) ver: 155441 tfle: 0 rta: 155441 rtaf: 8884 rtf: 155440 rtmbe: 0 rtbe: 0 rtbke: 0 rtbre: 0 rtbf: 0 rtb: 0 nt: 3055767
|
||||
rcu-torture: Reader Pipe: 727860534 34213 0 0 0 0 0 0 0 0 0
|
||||
rcu-torture: Reader Batch: 727877838 17003 0 0 0 0 0 0 0 0 0
|
||||
rcu-torture: Free-Block Circulation: 155440 155440 155440 155440 155440 155440 155440 155440 155440 155440 0
|
||||
rcu-torture:--- End of test: SUCCESS: nreaders=16 nfakewriters=4 stat_interval=30 verbose=0 test_no_idle_hz=1 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4
|
||||
|
||||
The command "dmesg | grep torture:" will extract this information on
|
||||
most systems. On more esoteric configurations, it may be necessary to
|
||||
use other commands to access the output of the printk()s used by
|
||||
the RCU torture test. The printk()s use KERN_ALERT, so they should
|
||||
be evident. ;-)
|
||||
|
||||
The first and last lines show the rcutorture module parameters, and the
|
||||
last line shows either "SUCCESS" or "FAILURE", based on rcutorture's
|
||||
automatic determination as to whether RCU operated correctly.
|
||||
|
||||
The entries are as follows:
|
||||
|
||||
* "rtc": The hexadecimal address of the structure currently visible
|
||||
to readers.
|
||||
|
||||
* "ver": The number of times since boot that the RCU writer task
|
||||
has changed the structure visible to readers.
|
||||
|
||||
* "tfle": If non-zero, indicates that the "torture freelist"
|
||||
containing structures to be placed into the "rtc" area is empty.
|
||||
This condition is important, since it can fool you into thinking
|
||||
that RCU is working when it is not. :-/
|
||||
|
||||
* "rta": Number of structures allocated from the torture freelist.
|
||||
|
||||
* "rtaf": Number of allocations from the torture freelist that have
|
||||
failed due to the list being empty. It is not unusual for this
|
||||
to be non-zero, but it is bad for it to be a large fraction of
|
||||
the value indicated by "rta".
|
||||
|
||||
* "rtf": Number of frees into the torture freelist.
|
||||
|
||||
* "rtmbe": A non-zero value indicates that rcutorture believes that
|
||||
rcu_assign_pointer() and rcu_dereference() are not working
|
||||
correctly. This value should be zero.
|
||||
|
||||
* "rtbe": A non-zero value indicates that one of the rcu_barrier()
|
||||
family of functions is not working correctly.
|
||||
|
||||
* "rtbke": rcutorture was unable to create the real-time kthreads
|
||||
used to force RCU priority inversion. This value should be zero.
|
||||
|
||||
* "rtbre": Although rcutorture successfully created the kthreads
|
||||
used to force RCU priority inversion, it was unable to set them
|
||||
to the real-time priority level of 1. This value should be zero.
|
||||
|
||||
* "rtbf": The number of times that RCU priority boosting failed
|
||||
to resolve RCU priority inversion.
|
||||
|
||||
* "rtb": The number of times that rcutorture attempted to force
|
||||
an RCU priority inversion condition. If you are testing RCU
|
||||
priority boosting via the "test_boost" module parameter, this
|
||||
value should be non-zero.
|
||||
|
||||
* "nt": The number of times rcutorture ran RCU read-side code from
|
||||
within a timer handler. This value should be non-zero only
|
||||
if you specified the "irqreader" module parameter.
|
||||
|
||||
* "Reader Pipe": Histogram of "ages" of structures seen by readers.
|
||||
If any entries past the first two are non-zero, RCU is broken.
|
||||
And rcutorture prints the error flag string "!!!" to make sure
|
||||
you notice. The age of a newly allocated structure is zero,
|
||||
it becomes one when removed from reader visibility, and is
|
||||
incremented once per grace period subsequently -- and is freed
|
||||
after passing through (RCU_TORTURE_PIPE_LEN-2) grace periods.
|
||||
|
||||
The output displayed above was taken from a correctly working
|
||||
RCU. If you want to see what it looks like when broken, break
|
||||
it yourself. ;-)
|
||||
|
||||
* "Reader Batch": Another histogram of "ages" of structures seen
|
||||
by readers, but in terms of counter flips (or batches) rather
|
||||
than in terms of grace periods. The legal number of non-zero
|
||||
entries is again two. The reason for this separate view is that
|
||||
it is sometimes easier to get the third entry to show up in the
|
||||
"Reader Batch" list than in the "Reader Pipe" list.
|
||||
|
||||
* "Free-Block Circulation": Shows the number of torture structures
|
||||
that have reached a given point in the pipeline. The first element
|
||||
should closely correspond to the number of structures allocated,
|
||||
the second to the number that have been removed from reader view,
|
||||
and all but the last remaining to the corresponding number of
|
||||
passes through a grace period. The last entry should be zero,
|
||||
as it is only incremented if a torture structure's counter
|
||||
somehow gets incremented farther than it should.
|
||||
|
||||
Different implementations of RCU can provide implementation-specific
|
||||
additional information. For example, Tree SRCU provides the following
|
||||
additional line::
|
||||
|
||||
srcud-torture: Tree SRCU per-CPU(idx=0): 0(35,-21) 1(-4,24) 2(1,1) 3(-26,20) 4(28,-47) 5(-9,4) 6(-10,14) 7(-14,11) T(1,6)
|
||||
|
||||
This line shows the per-CPU counter state, in this case for Tree SRCU
|
||||
using a dynamically allocated srcu_struct (hence "srcud-" rather than
|
||||
"srcu-"). The numbers in parentheses are the values of the "old" and
|
||||
"current" counters for the corresponding CPU. The "idx" value maps the
|
||||
"old" and "current" values to the underlying array, and is useful for
|
||||
debugging. The final "T" entry contains the totals of the counters.
|
||||
|
||||
Usage on Specific Kernel Builds
|
||||
===============================
|
||||
|
||||
It is sometimes desirable to torture RCU on a specific kernel build,
|
||||
for example, when preparing to put that kernel build into production.
|
||||
In that case, the kernel should be built with CONFIG_RCU_TORTURE_TEST=m
|
||||
so that the test can be started using modprobe and terminated using rmmod.
|
||||
|
||||
For example, the following script may be used to torture RCU::
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
modprobe rcutorture
|
||||
sleep 3600
|
||||
rmmod rcutorture
|
||||
dmesg | grep torture:
|
||||
|
||||
The output can be manually inspected for the error flag of "!!!".
|
||||
One could of course create a more elaborate script that automatically
|
||||
checked for such errors. The "rmmod" command forces a "SUCCESS",
|
||||
"FAILURE", or "RCU_HOTPLUG" indication to be printk()ed. The first
|
||||
two are self-explanatory, while the last indicates that while there
|
||||
were no RCU failures, CPU-hotplug problems were detected.
|
||||
|
||||
|
||||
Usage on Mainline Kernels
|
||||
=========================
|
||||
|
||||
When using rcutorture to test changes to RCU itself, it is often
|
||||
necessary to build a number of kernels in order to test that change
|
||||
across a broad range of combinations of the relevant Kconfig options
|
||||
and of the relevant kernel boot parameters. In this situation, use
|
||||
of modprobe and rmmod can be quite time-consuming and error-prone.
|
||||
|
||||
Therefore, the tools/testing/selftests/rcutorture/bin/kvm.sh
|
||||
script is available for mainline testing for x86, arm64, and
|
||||
powerpc. By default, it will run the series of tests specified by
|
||||
tools/testing/selftests/rcutorture/configs/rcu/CFLIST, with each test
|
||||
running for 30 minutes within a guest OS using a minimal userspace
|
||||
supplied by an automatically generated initrd. After the tests are
|
||||
complete, the resulting build products and console output are analyzed
|
||||
for errors and the results of the runs are summarized.
|
||||
|
||||
On larger systems, rcutorture testing can be accelerated by passing the
|
||||
--cpus argument to kvm.sh. For example, on a 64-CPU system, "--cpus 43"
|
||||
would use up to 43 CPUs to run tests concurrently, which as of v5.4 would
|
||||
complete all the scenarios in two batches, reducing the time to complete
|
||||
from about eight hours to about one hour (not counting the time to build
|
||||
the sixteen kernels). The "--dryrun sched" argument will not run tests,
|
||||
but rather tell you how the tests would be scheduled into batches. This
|
||||
can be useful when working out how many CPUs to specify in the --cpus
|
||||
argument.
|
||||
|
||||
Not all changes require that all scenarios be run. For example, a change
|
||||
to Tree SRCU might run only the SRCU-N and SRCU-P scenarios using the
|
||||
--configs argument to kvm.sh as follows: "--configs 'SRCU-N SRCU-P'".
|
||||
Large systems can run multiple copies of of the full set of scenarios,
|
||||
for example, a system with 448 hardware threads can run five instances
|
||||
of the full set concurrently. To make this happen::
|
||||
|
||||
kvm.sh --cpus 448 --configs '5*CFLIST'
|
||||
|
||||
Alternatively, such a system can run 56 concurrent instances of a single
|
||||
eight-CPU scenario::
|
||||
|
||||
kvm.sh --cpus 448 --configs '56*TREE04'
|
||||
|
||||
Or 28 concurrent instances of each of two eight-CPU scenarios::
|
||||
|
||||
kvm.sh --cpus 448 --configs '28*TREE03 28*TREE04'
|
||||
|
||||
Of course, each concurrent instance will use memory, which can be
|
||||
limited using the --memory argument, which defaults to 512M. Small
|
||||
values for memory may require disabling the callback-flooding tests
|
||||
using the --bootargs parameter discussed below.
|
||||
|
||||
Sometimes additional debugging is useful, and in such cases the --kconfig
|
||||
parameter to kvm.sh may be used, for example, ``--kconfig 'CONFIG_KASAN=y'``.
|
||||
|
||||
Kernel boot arguments can also be supplied, for example, to control
|
||||
rcutorture's module parameters. For example, to test a change to RCU's
|
||||
CPU stall-warning code, use "--bootargs 'rcutorture.stall_cpu=30'".
|
||||
This will of course result in the scripting reporting a failure, namely
|
||||
the resuling RCU CPU stall warning. As noted above, reducing memory may
|
||||
require disabling rcutorture's callback-flooding tests::
|
||||
|
||||
kvm.sh --cpus 448 --configs '56*TREE04' --memory 128M \
|
||||
--bootargs 'rcutorture.fwd_progress=0'
|
||||
|
||||
Sometimes all that is needed is a full set of kernel builds. This is
|
||||
what the --buildonly argument does.
|
||||
|
||||
Finally, the --trust-make argument allows each kernel build to reuse what
|
||||
it can from the previous kernel build.
|
||||
|
||||
There are additional more arcane arguments that are documented in the
|
||||
source code of the kvm.sh script.
|
||||
|
||||
If a run contains failures, the number of buildtime and runtime failures
|
||||
is listed at the end of the kvm.sh output, which you really should redirect
|
||||
to a file. The build products and console output of each run is kept in
|
||||
tools/testing/selftests/rcutorture/res in timestamped directories. A
|
||||
given directory can be supplied to kvm-find-errors.sh in order to have
|
||||
it cycle you through summaries of errors and full error logs. For example::
|
||||
|
||||
tools/testing/selftests/rcutorture/bin/kvm-find-errors.sh \
|
||||
tools/testing/selftests/rcutorture/res/2020.01.20-15.54.23
|
||||
|
||||
However, it is often more convenient to access the files directly.
|
||||
Files pertaining to all scenarios in a run reside in the top-level
|
||||
directory (2020.01.20-15.54.23 in the example above), while per-scenario
|
||||
files reside in a subdirectory named after the scenario (for example,
|
||||
"TREE04"). If a given scenario ran more than once (as in "--configs
|
||||
'56*TREE04'" above), the directories corresponding to the second and
|
||||
subsequent runs of that scenario include a sequence number, for example,
|
||||
"TREE04.2", "TREE04.3", and so on.
|
||||
|
||||
The most frequently used file in the top-level directory is testid.txt.
|
||||
If the test ran in a git repository, then this file contains the commit
|
||||
that was tested and any uncommitted changes in diff format.
|
||||
|
||||
The most frequently used files in each per-scenario-run directory are:
|
||||
|
||||
.config:
|
||||
This file contains the Kconfig options.
|
||||
|
||||
Make.out:
|
||||
This contains build output for a specific scenario.
|
||||
|
||||
console.log:
|
||||
This contains the console output for a specific scenario.
|
||||
This file may be examined once the kernel has booted, but
|
||||
it might not exist if the build failed.
|
||||
|
||||
vmlinux:
|
||||
This contains the kernel, which can be useful with tools like
|
||||
objdump and gdb.
|
||||
|
||||
A number of additional files are available, but are less frequently used.
|
||||
Many are intended for debugging of rcutorture itself or of its scripting.
|
||||
|
||||
As of v5.4, a successful run with the default set of scenarios produces
|
||||
the following summary at the end of the run on a 12-CPU system::
|
||||
|
||||
SRCU-N ------- 804233 GPs (148.932/s) [srcu: g10008272 f0x0 ]
|
||||
SRCU-P ------- 202320 GPs (37.4667/s) [srcud: g1809476 f0x0 ]
|
||||
SRCU-t ------- 1122086 GPs (207.794/s) [srcu: g0 f0x0 ]
|
||||
SRCU-u ------- 1111285 GPs (205.794/s) [srcud: g1 f0x0 ]
|
||||
TASKS01 ------- 19666 GPs (3.64185/s) [tasks: g0 f0x0 ]
|
||||
TASKS02 ------- 20541 GPs (3.80389/s) [tasks: g0 f0x0 ]
|
||||
TASKS03 ------- 19416 GPs (3.59556/s) [tasks: g0 f0x0 ]
|
||||
TINY01 ------- 836134 GPs (154.84/s) [rcu: g0 f0x0 ] n_max_cbs: 34198
|
||||
TINY02 ------- 850371 GPs (157.476/s) [rcu: g0 f0x0 ] n_max_cbs: 2631
|
||||
TREE01 ------- 162625 GPs (30.1157/s) [rcu: g1124169 f0x0 ]
|
||||
TREE02 ------- 333003 GPs (61.6672/s) [rcu: g2647753 f0x0 ] n_max_cbs: 35844
|
||||
TREE03 ------- 306623 GPs (56.782/s) [rcu: g2975325 f0x0 ] n_max_cbs: 1496497
|
||||
CPU count limited from 16 to 12
|
||||
TREE04 ------- 246149 GPs (45.5831/s) [rcu: g1695737 f0x0 ] n_max_cbs: 434961
|
||||
TREE05 ------- 314603 GPs (58.2598/s) [rcu: g2257741 f0x2 ] n_max_cbs: 193997
|
||||
TREE07 ------- 167347 GPs (30.9902/s) [rcu: g1079021 f0x0 ] n_max_cbs: 478732
|
||||
CPU count limited from 16 to 12
|
||||
TREE09 ------- 752238 GPs (139.303/s) [rcu: g13075057 f0x0 ] n_max_cbs: 99011
|
1153
Documentation/RCU/whatisRCU.rst
Normal file
31
Documentation/admin-guide/LSM/LoadPin.rst
Normal file
@ -0,0 +1,31 @@
|
||||
=======
|
||||
LoadPin
|
||||
=======
|
||||
|
||||
LoadPin is a Linux Security Module that ensures all kernel-loaded files
|
||||
(modules, firmware, etc) all originate from the same filesystem, with
|
||||
the expectation that such a filesystem is backed by a read-only device
|
||||
such as dm-verity or CDROM. This allows systems that have a verified
|
||||
and/or unchangeable filesystem to enforce module and firmware loading
|
||||
restrictions without needing to sign the files individually.
|
||||
|
||||
The LSM is selectable at build-time with ``CONFIG_SECURITY_LOADPIN``, and
|
||||
can be controlled at boot-time with the kernel command line option
|
||||
"``loadpin.enforce``". By default, it is enabled, but can be disabled at
|
||||
boot ("``loadpin.enforce=0``").
|
||||
|
||||
LoadPin starts pinning when it sees the first file loaded. If the
|
||||
block device backing the filesystem is not read-only, a sysctl is
|
||||
created to toggle pinning: ``/proc/sys/kernel/loadpin/enabled``. (Having
|
||||
a mutable filesystem means pinning is mutable too, but having the
|
||||
sysctl allows for easy testing on systems with a mutable filesystem.)
|
||||
|
||||
It's also possible to exclude specific file types from LoadPin using kernel
|
||||
command line option "``loadpin.exclude``". By default, all files are
|
||||
included, but they can be excluded using kernel command line option such
|
||||
as "``loadpin.exclude=kernel-module,kexec-image``". This allows to use
|
||||
different mechanisms such as ``CONFIG_MODULE_SIG`` and
|
||||
``CONFIG_KEXEC_VERIFY_SIG`` to verify kernel module and kernel image while
|
||||
still use LoadPin to protect the integrity of other files kernel loads. The
|
||||
full list of valid file types can be found in ``kernel_read_file_str``
|
||||
defined in ``include/linux/kernel_read_file.h``.
|
33
Documentation/admin-guide/LSM/SELinux.rst
Normal file
@ -0,0 +1,33 @@
|
||||
=======
|
||||
SELinux
|
||||
=======
|
||||
|
||||
If you want to use SELinux, chances are you will want
|
||||
to use the distro-provided policies, or install the
|
||||
latest reference policy release from
|
||||
|
||||
https://github.com/SELinuxProject/refpolicy
|
||||
|
||||
However, if you want to install a dummy policy for
|
||||
testing, you can do using ``mdp`` provided under
|
||||
scripts/selinux. Note that this requires the selinux
|
||||
userspace to be installed - in particular you will
|
||||
need checkpolicy to compile a kernel, and setfiles and
|
||||
fixfiles to label the filesystem.
|
||||
|
||||
1. Compile the kernel with selinux enabled.
|
||||
2. Type ``make`` to compile ``mdp``.
|
||||
3. Make sure that you are not running with
|
||||
SELinux enabled and a real policy. If
|
||||
you are, reboot with selinux disabled
|
||||
before continuing.
|
||||
4. Run install_policy.sh::
|
||||
|
||||
cd scripts/selinux
|
||||
sh install_policy.sh
|
||||
|
||||
Step 4 will create a new dummy policy valid for your
|
||||
kernel, with a single selinux user, role, and type.
|
||||
It will compile the policy, will set your ``SELINUXTYPE`` to
|
||||
``dummy`` in ``/etc/selinux/config``, install the compiled policy
|
||||
as ``dummy``, and relabel your filesystem.
|
118
Documentation/admin-guide/LSM/SafeSetID.rst
Normal file
@ -0,0 +1,118 @@
|
||||
=========
|
||||
SafeSetID
|
||||
=========
|
||||
SafeSetID is an LSM module that gates the setid family of syscalls to restrict
|
||||
UID/GID transitions from a given UID/GID to only those approved by a
|
||||
system-wide allowlist. These restrictions also prohibit the given UIDs/GIDs
|
||||
from obtaining auxiliary privileges associated with CAP_SET{U/G}ID, such as
|
||||
allowing a user to set up user namespace UID/GID mappings.
|
||||
|
||||
|
||||
Background
|
||||
==========
|
||||
In absence of file capabilities, processes spawned on a Linux system that need
|
||||
to switch to a different user must be spawned with CAP_SETUID privileges.
|
||||
CAP_SETUID is granted to programs running as root or those running as a non-root
|
||||
user that have been explicitly given the CAP_SETUID runtime capability. It is
|
||||
often preferable to use Linux runtime capabilities rather than file
|
||||
capabilities, since using file capabilities to run a program with elevated
|
||||
privileges opens up possible security holes since any user with access to the
|
||||
file can exec() that program to gain the elevated privileges.
|
||||
|
||||
While it is possible to implement a tree of processes by giving full
|
||||
CAP_SET{U/G}ID capabilities, this is often at odds with the goals of running a
|
||||
tree of processes under non-root user(s) in the first place. Specifically,
|
||||
since CAP_SETUID allows changing to any user on the system, including the root
|
||||
user, it is an overpowered capability for what is needed in this scenario,
|
||||
especially since programs often only call setuid() to drop privileges to a
|
||||
lesser-privileged user -- not elevate privileges. Unfortunately, there is no
|
||||
generally feasible way in Linux to restrict the potential UIDs that a user can
|
||||
switch to through setuid() beyond allowing a switch to any user on the system.
|
||||
This SafeSetID LSM seeks to provide a solution for restricting setid
|
||||
capabilities in such a way.
|
||||
|
||||
The main use case for this LSM is to allow a non-root program to transition to
|
||||
other untrusted uids without full blown CAP_SETUID capabilities. The non-root
|
||||
program would still need CAP_SETUID to do any kind of transition, but the
|
||||
additional restrictions imposed by this LSM would mean it is a "safer" version
|
||||
of CAP_SETUID since the non-root program cannot take advantage of CAP_SETUID to
|
||||
do any unapproved actions (e.g. setuid to uid 0 or create/enter new user
|
||||
namespace). The higher level goal is to allow for uid-based sandboxing of system
|
||||
services without having to give out CAP_SETUID all over the place just so that
|
||||
non-root programs can drop to even-lesser-privileged uids. This is especially
|
||||
relevant when one non-root daemon on the system should be allowed to spawn other
|
||||
processes as different uids, but its undesirable to give the daemon a
|
||||
basically-root-equivalent CAP_SETUID.
|
||||
|
||||
|
||||
Other Approaches Considered
|
||||
===========================
|
||||
|
||||
Solve this problem in userspace
|
||||
-------------------------------
|
||||
For candidate applications that would like to have restricted setid capabilities
|
||||
as implemented in this LSM, an alternative option would be to simply take away
|
||||
setid capabilities from the application completely and refactor the process
|
||||
spawning semantics in the application (e.g. by using a privileged helper program
|
||||
to do process spawning and UID/GID transitions). Unfortunately, there are a
|
||||
number of semantics around process spawning that would be affected by this, such
|
||||
as fork() calls where the program doesn't immediately call exec() after the
|
||||
fork(), parent processes specifying custom environment variables or command line
|
||||
args for spawned child processes, or inheritance of file handles across a
|
||||
fork()/exec(). Because of this, as solution that uses a privileged helper in
|
||||
userspace would likely be less appealing to incorporate into existing projects
|
||||
that rely on certain process-spawning semantics in Linux.
|
||||
|
||||
Use user namespaces
|
||||
-------------------
|
||||
Another possible approach would be to run a given process tree in its own user
|
||||
namespace and give programs in the tree setid capabilities. In this way,
|
||||
programs in the tree could change to any desired UID/GID in the context of their
|
||||
own user namespace, and only approved UIDs/GIDs could be mapped back to the
|
||||
initial system user namespace, affectively preventing privilege escalation.
|
||||
Unfortunately, it is not generally feasible to use user namespaces in isolation,
|
||||
without pairing them with other namespace types, which is not always an option.
|
||||
Linux checks for capabilities based off of the user namespace that "owns" some
|
||||
entity. For example, Linux has the notion that network namespaces are owned by
|
||||
the user namespace in which they were created. A consequence of this is that
|
||||
capability checks for access to a given network namespace are done by checking
|
||||
whether a task has the given capability in the context of the user namespace
|
||||
that owns the network namespace -- not necessarily the user namespace under
|
||||
which the given task runs. Therefore spawning a process in a new user namespace
|
||||
effectively prevents it from accessing the network namespace owned by the
|
||||
initial namespace. This is a deal-breaker for any application that expects to
|
||||
retain the CAP_NET_ADMIN capability for the purpose of adjusting network
|
||||
configurations. Using user namespaces in isolation causes problems regarding
|
||||
other system interactions, including use of pid namespaces and device creation.
|
||||
|
||||
Use an existing LSM
|
||||
-------------------
|
||||
None of the other in-tree LSMs have the capability to gate setid transitions, or
|
||||
even employ the security_task_fix_setuid hook at all. SELinux says of that hook:
|
||||
"Since setuid only affects the current process, and since the SELinux controls
|
||||
are not based on the Linux identity attributes, SELinux does not need to control
|
||||
this operation."
|
||||
|
||||
|
||||
Directions for use
|
||||
==================
|
||||
This LSM hooks the setid syscalls to make sure transitions are allowed if an
|
||||
applicable restriction policy is in place. Policies are configured through
|
||||
securityfs by writing to the safesetid/uid_allowlist_policy and
|
||||
safesetid/gid_allowlist_policy files at the location where securityfs is
|
||||
mounted. The format for adding a policy is '<UID>:<UID>' or '<GID>:<GID>',
|
||||
using literal numbers, and ending with a newline character such as '123:456\n'.
|
||||
Writing an empty string "" will flush the policy. Again, configuring a policy
|
||||
for a UID/GID will prevent that UID/GID from obtaining auxiliary setid
|
||||
privileges, such as allowing a user to set up user namespace UID/GID mappings.
|
||||
|
||||
Note on GID policies and setgroups()
|
||||
====================================
|
||||
In v5.9 we are adding support for limiting CAP_SETGID privileges as was done
|
||||
previously for CAP_SETUID. However, for compatibility with common sandboxing
|
||||
related code conventions in userspace, we currently allow arbitrary
|
||||
setgroups() calls for processes with CAP_SETGID restrictions. Until we add
|
||||
support in a future release for restricting setgroups() calls, these GID
|
||||
policies add no meaningful security. setgroups() restrictions will be enforced
|
||||
once we have the policy checking code in place, which will rely on GID policy
|
||||
configuration code added in v5.9.
|
861
Documentation/admin-guide/LSM/Smack.rst
Normal file
@ -0,0 +1,861 @@
|
||||
=====
|
||||
Smack
|
||||
=====
|
||||
|
||||
|
||||
"Good for you, you've decided to clean the elevator!"
|
||||
- The Elevator, from Dark Star
|
||||
|
||||
Smack is the Simplified Mandatory Access Control Kernel.
|
||||
Smack is a kernel based implementation of mandatory access
|
||||
control that includes simplicity in its primary design goals.
|
||||
|
||||
Smack is not the only Mandatory Access Control scheme
|
||||
available for Linux. Those new to Mandatory Access Control
|
||||
are encouraged to compare Smack with the other mechanisms
|
||||
available to determine which is best suited to the problem
|
||||
at hand.
|
||||
|
||||
Smack consists of three major components:
|
||||
|
||||
- The kernel
|
||||
- Basic utilities, which are helpful but not required
|
||||
- Configuration data
|
||||
|
||||
The kernel component of Smack is implemented as a Linux
|
||||
Security Modules (LSM) module. It requires netlabel and
|
||||
works best with file systems that support extended attributes,
|
||||
although xattr support is not strictly required.
|
||||
It is safe to run a Smack kernel under a "vanilla" distribution.
|
||||
|
||||
Smack kernels use the CIPSO IP option. Some network
|
||||
configurations are intolerant of IP options and can impede
|
||||
access to systems that use them as Smack does.
|
||||
|
||||
Smack is used in the Tizen operating system. Please
|
||||
go to http://wiki.tizen.org for information about how
|
||||
Smack is used in Tizen.
|
||||
|
||||
The current git repository for Smack user space is:
|
||||
|
||||
git://github.com/smack-team/smack.git
|
||||
|
||||
This should make and install on most modern distributions.
|
||||
There are five commands included in smackutil:
|
||||
|
||||
chsmack:
|
||||
display or set Smack extended attribute values
|
||||
|
||||
smackctl:
|
||||
load the Smack access rules
|
||||
|
||||
smackaccess:
|
||||
report if a process with one label has access
|
||||
to an object with another
|
||||
|
||||
These two commands are obsolete with the introduction of
|
||||
the smackfs/load2 and smackfs/cipso2 interfaces.
|
||||
|
||||
smackload:
|
||||
properly formats data for writing to smackfs/load
|
||||
|
||||
smackcipso:
|
||||
properly formats data for writing to smackfs/cipso
|
||||
|
||||
In keeping with the intent of Smack, configuration data is
|
||||
minimal and not strictly required. The most important
|
||||
configuration step is mounting the smackfs pseudo filesystem.
|
||||
If smackutil is installed the startup script will take care
|
||||
of this, but it can be manually as well.
|
||||
|
||||
Add this line to ``/etc/fstab``::
|
||||
|
||||
smackfs /sys/fs/smackfs smackfs defaults 0 0
|
||||
|
||||
The ``/sys/fs/smackfs`` directory is created by the kernel.
|
||||
|
||||
Smack uses extended attributes (xattrs) to store labels on filesystem
|
||||
objects. The attributes are stored in the extended attribute security
|
||||
name space. A process must have ``CAP_MAC_ADMIN`` to change any of these
|
||||
attributes.
|
||||
|
||||
The extended attributes that Smack uses are:
|
||||
|
||||
SMACK64
|
||||
Used to make access control decisions. In almost all cases
|
||||
the label given to a new filesystem object will be the label
|
||||
of the process that created it.
|
||||
|
||||
SMACK64EXEC
|
||||
The Smack label of a process that execs a program file with
|
||||
this attribute set will run with this attribute's value.
|
||||
|
||||
SMACK64MMAP
|
||||
Don't allow the file to be mmapped by a process whose Smack
|
||||
label does not allow all of the access permitted to a process
|
||||
with the label contained in this attribute. This is a very
|
||||
specific use case for shared libraries.
|
||||
|
||||
SMACK64TRANSMUTE
|
||||
Can only have the value "TRUE". If this attribute is present
|
||||
on a directory when an object is created in the directory and
|
||||
the Smack rule (more below) that permitted the write access
|
||||
to the directory includes the transmute ("t") mode the object
|
||||
gets the label of the directory instead of the label of the
|
||||
creating process. If the object being created is a directory
|
||||
the SMACK64TRANSMUTE attribute is set as well.
|
||||
|
||||
SMACK64IPIN
|
||||
This attribute is only available on file descriptors for sockets.
|
||||
Use the Smack label in this attribute for access control
|
||||
decisions on packets being delivered to this socket.
|
||||
|
||||
SMACK64IPOUT
|
||||
This attribute is only available on file descriptors for sockets.
|
||||
Use the Smack label in this attribute for access control
|
||||
decisions on packets coming from this socket.
|
||||
|
||||
There are multiple ways to set a Smack label on a file::
|
||||
|
||||
# attr -S -s SMACK64 -V "value" path
|
||||
# chsmack -a value path
|
||||
|
||||
A process can see the Smack label it is running with by
|
||||
reading ``/proc/self/attr/current``. A process with ``CAP_MAC_ADMIN``
|
||||
can set the process Smack by writing there.
|
||||
|
||||
Most Smack configuration is accomplished by writing to files
|
||||
in the smackfs filesystem. This pseudo-filesystem is mounted
|
||||
on ``/sys/fs/smackfs``.
|
||||
|
||||
access
|
||||
Provided for backward compatibility. The access2 interface
|
||||
is preferred and should be used instead.
|
||||
This interface reports whether a subject with the specified
|
||||
Smack label has a particular access to an object with a
|
||||
specified Smack label. Write a fixed format access rule to
|
||||
this file. The next read will indicate whether the access
|
||||
would be permitted. The text will be either "1" indicating
|
||||
access, or "0" indicating denial.
|
||||
|
||||
access2
|
||||
This interface reports whether a subject with the specified
|
||||
Smack label has a particular access to an object with a
|
||||
specified Smack label. Write a long format access rule to
|
||||
this file. The next read will indicate whether the access
|
||||
would be permitted. The text will be either "1" indicating
|
||||
access, or "0" indicating denial.
|
||||
|
||||
ambient
|
||||
This contains the Smack label applied to unlabeled network
|
||||
packets.
|
||||
|
||||
change-rule
|
||||
This interface allows modification of existing access control rules.
|
||||
The format accepted on write is::
|
||||
|
||||
"%s %s %s %s"
|
||||
|
||||
where the first string is the subject label, the second the
|
||||
object label, the third the access to allow and the fourth the
|
||||
access to deny. The access strings may contain only the characters
|
||||
"rwxat-". If a rule for a given subject and object exists it will be
|
||||
modified by enabling the permissions in the third string and disabling
|
||||
those in the fourth string. If there is no such rule it will be
|
||||
created using the access specified in the third and the fourth strings.
|
||||
|
||||
cipso
|
||||
Provided for backward compatibility. The cipso2 interface
|
||||
is preferred and should be used instead.
|
||||
This interface allows a specific CIPSO header to be assigned
|
||||
to a Smack label. The format accepted on write is::
|
||||
|
||||
"%24s%4d%4d"["%4d"]...
|
||||
|
||||
The first string is a fixed Smack label. The first number is
|
||||
the level to use. The second number is the number of categories.
|
||||
The following numbers are the categories::
|
||||
|
||||
"level-3-cats-5-19 3 2 5 19"
|
||||
|
||||
cipso2
|
||||
This interface allows a specific CIPSO header to be assigned
|
||||
to a Smack label. The format accepted on write is::
|
||||
|
||||
"%s%4d%4d"["%4d"]...
|
||||
|
||||
The first string is a long Smack label. The first number is
|
||||
the level to use. The second number is the number of categories.
|
||||
The following numbers are the categories::
|
||||
|
||||
"level-3-cats-5-19 3 2 5 19"
|
||||
|
||||
direct
|
||||
This contains the CIPSO level used for Smack direct label
|
||||
representation in network packets.
|
||||
|
||||
doi
|
||||
This contains the CIPSO domain of interpretation used in
|
||||
network packets.
|
||||
|
||||
ipv6host
|
||||
This interface allows specific IPv6 internet addresses to be
|
||||
treated as single label hosts. Packets are sent to single
|
||||
label hosts only from processes that have Smack write access
|
||||
to the host label. All packets received from single label hosts
|
||||
are given the specified label. The format accepted on write is::
|
||||
|
||||
"%h:%h:%h:%h:%h:%h:%h:%h label" or
|
||||
"%h:%h:%h:%h:%h:%h:%h:%h/%d label".
|
||||
|
||||
The "::" address shortcut is not supported.
|
||||
If label is "-DELETE" a matched entry will be deleted.
|
||||
|
||||
load
|
||||
Provided for backward compatibility. The load2 interface
|
||||
is preferred and should be used instead.
|
||||
This interface allows access control rules in addition to
|
||||
the system defined rules to be specified. The format accepted
|
||||
on write is::
|
||||
|
||||
"%24s%24s%5s"
|
||||
|
||||
where the first string is the subject label, the second the
|
||||
object label, and the third the requested access. The access
|
||||
string may contain only the characters "rwxat-", and specifies
|
||||
which sort of access is allowed. The "-" is a placeholder for
|
||||
permissions that are not allowed. The string "r-x--" would
|
||||
specify read and execute access. Labels are limited to 23
|
||||
characters in length.
|
||||
|
||||
load2
|
||||
This interface allows access control rules in addition to
|
||||
the system defined rules to be specified. The format accepted
|
||||
on write is::
|
||||
|
||||
"%s %s %s"
|
||||
|
||||
where the first string is the subject label, the second the
|
||||
object label, and the third the requested access. The access
|
||||
string may contain only the characters "rwxat-", and specifies
|
||||
which sort of access is allowed. The "-" is a placeholder for
|
||||
permissions that are not allowed. The string "r-x--" would
|
||||
specify read and execute access.
|
||||
|
||||
load-self
|
||||
Provided for backward compatibility. The load-self2 interface
|
||||
is preferred and should be used instead.
|
||||
This interface allows process specific access rules to be
|
||||
defined. These rules are only consulted if access would
|
||||
otherwise be permitted, and are intended to provide additional
|
||||
restrictions on the process. The format is the same as for
|
||||
the load interface.
|
||||
|
||||
load-self2
|
||||
This interface allows process specific access rules to be
|
||||
defined. These rules are only consulted if access would
|
||||
otherwise be permitted, and are intended to provide additional
|
||||
restrictions on the process. The format is the same as for
|
||||
the load2 interface.
|
||||
|
||||
logging
|
||||
This contains the Smack logging state.
|
||||
|
||||
mapped
|
||||
This contains the CIPSO level used for Smack mapped label
|
||||
representation in network packets.
|
||||
|
||||
netlabel
|
||||
This interface allows specific internet addresses to be
|
||||
treated as single label hosts. Packets are sent to single
|
||||
label hosts without CIPSO headers, but only from processes
|
||||
that have Smack write access to the host label. All packets
|
||||
received from single label hosts are given the specified
|
||||
label. The format accepted on write is::
|
||||
|
||||
"%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label".
|
||||
|
||||
If the label specified is "-CIPSO" the address is treated
|
||||
as a host that supports CIPSO headers.
|
||||
|
||||
onlycap
|
||||
This contains labels processes must have for CAP_MAC_ADMIN
|
||||
and ``CAP_MAC_OVERRIDE`` to be effective. If this file is empty
|
||||
these capabilities are effective at for processes with any
|
||||
label. The values are set by writing the desired labels, separated
|
||||
by spaces, to the file or cleared by writing "-" to the file.
|
||||
|
||||
ptrace
|
||||
This is used to define the current ptrace policy
|
||||
|
||||
0 - default:
|
||||
this is the policy that relies on Smack access rules.
|
||||
For the ``PTRACE_READ`` a subject needs to have a read access on
|
||||
object. For the ``PTRACE_ATTACH`` a read-write access is required.
|
||||
|
||||
1 - exact:
|
||||
this is the policy that limits ``PTRACE_ATTACH``. Attach is
|
||||
only allowed when subject's and object's labels are equal.
|
||||
``PTRACE_READ`` is not affected. Can be overridden with ``CAP_SYS_PTRACE``.
|
||||
|
||||
2 - draconian:
|
||||
this policy behaves like the 'exact' above with an
|
||||
exception that it can't be overridden with ``CAP_SYS_PTRACE``.
|
||||
|
||||
revoke-subject
|
||||
Writing a Smack label here sets the access to '-' for all access
|
||||
rules with that subject label.
|
||||
|
||||
unconfined
|
||||
If the kernel is configured with ``CONFIG_SECURITY_SMACK_BRINGUP``
|
||||
a process with ``CAP_MAC_ADMIN`` can write a label into this interface.
|
||||
Thereafter, accesses that involve that label will be logged and
|
||||
the access permitted if it wouldn't be otherwise. Note that this
|
||||
is dangerous and can ruin the proper labeling of your system.
|
||||
It should never be used in production.
|
||||
|
||||
relabel-self
|
||||
This interface contains a list of labels to which the process can
|
||||
transition to, by writing to ``/proc/self/attr/current``.
|
||||
Normally a process can change its own label to any legal value, but only
|
||||
if it has ``CAP_MAC_ADMIN``. This interface allows a process without
|
||||
``CAP_MAC_ADMIN`` to relabel itself to one of labels from predefined list.
|
||||
A process without ``CAP_MAC_ADMIN`` can change its label only once. When it
|
||||
does, this list will be cleared.
|
||||
The values are set by writing the desired labels, separated
|
||||
by spaces, to the file or cleared by writing "-" to the file.
|
||||
|
||||
If you are using the smackload utility
|
||||
you can add access rules in ``/etc/smack/accesses``. They take the form::
|
||||
|
||||
subjectlabel objectlabel access
|
||||
|
||||
access is a combination of the letters rwxatb which specify the
|
||||
kind of access permitted a subject with subjectlabel on an
|
||||
object with objectlabel. If there is no rule no access is allowed.
|
||||
|
||||
Look for additional programs on http://schaufler-ca.com
|
||||
|
||||
The Simplified Mandatory Access Control Kernel (Whitepaper)
|
||||
===========================================================
|
||||
|
||||
Casey Schaufler
|
||||
casey@schaufler-ca.com
|
||||
|
||||
Mandatory Access Control
|
||||
------------------------
|
||||
|
||||
Computer systems employ a variety of schemes to constrain how information is
|
||||
shared among the people and services using the machine. Some of these schemes
|
||||
allow the program or user to decide what other programs or users are allowed
|
||||
access to pieces of data. These schemes are called discretionary access
|
||||
control mechanisms because the access control is specified at the discretion
|
||||
of the user. Other schemes do not leave the decision regarding what a user or
|
||||
program can access up to users or programs. These schemes are called mandatory
|
||||
access control mechanisms because you don't have a choice regarding the users
|
||||
or programs that have access to pieces of data.
|
||||
|
||||
Bell & LaPadula
|
||||
---------------
|
||||
|
||||
From the middle of the 1980's until the turn of the century Mandatory Access
|
||||
Control (MAC) was very closely associated with the Bell & LaPadula security
|
||||
model, a mathematical description of the United States Department of Defense
|
||||
policy for marking paper documents. MAC in this form enjoyed a following
|
||||
within the Capital Beltway and Scandinavian supercomputer centers but was
|
||||
often sited as failing to address general needs.
|
||||
|
||||
Domain Type Enforcement
|
||||
-----------------------
|
||||
|
||||
Around the turn of the century Domain Type Enforcement (DTE) became popular.
|
||||
This scheme organizes users, programs, and data into domains that are
|
||||
protected from each other. This scheme has been widely deployed as a component
|
||||
of popular Linux distributions. The administrative overhead required to
|
||||
maintain this scheme and the detailed understanding of the whole system
|
||||
necessary to provide a secure domain mapping leads to the scheme being
|
||||
disabled or used in limited ways in the majority of cases.
|
||||
|
||||
Smack
|
||||
-----
|
||||
|
||||
Smack is a Mandatory Access Control mechanism designed to provide useful MAC
|
||||
while avoiding the pitfalls of its predecessors. The limitations of Bell &
|
||||
LaPadula are addressed by providing a scheme whereby access can be controlled
|
||||
according to the requirements of the system and its purpose rather than those
|
||||
imposed by an arcane government policy. The complexity of Domain Type
|
||||
Enforcement and avoided by defining access controls in terms of the access
|
||||
modes already in use.
|
||||
|
||||
Smack Terminology
|
||||
-----------------
|
||||
|
||||
The jargon used to talk about Smack will be familiar to those who have dealt
|
||||
with other MAC systems and shouldn't be too difficult for the uninitiated to
|
||||
pick up. There are four terms that are used in a specific way and that are
|
||||
especially important:
|
||||
|
||||
Subject:
|
||||
A subject is an active entity on the computer system.
|
||||
On Smack a subject is a task, which is in turn the basic unit
|
||||
of execution.
|
||||
|
||||
Object:
|
||||
An object is a passive entity on the computer system.
|
||||
On Smack files of all types, IPC, and tasks can be objects.
|
||||
|
||||
Access:
|
||||
Any attempt by a subject to put information into or get
|
||||
information from an object is an access.
|
||||
|
||||
Label:
|
||||
Data that identifies the Mandatory Access Control
|
||||
characteristics of a subject or an object.
|
||||
|
||||
These definitions are consistent with the traditional use in the security
|
||||
community. There are also some terms from Linux that are likely to crop up:
|
||||
|
||||
Capability:
|
||||
A task that possesses a capability has permission to
|
||||
violate an aspect of the system security policy, as identified by
|
||||
the specific capability. A task that possesses one or more
|
||||
capabilities is a privileged task, whereas a task with no
|
||||
capabilities is an unprivileged task.
|
||||
|
||||
Privilege:
|
||||
A task that is allowed to violate the system security
|
||||
policy is said to have privilege. As of this writing a task can
|
||||
have privilege either by possessing capabilities or by having an
|
||||
effective user of root.
|
||||
|
||||
Smack Basics
|
||||
------------
|
||||
|
||||
Smack is an extension to a Linux system. It enforces additional restrictions
|
||||
on what subjects can access which objects, based on the labels attached to
|
||||
each of the subject and the object.
|
||||
|
||||
Labels
|
||||
~~~~~~
|
||||
|
||||
Smack labels are ASCII character strings. They can be up to 255 characters
|
||||
long, but keeping them to twenty-three characters is recommended.
|
||||
Single character labels using special characters, that being anything
|
||||
other than a letter or digit, are reserved for use by the Smack development
|
||||
team. Smack labels are unstructured, case sensitive, and the only operation
|
||||
ever performed on them is comparison for equality. Smack labels cannot
|
||||
contain unprintable characters, the "/" (slash), the "\" (backslash), the "'"
|
||||
(quote) and '"' (double-quote) characters.
|
||||
Smack labels cannot begin with a '-'. This is reserved for special options.
|
||||
|
||||
There are some predefined labels::
|
||||
|
||||
_ Pronounced "floor", a single underscore character.
|
||||
^ Pronounced "hat", a single circumflex character.
|
||||
* Pronounced "star", a single asterisk character.
|
||||
? Pronounced "huh", a single question mark character.
|
||||
@ Pronounced "web", a single at sign character.
|
||||
|
||||
Every task on a Smack system is assigned a label. The Smack label
|
||||
of a process will usually be assigned by the system initialization
|
||||
mechanism.
|
||||
|
||||
Access Rules
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Smack uses the traditional access modes of Linux. These modes are read,
|
||||
execute, write, and occasionally append. There are a few cases where the
|
||||
access mode may not be obvious. These include:
|
||||
|
||||
Signals:
|
||||
A signal is a write operation from the subject task to
|
||||
the object task.
|
||||
|
||||
Internet Domain IPC:
|
||||
Transmission of a packet is considered a
|
||||
write operation from the source task to the destination task.
|
||||
|
||||
Smack restricts access based on the label attached to a subject and the label
|
||||
attached to the object it is trying to access. The rules enforced are, in
|
||||
order:
|
||||
|
||||
1. Any access requested by a task labeled "*" is denied.
|
||||
2. A read or execute access requested by a task labeled "^"
|
||||
is permitted.
|
||||
3. A read or execute access requested on an object labeled "_"
|
||||
is permitted.
|
||||
4. Any access requested on an object labeled "*" is permitted.
|
||||
5. Any access requested by a task on an object with the same
|
||||
label is permitted.
|
||||
6. Any access requested that is explicitly defined in the loaded
|
||||
rule set is permitted.
|
||||
7. Any other access is denied.
|
||||
|
||||
Smack Access Rules
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
With the isolation provided by Smack access separation is simple. There are
|
||||
many interesting cases where limited access by subjects to objects with
|
||||
different labels is desired. One example is the familiar spy model of
|
||||
sensitivity, where a scientist working on a highly classified project would be
|
||||
able to read documents of lower classifications and anything she writes will
|
||||
be "born" highly classified. To accommodate such schemes Smack includes a
|
||||
mechanism for specifying rules allowing access between labels.
|
||||
|
||||
Access Rule Format
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The format of an access rule is::
|
||||
|
||||
subject-label object-label access
|
||||
|
||||
Where subject-label is the Smack label of the task, object-label is the Smack
|
||||
label of the thing being accessed, and access is a string specifying the sort
|
||||
of access allowed. The access specification is searched for letters that
|
||||
describe access modes:
|
||||
|
||||
a: indicates that append access should be granted.
|
||||
r: indicates that read access should be granted.
|
||||
w: indicates that write access should be granted.
|
||||
x: indicates that execute access should be granted.
|
||||
t: indicates that the rule requests transmutation.
|
||||
b: indicates that the rule should be reported for bring-up.
|
||||
|
||||
Uppercase values for the specification letters are allowed as well.
|
||||
Access mode specifications can be in any order. Examples of acceptable rules
|
||||
are::
|
||||
|
||||
TopSecret Secret rx
|
||||
Secret Unclass R
|
||||
Manager Game x
|
||||
User HR w
|
||||
Snap Crackle rwxatb
|
||||
New Old rRrRr
|
||||
Closed Off -
|
||||
|
||||
Examples of unacceptable rules are::
|
||||
|
||||
Top Secret Secret rx
|
||||
Ace Ace r
|
||||
Odd spells waxbeans
|
||||
|
||||
Spaces are not allowed in labels. Since a subject always has access to files
|
||||
with the same label specifying a rule for that case is pointless. Only
|
||||
valid letters (rwxatbRWXATB) and the dash ('-') character are allowed in
|
||||
access specifications. The dash is a placeholder, so "a-r" is the same
|
||||
as "ar". A lone dash is used to specify that no access should be allowed.
|
||||
|
||||
Applying Access Rules
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The developers of Linux rarely define new sorts of things, usually importing
|
||||
schemes and concepts from other systems. Most often, the other systems are
|
||||
variants of Unix. Unix has many endearing properties, but consistency of
|
||||
access control models is not one of them. Smack strives to treat accesses as
|
||||
uniformly as is sensible while keeping with the spirit of the underlying
|
||||
mechanism.
|
||||
|
||||
File system objects including files, directories, named pipes, symbolic links,
|
||||
and devices require access permissions that closely match those used by mode
|
||||
bit access. To open a file for reading read access is required on the file. To
|
||||
search a directory requires execute access. Creating a file with write access
|
||||
requires both read and write access on the containing directory. Deleting a
|
||||
file requires read and write access to the file and to the containing
|
||||
directory. It is possible that a user may be able to see that a file exists
|
||||
but not any of its attributes by the circumstance of having read access to the
|
||||
containing directory but not to the differently labeled file. This is an
|
||||
artifact of the file name being data in the directory, not a part of the file.
|
||||
|
||||
If a directory is marked as transmuting (SMACK64TRANSMUTE=TRUE) and the
|
||||
access rule that allows a process to create an object in that directory
|
||||
includes 't' access the label assigned to the new object will be that
|
||||
of the directory, not the creating process. This makes it much easier
|
||||
for two processes with different labels to share data without granting
|
||||
access to all of their files.
|
||||
|
||||
IPC objects, message queues, semaphore sets, and memory segments exist in flat
|
||||
namespaces and access requests are only required to match the object in
|
||||
question.
|
||||
|
||||
Process objects reflect tasks on the system and the Smack label used to access
|
||||
them is the same Smack label that the task would use for its own access
|
||||
attempts. Sending a signal via the kill() system call is a write operation
|
||||
from the signaler to the recipient. Debugging a process requires both reading
|
||||
and writing. Creating a new task is an internal operation that results in two
|
||||
tasks with identical Smack labels and requires no access checks.
|
||||
|
||||
Sockets are data structures attached to processes and sending a packet from
|
||||
one process to another requires that the sender have write access to the
|
||||
receiver. The receiver is not required to have read access to the sender.
|
||||
|
||||
Setting Access Rules
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The configuration file /etc/smack/accesses contains the rules to be set at
|
||||
system startup. The contents are written to the special file
|
||||
/sys/fs/smackfs/load2. Rules can be added at any time and take effect
|
||||
immediately. For any pair of subject and object labels there can be only
|
||||
one rule, with the most recently specified overriding any earlier
|
||||
specification.
|
||||
|
||||
Task Attribute
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
The Smack label of a process can be read from /proc/<pid>/attr/current. A
|
||||
process can read its own Smack label from /proc/self/attr/current. A
|
||||
privileged process can change its own Smack label by writing to
|
||||
/proc/self/attr/current but not the label of another process.
|
||||
|
||||
File Attribute
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
The Smack label of a filesystem object is stored as an extended attribute
|
||||
named SMACK64 on the file. This attribute is in the security namespace. It can
|
||||
only be changed by a process with privilege.
|
||||
|
||||
Privilege
|
||||
~~~~~~~~~
|
||||
|
||||
A process with CAP_MAC_OVERRIDE or CAP_MAC_ADMIN is privileged.
|
||||
CAP_MAC_OVERRIDE allows the process access to objects it would
|
||||
be denied otherwise. CAP_MAC_ADMIN allows a process to change
|
||||
Smack data, including rules and attributes.
|
||||
|
||||
Smack Networking
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
As mentioned before, Smack enforces access control on network protocol
|
||||
transmissions. Every packet sent by a Smack process is tagged with its Smack
|
||||
label. This is done by adding a CIPSO tag to the header of the IP packet. Each
|
||||
packet received is expected to have a CIPSO tag that identifies the label and
|
||||
if it lacks such a tag the network ambient label is assumed. Before the packet
|
||||
is delivered a check is made to determine that a subject with the label on the
|
||||
packet has write access to the receiving process and if that is not the case
|
||||
the packet is dropped.
|
||||
|
||||
CIPSO Configuration
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It is normally unnecessary to specify the CIPSO configuration. The default
|
||||
values used by the system handle all internal cases. Smack will compose CIPSO
|
||||
label values to match the Smack labels being used without administrative
|
||||
intervention. Unlabeled packets that come into the system will be given the
|
||||
ambient label.
|
||||
|
||||
Smack requires configuration in the case where packets from a system that is
|
||||
not Smack that speaks CIPSO may be encountered. Usually this will be a Trusted
|
||||
Solaris system, but there are other, less widely deployed systems out there.
|
||||
CIPSO provides 3 important values, a Domain Of Interpretation (DOI), a level,
|
||||
and a category set with each packet. The DOI is intended to identify a group
|
||||
of systems that use compatible labeling schemes, and the DOI specified on the
|
||||
Smack system must match that of the remote system or packets will be
|
||||
discarded. The DOI is 3 by default. The value can be read from
|
||||
/sys/fs/smackfs/doi and can be changed by writing to /sys/fs/smackfs/doi.
|
||||
|
||||
The label and category set are mapped to a Smack label as defined in
|
||||
/etc/smack/cipso.
|
||||
|
||||
A Smack/CIPSO mapping has the form::
|
||||
|
||||
smack level [category [category]*]
|
||||
|
||||
Smack does not expect the level or category sets to be related in any
|
||||
particular way and does not assume or assign accesses based on them. Some
|
||||
examples of mappings::
|
||||
|
||||
TopSecret 7
|
||||
TS:A,B 7 1 2
|
||||
SecBDE 5 2 4 6
|
||||
RAFTERS 7 12 26
|
||||
|
||||
The ":" and "," characters are permitted in a Smack label but have no special
|
||||
meaning.
|
||||
|
||||
The mapping of Smack labels to CIPSO values is defined by writing to
|
||||
/sys/fs/smackfs/cipso2.
|
||||
|
||||
In addition to explicit mappings Smack supports direct CIPSO mappings. One
|
||||
CIPSO level is used to indicate that the category set passed in the packet is
|
||||
in fact an encoding of the Smack label. The level used is 250 by default. The
|
||||
value can be read from /sys/fs/smackfs/direct and changed by writing to
|
||||
/sys/fs/smackfs/direct.
|
||||
|
||||
Socket Attributes
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are two attributes that are associated with sockets. These attributes
|
||||
can only be set by privileged tasks, but any task can read them for their own
|
||||
sockets.
|
||||
|
||||
SMACK64IPIN:
|
||||
The Smack label of the task object. A privileged
|
||||
program that will enforce policy may set this to the star label.
|
||||
|
||||
SMACK64IPOUT:
|
||||
The Smack label transmitted with outgoing packets.
|
||||
A privileged program may set this to match the label of another
|
||||
task with which it hopes to communicate.
|
||||
|
||||
Smack Netlabel Exceptions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You will often find that your labeled application has to talk to the outside,
|
||||
unlabeled world. To do this there's a special file /sys/fs/smackfs/netlabel
|
||||
where you can add some exceptions in the form of::
|
||||
|
||||
@IP1 LABEL1 or
|
||||
@IP2/MASK LABEL2
|
||||
|
||||
It means that your application will have unlabeled access to @IP1 if it has
|
||||
write access on LABEL1, and access to the subnet @IP2/MASK if it has write
|
||||
access on LABEL2.
|
||||
|
||||
Entries in the /sys/fs/smackfs/netlabel file are matched by longest mask
|
||||
first, like in classless IPv4 routing.
|
||||
|
||||
A special label '@' and an option '-CIPSO' can be used there::
|
||||
|
||||
@ means Internet, any application with any label has access to it
|
||||
-CIPSO means standard CIPSO networking
|
||||
|
||||
If you don't know what CIPSO is and don't plan to use it, you can just do::
|
||||
|
||||
echo 127.0.0.1 -CIPSO > /sys/fs/smackfs/netlabel
|
||||
echo 0.0.0.0/0 @ > /sys/fs/smackfs/netlabel
|
||||
|
||||
If you use CIPSO on your 192.168.0.0/16 local network and need also unlabeled
|
||||
Internet access, you can have::
|
||||
|
||||
echo 127.0.0.1 -CIPSO > /sys/fs/smackfs/netlabel
|
||||
echo 192.168.0.0/16 -CIPSO > /sys/fs/smackfs/netlabel
|
||||
echo 0.0.0.0/0 @ > /sys/fs/smackfs/netlabel
|
||||
|
||||
Writing Applications for Smack
|
||||
------------------------------
|
||||
|
||||
There are three sorts of applications that will run on a Smack system. How an
|
||||
application interacts with Smack will determine what it will have to do to
|
||||
work properly under Smack.
|
||||
|
||||
Smack Ignorant Applications
|
||||
---------------------------
|
||||
|
||||
By far the majority of applications have no reason whatever to care about the
|
||||
unique properties of Smack. Since invoking a program has no impact on the
|
||||
Smack label associated with the process the only concern likely to arise is
|
||||
whether the process has execute access to the program.
|
||||
|
||||
Smack Relevant Applications
|
||||
---------------------------
|
||||
|
||||
Some programs can be improved by teaching them about Smack, but do not make
|
||||
any security decisions themselves. The utility ls(1) is one example of such a
|
||||
program.
|
||||
|
||||
Smack Enforcing Applications
|
||||
----------------------------
|
||||
|
||||
These are special programs that not only know about Smack, but participate in
|
||||
the enforcement of system policy. In most cases these are the programs that
|
||||
set up user sessions. There are also network services that provide information
|
||||
to processes running with various labels.
|
||||
|
||||
File System Interfaces
|
||||
----------------------
|
||||
|
||||
Smack maintains labels on file system objects using extended attributes. The
|
||||
Smack label of a file, directory, or other file system object can be obtained
|
||||
using getxattr(2)::
|
||||
|
||||
len = getxattr("/", "security.SMACK64", value, sizeof (value));
|
||||
|
||||
will put the Smack label of the root directory into value. A privileged
|
||||
process can set the Smack label of a file system object with setxattr(2)::
|
||||
|
||||
len = strlen("Rubble");
|
||||
rc = setxattr("/foo", "security.SMACK64", "Rubble", len, 0);
|
||||
|
||||
will set the Smack label of /foo to "Rubble" if the program has appropriate
|
||||
privilege.
|
||||
|
||||
Socket Interfaces
|
||||
-----------------
|
||||
|
||||
The socket attributes can be read using fgetxattr(2).
|
||||
|
||||
A privileged process can set the Smack label of outgoing packets with
|
||||
fsetxattr(2)::
|
||||
|
||||
len = strlen("Rubble");
|
||||
rc = fsetxattr(fd, "security.SMACK64IPOUT", "Rubble", len, 0);
|
||||
|
||||
will set the Smack label "Rubble" on packets going out from the socket if the
|
||||
program has appropriate privilege::
|
||||
|
||||
rc = fsetxattr(fd, "security.SMACK64IPIN, "*", strlen("*"), 0);
|
||||
|
||||
will set the Smack label "*" as the object label against which incoming
|
||||
packets will be checked if the program has appropriate privilege.
|
||||
|
||||
Administration
|
||||
--------------
|
||||
|
||||
Smack supports some mount options:
|
||||
|
||||
smackfsdef=label:
|
||||
specifies the label to give files that lack
|
||||
the Smack label extended attribute.
|
||||
|
||||
smackfsroot=label:
|
||||
specifies the label to assign the root of the
|
||||
file system if it lacks the Smack extended attribute.
|
||||
|
||||
smackfshat=label:
|
||||
specifies a label that must have read access to
|
||||
all labels set on the filesystem. Not yet enforced.
|
||||
|
||||
smackfsfloor=label:
|
||||
specifies a label to which all labels set on the
|
||||
filesystem must have read access. Not yet enforced.
|
||||
|
||||
smackfstransmute=label:
|
||||
behaves exactly like smackfsroot except that it also
|
||||
sets the transmute flag on the root of the mount
|
||||
|
||||
These mount options apply to all file system types.
|
||||
|
||||
Smack auditing
|
||||
--------------
|
||||
|
||||
If you want Smack auditing of security events, you need to set CONFIG_AUDIT
|
||||
in your kernel configuration.
|
||||
By default, all denied events will be audited. You can change this behavior by
|
||||
writing a single character to the /sys/fs/smackfs/logging file::
|
||||
|
||||
0 : no logging
|
||||
1 : log denied (default)
|
||||
2 : log accepted
|
||||
3 : log denied & accepted
|
||||
|
||||
Events are logged as 'key=value' pairs, for each event you at least will get
|
||||
the subject, the object, the rights requested, the action, the kernel function
|
||||
that triggered the event, plus other pairs depending on the type of event
|
||||
audited.
|
||||
|
||||
Bringup Mode
|
||||
------------
|
||||
|
||||
Bringup mode provides logging features that can make application
|
||||
configuration and system bringup easier. Configure the kernel with
|
||||
CONFIG_SECURITY_SMACK_BRINGUP to enable these features. When bringup
|
||||
mode is enabled accesses that succeed due to rules marked with the "b"
|
||||
access mode will logged. When a new label is introduced for processes
|
||||
rules can be added aggressively, marked with the "b". The logging allows
|
||||
tracking of which rules actual get used for that label.
|
||||
|
||||
Another feature of bringup mode is the "unconfined" option. Writing
|
||||
a label to /sys/fs/smackfs/unconfined makes subjects with that label
|
||||
able to access any object, and objects with that label accessible to
|
||||
all subjects. Any access that is granted because a label is unconfined
|
||||
is logged. This feature is dangerous, as files and directories may
|
||||
be created in places they couldn't if the policy were being enforced.
|
75
Documentation/admin-guide/LSM/Yama.rst
Normal file
@ -0,0 +1,75 @@
|
||||
====
|
||||
Yama
|
||||
====
|
||||
|
||||
Yama is a Linux Security Module that collects system-wide DAC security
|
||||
protections that are not handled by the core kernel itself. This is
|
||||
selectable at build-time with ``CONFIG_SECURITY_YAMA``, and can be controlled
|
||||
at run-time through sysctls in ``/proc/sys/kernel/yama``:
|
||||
|
||||
ptrace_scope
|
||||
============
|
||||
|
||||
As Linux grows in popularity, it will become a larger target for
|
||||
malware. One particularly troubling weakness of the Linux process
|
||||
interfaces is that a single user is able to examine the memory and
|
||||
running state of any of their processes. For example, if one application
|
||||
(e.g. Pidgin) was compromised, it would be possible for an attacker to
|
||||
attach to other running processes (e.g. Firefox, SSH sessions, GPG agent,
|
||||
etc) to extract additional credentials and continue to expand the scope
|
||||
of their attack without resorting to user-assisted phishing.
|
||||
|
||||
This is not a theoretical problem. `SSH session hijacking
|
||||
<https://www.blackhat.com/presentations/bh-usa-05/bh-us-05-boileau.pdf>`_
|
||||
and `arbitrary code injection
|
||||
<https://c-skills.blogspot.com/2007/05/injectso.html>`_ attacks already
|
||||
exist and remain possible if ptrace is allowed to operate as before.
|
||||
Since ptrace is not commonly used by non-developers and non-admins, system
|
||||
builders should be allowed the option to disable this debugging system.
|
||||
|
||||
For a solution, some applications use ``prctl(PR_SET_DUMPABLE, ...)`` to
|
||||
specifically disallow such ptrace attachment (e.g. ssh-agent), but many
|
||||
do not. A more general solution is to only allow ptrace directly from a
|
||||
parent to a child process (i.e. direct "gdb EXE" and "strace EXE" still
|
||||
work), or with ``CAP_SYS_PTRACE`` (i.e. "gdb --pid=PID", and "strace -p PID"
|
||||
still work as root).
|
||||
|
||||
In mode 1, software that has defined application-specific relationships
|
||||
between a debugging process and its inferior (crash handlers, etc),
|
||||
``prctl(PR_SET_PTRACER, pid, ...)`` can be used. An inferior can declare which
|
||||
other process (and its descendants) are allowed to call ``PTRACE_ATTACH``
|
||||
against it. Only one such declared debugging process can exists for
|
||||
each inferior at a time. For example, this is used by KDE, Chromium, and
|
||||
Firefox's crash handlers, and by Wine for allowing only Wine processes
|
||||
to ptrace each other. If a process wishes to entirely disable these ptrace
|
||||
restrictions, it can call ``prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...)``
|
||||
so that any otherwise allowed process (even those in external pid namespaces)
|
||||
may attach.
|
||||
|
||||
The sysctl settings (writable only with ``CAP_SYS_PTRACE``) are:
|
||||
|
||||
0 - classic ptrace permissions:
|
||||
a process can ``PTRACE_ATTACH`` to any other
|
||||
process running under the same uid, as long as it is dumpable (i.e.
|
||||
did not transition uids, start privileged, or have called
|
||||
``prctl(PR_SET_DUMPABLE...)`` already). Similarly, ``PTRACE_TRACEME`` is
|
||||
unchanged.
|
||||
|
||||
1 - restricted ptrace:
|
||||
a process must have a predefined relationship
|
||||
with the inferior it wants to call ``PTRACE_ATTACH`` on. By default,
|
||||
this relationship is that of only its descendants when the above
|
||||
classic criteria is also met. To change the relationship, an
|
||||
inferior can call ``prctl(PR_SET_PTRACER, debugger, ...)`` to declare
|
||||
an allowed debugger PID to call ``PTRACE_ATTACH`` on the inferior.
|
||||
Using ``PTRACE_TRACEME`` is unchanged.
|
||||
|
||||
2 - admin-only attach:
|
||||
only processes with ``CAP_SYS_PTRACE`` may use ptrace, either with
|
||||
``PTRACE_ATTACH`` or through children calling ``PTRACE_TRACEME``.
|
||||
|
||||
3 - no attach:
|
||||
no processes may use ptrace with ``PTRACE_ATTACH`` nor via
|
||||
``PTRACE_TRACEME``. Once set, this sysctl value cannot be changed.
|
||||
|
||||
The original children-only logic was based on the restrictions in grsecurity.
|
51
Documentation/admin-guide/LSM/apparmor.rst
Normal file
@ -0,0 +1,51 @@
|
||||
========
|
||||
AppArmor
|
||||
========
|
||||
|
||||
What is AppArmor?
|
||||
=================
|
||||
|
||||
AppArmor is MAC style security extension for the Linux kernel. It implements
|
||||
a task centered policy, with task "profiles" being created and loaded
|
||||
from user space. Tasks on the system that do not have a profile defined for
|
||||
them run in an unconfined state which is equivalent to standard Linux DAC
|
||||
permissions.
|
||||
|
||||
How to enable/disable
|
||||
=====================
|
||||
|
||||
set ``CONFIG_SECURITY_APPARMOR=y``
|
||||
|
||||
If AppArmor should be selected as the default security module then set::
|
||||
|
||||
CONFIG_DEFAULT_SECURITY="apparmor"
|
||||
CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
|
||||
|
||||
Build the kernel
|
||||
|
||||
If AppArmor is not the default security module it can be enabled by passing
|
||||
``security=apparmor`` on the kernel's command line.
|
||||
|
||||
If AppArmor is the default security module it can be disabled by passing
|
||||
``apparmor=0, security=XXXX`` (where ``XXXX`` is valid security module), on the
|
||||
kernel's command line.
|
||||
|
||||
For AppArmor to enforce any restrictions beyond standard Linux DAC permissions
|
||||
policy must be loaded into the kernel from user space (see the Documentation
|
||||
and tools links).
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
Documentation can be found on the wiki, linked below.
|
||||
|
||||
Links
|
||||
=====
|
||||
|
||||
Mailing List - apparmor@lists.ubuntu.com
|
||||
|
||||
Wiki - http://wiki.apparmor.net
|
||||
|
||||
User space tools - https://gitlab.com/apparmor
|
||||
|
||||
Kernel module - git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
|
49
Documentation/admin-guide/LSM/index.rst
Normal file
@ -0,0 +1,49 @@
|
||||
===========================
|
||||
Linux Security Module Usage
|
||||
===========================
|
||||
|
||||
The Linux Security Module (LSM) framework provides a mechanism for
|
||||
various security checks to be hooked by new kernel extensions. The name
|
||||
"module" is a bit of a misnomer since these extensions are not actually
|
||||
loadable kernel modules. Instead, they are selectable at build-time via
|
||||
CONFIG_DEFAULT_SECURITY and can be overridden at boot-time via the
|
||||
``"security=..."`` kernel command line argument, in the case where multiple
|
||||
LSMs were built into a given kernel.
|
||||
|
||||
The primary users of the LSM interface are Mandatory Access Control
|
||||
(MAC) extensions which provide a comprehensive security policy. Examples
|
||||
include SELinux, Smack, Tomoyo, and AppArmor. In addition to the larger
|
||||
MAC extensions, other extensions can be built using the LSM to provide
|
||||
specific changes to system operation when these tweaks are not available
|
||||
in the core functionality of Linux itself.
|
||||
|
||||
The Linux capabilities modules will always be included. This may be
|
||||
followed by any number of "minor" modules and at most one "major" module.
|
||||
For more details on capabilities, see ``capabilities(7)`` in the Linux
|
||||
man-pages project.
|
||||
|
||||
A list of the active security modules can be found by reading
|
||||
``/sys/kernel/security/lsm``. This is a comma separated list, and
|
||||
will always include the capability module. The list reflects the
|
||||
order in which checks are made. The capability module will always
|
||||
be first, followed by any "minor" modules (e.g. Yama) and then
|
||||
the one "major" module (e.g. SELinux) if there is one configured.
|
||||
|
||||
Process attributes associated with "major" security modules should
|
||||
be accessed and maintained using the special files in ``/proc/.../attr``.
|
||||
A security module may maintain a module specific subdirectory there,
|
||||
named after the module. ``/proc/.../attr/smack`` is provided by the Smack
|
||||
security module and contains all its special files. The files directly
|
||||
in ``/proc/.../attr`` remain as legacy interfaces for modules that provide
|
||||
subdirectories.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
apparmor
|
||||
LoadPin
|
||||
SELinux
|
||||
Smack
|
||||
tomoyo
|
||||
Yama
|
||||
SafeSetID
|
65
Documentation/admin-guide/LSM/tomoyo.rst
Normal file
@ -0,0 +1,65 @@
|
||||
======
|
||||
TOMOYO
|
||||
======
|
||||
|
||||
What is TOMOYO?
|
||||
===============
|
||||
|
||||
TOMOYO is a name-based MAC extension (LSM module) for the Linux kernel.
|
||||
|
||||
LiveCD-based tutorials are available at
|
||||
|
||||
http://tomoyo.sourceforge.jp/1.8/ubuntu12.04-live.html
|
||||
http://tomoyo.sourceforge.jp/1.8/centos6-live.html
|
||||
|
||||
Though these tutorials use non-LSM version of TOMOYO, they are useful for you
|
||||
to know what TOMOYO is.
|
||||
|
||||
How to enable TOMOYO?
|
||||
=====================
|
||||
|
||||
Build the kernel with ``CONFIG_SECURITY_TOMOYO=y`` and pass ``security=tomoyo`` on
|
||||
kernel's command line.
|
||||
|
||||
Please see http://tomoyo.osdn.jp/2.5/ for details.
|
||||
|
||||
Where is documentation?
|
||||
=======================
|
||||
|
||||
User <-> Kernel interface documentation is available at
|
||||
https://tomoyo.osdn.jp/2.5/policy-specification/index.html .
|
||||
|
||||
Materials we prepared for seminars and symposiums are available at
|
||||
https://osdn.jp/projects/tomoyo/docs/?category_id=532&language_id=1 .
|
||||
Below lists are chosen from three aspects.
|
||||
|
||||
What is TOMOYO?
|
||||
TOMOYO Linux Overview
|
||||
https://osdn.jp/projects/tomoyo/docs/lca2009-takeda.pdf
|
||||
TOMOYO Linux: pragmatic and manageable security for Linux
|
||||
https://osdn.jp/projects/tomoyo/docs/freedomhectaipei-tomoyo.pdf
|
||||
TOMOYO Linux: A Practical Method to Understand and Protect Your Own Linux Box
|
||||
https://osdn.jp/projects/tomoyo/docs/PacSec2007-en-no-demo.pdf
|
||||
|
||||
What can TOMOYO do?
|
||||
Deep inside TOMOYO Linux
|
||||
https://osdn.jp/projects/tomoyo/docs/lca2009-kumaneko.pdf
|
||||
The role of "pathname based access control" in security.
|
||||
https://osdn.jp/projects/tomoyo/docs/lfj2008-bof.pdf
|
||||
|
||||
History of TOMOYO?
|
||||
Realities of Mainlining
|
||||
https://osdn.jp/projects/tomoyo/docs/lfj2008.pdf
|
||||
|
||||
What is future plan?
|
||||
====================
|
||||
|
||||
We believe that inode based security and name based security are complementary
|
||||
and both should be used together. But unfortunately, so far, we cannot enable
|
||||
multiple LSM modules at the same time. We feel sorry that you have to give up
|
||||
SELinux/SMACK/AppArmor etc. when you want to use TOMOYO.
|
||||
|
||||
We hope that LSM becomes stackable in future. Meanwhile, you can use non-LSM
|
||||
version of TOMOYO, available at http://tomoyo.osdn.jp/1.8/ .
|
||||
LSM version of TOMOYO is a subset of non-LSM version of TOMOYO. We are planning
|
||||
to port non-LSM version's functionalities to LSM versions.
|
117
Documentation/admin-guide/cgroup-v1/rdma.rst
Normal file
@ -0,0 +1,117 @@
|
||||
===============
|
||||
RDMA Controller
|
||||
===============
|
||||
|
||||
.. Contents
|
||||
|
||||
1. Overview
|
||||
1-1. What is RDMA controller?
|
||||
1-2. Why RDMA controller needed?
|
||||
1-3. How is RDMA controller implemented?
|
||||
2. Usage Examples
|
||||
|
||||
1. Overview
|
||||
===========
|
||||
|
||||
1-1. What is RDMA controller?
|
||||
-----------------------------
|
||||
|
||||
RDMA controller allows user to limit RDMA/IB specific resources that a given
|
||||
set of processes can use. These processes are grouped using RDMA controller.
|
||||
|
||||
RDMA controller defines two resources which can be limited for processes of a
|
||||
cgroup.
|
||||
|
||||
1-2. Why RDMA controller needed?
|
||||
--------------------------------
|
||||
|
||||
Currently user space applications can easily take away all the rdma verb
|
||||
specific resources such as AH, CQ, QP, MR etc. Due to which other applications
|
||||
in other cgroup or kernel space ULPs may not even get chance to allocate any
|
||||
rdma resources. This can lead to service unavailability.
|
||||
|
||||
Therefore RDMA controller is needed through which resource consumption
|
||||
of processes can be limited. Through this controller different rdma
|
||||
resources can be accounted.
|
||||
|
||||
1-3. How is RDMA controller implemented?
|
||||
----------------------------------------
|
||||
|
||||
RDMA cgroup allows limit configuration of resources. Rdma cgroup maintains
|
||||
resource accounting per cgroup, per device using resource pool structure.
|
||||
Each such resource pool is limited up to 64 resources in given resource pool
|
||||
by rdma cgroup, which can be extended later if required.
|
||||
|
||||
This resource pool object is linked to the cgroup css. Typically there
|
||||
are 0 to 4 resource pool instances per cgroup, per device in most use cases.
|
||||
But nothing limits to have it more. At present hundreds of RDMA devices per
|
||||
single cgroup may not be handled optimally, however there is no
|
||||
known use case or requirement for such configuration either.
|
||||
|
||||
Since RDMA resources can be allocated from any process and can be freed by any
|
||||
of the child processes which shares the address space, rdma resources are
|
||||
always owned by the creator cgroup css. This allows process migration from one
|
||||
to other cgroup without major complexity of transferring resource ownership;
|
||||
because such ownership is not really present due to shared nature of
|
||||
rdma resources. Linking resources around css also ensures that cgroups can be
|
||||
deleted after processes migrated. This allow progress migration as well with
|
||||
active resources, even though that is not a primary use case.
|
||||
|
||||
Whenever RDMA resource charging occurs, owner rdma cgroup is returned to
|
||||
the caller. Same rdma cgroup should be passed while uncharging the resource.
|
||||
This also allows process migrated with active RDMA resource to charge
|
||||
to new owner cgroup for new resource. It also allows to uncharge resource of
|
||||
a process from previously charged cgroup which is migrated to new cgroup,
|
||||
even though that is not a primary use case.
|
||||
|
||||
Resource pool object is created in following situations.
|
||||
(a) User sets the limit and no previous resource pool exist for the device
|
||||
of interest for the cgroup.
|
||||
(b) No resource limits were configured, but IB/RDMA stack tries to
|
||||
charge the resource. So that it correctly uncharge them when applications are
|
||||
running without limits and later on when limits are enforced during uncharging,
|
||||
otherwise usage count will drop to negative.
|
||||
|
||||
Resource pool is destroyed if all the resource limits are set to max and
|
||||
it is the last resource getting deallocated.
|
||||
|
||||
User should set all the limit to max value if it intents to remove/unconfigure
|
||||
the resource pool for a particular device.
|
||||
|
||||
IB stack honors limits enforced by the rdma controller. When application
|
||||
query about maximum resource limits of IB device, it returns minimum of
|
||||
what is configured by user for a given cgroup and what is supported by
|
||||
IB device.
|
||||
|
||||
Following resources can be accounted by rdma controller.
|
||||
|
||||
========== =============================
|
||||
hca_handle Maximum number of HCA Handles
|
||||
hca_object Maximum number of HCA Objects
|
||||
========== =============================
|
||||
|
||||
2. Usage Examples
|
||||
=================
|
||||
|
||||
(a) Configure resource limit::
|
||||
|
||||
echo mlx4_0 hca_handle=2 hca_object=2000 > /sys/fs/cgroup/rdma/1/rdma.max
|
||||
echo ocrdma1 hca_handle=3 > /sys/fs/cgroup/rdma/2/rdma.max
|
||||
|
||||
(b) Query resource limit::
|
||||
|
||||
cat /sys/fs/cgroup/rdma/2/rdma.max
|
||||
#Output:
|
||||
mlx4_0 hca_handle=2 hca_object=2000
|
||||
ocrdma1 hca_handle=3 hca_object=max
|
||||
|
||||
(c) Query current usage::
|
||||
|
||||
cat /sys/fs/cgroup/rdma/2/rdma.current
|
||||
#Output:
|
||||
mlx4_0 hca_handle=1 hca_object=20
|
||||
ocrdma1 hca_handle=1 hca_object=23
|
||||
|
||||
(d) Delete resource limit::
|
||||
|
||||
echo mlx4_0 hca_handle=max hca_object=max > /sys/fs/cgroup/rdma/1/rdma.max
|
69
Documentation/admin-guide/cifs/authors.rst
Normal file
@ -0,0 +1,69 @@
|
||||
=======
|
||||
Authors
|
||||
=======
|
||||
|
||||
Original Author
|
||||
---------------
|
||||
|
||||
Steve French (smfrench@gmail.com, sfrench@samba.org)
|
||||
|
||||
The author wishes to express his appreciation and thanks to:
|
||||
Andrew Tridgell (Samba team) for his early suggestions about SMB/CIFS VFS
|
||||
improvements. Thanks to IBM for allowing me time and test resources to pursue
|
||||
this project, to Jim McDonough from IBM (and the Samba Team) for his help, to
|
||||
the IBM Linux JFS team for explaining many esoteric Linux filesystem features.
|
||||
Jeremy Allison of the Samba team has done invaluable work in adding the server
|
||||
side of the original CIFS Unix extensions and reviewing and implementing
|
||||
portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank
|
||||
Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
|
||||
for proving years ago that very good smb/cifs clients could be done on Unix-like
|
||||
operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John
|
||||
Newbigin and others for their work on the Linux smbfs module. Thanks to
|
||||
the other members of the Storage Network Industry Association CIFS Technical
|
||||
Workgroup for their work specifying this highly complex protocol and finally
|
||||
thanks to the Samba team for their technical advice and encouragement.
|
||||
|
||||
Patch Contributors
|
||||
------------------
|
||||
|
||||
- Zwane Mwaikambo
|
||||
- Andi Kleen
|
||||
- Amrut Joshi
|
||||
- Shobhit Dayal
|
||||
- Sergey Vlasov
|
||||
- Richard Hughes
|
||||
- Yury Umanets
|
||||
- Mark Hamzy (for some of the early cifs IPv6 work)
|
||||
- Domen Puncer
|
||||
- Jesper Juhl (in particular for lots of whitespace/formatting cleanup)
|
||||
- Vince Negri and Dave Stahl (for finding an important caching bug)
|
||||
- Adrian Bunk (kcalloc cleanups)
|
||||
- Miklos Szeredi
|
||||
- Kazeon team for various fixes especially for 2.4 version.
|
||||
- Asser Ferno (Change Notify support)
|
||||
- Shaggy (Dave Kleikamp) for innumerable small fs suggestions and some good cleanup
|
||||
- Gunter Kukkukk (testing and suggestions for support of old servers)
|
||||
- Igor Mammedov (DFS support)
|
||||
- Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code)
|
||||
- Scott Lovenberg
|
||||
- Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features)
|
||||
- Aurelien Aptel (for DFS SMB3 work and some key bug fixes)
|
||||
- Ronnie Sahlberg (for SMB3 xattr work, bug fixes, and lots of great work on compounding)
|
||||
- Shirish Pargaonkar (for many ACL patches over the years)
|
||||
- Sachin Prabhu (many bug fixes, including for reconnect, copy offload and security)
|
||||
- Paulo Alcantara (for some excellent work in DFS, and in booting from SMB3)
|
||||
- Long Li (some great work on RDMA, SMB Direct)
|
||||
|
||||
|
||||
Test case and Bug Report contributors
|
||||
-------------------------------------
|
||||
Thanks to those in the community who have submitted detailed bug reports
|
||||
and debug of problems they have found: Jochen Dolze, David Blaine,
|
||||
Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
|
||||
Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
|
||||
Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special
|
||||
mention to the Stanford Checker (SWAT) which pointed out many minor
|
||||
bugs in error paths. Valuable suggestions also have come from Al Viro
|
||||
and Dave Miller.
|
||||
|
||||
And thanks to the IBM LTC and Power test teams and SuSE and Citrix and RedHat testers for finding multiple bugs during excellent stress test runs.
|
9
Documentation/admin-guide/cifs/changes.rst
Normal file
@ -0,0 +1,9 @@
|
||||
=======
|
||||
Changes
|
||||
=======
|
||||
|
||||
See https://wiki.samba.org/index.php/LinuxCIFSKernel for summary
|
||||
information about fixes/improvements to CIFS/SMB2/SMB3 support (changes
|
||||
to cifs.ko module) by kernel version (and cifs internal module version).
|
||||
This may be easier to read than parsing the output of "git log fs/cifs"
|
||||
by release.
|
21
Documentation/admin-guide/cifs/index.rst
Normal file
@ -0,0 +1,21 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====
|
||||
CIFS
|
||||
====
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
introduction
|
||||
usage
|
||||
todo
|
||||
changes
|
||||
authors
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
Indices
|
||||
=======
|
||||
|
||||
* :ref:`genindex`
|
53
Documentation/admin-guide/cifs/introduction.rst
Normal file
@ -0,0 +1,53 @@
|
||||
============
|
||||
Introduction
|
||||
============
|
||||
|
||||
This is the client VFS module for the SMB3 NAS protocol as well
|
||||
as for older dialects such as the Common Internet File System (CIFS)
|
||||
protocol which was the successor to the Server Message Block
|
||||
(SMB) protocol, the native file sharing mechanism for most early
|
||||
PC operating systems. New and improved versions of CIFS are now
|
||||
called SMB2 and SMB3. Use of SMB3 (and later, including SMB3.1.1
|
||||
the most current dialect) is strongly preferred over using older
|
||||
dialects like CIFS due to security reasons. All modern dialects,
|
||||
including the most recent, SMB3.1.1, are supported by the CIFS VFS
|
||||
module. The SMB3 protocol is implemented and supported by all major
|
||||
file servers such as Windows (including Windows 2019 Server), as
|
||||
well as by Samba (which provides excellent CIFS/SMB2/SMB3 server
|
||||
support and tools for Linux and many other operating systems).
|
||||
Apple systems also support SMB3 well, as do most Network Attached
|
||||
Storage vendors, so this network filesystem client can mount to a
|
||||
wide variety of systems. It also supports mounting to the cloud
|
||||
(for example Microsoft Azure), including the necessary security
|
||||
features.
|
||||
|
||||
The intent of this module is to provide the most advanced network
|
||||
file system function for SMB3 compliant servers, including advanced
|
||||
security features, excellent parallelized high performance i/o, better
|
||||
POSIX compliance, secure per-user session establishment, encryption,
|
||||
high performance safe distributed caching (leases/oplocks), optional packet
|
||||
signing, large files, Unicode support and other internationalization
|
||||
improvements. Since both Samba server and this filesystem client support the
|
||||
CIFS Unix extensions, and the Linux client also suppors SMB3 POSIX extensions,
|
||||
the combination can provide a reasonable alternative to other network and
|
||||
cluster file systems for fileserving in some Linux to Linux environments,
|
||||
not just in Linux to Windows (or Linux to Mac) environments.
|
||||
|
||||
This filesystem has a mount utility (mount.cifs) and various user space
|
||||
tools (including smbinfo and setcifsacl) that can be obtained from
|
||||
|
||||
https://git.samba.org/?p=cifs-utils.git
|
||||
|
||||
or
|
||||
|
||||
git://git.samba.org/cifs-utils.git
|
||||
|
||||
mount.cifs should be installed in the directory with the other mount helpers.
|
||||
|
||||
For more information on the module see the project wiki page at
|
||||
|
||||
https://wiki.samba.org/index.php/LinuxCIFS
|
||||
|
||||
and
|
||||
|
||||
https://wiki.samba.org/index.php/LinuxCIFS_utils
|
135
Documentation/admin-guide/cifs/todo.rst
Normal file
@ -0,0 +1,135 @@
|
||||
====
|
||||
TODO
|
||||
====
|
||||
|
||||
Version 2.14 December 21, 2018
|
||||
|
||||
A Partial List of Missing Features
|
||||
==================================
|
||||
|
||||
Contributions are welcome. There are plenty of opportunities
|
||||
for visible, important contributions to this module. Here
|
||||
is a partial list of the known problems and missing features:
|
||||
|
||||
a) SMB3 (and SMB3.1.1) missing optional features:
|
||||
|
||||
- multichannel (partially integrated), integration of multichannel with RDMA
|
||||
- directory leases (improved metadata caching). Currently only implemented for root dir
|
||||
- T10 copy offload ie "ODX" (copy chunk, and "Duplicate Extents" ioctl
|
||||
currently the only two server side copy mechanisms supported)
|
||||
|
||||
b) improved sparse file support (fiemap and SEEK_HOLE are implemented
|
||||
but additional features would be supportable by the protocol such
|
||||
as FALLOC_FL_COLLAPSE_RANGE and FALLOC_FL_INSERT_RANGE)
|
||||
|
||||
c) Directory entry caching relies on a 1 second timer, rather than
|
||||
using Directory Leases, currently only the root file handle is cached longer
|
||||
by leveraging Directory Leases
|
||||
|
||||
d) quota support (needs minor kernel change since quota calls otherwise
|
||||
won't make it to network filesystems or deviceless filesystems).
|
||||
|
||||
e) Additional use cases can be optimized to use "compounding" (e.g.
|
||||
open/query/close and open/setinfo/close) to reduce the number of
|
||||
roundtrips to the server and improve performance. Various cases
|
||||
(stat, statfs, create, unlink, mkdir, xattrs) already have been improved by
|
||||
using compounding but more can be done. In addition we could
|
||||
significantly reduce redundant opens by using deferred close (with
|
||||
handle caching leases) and better using reference counters on file
|
||||
handles.
|
||||
|
||||
f) Finish inotify support so kde and gnome file list windows
|
||||
will autorefresh (partially complete by Asser). Needs minor kernel
|
||||
vfs change to support removing D_NOTIFY on a file.
|
||||
|
||||
g) Add GUI tool to configure /proc/fs/cifs settings and for display of
|
||||
the CIFS statistics (started)
|
||||
|
||||
h) implement support for security and trusted categories of xattrs
|
||||
(requires minor protocol extension) to enable better support for SELINUX
|
||||
|
||||
i) Add support for tree connect contexts (see MS-SMB2) a new SMB3.1.1 protocol
|
||||
feature (may be especially useful for virtualization).
|
||||
|
||||
j) Create UID mapping facility so server UIDs can be mapped on a per
|
||||
mount or a per server basis to client UIDs or nobody if no mapping
|
||||
exists. Also better integration with winbind for resolving SID owners
|
||||
|
||||
k) Add tools to take advantage of more smb3 specific ioctls and features
|
||||
(passthrough ioctl/fsctl is now implemented in cifs.ko to allow
|
||||
sending various SMB3 fsctls and query info and set info calls
|
||||
directly from user space) Add tools to make setting various non-POSIX
|
||||
metadata attributes easier from tools (e.g. extending what was done
|
||||
in smb-info tool).
|
||||
|
||||
l) encrypted file support (currently the attribute showing the file is
|
||||
encrypted on the server is reported, but changing the attribute is not
|
||||
supported).
|
||||
|
||||
m) improved stats gathering tools (perhaps integration with nfsometer?)
|
||||
to extend and make easier to use what is currently in /proc/fs/cifs/Stats
|
||||
|
||||
n) Add support for claims based ACLs ("DAC")
|
||||
|
||||
o) mount helper GUI (to simplify the various configuration options on mount)
|
||||
|
||||
p) Expand support for witness protocol to allow for notification of share
|
||||
move, and server network adapter changes. Currently only notifications by
|
||||
the witness protocol for server move is supported by the Linux client.
|
||||
|
||||
q) Allow mount.cifs to be more verbose in reporting errors with dialect
|
||||
or unsupported feature errors. This would now be easier due to the
|
||||
implementation of the new mount API.
|
||||
|
||||
r) updating cifs documentation, and user guide.
|
||||
|
||||
s) Addressing bugs found by running a broader set of xfstests in standard
|
||||
file system xfstest suite.
|
||||
|
||||
t) split cifs and smb3 support into separate modules so legacy (and less
|
||||
secure) CIFS dialect can be disabled in environments that don't need it
|
||||
and simplify the code.
|
||||
|
||||
v) Additional testing of POSIX Extensions for SMB3.1.1
|
||||
|
||||
w) Add support for additional strong encryption types, and additional spnego
|
||||
authentication mechanisms (see MS-SMB2). GCM-256 is now partially implemented.
|
||||
|
||||
x) Finish support for SMB3.1.1 compression
|
||||
|
||||
Known Bugs
|
||||
==========
|
||||
|
||||
See https://bugzilla.samba.org - search on product "CifsVFS" for
|
||||
current bug list. Also check http://bugzilla.kernel.org (Product = File System, Component = CIFS)
|
||||
|
||||
1) existing symbolic links (Windows reparse points) are recognized but
|
||||
can not be created remotely. They are implemented for Samba and those that
|
||||
support the CIFS Unix extensions, although earlier versions of Samba
|
||||
overly restrict the pathnames.
|
||||
2) follow_link and readdir code does not follow dfs junctions
|
||||
but recognizes them
|
||||
|
||||
Misc testing to do
|
||||
==================
|
||||
1) check out max path names and max path name components against various server
|
||||
types. Try nested symlinks (8 deep). Return max path name in stat -f information
|
||||
|
||||
2) Improve xfstest's cifs/smb3 enablement and adapt xfstests where needed to test
|
||||
cifs/smb3 better
|
||||
|
||||
3) Additional performance testing and optimization using iozone and similar -
|
||||
there are some easy changes that can be done to parallelize sequential writes,
|
||||
and when signing is disabled to request larger read sizes (larger than
|
||||
negotiated size) and send larger write sizes to modern servers.
|
||||
|
||||
4) More exhaustively test against less common servers
|
||||
|
||||
5) Continue to extend the smb3 "buildbot" which does automated xfstesting
|
||||
against Windows, Samba and Azure currently - to add additional tests and
|
||||
to allow the buildbot to execute the tests faster. The URL for the
|
||||
buildbot is: http://smb3-test-rhel-75.southcentralus.cloudapp.azure.com
|
||||
|
||||
6) Address various coverity warnings (most are not bugs per-se, but
|
||||
the more warnings are addressed, the easier it is to spot real
|
||||
problems that static analyzers will point out in the future).
|
870
Documentation/admin-guide/cifs/usage.rst
Normal file
@ -0,0 +1,870 @@
|
||||
=====
|
||||
Usage
|
||||
=====
|
||||
|
||||
This module supports the SMB3 family of advanced network protocols (as well
|
||||
as older dialects, originally called "CIFS" or SMB1).
|
||||
|
||||
The CIFS VFS module for Linux supports many advanced network filesystem
|
||||
features such as hierarchical DFS like namespace, hardlinks, locking and more.
|
||||
It was designed to comply with the SNIA CIFS Technical Reference (which
|
||||
supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
|
||||
practical interoperability with Windows 2000, Windows XP, Samba and equivalent
|
||||
servers. This code was developed in participation with the Protocol Freedom
|
||||
Information Foundation. CIFS and now SMB3 has now become a defacto
|
||||
standard for interoperating between Macs and Windows and major NAS appliances.
|
||||
|
||||
Please see
|
||||
MS-SMB2 (for detailed SMB2/SMB3/SMB3.1.1 protocol specification)
|
||||
or https://samba.org/samba/PFIF/
|
||||
for more details.
|
||||
|
||||
|
||||
For questions or bug reports please contact:
|
||||
|
||||
smfrench@gmail.com
|
||||
|
||||
See the project page at: https://wiki.samba.org/index.php/LinuxCIFS_utils
|
||||
|
||||
Build instructions
|
||||
==================
|
||||
|
||||
For Linux:
|
||||
|
||||
1) Download the kernel (e.g. from https://www.kernel.org)
|
||||
and change directory into the top of the kernel directory tree
|
||||
(e.g. /usr/src/linux-2.5.73)
|
||||
2) make menuconfig (or make xconfig)
|
||||
3) select cifs from within the network filesystem choices
|
||||
4) save and exit
|
||||
5) make
|
||||
|
||||
|
||||
Installation instructions
|
||||
=========================
|
||||
|
||||
If you have built the CIFS vfs as module (successfully) simply
|
||||
type ``make modules_install`` (or if you prefer, manually copy the file to
|
||||
the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.ko).
|
||||
|
||||
If you have built the CIFS vfs into the kernel itself, follow the instructions
|
||||
for your distribution on how to install a new kernel (usually you
|
||||
would simply type ``make install``).
|
||||
|
||||
If you do not have the utility mount.cifs (in the Samba 4.x source tree and on
|
||||
the CIFS VFS web site) copy it to the same directory in which mount helpers
|
||||
reside (usually /sbin). Although the helper software is not
|
||||
required, mount.cifs is recommended. Most distros include a ``cifs-utils``
|
||||
package that includes this utility so it is recommended to install this.
|
||||
|
||||
Note that running the Winbind pam/nss module (logon service) on all of your
|
||||
Linux clients is useful in mapping Uids and Gids consistently across the
|
||||
domain to the proper network user. The mount.cifs mount helper can be
|
||||
found at cifs-utils.git on git.samba.org
|
||||
|
||||
If cifs is built as a module, then the size and number of network buffers
|
||||
and maximum number of simultaneous requests to one server can be configured.
|
||||
Changing these from their defaults is not recommended. By executing modinfo::
|
||||
|
||||
modinfo kernel/fs/cifs/cifs.ko
|
||||
|
||||
on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made
|
||||
at module initialization time (by running insmod cifs.ko) can be seen.
|
||||
|
||||
Recommendations
|
||||
===============
|
||||
|
||||
To improve security the SMB2.1 dialect or later (usually will get SMB3) is now
|
||||
the new default. To use old dialects (e.g. to mount Windows XP) use "vers=1.0"
|
||||
on mount (or vers=2.0 for Windows Vista). Note that the CIFS (vers=1.0) is
|
||||
much older and less secure than the default dialect SMB3 which includes
|
||||
many advanced security features such as downgrade attack detection
|
||||
and encrypted shares and stronger signing and authentication algorithms.
|
||||
There are additional mount options that may be helpful for SMB3 to get
|
||||
improved POSIX behavior (NB: can use vers=3.0 to force only SMB3, never 2.1):
|
||||
|
||||
``mfsymlinks`` and either ``cifsacl`` or ``modefromsid`` (usually with ``idsfromsid``)
|
||||
|
||||
Allowing User Mounts
|
||||
====================
|
||||
|
||||
To permit users to mount and unmount over directories they own is possible
|
||||
with the cifs vfs. A way to enable such mounting is to mark the mount.cifs
|
||||
utility as suid (e.g. ``chmod +s /sbin/mount.cifs``). To enable users to
|
||||
umount shares they mount requires
|
||||
|
||||
1) mount.cifs version 1.4 or later
|
||||
2) an entry for the share in /etc/fstab indicating that a user may
|
||||
unmount it e.g.::
|
||||
|
||||
//server/usersharename /mnt/username cifs user 0 0
|
||||
|
||||
Note that when the mount.cifs utility is run suid (allowing user mounts),
|
||||
in order to reduce risks, the ``nosuid`` mount flag is passed in on mount to
|
||||
disallow execution of an suid program mounted on the remote target.
|
||||
When mount is executed as root, nosuid is not passed in by default,
|
||||
and execution of suid programs on the remote target would be enabled
|
||||
by default. This can be changed, as with nfs and other filesystems,
|
||||
by simply specifying ``nosuid`` among the mount options. For user mounts
|
||||
though to be able to pass the suid flag to mount requires rebuilding
|
||||
mount.cifs with the following flag: CIFS_ALLOW_USR_SUID
|
||||
|
||||
There is a corresponding manual page for cifs mounting in the Samba 3.0 and
|
||||
later source tree in docs/manpages/mount.cifs.8
|
||||
|
||||
Allowing User Unmounts
|
||||
======================
|
||||
|
||||
To permit users to unmount directories that they have user mounted (see above),
|
||||
the utility umount.cifs may be used. It may be invoked directly, or if
|
||||
umount.cifs is placed in /sbin, umount can invoke the cifs umount helper
|
||||
(at least for most versions of the umount utility) for umount of cifs
|
||||
mounts, unless umount is invoked with -i (which will avoid invoking a umount
|
||||
helper). As with mount.cifs, to enable user unmounts umount.cifs must be marked
|
||||
as suid (e.g. ``chmod +s /sbin/umount.cifs``) or equivalent (some distributions
|
||||
allow adding entries to a file to the /etc/permissions file to achieve the
|
||||
equivalent suid effect). For this utility to succeed the target path
|
||||
must be a cifs mount, and the uid of the current user must match the uid
|
||||
of the user who mounted the resource.
|
||||
|
||||
Also note that the customary way of allowing user mounts and unmounts is
|
||||
(instead of using mount.cifs and unmount.cifs as suid) to add a line
|
||||
to the file /etc/fstab for each //server/share you wish to mount, but
|
||||
this can become unwieldy when potential mount targets include many
|
||||
or unpredictable UNC names.
|
||||
|
||||
Samba Considerations
|
||||
====================
|
||||
|
||||
Most current servers support SMB2.1 and SMB3 which are more secure,
|
||||
but there are useful protocol extensions for the older less secure CIFS
|
||||
dialect, so to get the maximum benefit if mounting using the older dialect
|
||||
(CIFS/SMB1), we recommend using a server that supports the SNIA CIFS
|
||||
Unix Extensions standard (e.g. almost any version of Samba ie version
|
||||
2.2.5 or later) but the CIFS vfs works fine with a wide variety of CIFS servers.
|
||||
Note that uid, gid and file permissions will display default values if you do
|
||||
not have a server that supports the Unix extensions for CIFS (such as Samba
|
||||
2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add
|
||||
the line::
|
||||
|
||||
unix extensions = yes
|
||||
|
||||
to your smb.conf file on the server. Note that the following smb.conf settings
|
||||
are also useful (on the Samba server) when the majority of clients are Unix or
|
||||
Linux::
|
||||
|
||||
case sensitive = yes
|
||||
delete readonly = yes
|
||||
ea support = yes
|
||||
|
||||
Note that server ea support is required for supporting xattrs from the Linux
|
||||
cifs client, and that EA support is present in later versions of Samba (e.g.
|
||||
3.0.6 and later (also EA support works in all versions of Windows, at least to
|
||||
shares on NTFS filesystems). Extended Attribute (xattr) support is an optional
|
||||
feature of most Linux filesystems which may require enabling via
|
||||
make menuconfig. Client support for extended attributes (user xattr) can be
|
||||
disabled on a per-mount basis by specifying ``nouser_xattr`` on mount.
|
||||
|
||||
The CIFS client can get and set POSIX ACLs (getfacl, setfacl) to Samba servers
|
||||
version 3.10 and later. Setting POSIX ACLs requires enabling both XATTR and
|
||||
then POSIX support in the CIFS configuration options when building the cifs
|
||||
module. POSIX ACL support can be disabled on a per mount basic by specifying
|
||||
``noacl`` on mount.
|
||||
|
||||
Some administrators may want to change Samba's smb.conf ``map archive`` and
|
||||
``create mask`` parameters from the default. Unless the create mask is changed
|
||||
newly created files can end up with an unnecessarily restrictive default mode,
|
||||
which may not be what you want, although if the CIFS Unix extensions are
|
||||
enabled on the server and client, subsequent setattr calls (e.g. chmod) can
|
||||
fix the mode. Note that creating special devices (mknod) remotely
|
||||
may require specifying a mkdev function to Samba if you are not using
|
||||
Samba 3.0.6 or later. For more information on these see the manual pages
|
||||
(``man smb.conf``) on the Samba server system. Note that the cifs vfs,
|
||||
unlike the smbfs vfs, does not read the smb.conf on the client system
|
||||
(the few optional settings are passed in on mount via -o parameters instead).
|
||||
Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete
|
||||
open files (required for strict POSIX compliance). Windows Servers already
|
||||
supported this feature. Samba server does not allow symlinks that refer to files
|
||||
outside of the share, so in Samba versions prior to 3.0.6, most symlinks to
|
||||
files with absolute paths (ie beginning with slash) such as::
|
||||
|
||||
ln -s /mnt/foo bar
|
||||
|
||||
would be forbidden. Samba 3.0.6 server or later includes the ability to create
|
||||
such symlinks safely by converting unsafe symlinks (ie symlinks to server
|
||||
files that are outside of the share) to a samba specific format on the server
|
||||
that is ignored by local server applications and non-cifs clients and that will
|
||||
not be traversed by the Samba server). This is opaque to the Linux client
|
||||
application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or
|
||||
later, but only for remote clients using the CIFS Unix extensions, and will
|
||||
be invisible to Windows clients and typically will not affect local
|
||||
applications running on the same server as Samba.
|
||||
|
||||
Use instructions
|
||||
================
|
||||
|
||||
Once the CIFS VFS support is built into the kernel or installed as a module
|
||||
(cifs.ko), you can use mount syntax like the following to access Samba or
|
||||
Mac or Windows servers::
|
||||
|
||||
mount -t cifs //9.53.216.11/e$ /mnt -o username=myname,password=mypassword
|
||||
|
||||
Before -o the option -v may be specified to make the mount.cifs
|
||||
mount helper display the mount steps more verbosely.
|
||||
After -o the following commonly used cifs vfs specific options
|
||||
are supported::
|
||||
|
||||
username=<username>
|
||||
password=<password>
|
||||
domain=<domain name>
|
||||
|
||||
Other cifs mount options are described below. Use of TCP names (in addition to
|
||||
ip addresses) is available if the mount helper (mount.cifs) is installed. If
|
||||
you do not trust the server to which are mounted, or if you do not have
|
||||
cifs signing enabled (and the physical network is insecure), consider use
|
||||
of the standard mount options ``noexec`` and ``nosuid`` to reduce the risk of
|
||||
running an altered binary on your local system (downloaded from a hostile server
|
||||
or altered by a hostile router).
|
||||
|
||||
Although mounting using format corresponding to the CIFS URL specification is
|
||||
not possible in mount.cifs yet, it is possible to use an alternate format
|
||||
for the server and sharename (which is somewhat similar to NFS style mount
|
||||
syntax) instead of the more widely used UNC format (i.e. \\server\share)::
|
||||
|
||||
mount -t cifs tcp_name_of_server:share_name /mnt -o user=myname,pass=mypasswd
|
||||
|
||||
When using the mount helper mount.cifs, passwords may be specified via alternate
|
||||
mechanisms, instead of specifying it after -o using the normal ``pass=`` syntax
|
||||
on the command line:
|
||||
1) By including it in a credential file. Specify credentials=filename as one
|
||||
of the mount options. Credential files contain two lines::
|
||||
|
||||
username=someuser
|
||||
password=your_password
|
||||
|
||||
2) By specifying the password in the PASSWD environment variable (similarly
|
||||
the user name can be taken from the USER environment variable).
|
||||
3) By specifying the password in a file by name via PASSWD_FILE
|
||||
4) By specifying the password in a file by file descriptor via PASSWD_FD
|
||||
|
||||
If no password is provided, mount.cifs will prompt for password entry
|
||||
|
||||
Restrictions
|
||||
============
|
||||
|
||||
Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
|
||||
1001/1002 support for "Netbios-Over-TCP/IP." This is not likely to be a
|
||||
problem as most servers support this.
|
||||
|
||||
Valid filenames differ between Windows and Linux. Windows typically restricts
|
||||
filenames which contain certain reserved characters (e.g.the character :
|
||||
which is used to delimit the beginning of a stream name by Windows), while
|
||||
Linux allows a slightly wider set of valid characters in filenames. Windows
|
||||
servers can remap such characters when an explicit mapping is specified in
|
||||
the Server's registry. Samba starting with version 3.10 will allow such
|
||||
filenames (ie those which contain valid Linux characters, which normally
|
||||
would be forbidden for Windows/CIFS semantics) as long as the server is
|
||||
configured for Unix Extensions (and the client has not disabled
|
||||
/proc/fs/cifs/LinuxExtensionsEnabled). In addition the mount option
|
||||
``mapposix`` can be used on CIFS (vers=1.0) to force the mapping of
|
||||
illegal Windows/NTFS/SMB characters to a remap range (this mount parameter
|
||||
is the default for SMB3). This remap (``mapposix``) range is also
|
||||
compatible with Mac (and "Services for Mac" on some older Windows).
|
||||
|
||||
CIFS VFS Mount Options
|
||||
======================
|
||||
A partial list of the supported mount options follows:
|
||||
|
||||
username
|
||||
The user name to use when trying to establish
|
||||
the CIFS session.
|
||||
password
|
||||
The user password. If the mount helper is
|
||||
installed, the user will be prompted for password
|
||||
if not supplied.
|
||||
ip
|
||||
The ip address of the target server
|
||||
unc
|
||||
The target server Universal Network Name (export) to
|
||||
mount.
|
||||
domain
|
||||
Set the SMB/CIFS workgroup name prepended to the
|
||||
username during CIFS session establishment
|
||||
forceuid
|
||||
Set the default uid for inodes to the uid
|
||||
passed in on mount. For mounts to servers
|
||||
which do support the CIFS Unix extensions, such as a
|
||||
properly configured Samba server, the server provides
|
||||
the uid, gid and mode so this parameter should not be
|
||||
specified unless the server and clients uid and gid
|
||||
numbering differ. If the server and client are in the
|
||||
same domain (e.g. running winbind or nss_ldap) and
|
||||
the server supports the Unix Extensions then the uid
|
||||
and gid can be retrieved from the server (and uid
|
||||
and gid would not have to be specified on the mount.
|
||||
For servers which do not support the CIFS Unix
|
||||
extensions, the default uid (and gid) returned on lookup
|
||||
of existing files will be the uid (gid) of the person
|
||||
who executed the mount (root, except when mount.cifs
|
||||
is configured setuid for user mounts) unless the ``uid=``
|
||||
(gid) mount option is specified. Also note that permission
|
||||
checks (authorization checks) on accesses to a file occur
|
||||
at the server, but there are cases in which an administrator
|
||||
may want to restrict at the client as well. For those
|
||||
servers which do not report a uid/gid owner
|
||||
(such as Windows), permissions can also be checked at the
|
||||
client, and a crude form of client side permission checking
|
||||
can be enabled by specifying file_mode and dir_mode on
|
||||
the client. (default)
|
||||
forcegid
|
||||
(similar to above but for the groupid instead of uid) (default)
|
||||
noforceuid
|
||||
Fill in file owner information (uid) by requesting it from
|
||||
the server if possible. With this option, the value given in
|
||||
the uid= option (on mount) will only be used if the server
|
||||
can not support returning uids on inodes.
|
||||
noforcegid
|
||||
(similar to above but for the group owner, gid, instead of uid)
|
||||
uid
|
||||
Set the default uid for inodes, and indicate to the
|
||||
cifs kernel driver which local user mounted. If the server
|
||||
supports the unix extensions the default uid is
|
||||
not used to fill in the owner fields of inodes (files)
|
||||
unless the ``forceuid`` parameter is specified.
|
||||
gid
|
||||
Set the default gid for inodes (similar to above).
|
||||
file_mode
|
||||
If CIFS Unix extensions are not supported by the server
|
||||
this overrides the default mode for file inodes.
|
||||
fsc
|
||||
Enable local disk caching using FS-Cache (off by default). This
|
||||
option could be useful to improve performance on a slow link,
|
||||
heavily loaded server and/or network where reading from the
|
||||
disk is faster than reading from the server (over the network).
|
||||
This could also impact scalability positively as the
|
||||
number of calls to the server are reduced. However, local
|
||||
caching is not suitable for all workloads for e.g. read-once
|
||||
type workloads. So, you need to consider carefully your
|
||||
workload/scenario before using this option. Currently, local
|
||||
disk caching is functional for CIFS files opened as read-only.
|
||||
dir_mode
|
||||
If CIFS Unix extensions are not supported by the server
|
||||
this overrides the default mode for directory inodes.
|
||||
port
|
||||
attempt to contact the server on this tcp port, before
|
||||
trying the usual ports (port 445, then 139).
|
||||
iocharset
|
||||
Codepage used to convert local path names to and from
|
||||
Unicode. Unicode is used by default for network path
|
||||
names if the server supports it. If iocharset is
|
||||
not specified then the nls_default specified
|
||||
during the local client kernel build will be used.
|
||||
If server does not support Unicode, this parameter is
|
||||
unused.
|
||||
rsize
|
||||
default read size (usually 16K). The client currently
|
||||
can not use rsize larger than CIFSMaxBufSize. CIFSMaxBufSize
|
||||
defaults to 16K and may be changed (from 8K to the maximum
|
||||
kmalloc size allowed by your kernel) at module install time
|
||||
for cifs.ko. Setting CIFSMaxBufSize to a very large value
|
||||
will cause cifs to use more memory and may reduce performance
|
||||
in some cases. To use rsize greater than 127K (the original
|
||||
cifs protocol maximum) also requires that the server support
|
||||
a new Unix Capability flag (for very large read) which some
|
||||
newer servers (e.g. Samba 3.0.26 or later) do. rsize can be
|
||||
set from a minimum of 2048 to a maximum of 130048 (127K or
|
||||
CIFSMaxBufSize, whichever is smaller)
|
||||
wsize
|
||||
default write size (default 57344)
|
||||
maximum wsize currently allowed by CIFS is 57344 (fourteen
|
||||
4096 byte pages)
|
||||
actimeo=n
|
||||
attribute cache timeout in seconds (default 1 second).
|
||||
After this timeout, the cifs client requests fresh attribute
|
||||
information from the server. This option allows to tune the
|
||||
attribute cache timeout to suit the workload needs. Shorter
|
||||
timeouts mean better the cache coherency, but increased number
|
||||
of calls to the server. Longer timeouts mean reduced number
|
||||
of calls to the server at the expense of less stricter cache
|
||||
coherency checks (i.e. incorrect attribute cache for a short
|
||||
period of time).
|
||||
rw
|
||||
mount the network share read-write (note that the
|
||||
server may still consider the share read-only)
|
||||
ro
|
||||
mount network share read-only
|
||||
version
|
||||
used to distinguish different versions of the
|
||||
mount helper utility (not typically needed)
|
||||
sep
|
||||
if first mount option (after the -o), overrides
|
||||
the comma as the separator between the mount
|
||||
parms. e.g.::
|
||||
|
||||
-o user=myname,password=mypassword,domain=mydom
|
||||
|
||||
could be passed instead with period as the separator by::
|
||||
|
||||
-o sep=.user=myname.password=mypassword.domain=mydom
|
||||
|
||||
this might be useful when comma is contained within username
|
||||
or password or domain. This option is less important
|
||||
when the cifs mount helper cifs.mount (version 1.1 or later)
|
||||
is used.
|
||||
nosuid
|
||||
Do not allow remote executables with the suid bit
|
||||
program to be executed. This is only meaningful for mounts
|
||||
to servers such as Samba which support the CIFS Unix Extensions.
|
||||
If you do not trust the servers in your network (your mount
|
||||
targets) it is recommended that you specify this option for
|
||||
greater security.
|
||||
exec
|
||||
Permit execution of binaries on the mount.
|
||||
noexec
|
||||
Do not permit execution of binaries on the mount.
|
||||
dev
|
||||
Recognize block devices on the remote mount.
|
||||
nodev
|
||||
Do not recognize devices on the remote mount.
|
||||
suid
|
||||
Allow remote files on this mountpoint with suid enabled to
|
||||
be executed (default for mounts when executed as root,
|
||||
nosuid is default for user mounts).
|
||||
credentials
|
||||
Although ignored by the cifs kernel component, it is used by
|
||||
the mount helper, mount.cifs. When mount.cifs is installed it
|
||||
opens and reads the credential file specified in order
|
||||
to obtain the userid and password arguments which are passed to
|
||||
the cifs vfs.
|
||||
guest
|
||||
Although ignored by the kernel component, the mount.cifs
|
||||
mount helper will not prompt the user for a password
|
||||
if guest is specified on the mount options. If no
|
||||
password is specified a null password will be used.
|
||||
perm
|
||||
Client does permission checks (vfs_permission check of uid
|
||||
and gid of the file against the mode and desired operation),
|
||||
Note that this is in addition to the normal ACL check on the
|
||||
target machine done by the server software.
|
||||
Client permission checking is enabled by default.
|
||||
noperm
|
||||
Client does not do permission checks. This can expose
|
||||
files on this mount to access by other users on the local
|
||||
client system. It is typically only needed when the server
|
||||
supports the CIFS Unix Extensions but the UIDs/GIDs on the
|
||||
client and server system do not match closely enough to allow
|
||||
access by the user doing the mount, but it may be useful with
|
||||
non CIFS Unix Extension mounts for cases in which the default
|
||||
mode is specified on the mount but is not to be enforced on the
|
||||
client (e.g. perhaps when MultiUserMount is enabled)
|
||||
Note that this does not affect the normal ACL check on the
|
||||
target machine done by the server software (of the server
|
||||
ACL against the user name provided at mount time).
|
||||
serverino
|
||||
Use server's inode numbers instead of generating automatically
|
||||
incrementing inode numbers on the client. Although this will
|
||||
make it easier to spot hardlinked files (as they will have
|
||||
the same inode numbers) and inode numbers may be persistent,
|
||||
note that the server does not guarantee that the inode numbers
|
||||
are unique if multiple server side mounts are exported under a
|
||||
single share (since inode numbers on the servers might not
|
||||
be unique if multiple filesystems are mounted under the same
|
||||
shared higher level directory). Note that some older
|
||||
(e.g. pre-Windows 2000) do not support returning UniqueIDs
|
||||
or the CIFS Unix Extensions equivalent and for those
|
||||
this mount option will have no effect. Exporting cifs mounts
|
||||
under nfsd requires this mount option on the cifs mount.
|
||||
This is now the default if server supports the
|
||||
required network operation.
|
||||
noserverino
|
||||
Client generates inode numbers (rather than using the actual one
|
||||
from the server). These inode numbers will vary after
|
||||
unmount or reboot which can confuse some applications,
|
||||
but not all server filesystems support unique inode
|
||||
numbers.
|
||||
setuids
|
||||
If the CIFS Unix extensions are negotiated with the server
|
||||
the client will attempt to set the effective uid and gid of
|
||||
the local process on newly created files, directories, and
|
||||
devices (create, mkdir, mknod). If the CIFS Unix Extensions
|
||||
are not negotiated, for newly created files and directories
|
||||
instead of using the default uid and gid specified on
|
||||
the mount, cache the new file's uid and gid locally which means
|
||||
that the uid for the file can change when the inode is
|
||||
reloaded (or the user remounts the share).
|
||||
nosetuids
|
||||
The client will not attempt to set the uid and gid on
|
||||
on newly created files, directories, and devices (create,
|
||||
mkdir, mknod) which will result in the server setting the
|
||||
uid and gid to the default (usually the server uid of the
|
||||
user who mounted the share). Letting the server (rather than
|
||||
the client) set the uid and gid is the default. If the CIFS
|
||||
Unix Extensions are not negotiated then the uid and gid for
|
||||
new files will appear to be the uid (gid) of the mounter or the
|
||||
uid (gid) parameter specified on the mount.
|
||||
netbiosname
|
||||
When mounting to servers via port 139, specifies the RFC1001
|
||||
source name to use to represent the client netbios machine
|
||||
name when doing the RFC1001 netbios session initialize.
|
||||
direct
|
||||
Do not do inode data caching on files opened on this mount.
|
||||
This precludes mmapping files on this mount. In some cases
|
||||
with fast networks and little or no caching benefits on the
|
||||
client (e.g. when the application is doing large sequential
|
||||
reads bigger than page size without rereading the same data)
|
||||
this can provide better performance than the default
|
||||
behavior which caches reads (readahead) and writes
|
||||
(writebehind) through the local Linux client pagecache
|
||||
if oplock (caching token) is granted and held. Note that
|
||||
direct allows write operations larger than page size
|
||||
to be sent to the server.
|
||||
strictcache
|
||||
Use for switching on strict cache mode. In this mode the
|
||||
client read from the cache all the time it has Oplock Level II,
|
||||
otherwise - read from the server. All written data are stored
|
||||
in the cache, but if the client doesn't have Exclusive Oplock,
|
||||
it writes the data to the server.
|
||||
rwpidforward
|
||||
Forward pid of a process who opened a file to any read or write
|
||||
operation on that file. This prevent applications like WINE
|
||||
from failing on read and write if we use mandatory brlock style.
|
||||
acl
|
||||
Allow setfacl and getfacl to manage posix ACLs if server
|
||||
supports them. (default)
|
||||
noacl
|
||||
Do not allow setfacl and getfacl calls on this mount
|
||||
user_xattr
|
||||
Allow getting and setting user xattrs (those attributes whose
|
||||
name begins with ``user.`` or ``os2.``) as OS/2 EAs (extended
|
||||
attributes) to the server. This allows support of the
|
||||
setfattr and getfattr utilities. (default)
|
||||
nouser_xattr
|
||||
Do not allow getfattr/setfattr to get/set/list xattrs
|
||||
mapchars
|
||||
Translate six of the seven reserved characters (not backslash)::
|
||||
|
||||
*?<>|:
|
||||
|
||||
to the remap range (above 0xF000), which also
|
||||
allows the CIFS client to recognize files created with
|
||||
such characters by Windows's POSIX emulation. This can
|
||||
also be useful when mounting to most versions of Samba
|
||||
(which also forbids creating and opening files
|
||||
whose names contain any of these seven characters).
|
||||
This has no effect if the server does not support
|
||||
Unicode on the wire.
|
||||
nomapchars
|
||||
Do not translate any of these seven characters (default).
|
||||
nocase
|
||||
Request case insensitive path name matching (case
|
||||
sensitive is the default if the server supports it).
|
||||
(mount option ``ignorecase`` is identical to ``nocase``)
|
||||
posixpaths
|
||||
If CIFS Unix extensions are supported, attempt to
|
||||
negotiate posix path name support which allows certain
|
||||
characters forbidden in typical CIFS filenames, without
|
||||
requiring remapping. (default)
|
||||
noposixpaths
|
||||
If CIFS Unix extensions are supported, do not request
|
||||
posix path name support (this may cause servers to
|
||||
reject creatingfile with certain reserved characters).
|
||||
nounix
|
||||
Disable the CIFS Unix Extensions for this mount (tree
|
||||
connection). This is rarely needed, but it may be useful
|
||||
in order to turn off multiple settings all at once (ie
|
||||
posix acls, posix locks, posix paths, symlink support
|
||||
and retrieving uids/gids/mode from the server) or to
|
||||
work around a bug in server which implement the Unix
|
||||
Extensions.
|
||||
nobrl
|
||||
Do not send byte range lock requests to the server.
|
||||
This is necessary for certain applications that break
|
||||
with cifs style mandatory byte range locks (and most
|
||||
cifs servers do not yet support requesting advisory
|
||||
byte range locks).
|
||||
forcemandatorylock
|
||||
Even if the server supports posix (advisory) byte range
|
||||
locking, send only mandatory lock requests. For some
|
||||
(presumably rare) applications, originally coded for
|
||||
DOS/Windows, which require Windows style mandatory byte range
|
||||
locking, they may be able to take advantage of this option,
|
||||
forcing the cifs client to only send mandatory locks
|
||||
even if the cifs server would support posix advisory locks.
|
||||
``forcemand`` is accepted as a shorter form of this mount
|
||||
option.
|
||||
nostrictsync
|
||||
If this mount option is set, when an application does an
|
||||
fsync call then the cifs client does not send an SMB Flush
|
||||
to the server (to force the server to write all dirty data
|
||||
for this file immediately to disk), although cifs still sends
|
||||
all dirty (cached) file data to the server and waits for the
|
||||
server to respond to the write. Since SMB Flush can be
|
||||
very slow, and some servers may be reliable enough (to risk
|
||||
delaying slightly flushing the data to disk on the server),
|
||||
turning on this option may be useful to improve performance for
|
||||
applications that fsync too much, at a small risk of server
|
||||
crash. If this mount option is not set, by default cifs will
|
||||
send an SMB flush request (and wait for a response) on every
|
||||
fsync call.
|
||||
nodfs
|
||||
Disable DFS (global name space support) even if the
|
||||
server claims to support it. This can help work around
|
||||
a problem with parsing of DFS paths with Samba server
|
||||
versions 3.0.24 and 3.0.25.
|
||||
remount
|
||||
remount the share (often used to change from ro to rw mounts
|
||||
or vice versa)
|
||||
cifsacl
|
||||
Report mode bits (e.g. on stat) based on the Windows ACL for
|
||||
the file. (EXPERIMENTAL)
|
||||
servern
|
||||
Specify the server 's netbios name (RFC1001 name) to use
|
||||
when attempting to setup a session to the server.
|
||||
This is needed for mounting to some older servers (such
|
||||
as OS/2 or Windows 98 and Windows ME) since they do not
|
||||
support a default server name. A server name can be up
|
||||
to 15 characters long and is usually uppercased.
|
||||
sfu
|
||||
When the CIFS Unix Extensions are not negotiated, attempt to
|
||||
create device files and fifos in a format compatible with
|
||||
Services for Unix (SFU). In addition retrieve bits 10-12
|
||||
of the mode via the SETFILEBITS extended attribute (as
|
||||
SFU does). In the future the bottom 9 bits of the
|
||||
mode also will be emulated using queries of the security
|
||||
descriptor (ACL).
|
||||
mfsymlinks
|
||||
Enable support for Minshall+French symlinks
|
||||
(see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks)
|
||||
This option is ignored when specified together with the
|
||||
'sfu' option. Minshall+French symlinks are used even if
|
||||
the server supports the CIFS Unix Extensions.
|
||||
sign
|
||||
Must use packet signing (helps avoid unwanted data modification
|
||||
by intermediate systems in the route). Note that signing
|
||||
does not work with lanman or plaintext authentication.
|
||||
seal
|
||||
Must seal (encrypt) all data on this mounted share before
|
||||
sending on the network. Requires support for Unix Extensions.
|
||||
Note that this differs from the sign mount option in that it
|
||||
causes encryption of data sent over this mounted share but other
|
||||
shares mounted to the same server are unaffected.
|
||||
locallease
|
||||
This option is rarely needed. Fcntl F_SETLEASE is
|
||||
used by some applications such as Samba and NFSv4 server to
|
||||
check to see whether a file is cacheable. CIFS has no way
|
||||
to explicitly request a lease, but can check whether a file
|
||||
is cacheable (oplocked). Unfortunately, even if a file
|
||||
is not oplocked, it could still be cacheable (ie cifs client
|
||||
could grant fcntl leases if no other local processes are using
|
||||
the file) for cases for example such as when the server does not
|
||||
support oplocks and the user is sure that the only updates to
|
||||
the file will be from this client. Specifying this mount option
|
||||
will allow the cifs client to check for leases (only) locally
|
||||
for files which are not oplocked instead of denying leases
|
||||
in that case. (EXPERIMENTAL)
|
||||
sec
|
||||
Security mode. Allowed values are:
|
||||
|
||||
none
|
||||
attempt to connection as a null user (no name)
|
||||
krb5
|
||||
Use Kerberos version 5 authentication
|
||||
krb5i
|
||||
Use Kerberos authentication and packet signing
|
||||
ntlm
|
||||
Use NTLM password hashing (default)
|
||||
ntlmi
|
||||
Use NTLM password hashing with signing (if
|
||||
/proc/fs/cifs/PacketSigningEnabled on or if
|
||||
server requires signing also can be the default)
|
||||
ntlmv2
|
||||
Use NTLMv2 password hashing
|
||||
ntlmv2i
|
||||
Use NTLMv2 password hashing with packet signing
|
||||
lanman
|
||||
(if configured in kernel config) use older
|
||||
lanman hash
|
||||
hard
|
||||
Retry file operations if server is not responding
|
||||
soft
|
||||
Limit retries to unresponsive servers (usually only
|
||||
one retry) before returning an error. (default)
|
||||
|
||||
The mount.cifs mount helper also accepts a few mount options before -o
|
||||
including:
|
||||
|
||||
=============== ===============================================================
|
||||
-S take password from stdin (equivalent to setting the environment
|
||||
variable ``PASSWD_FD=0``
|
||||
-V print mount.cifs version
|
||||
-? display simple usage information
|
||||
=============== ===============================================================
|
||||
|
||||
With most 2.6 kernel versions of modutils, the version of the cifs kernel
|
||||
module can be displayed via modinfo.
|
||||
|
||||
Misc /proc/fs/cifs Flags and Debug Info
|
||||
=======================================
|
||||
|
||||
Informational pseudo-files:
|
||||
|
||||
======================= =======================================================
|
||||
DebugData Displays information about active CIFS sessions and
|
||||
shares, features enabled as well as the cifs.ko
|
||||
version.
|
||||
Stats Lists summary resource usage information as well as per
|
||||
share statistics.
|
||||
open_files List all the open file handles on all active SMB sessions.
|
||||
======================= =======================================================
|
||||
|
||||
Configuration pseudo-files:
|
||||
|
||||
======================= =======================================================
|
||||
SecurityFlags Flags which control security negotiation and
|
||||
also packet signing. Authentication (may/must)
|
||||
flags (e.g. for NTLM and/or NTLMv2) may be combined with
|
||||
the signing flags. Specifying two different password
|
||||
hashing mechanisms (as "must use") on the other hand
|
||||
does not make much sense. Default flags are::
|
||||
|
||||
0x07007
|
||||
|
||||
(NTLM, NTLMv2 and packet signing allowed). The maximum
|
||||
allowable flags if you want to allow mounts to servers
|
||||
using weaker password hashes is 0x37037 (lanman,
|
||||
plaintext, ntlm, ntlmv2, signing allowed). Some
|
||||
SecurityFlags require the corresponding menuconfig
|
||||
options to be enabled. Enabling plaintext
|
||||
authentication currently requires also enabling
|
||||
lanman authentication in the security flags
|
||||
because the cifs module only supports sending
|
||||
laintext passwords using the older lanman dialect
|
||||
form of the session setup SMB. (e.g. for authentication
|
||||
using plain text passwords, set the SecurityFlags
|
||||
to 0x30030)::
|
||||
|
||||
may use packet signing 0x00001
|
||||
must use packet signing 0x01001
|
||||
may use NTLM (most common password hash) 0x00002
|
||||
must use NTLM 0x02002
|
||||
may use NTLMv2 0x00004
|
||||
must use NTLMv2 0x04004
|
||||
may use Kerberos security 0x00008
|
||||
must use Kerberos 0x08008
|
||||
may use lanman (weak) password hash 0x00010
|
||||
must use lanman password hash 0x10010
|
||||
may use plaintext passwords 0x00020
|
||||
must use plaintext passwords 0x20020
|
||||
(reserved for future packet encryption) 0x00040
|
||||
|
||||
cifsFYI If set to non-zero value, additional debug information
|
||||
will be logged to the system error log. This field
|
||||
contains three flags controlling different classes of
|
||||
debugging entries. The maximum value it can be set
|
||||
to is 7 which enables all debugging points (default 0).
|
||||
Some debugging statements are not compiled into the
|
||||
cifs kernel unless CONFIG_CIFS_DEBUG2 is enabled in the
|
||||
kernel configuration. cifsFYI may be set to one or
|
||||
nore of the following flags (7 sets them all)::
|
||||
|
||||
+-----------------------------------------------+------+
|
||||
| log cifs informational messages | 0x01 |
|
||||
+-----------------------------------------------+------+
|
||||
| log return codes from cifs entry points | 0x02 |
|
||||
+-----------------------------------------------+------+
|
||||
| log slow responses | 0x04 |
|
||||
| (ie which take longer than 1 second) | |
|
||||
| | |
|
||||
| CONFIG_CIFS_STATS2 must be enabled in .config | |
|
||||
+-----------------------------------------------+------+
|
||||
|
||||
traceSMB If set to one, debug information is logged to the
|
||||
system error log with the start of smb requests
|
||||
and responses (default 0)
|
||||
LookupCacheEnable If set to one, inode information is kept cached
|
||||
for one second improving performance of lookups
|
||||
(default 1)
|
||||
LinuxExtensionsEnabled If set to one then the client will attempt to
|
||||
use the CIFS "UNIX" extensions which are optional
|
||||
protocol enhancements that allow CIFS servers
|
||||
to return accurate UID/GID information as well
|
||||
as support symbolic links. If you use servers
|
||||
such as Samba that support the CIFS Unix
|
||||
extensions but do not want to use symbolic link
|
||||
support and want to map the uid and gid fields
|
||||
to values supplied at mount (rather than the
|
||||
actual values, then set this to zero. (default 1)
|
||||
dfscache List the content of the DFS cache.
|
||||
If set to 0, the client will clear the cache.
|
||||
======================= =======================================================
|
||||
|
||||
These experimental features and tracing can be enabled by changing flags in
|
||||
/proc/fs/cifs (after the cifs module has been installed or built into the
|
||||
kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
|
||||
tracing to the kernel message log type::
|
||||
|
||||
echo 7 > /proc/fs/cifs/cifsFYI
|
||||
|
||||
cifsFYI functions as a bit mask. Setting it to 1 enables additional kernel
|
||||
logging of various informational messages. 2 enables logging of non-zero
|
||||
SMB return codes while 4 enables logging of requests that take longer
|
||||
than one second to complete (except for byte range lock requests).
|
||||
Setting it to 4 requires CONFIG_CIFS_STATS2 to be set in kernel configuration
|
||||
(.config). Setting it to seven enables all three. Finally, tracing
|
||||
the start of smb requests and responses can be enabled via::
|
||||
|
||||
echo 1 > /proc/fs/cifs/traceSMB
|
||||
|
||||
Per share (per client mount) statistics are available in /proc/fs/cifs/Stats.
|
||||
Additional information is available if CONFIG_CIFS_STATS2 is enabled in the
|
||||
kernel configuration (.config). The statistics returned include counters which
|
||||
represent the number of attempted and failed (ie non-zero return code from the
|
||||
server) SMB3 (or cifs) requests grouped by request type (read, write, close etc.).
|
||||
Also recorded is the total bytes read and bytes written to the server for
|
||||
that share. Note that due to client caching effects this can be less than the
|
||||
number of bytes read and written by the application running on the client.
|
||||
Statistics can be reset to zero by ``echo 0 > /proc/fs/cifs/Stats`` which may be
|
||||
useful if comparing performance of two different scenarios.
|
||||
|
||||
Also note that ``cat /proc/fs/cifs/DebugData`` will display information about
|
||||
the active sessions and the shares that are mounted.
|
||||
|
||||
Enabling Kerberos (extended security) works but requires version 1.2 or later
|
||||
of the helper program cifs.upcall to be present and to be configured in the
|
||||
/etc/request-key.conf file. The cifs.upcall helper program is from the Samba
|
||||
project(https://www.samba.org). NTLM and NTLMv2 and LANMAN support do not
|
||||
require this helper. Note that NTLMv2 security (which does not require the
|
||||
cifs.upcall helper program), instead of using Kerberos, is sufficient for
|
||||
some use cases.
|
||||
|
||||
DFS support allows transparent redirection to shares in an MS-DFS name space.
|
||||
In addition, DFS support for target shares which are specified as UNC
|
||||
names which begin with host names (rather than IP addresses) requires
|
||||
a user space helper (such as cifs.upcall) to be present in order to
|
||||
translate host names to ip address, and the user space helper must also
|
||||
be configured in the file /etc/request-key.conf. Samba, Windows servers and
|
||||
many NAS appliances support DFS as a way of constructing a global name
|
||||
space to ease network configuration and improve reliability.
|
||||
|
||||
To use cifs Kerberos and DFS support, the Linux keyutils package should be
|
||||
installed and something like the following lines should be added to the
|
||||
/etc/request-key.conf file::
|
||||
|
||||
create cifs.spnego * * /usr/local/sbin/cifs.upcall %k
|
||||
create dns_resolver * * /usr/local/sbin/cifs.upcall %k
|
||||
|
||||
CIFS kernel module parameters
|
||||
=============================
|
||||
These module parameters can be specified or modified either during the time of
|
||||
module loading or during the runtime by using the interface::
|
||||
|
||||
/proc/module/cifs/parameters/<param>
|
||||
|
||||
i.e.::
|
||||
|
||||
echo "value" > /sys/module/cifs/parameters/<param>
|
||||
|
||||
================= ==========================================================
|
||||
1. enable_oplocks Enable or disable oplocks. Oplocks are enabled by default.
|
||||
[Y/y/1]. To disable use any of [N/n/0].
|
||||
================= ==========================================================
|
62
Documentation/admin-guide/cifs/winucase_convert.pl
Normal file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# winucase_convert.pl -- convert "Windows 8 Upper Case Mapping Table.txt" to
|
||||
# a two-level set of C arrays.
|
||||
#
|
||||
# Copyright 2013: Jeff Layton <jlayton@redhat.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
while(<>) {
|
||||
next if (!/^0x(..)(..)\t0x(....)\t/);
|
||||
$firstchar = hex($1);
|
||||
$secondchar = hex($2);
|
||||
$uppercase = hex($3);
|
||||
|
||||
$top[$firstchar][$secondchar] = $uppercase;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
next if (!$top[$i]);
|
||||
|
||||
printf("static const wchar_t t2_%2.2x[256] = {", $i);
|
||||
for ($j = 0; $j < 256; $j++) {
|
||||
if (($j % 8) == 0) {
|
||||
print "\n\t";
|
||||
} else {
|
||||
print " ";
|
||||
}
|
||||
printf("0x%4.4x,", $top[$i][$j] ? $top[$i][$j] : 0);
|
||||
}
|
||||
print "\n};\n\n";
|
||||
}
|
||||
|
||||
printf("static const wchar_t *const toplevel[256] = {", $i);
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
if (($i % 8) == 0) {
|
||||
print "\n\t";
|
||||
} elsif ($top[$i]) {
|
||||
print " ";
|
||||
} else {
|
||||
print " ";
|
||||
}
|
||||
|
||||
if ($top[$i]) {
|
||||
printf("t2_%2.2x,", $i);
|
||||
} else {
|
||||
print "NULL,";
|
||||
}
|
||||
}
|
||||
print "\n};\n\n";
|
131
Documentation/admin-guide/device-mapper/cache-policies.rst
Normal file
@ -0,0 +1,131 @@
|
||||
=============================
|
||||
Guidance for writing policies
|
||||
=============================
|
||||
|
||||
Try to keep transactionality out of it. The core is careful to
|
||||
avoid asking about anything that is migrating. This is a pain, but
|
||||
makes it easier to write the policies.
|
||||
|
||||
Mappings are loaded into the policy at construction time.
|
||||
|
||||
Every bio that is mapped by the target is referred to the policy.
|
||||
The policy can return a simple HIT or MISS or issue a migration.
|
||||
|
||||
Currently there's no way for the policy to issue background work,
|
||||
e.g. to start writing back dirty blocks that are going to be evicted
|
||||
soon.
|
||||
|
||||
Because we map bios, rather than requests it's easy for the policy
|
||||
to get fooled by many small bios. For this reason the core target
|
||||
issues periodic ticks to the policy. It's suggested that the policy
|
||||
doesn't update states (eg, hit counts) for a block more than once
|
||||
for each tick. The core ticks by watching bios complete, and so
|
||||
trying to see when the io scheduler has let the ios run.
|
||||
|
||||
|
||||
Overview of supplied cache replacement policies
|
||||
===============================================
|
||||
|
||||
multiqueue (mq)
|
||||
---------------
|
||||
|
||||
This policy is now an alias for smq (see below).
|
||||
|
||||
The following tunables are accepted, but have no effect::
|
||||
|
||||
'sequential_threshold <#nr_sequential_ios>'
|
||||
'random_threshold <#nr_random_ios>'
|
||||
'read_promote_adjustment <value>'
|
||||
'write_promote_adjustment <value>'
|
||||
'discard_promote_adjustment <value>'
|
||||
|
||||
Stochastic multiqueue (smq)
|
||||
---------------------------
|
||||
|
||||
This policy is the default.
|
||||
|
||||
The stochastic multi-queue (smq) policy addresses some of the problems
|
||||
with the multiqueue (mq) policy.
|
||||
|
||||
The smq policy (vs mq) offers the promise of less memory utilization,
|
||||
improved performance and increased adaptability in the face of changing
|
||||
workloads. smq also does not have any cumbersome tuning knobs.
|
||||
|
||||
Users may switch from "mq" to "smq" simply by appropriately reloading a
|
||||
DM table that is using the cache target. Doing so will cause all of the
|
||||
mq policy's hints to be dropped. Also, performance of the cache may
|
||||
degrade slightly until smq recalculates the origin device's hotspots
|
||||
that should be cached.
|
||||
|
||||
Memory usage
|
||||
^^^^^^^^^^^^
|
||||
|
||||
The mq policy used a lot of memory; 88 bytes per cache block on a 64
|
||||
bit machine.
|
||||
|
||||
smq uses 28bit indexes to implement its data structures rather than
|
||||
pointers. It avoids storing an explicit hit count for each block. It
|
||||
has a 'hotspot' queue, rather than a pre-cache, which uses a quarter of
|
||||
the entries (each hotspot block covers a larger area than a single
|
||||
cache block).
|
||||
|
||||
All this means smq uses ~25bytes per cache block. Still a lot of
|
||||
memory, but a substantial improvement nontheless.
|
||||
|
||||
Level balancing
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
mq placed entries in different levels of the multiqueue structures
|
||||
based on their hit count (~ln(hit count)). This meant the bottom
|
||||
levels generally had the most entries, and the top ones had very
|
||||
few. Having unbalanced levels like this reduced the efficacy of the
|
||||
multiqueue.
|
||||
|
||||
smq does not maintain a hit count, instead it swaps hit entries with
|
||||
the least recently used entry from the level above. The overall
|
||||
ordering being a side effect of this stochastic process. With this
|
||||
scheme we can decide how many entries occupy each multiqueue level,
|
||||
resulting in better promotion/demotion decisions.
|
||||
|
||||
Adaptability:
|
||||
The mq policy maintained a hit count for each cache block. For a
|
||||
different block to get promoted to the cache its hit count has to
|
||||
exceed the lowest currently in the cache. This meant it could take a
|
||||
long time for the cache to adapt between varying IO patterns.
|
||||
|
||||
smq doesn't maintain hit counts, so a lot of this problem just goes
|
||||
away. In addition it tracks performance of the hotspot queue, which
|
||||
is used to decide which blocks to promote. If the hotspot queue is
|
||||
performing badly then it starts moving entries more quickly between
|
||||
levels. This lets it adapt to new IO patterns very quickly.
|
||||
|
||||
Performance
|
||||
^^^^^^^^^^^
|
||||
|
||||
Testing smq shows substantially better performance than mq.
|
||||
|
||||
cleaner
|
||||
-------
|
||||
|
||||
The cleaner writes back all dirty blocks in a cache to decommission it.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
The syntax for a table is::
|
||||
|
||||
cache <metadata dev> <cache dev> <origin dev> <block size>
|
||||
<#feature_args> [<feature arg>]*
|
||||
<policy> <#policy_args> [<policy arg>]*
|
||||
|
||||
The syntax to send a message using the dmsetup command is::
|
||||
|
||||
dmsetup message <mapped device> 0 sequential_threshold 1024
|
||||
dmsetup message <mapped device> 0 random_threshold 8
|
||||
|
||||
Using dmsetup::
|
||||
|
||||
dmsetup create blah --table "0 268435456 cache /dev/sdb /dev/sdc \
|
||||
/dev/sdd 512 0 mq 4 sequential_threshold 1024 random_threshold 8"
|
||||
creates a 128GB large mapped device named 'blah' with the
|
||||
sequential threshold set to 1024 and the random_threshold set to 8.
|
337
Documentation/admin-guide/device-mapper/cache.rst
Normal file
@ -0,0 +1,337 @@
|
||||
=====
|
||||
Cache
|
||||
=====
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
dm-cache is a device mapper target written by Joe Thornber, Heinz
|
||||
Mauelshagen, and Mike Snitzer.
|
||||
|
||||
It aims to improve performance of a block device (eg, a spindle) by
|
||||
dynamically migrating some of its data to a faster, smaller device
|
||||
(eg, an SSD).
|
||||
|
||||
This device-mapper solution allows us to insert this caching at
|
||||
different levels of the dm stack, for instance above the data device for
|
||||
a thin-provisioning pool. Caching solutions that are integrated more
|
||||
closely with the virtual memory system should give better performance.
|
||||
|
||||
The target reuses the metadata library used in the thin-provisioning
|
||||
library.
|
||||
|
||||
The decision as to what data to migrate and when is left to a plug-in
|
||||
policy module. Several of these have been written as we experiment,
|
||||
and we hope other people will contribute others for specific io
|
||||
scenarios (eg. a vm image server).
|
||||
|
||||
Glossary
|
||||
========
|
||||
|
||||
Migration
|
||||
Movement of the primary copy of a logical block from one
|
||||
device to the other.
|
||||
Promotion
|
||||
Migration from slow device to fast device.
|
||||
Demotion
|
||||
Migration from fast device to slow device.
|
||||
|
||||
The origin device always contains a copy of the logical block, which
|
||||
may be out of date or kept in sync with the copy on the cache device
|
||||
(depending on policy).
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
Sub-devices
|
||||
-----------
|
||||
|
||||
The target is constructed by passing three devices to it (along with
|
||||
other parameters detailed later):
|
||||
|
||||
1. An origin device - the big, slow one.
|
||||
|
||||
2. A cache device - the small, fast one.
|
||||
|
||||
3. A small metadata device - records which blocks are in the cache,
|
||||
which are dirty, and extra hints for use by the policy object.
|
||||
This information could be put on the cache device, but having it
|
||||
separate allows the volume manager to configure it differently,
|
||||
e.g. as a mirror for extra robustness. This metadata device may only
|
||||
be used by a single cache device.
|
||||
|
||||
Fixed block size
|
||||
----------------
|
||||
|
||||
The origin is divided up into blocks of a fixed size. This block size
|
||||
is configurable when you first create the cache. Typically we've been
|
||||
using block sizes of 256KB - 1024KB. The block size must be between 64
|
||||
sectors (32KB) and 2097152 sectors (1GB) and a multiple of 64 sectors (32KB).
|
||||
|
||||
Having a fixed block size simplifies the target a lot. But it is
|
||||
something of a compromise. For instance, a small part of a block may be
|
||||
getting hit a lot, yet the whole block will be promoted to the cache.
|
||||
So large block sizes are bad because they waste cache space. And small
|
||||
block sizes are bad because they increase the amount of metadata (both
|
||||
in core and on disk).
|
||||
|
||||
Cache operating modes
|
||||
---------------------
|
||||
|
||||
The cache has three operating modes: writeback, writethrough and
|
||||
passthrough.
|
||||
|
||||
If writeback, the default, is selected then a write to a block that is
|
||||
cached will go only to the cache and the block will be marked dirty in
|
||||
the metadata.
|
||||
|
||||
If writethrough is selected then a write to a cached block will not
|
||||
complete until it has hit both the origin and cache devices. Clean
|
||||
blocks should remain clean.
|
||||
|
||||
If passthrough is selected, useful when the cache contents are not known
|
||||
to be coherent with the origin device, then all reads are served from
|
||||
the origin device (all reads miss the cache) and all writes are
|
||||
forwarded to the origin device; additionally, write hits cause cache
|
||||
block invalidates. To enable passthrough mode the cache must be clean.
|
||||
Passthrough mode allows a cache device to be activated without having to
|
||||
worry about coherency. Coherency that exists is maintained, although
|
||||
the cache will gradually cool as writes take place. If the coherency of
|
||||
the cache can later be verified, or established through use of the
|
||||
"invalidate_cblocks" message, the cache device can be transitioned to
|
||||
writethrough or writeback mode while still warm. Otherwise, the cache
|
||||
contents can be discarded prior to transitioning to the desired
|
||||
operating mode.
|
||||
|
||||
A simple cleaner policy is provided, which will clean (write back) all
|
||||
dirty blocks in a cache. Useful for decommissioning a cache or when
|
||||
shrinking a cache. Shrinking the cache's fast device requires all cache
|
||||
blocks, in the area of the cache being removed, to be clean. If the
|
||||
area being removed from the cache still contains dirty blocks the resize
|
||||
will fail. Care must be taken to never reduce the volume used for the
|
||||
cache's fast device until the cache is clean. This is of particular
|
||||
importance if writeback mode is used. Writethrough and passthrough
|
||||
modes already maintain a clean cache. Future support to partially clean
|
||||
the cache, above a specified threshold, will allow for keeping the cache
|
||||
warm and in writeback mode during resize.
|
||||
|
||||
Migration throttling
|
||||
--------------------
|
||||
|
||||
Migrating data between the origin and cache device uses bandwidth.
|
||||
The user can set a throttle to prevent more than a certain amount of
|
||||
migration occurring at any one time. Currently we're not taking any
|
||||
account of normal io traffic going to the devices. More work needs
|
||||
doing here to avoid migrating during those peak io moments.
|
||||
|
||||
For the time being, a message "migration_threshold <#sectors>"
|
||||
can be used to set the maximum number of sectors being migrated,
|
||||
the default being 2048 sectors (1MB).
|
||||
|
||||
Updating on-disk metadata
|
||||
-------------------------
|
||||
|
||||
On-disk metadata is committed every time a FLUSH or FUA bio is written.
|
||||
If no such requests are made then commits will occur every second. This
|
||||
means the cache behaves like a physical disk that has a volatile write
|
||||
cache. If power is lost you may lose some recent writes. The metadata
|
||||
should always be consistent in spite of any crash.
|
||||
|
||||
The 'dirty' state for a cache block changes far too frequently for us
|
||||
to keep updating it on the fly. So we treat it as a hint. In normal
|
||||
operation it will be written when the dm device is suspended. If the
|
||||
system crashes all cache blocks will be assumed dirty when restarted.
|
||||
|
||||
Per-block policy hints
|
||||
----------------------
|
||||
|
||||
Policy plug-ins can store a chunk of data per cache block. It's up to
|
||||
the policy how big this chunk is, but it should be kept small. Like the
|
||||
dirty flags this data is lost if there's a crash so a safe fallback
|
||||
value should always be possible.
|
||||
|
||||
Policy hints affect performance, not correctness.
|
||||
|
||||
Policy messaging
|
||||
----------------
|
||||
|
||||
Policies will have different tunables, specific to each one, so we
|
||||
need a generic way of getting and setting these. Device-mapper
|
||||
messages are used. Refer to cache-policies.txt.
|
||||
|
||||
Discard bitset resolution
|
||||
-------------------------
|
||||
|
||||
We can avoid copying data during migration if we know the block has
|
||||
been discarded. A prime example of this is when mkfs discards the
|
||||
whole block device. We store a bitset tracking the discard state of
|
||||
blocks. However, we allow this bitset to have a different block size
|
||||
from the cache blocks. This is because we need to track the discard
|
||||
state for all of the origin device (compare with the dirty bitset
|
||||
which is just for the smaller cache device).
|
||||
|
||||
Target interface
|
||||
================
|
||||
|
||||
Constructor
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
cache <metadata dev> <cache dev> <origin dev> <block size>
|
||||
<#feature args> [<feature arg>]*
|
||||
<policy> <#policy args> [policy args]*
|
||||
|
||||
================ =======================================================
|
||||
metadata dev fast device holding the persistent metadata
|
||||
cache dev fast device holding cached data blocks
|
||||
origin dev slow device holding original data blocks
|
||||
block size cache unit size in sectors
|
||||
|
||||
#feature args number of feature arguments passed
|
||||
feature args writethrough or passthrough (The default is writeback.)
|
||||
|
||||
policy the replacement policy to use
|
||||
#policy args an even number of arguments corresponding to
|
||||
key/value pairs passed to the policy
|
||||
policy args key/value pairs passed to the policy
|
||||
E.g. 'sequential_threshold 1024'
|
||||
See cache-policies.txt for details.
|
||||
================ =======================================================
|
||||
|
||||
Optional feature arguments are:
|
||||
|
||||
|
||||
==================== ========================================================
|
||||
writethrough write through caching that prohibits cache block
|
||||
content from being different from origin block content.
|
||||
Without this argument, the default behaviour is to write
|
||||
back cache block contents later for performance reasons,
|
||||
so they may differ from the corresponding origin blocks.
|
||||
|
||||
passthrough a degraded mode useful for various cache coherency
|
||||
situations (e.g., rolling back snapshots of
|
||||
underlying storage). Reads and writes always go to
|
||||
the origin. If a write goes to a cached origin
|
||||
block, then the cache block is invalidated.
|
||||
To enable passthrough mode the cache must be clean.
|
||||
|
||||
metadata2 use version 2 of the metadata. This stores the dirty
|
||||
bits in a separate btree, which improves speed of
|
||||
shutting down the cache.
|
||||
|
||||
no_discard_passdown disable passing down discards from the cache
|
||||
to the origin's data device.
|
||||
==================== ========================================================
|
||||
|
||||
A policy called 'default' is always registered. This is an alias for
|
||||
the policy we currently think is giving best all round performance.
|
||||
|
||||
As the default policy could vary between kernels, if you are relying on
|
||||
the characteristics of a specific policy, always request it by name.
|
||||
|
||||
Status
|
||||
------
|
||||
|
||||
::
|
||||
|
||||
<metadata block size> <#used metadata blocks>/<#total metadata blocks>
|
||||
<cache block size> <#used cache blocks>/<#total cache blocks>
|
||||
<#read hits> <#read misses> <#write hits> <#write misses>
|
||||
<#demotions> <#promotions> <#dirty> <#features> <features>*
|
||||
<#core args> <core args>* <policy name> <#policy args> <policy args>*
|
||||
<cache metadata mode>
|
||||
|
||||
|
||||
========================= =====================================================
|
||||
metadata block size Fixed block size for each metadata block in
|
||||
sectors
|
||||
#used metadata blocks Number of metadata blocks used
|
||||
#total metadata blocks Total number of metadata blocks
|
||||
cache block size Configurable block size for the cache device
|
||||
in sectors
|
||||
#used cache blocks Number of blocks resident in the cache
|
||||
#total cache blocks Total number of cache blocks
|
||||
#read hits Number of times a READ bio has been mapped
|
||||
to the cache
|
||||
#read misses Number of times a READ bio has been mapped
|
||||
to the origin
|
||||
#write hits Number of times a WRITE bio has been mapped
|
||||
to the cache
|
||||
#write misses Number of times a WRITE bio has been
|
||||
mapped to the origin
|
||||
#demotions Number of times a block has been removed
|
||||
from the cache
|
||||
#promotions Number of times a block has been moved to
|
||||
the cache
|
||||
#dirty Number of blocks in the cache that differ
|
||||
from the origin
|
||||
#feature args Number of feature args to follow
|
||||
feature args 'writethrough' (optional)
|
||||
#core args Number of core arguments (must be even)
|
||||
core args Key/value pairs for tuning the core
|
||||
e.g. migration_threshold
|
||||
policy name Name of the policy
|
||||
#policy args Number of policy arguments to follow (must be even)
|
||||
policy args Key/value pairs e.g. sequential_threshold
|
||||
cache metadata mode ro if read-only, rw if read-write
|
||||
|
||||
In serious cases where even a read-only mode is
|
||||
deemed unsafe no further I/O will be permitted and
|
||||
the status will just contain the string 'Fail'.
|
||||
The userspace recovery tools should then be used.
|
||||
needs_check 'needs_check' if set, '-' if not set
|
||||
A metadata operation has failed, resulting in the
|
||||
needs_check flag being set in the metadata's
|
||||
superblock. The metadata device must be
|
||||
deactivated and checked/repaired before the
|
||||
cache can be made fully operational again.
|
||||
'-' indicates needs_check is not set.
|
||||
========================= =====================================================
|
||||
|
||||
Messages
|
||||
--------
|
||||
|
||||
Policies will have different tunables, specific to each one, so we
|
||||
need a generic way of getting and setting these. Device-mapper
|
||||
messages are used. (A sysfs interface would also be possible.)
|
||||
|
||||
The message format is::
|
||||
|
||||
<key> <value>
|
||||
|
||||
E.g.::
|
||||
|
||||
dmsetup message my_cache 0 sequential_threshold 1024
|
||||
|
||||
|
||||
Invalidation is removing an entry from the cache without writing it
|
||||
back. Cache blocks can be invalidated via the invalidate_cblocks
|
||||
message, which takes an arbitrary number of cblock ranges. Each cblock
|
||||
range's end value is "one past the end", meaning 5-10 expresses a range
|
||||
of values from 5 to 9. Each cblock must be expressed as a decimal
|
||||
value, in the future a variant message that takes cblock ranges
|
||||
expressed in hexadecimal may be needed to better support efficient
|
||||
invalidation of larger caches. The cache must be in passthrough mode
|
||||
when invalidate_cblocks is used::
|
||||
|
||||
invalidate_cblocks [<cblock>|<cblock begin>-<cblock end>]*
|
||||
|
||||
E.g.::
|
||||
|
||||
dmsetup message my_cache 0 invalidate_cblocks 2345 3456-4567 5678-6789
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
The test suite can be found here:
|
||||
|
||||
https://github.com/jthornber/device-mapper-test-suite
|
||||
|
||||
::
|
||||
|
||||
dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
|
||||
/dev/mapper/ssd /dev/mapper/origin 512 1 writeback default 0'
|
||||
dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
|
||||
/dev/mapper/ssd /dev/mapper/origin 1024 1 writeback \
|
||||
mq 4 sequential_threshold 1024 random_threshold 8'
|
31
Documentation/admin-guide/device-mapper/delay.rst
Normal file
@ -0,0 +1,31 @@
|
||||
========
|
||||
dm-delay
|
||||
========
|
||||
|
||||
Device-Mapper's "delay" target delays reads and/or writes
|
||||
and maps them to different devices.
|
||||
|
||||
Parameters::
|
||||
|
||||
<device> <offset> <delay> [<write_device> <write_offset> <write_delay>
|
||||
[<flush_device> <flush_offset> <flush_delay>]]
|
||||
|
||||
With separate write parameters, the first set is only used for reads.
|
||||
Offsets are specified in sectors.
|
||||
Delays are specified in milliseconds.
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
|
||||
::
|
||||
|
||||
#!/bin/sh
|
||||
# Create device delaying rw operation for 500ms
|
||||
echo "0 `blockdev --getsz $1` delay $1 0 500" | dmsetup create delayed
|
||||
|
||||
::
|
||||
|
||||
#!/bin/sh
|
||||
# Create device delaying only write operation for 500ms and
|
||||
# splitting reads and writes to different devices $1 $2
|
||||
echo "0 `blockdev --getsz $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
|
333
Documentation/admin-guide/device-mapper/dm-clone.rst
Normal file
@ -0,0 +1,333 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
========
|
||||
dm-clone
|
||||
========
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
dm-clone is a device mapper target which produces a one-to-one copy of an
|
||||
existing, read-only source device into a writable destination device: It
|
||||
presents a virtual block device which makes all data appear immediately, and
|
||||
redirects reads and writes accordingly.
|
||||
|
||||
The main use case of dm-clone is to clone a potentially remote, high-latency,
|
||||
read-only, archival-type block device into a writable, fast, primary-type device
|
||||
for fast, low-latency I/O. The cloned device is visible/mountable immediately
|
||||
and the copy of the source device to the destination device happens in the
|
||||
background, in parallel with user I/O.
|
||||
|
||||
For example, one could restore an application backup from a read-only copy,
|
||||
accessible through a network storage protocol (NBD, Fibre Channel, iSCSI, AoE,
|
||||
etc.), into a local SSD or NVMe device, and start using the device immediately,
|
||||
without waiting for the restore to complete.
|
||||
|
||||
When the cloning completes, the dm-clone table can be removed altogether and be
|
||||
replaced, e.g., by a linear table, mapping directly to the destination device.
|
||||
|
||||
The dm-clone target reuses the metadata library used by the thin-provisioning
|
||||
target.
|
||||
|
||||
Glossary
|
||||
========
|
||||
|
||||
Hydration
|
||||
The process of filling a region of the destination device with data from
|
||||
the same region of the source device, i.e., copying the region from the
|
||||
source to the destination device.
|
||||
|
||||
Once a region gets hydrated we redirect all I/O regarding it to the destination
|
||||
device.
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
Sub-devices
|
||||
-----------
|
||||
|
||||
The target is constructed by passing three devices to it (along with other
|
||||
parameters detailed later):
|
||||
|
||||
1. A source device - the read-only device that gets cloned and source of the
|
||||
hydration.
|
||||
|
||||
2. A destination device - the destination of the hydration, which will become a
|
||||
clone of the source device.
|
||||
|
||||
3. A small metadata device - it records which regions are already valid in the
|
||||
destination device, i.e., which regions have already been hydrated, or have
|
||||
been written to directly, via user I/O.
|
||||
|
||||
The size of the destination device must be at least equal to the size of the
|
||||
source device.
|
||||
|
||||
Regions
|
||||
-------
|
||||
|
||||
dm-clone divides the source and destination devices in fixed sized regions.
|
||||
Regions are the unit of hydration, i.e., the minimum amount of data copied from
|
||||
the source to the destination device.
|
||||
|
||||
The region size is configurable when you first create the dm-clone device. The
|
||||
recommended region size is the same as the file system block size, which usually
|
||||
is 4KB. The region size must be between 8 sectors (4KB) and 2097152 sectors
|
||||
(1GB) and a power of two.
|
||||
|
||||
Reads and writes from/to hydrated regions are serviced from the destination
|
||||
device.
|
||||
|
||||
A read to a not yet hydrated region is serviced directly from the source device.
|
||||
|
||||
A write to a not yet hydrated region will be delayed until the corresponding
|
||||
region has been hydrated and the hydration of the region starts immediately.
|
||||
|
||||
Note that a write request with size equal to region size will skip copying of
|
||||
the corresponding region from the source device and overwrite the region of the
|
||||
destination device directly.
|
||||
|
||||
Discards
|
||||
--------
|
||||
|
||||
dm-clone interprets a discard request to a range that hasn't been hydrated yet
|
||||
as a hint to skip hydration of the regions covered by the request, i.e., it
|
||||
skips copying the region's data from the source to the destination device, and
|
||||
only updates its metadata.
|
||||
|
||||
If the destination device supports discards, then by default dm-clone will pass
|
||||
down discard requests to it.
|
||||
|
||||
Background Hydration
|
||||
--------------------
|
||||
|
||||
dm-clone copies continuously from the source to the destination device, until
|
||||
all of the device has been copied.
|
||||
|
||||
Copying data from the source to the destination device uses bandwidth. The user
|
||||
can set a throttle to prevent more than a certain amount of copying occurring at
|
||||
any one time. Moreover, dm-clone takes into account user I/O traffic going to
|
||||
the devices and pauses the background hydration when there is I/O in-flight.
|
||||
|
||||
A message `hydration_threshold <#regions>` can be used to set the maximum number
|
||||
of regions being copied, the default being 1 region.
|
||||
|
||||
dm-clone employs dm-kcopyd for copying portions of the source device to the
|
||||
destination device. By default, we issue copy requests of size equal to the
|
||||
region size. A message `hydration_batch_size <#regions>` can be used to tune the
|
||||
size of these copy requests. Increasing the hydration batch size results in
|
||||
dm-clone trying to batch together contiguous regions, so we copy the data in
|
||||
batches of this many regions.
|
||||
|
||||
When the hydration of the destination device finishes, a dm event will be sent
|
||||
to user space.
|
||||
|
||||
Updating on-disk metadata
|
||||
-------------------------
|
||||
|
||||
On-disk metadata is committed every time a FLUSH or FUA bio is written. If no
|
||||
such requests are made then commits will occur every second. This means the
|
||||
dm-clone device behaves like a physical disk that has a volatile write cache. If
|
||||
power is lost you may lose some recent writes. The metadata should always be
|
||||
consistent in spite of any crash.
|
||||
|
||||
Target Interface
|
||||
================
|
||||
|
||||
Constructor
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
clone <metadata dev> <destination dev> <source dev> <region size>
|
||||
[<#feature args> [<feature arg>]* [<#core args> [<core arg>]*]]
|
||||
|
||||
================ ==============================================================
|
||||
metadata dev Fast device holding the persistent metadata
|
||||
destination dev The destination device, where the source will be cloned
|
||||
source dev Read only device containing the data that gets cloned
|
||||
region size The size of a region in sectors
|
||||
|
||||
#feature args Number of feature arguments passed
|
||||
feature args no_hydration or no_discard_passdown
|
||||
|
||||
#core args An even number of arguments corresponding to key/value pairs
|
||||
passed to dm-clone
|
||||
core args Key/value pairs passed to dm-clone, e.g. `hydration_threshold
|
||||
256`
|
||||
================ ==============================================================
|
||||
|
||||
Optional feature arguments are:
|
||||
|
||||
==================== =========================================================
|
||||
no_hydration Create a dm-clone instance with background hydration
|
||||
disabled
|
||||
no_discard_passdown Disable passing down discards to the destination device
|
||||
==================== =========================================================
|
||||
|
||||
Optional core arguments are:
|
||||
|
||||
================================ ==============================================
|
||||
hydration_threshold <#regions> Maximum number of regions being copied from
|
||||
the source to the destination device at any
|
||||
one time, during background hydration.
|
||||
hydration_batch_size <#regions> During background hydration, try to batch
|
||||
together contiguous regions, so we copy data
|
||||
from the source to the destination device in
|
||||
batches of this many regions.
|
||||
================================ ==============================================
|
||||
|
||||
Status
|
||||
------
|
||||
|
||||
::
|
||||
|
||||
<metadata block size> <#used metadata blocks>/<#total metadata blocks>
|
||||
<region size> <#hydrated regions>/<#total regions> <#hydrating regions>
|
||||
<#feature args> <feature args>* <#core args> <core args>*
|
||||
<clone metadata mode>
|
||||
|
||||
======================= =======================================================
|
||||
metadata block size Fixed block size for each metadata block in sectors
|
||||
#used metadata blocks Number of metadata blocks used
|
||||
#total metadata blocks Total number of metadata blocks
|
||||
region size Configurable region size for the device in sectors
|
||||
#hydrated regions Number of regions that have finished hydrating
|
||||
#total regions Total number of regions to hydrate
|
||||
#hydrating regions Number of regions currently hydrating
|
||||
#feature args Number of feature arguments to follow
|
||||
feature args Feature arguments, e.g. `no_hydration`
|
||||
#core args Even number of core arguments to follow
|
||||
core args Key/value pairs for tuning the core, e.g.
|
||||
`hydration_threshold 256`
|
||||
clone metadata mode ro if read-only, rw if read-write
|
||||
|
||||
In serious cases where even a read-only mode is deemed
|
||||
unsafe no further I/O will be permitted and the status
|
||||
will just contain the string 'Fail'. If the metadata
|
||||
mode changes, a dm event will be sent to user space.
|
||||
======================= =======================================================
|
||||
|
||||
Messages
|
||||
--------
|
||||
|
||||
`disable_hydration`
|
||||
Disable the background hydration of the destination device.
|
||||
|
||||
`enable_hydration`
|
||||
Enable the background hydration of the destination device.
|
||||
|
||||
`hydration_threshold <#regions>`
|
||||
Set background hydration threshold.
|
||||
|
||||
`hydration_batch_size <#regions>`
|
||||
Set background hydration batch size.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Clone a device containing a file system
|
||||
---------------------------------------
|
||||
|
||||
1. Create the dm-clone device.
|
||||
|
||||
::
|
||||
|
||||
dmsetup create clone --table "0 1048576000 clone $metadata_dev $dest_dev \
|
||||
$source_dev 8 1 no_hydration"
|
||||
|
||||
2. Mount the device and trim the file system. dm-clone interprets the discards
|
||||
sent by the file system and it will not hydrate the unused space.
|
||||
|
||||
::
|
||||
|
||||
mount /dev/mapper/clone /mnt/cloned-fs
|
||||
fstrim /mnt/cloned-fs
|
||||
|
||||
3. Enable background hydration of the destination device.
|
||||
|
||||
::
|
||||
|
||||
dmsetup message clone 0 enable_hydration
|
||||
|
||||
4. When the hydration finishes, we can replace the dm-clone table with a linear
|
||||
table.
|
||||
|
||||
::
|
||||
|
||||
dmsetup suspend clone
|
||||
dmsetup load clone --table "0 1048576000 linear $dest_dev 0"
|
||||
dmsetup resume clone
|
||||
|
||||
The metadata device is no longer needed and can be safely discarded or reused
|
||||
for other purposes.
|
||||
|
||||
Known issues
|
||||
============
|
||||
|
||||
1. We redirect reads, to not-yet-hydrated regions, to the source device. If
|
||||
reading the source device has high latency and the user repeatedly reads from
|
||||
the same regions, this behaviour could degrade performance. We should use
|
||||
these reads as hints to hydrate the relevant regions sooner. Currently, we
|
||||
rely on the page cache to cache these regions, so we hopefully don't end up
|
||||
reading them multiple times from the source device.
|
||||
|
||||
2. Release in-core resources, i.e., the bitmaps tracking which regions are
|
||||
hydrated, after the hydration has finished.
|
||||
|
||||
3. During background hydration, if we fail to read the source or write to the
|
||||
destination device, we print an error message, but the hydration process
|
||||
continues indefinitely, until it succeeds. We should stop the background
|
||||
hydration after a number of failures and emit a dm event for user space to
|
||||
notice.
|
||||
|
||||
Why not...?
|
||||
===========
|
||||
|
||||
We explored the following alternatives before implementing dm-clone:
|
||||
|
||||
1. Use dm-cache with cache size equal to the source device and implement a new
|
||||
cloning policy:
|
||||
|
||||
* The resulting cache device is not a one-to-one mirror of the source device
|
||||
and thus we cannot remove the cache device once cloning completes.
|
||||
|
||||
* dm-cache writes to the source device, which violates our requirement that
|
||||
the source device must be treated as read-only.
|
||||
|
||||
* Caching is semantically different from cloning.
|
||||
|
||||
2. Use dm-snapshot with a COW device equal to the source device:
|
||||
|
||||
* dm-snapshot stores its metadata in the COW device, so the resulting device
|
||||
is not a one-to-one mirror of the source device.
|
||||
|
||||
* No background copying mechanism.
|
||||
|
||||
* dm-snapshot needs to commit its metadata whenever a pending exception
|
||||
completes, to ensure snapshot consistency. In the case of cloning, we don't
|
||||
need to be so strict and can rely on committing metadata every time a FLUSH
|
||||
or FUA bio is written, or periodically, like dm-thin and dm-cache do. This
|
||||
improves the performance significantly.
|
||||
|
||||
3. Use dm-mirror: The mirror target has a background copying/mirroring
|
||||
mechanism, but it writes to all mirrors, thus violating our requirement that
|
||||
the source device must be treated as read-only.
|
||||
|
||||
4. Use dm-thin's external snapshot functionality. This approach is the most
|
||||
promising among all alternatives, as the thinly-provisioned volume is a
|
||||
one-to-one mirror of the source device and handles reads and writes to
|
||||
un-provisioned/not-yet-cloned areas the same way as dm-clone does.
|
||||
|
||||
Still:
|
||||
|
||||
* There is no background copying mechanism, though one could be implemented.
|
||||
|
||||
* Most importantly, we want to support arbitrary block devices as the
|
||||
destination of the cloning process and not restrict ourselves to
|
||||
thinly-provisioned volumes. Thin-provisioning has an inherent metadata
|
||||
overhead, for maintaining the thin volume mappings, which significantly
|
||||
degrades performance.
|
||||
|
||||
Moreover, cloning a device shouldn't force the use of thin-provisioning. On
|
||||
the other hand, if we wish to use thin provisioning, we can just use a thin
|
||||
LV as dm-clone's destination device.
|
181
Documentation/admin-guide/device-mapper/dm-crypt.rst
Normal file
@ -0,0 +1,181 @@
|
||||
========
|
||||
dm-crypt
|
||||
========
|
||||
|
||||
Device-Mapper's "crypt" target provides transparent encryption of block devices
|
||||
using the kernel crypto API.
|
||||
|
||||
For a more detailed description of supported parameters see:
|
||||
https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
|
||||
|
||||
Parameters::
|
||||
|
||||
<cipher> <key> <iv_offset> <device path> \
|
||||
<offset> [<#opt_params> <opt_params>]
|
||||
|
||||
<cipher>
|
||||
Encryption cipher, encryption mode and Initial Vector (IV) generator.
|
||||
|
||||
The cipher specifications format is::
|
||||
|
||||
cipher[:keycount]-chainmode-ivmode[:ivopts]
|
||||
|
||||
Examples::
|
||||
|
||||
aes-cbc-essiv:sha256
|
||||
aes-xts-plain64
|
||||
serpent-xts-plain64
|
||||
|
||||
Cipher format also supports direct specification with kernel crypt API
|
||||
format (selected by capi: prefix). The IV specification is the same
|
||||
as for the first format type.
|
||||
This format is mainly used for specification of authenticated modes.
|
||||
|
||||
The crypto API cipher specifications format is::
|
||||
|
||||
capi:cipher_api_spec-ivmode[:ivopts]
|
||||
|
||||
Examples::
|
||||
|
||||
capi:cbc(aes)-essiv:sha256
|
||||
capi:xts(aes)-plain64
|
||||
|
||||
Examples of authenticated modes::
|
||||
|
||||
capi:gcm(aes)-random
|
||||
capi:authenc(hmac(sha256),xts(aes))-random
|
||||
capi:rfc7539(chacha20,poly1305)-random
|
||||
|
||||
The /proc/crypto contains a list of currently loaded crypto modes.
|
||||
|
||||
<key>
|
||||
Key used for encryption. It is encoded either as a hexadecimal number
|
||||
or it can be passed as <key_string> prefixed with single colon
|
||||
character (':') for keys residing in kernel keyring service.
|
||||
You can only use key sizes that are valid for the selected cipher
|
||||
in combination with the selected iv mode.
|
||||
Note that for some iv modes the key string can contain additional
|
||||
keys (for example IV seed) so the key contains more parts concatenated
|
||||
into a single string.
|
||||
|
||||
<key_string>
|
||||
The kernel keyring key is identified by string in following format:
|
||||
<key_size>:<key_type>:<key_description>.
|
||||
|
||||
<key_size>
|
||||
The encryption key size in bytes. The kernel key payload size must match
|
||||
the value passed in <key_size>.
|
||||
|
||||
<key_type>
|
||||
Either 'logon', 'user', 'encrypted' or 'trusted' kernel key type.
|
||||
|
||||
<key_description>
|
||||
The kernel keyring key description crypt target should look for
|
||||
when loading key of <key_type>.
|
||||
|
||||
<keycount>
|
||||
Multi-key compatibility mode. You can define <keycount> keys and
|
||||
then sectors are encrypted according to their offsets (sector 0 uses key0;
|
||||
sector 1 uses key1 etc.). <keycount> must be a power of two.
|
||||
|
||||
<iv_offset>
|
||||
The IV offset is a sector count that is added to the sector number
|
||||
before creating the IV.
|
||||
|
||||
<device path>
|
||||
This is the device that is going to be used as backend and contains the
|
||||
encrypted data. You can specify it as a path like /dev/xxx or a device
|
||||
number <major>:<minor>.
|
||||
|
||||
<offset>
|
||||
Starting sector within the device where the encrypted data begins.
|
||||
|
||||
<#opt_params>
|
||||
Number of optional parameters. If there are no optional parameters,
|
||||
the optional parameters section can be skipped or #opt_params can be zero.
|
||||
Otherwise #opt_params is the number of following arguments.
|
||||
|
||||
Example of optional parameters section:
|
||||
3 allow_discards same_cpu_crypt submit_from_crypt_cpus
|
||||
|
||||
allow_discards
|
||||
Block discard requests (a.k.a. TRIM) are passed through the crypt device.
|
||||
The default is to ignore discard requests.
|
||||
|
||||
WARNING: Assess the specific security risks carefully before enabling this
|
||||
option. For example, allowing discards on encrypted devices may lead to
|
||||
the leak of information about the ciphertext device (filesystem type,
|
||||
used space etc.) if the discarded blocks can be located easily on the
|
||||
device later.
|
||||
|
||||
same_cpu_crypt
|
||||
Perform encryption using the same cpu that IO was submitted on.
|
||||
The default is to use an unbound workqueue so that encryption work
|
||||
is automatically balanced between available CPUs.
|
||||
|
||||
submit_from_crypt_cpus
|
||||
Disable offloading writes to a separate thread after encryption.
|
||||
There are some situations where offloading write bios from the
|
||||
encryption threads to a single thread degrades performance
|
||||
significantly. The default is to offload write bios to the same
|
||||
thread because it benefits CFQ to have writes submitted using the
|
||||
same context.
|
||||
|
||||
no_read_workqueue
|
||||
Bypass dm-crypt internal workqueue and process read requests synchronously.
|
||||
|
||||
no_write_workqueue
|
||||
Bypass dm-crypt internal workqueue and process write requests synchronously.
|
||||
This option is automatically enabled for host-managed zoned block devices
|
||||
(e.g. host-managed SMR hard-disks).
|
||||
|
||||
integrity:<bytes>:<type>
|
||||
The device requires additional <bytes> metadata per-sector stored
|
||||
in per-bio integrity structure. This metadata must by provided
|
||||
by underlying dm-integrity target.
|
||||
|
||||
The <type> can be "none" if metadata is used only for persistent IV.
|
||||
|
||||
For Authenticated Encryption with Additional Data (AEAD)
|
||||
the <type> is "aead". An AEAD mode additionally calculates and verifies
|
||||
integrity for the encrypted device. The additional space is then
|
||||
used for storing authentication tag (and persistent IV if needed).
|
||||
|
||||
sector_size:<bytes>
|
||||
Use <bytes> as the encryption unit instead of 512 bytes sectors.
|
||||
This option can be in range 512 - 4096 bytes and must be power of two.
|
||||
Virtual device will announce this size as a minimal IO and logical sector.
|
||||
|
||||
iv_large_sectors
|
||||
IV generators will use sector number counted in <sector_size> units
|
||||
instead of default 512 bytes sectors.
|
||||
|
||||
For example, if <sector_size> is 4096 bytes, plain64 IV for the second
|
||||
sector will be 8 (without flag) and 1 if iv_large_sectors is present.
|
||||
The <iv_offset> must be multiple of <sector_size> (in 512 bytes units)
|
||||
if this flag is specified.
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
|
||||
encryption with dm-crypt using the 'cryptsetup' utility, see
|
||||
https://gitlab.com/cryptsetup/cryptsetup
|
||||
|
||||
::
|
||||
|
||||
#!/bin/sh
|
||||
# Create a crypt device using dmsetup
|
||||
dmsetup create crypt1 --table "0 `blockdev --getsz $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
|
||||
|
||||
::
|
||||
|
||||
#!/bin/sh
|
||||
# Create a crypt device using dmsetup when encryption key is stored in keyring service
|
||||
dmsetup create crypt2 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 :32:logon:my_prefix:my_key 0 $1 0"
|
||||
|
||||
::
|
||||
|
||||
#!/bin/sh
|
||||
# Create a crypt device using cryptsetup and LUKS header with default cipher
|
||||
cryptsetup luksFormat $1
|
||||
cryptsetup luksOpen $1 crypt1
|
305
Documentation/admin-guide/device-mapper/dm-dust.rst
Normal file
@ -0,0 +1,305 @@
|
||||
dm-dust
|
||||
=======
|
||||
|
||||
This target emulates the behavior of bad sectors at arbitrary
|
||||
locations, and the ability to enable the emulation of the failures
|
||||
at an arbitrary time.
|
||||
|
||||
This target behaves similarly to a linear target. At a given time,
|
||||
the user can send a message to the target to start failing read
|
||||
requests on specific blocks (to emulate the behavior of a hard disk
|
||||
drive with bad sectors).
|
||||
|
||||
When the failure behavior is enabled (i.e.: when the output of
|
||||
"dmsetup status" displays "fail_read_on_bad_block"), reads of blocks
|
||||
in the "bad block list" will fail with EIO ("Input/output error").
|
||||
|
||||
Writes of blocks in the "bad block list will result in the following:
|
||||
|
||||
1. Remove the block from the "bad block list".
|
||||
2. Successfully complete the write.
|
||||
|
||||
This emulates the "remapped sector" behavior of a drive with bad
|
||||
sectors.
|
||||
|
||||
Normally, a drive that is encountering bad sectors will most likely
|
||||
encounter more bad sectors, at an unknown time or location.
|
||||
With dm-dust, the user can use the "addbadblock" and "removebadblock"
|
||||
messages to add arbitrary bad blocks at new locations, and the
|
||||
"enable" and "disable" messages to modulate the state of whether the
|
||||
configured "bad blocks" will be treated as bad, or bypassed.
|
||||
This allows the pre-writing of test data and metadata prior to
|
||||
simulating a "failure" event where bad sectors start to appear.
|
||||
|
||||
Table parameters
|
||||
----------------
|
||||
<device_path> <offset> <blksz>
|
||||
|
||||
Mandatory parameters:
|
||||
<device_path>:
|
||||
Path to the block device.
|
||||
|
||||
<offset>:
|
||||
Offset to data area from start of device_path
|
||||
|
||||
<blksz>:
|
||||
Block size in bytes
|
||||
|
||||
(minimum 512, maximum 1073741824, must be a power of 2)
|
||||
|
||||
Usage instructions
|
||||
------------------
|
||||
|
||||
First, find the size (in 512-byte sectors) of the device to be used::
|
||||
|
||||
$ sudo blockdev --getsz /dev/vdb1
|
||||
33552384
|
||||
|
||||
Create the dm-dust device:
|
||||
(For a device with a block size of 512 bytes)
|
||||
|
||||
::
|
||||
|
||||
$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 512'
|
||||
|
||||
(For a device with a block size of 4096 bytes)
|
||||
|
||||
::
|
||||
|
||||
$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 4096'
|
||||
|
||||
Check the status of the read behavior ("bypass" indicates that all I/O
|
||||
will be passed through to the underlying device; "verbose" indicates that
|
||||
bad block additions, removals, and remaps will be verbosely logged)::
|
||||
|
||||
$ sudo dmsetup status dust1
|
||||
0 33552384 dust 252:17 bypass verbose
|
||||
|
||||
$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=128 iflag=direct
|
||||
128+0 records in
|
||||
128+0 records out
|
||||
|
||||
$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
|
||||
128+0 records in
|
||||
128+0 records out
|
||||
|
||||
Adding and removing bad blocks
|
||||
------------------------------
|
||||
|
||||
At any time (i.e.: whether the device has the "bad block" emulation
|
||||
enabled or disabled), bad blocks may be added or removed from the
|
||||
device via the "addbadblock" and "removebadblock" messages::
|
||||
|
||||
$ sudo dmsetup message dust1 0 addbadblock 60
|
||||
kernel: device-mapper: dust: badblock added at block 60
|
||||
|
||||
$ sudo dmsetup message dust1 0 addbadblock 67
|
||||
kernel: device-mapper: dust: badblock added at block 67
|
||||
|
||||
$ sudo dmsetup message dust1 0 addbadblock 72
|
||||
kernel: device-mapper: dust: badblock added at block 72
|
||||
|
||||
These bad blocks will be stored in the "bad block list".
|
||||
While the device is in "bypass" mode, reads and writes will succeed::
|
||||
|
||||
$ sudo dmsetup status dust1
|
||||
0 33552384 dust 252:17 bypass
|
||||
|
||||
Enabling block read failures
|
||||
----------------------------
|
||||
|
||||
To enable the "fail read on bad block" behavior, send the "enable" message::
|
||||
|
||||
$ sudo dmsetup message dust1 0 enable
|
||||
kernel: device-mapper: dust: enabling read failures on bad sectors
|
||||
|
||||
$ sudo dmsetup status dust1
|
||||
0 33552384 dust 252:17 fail_read_on_bad_block
|
||||
|
||||
With the device in "fail read on bad block" mode, attempting to read a
|
||||
block will encounter an "Input/output error"::
|
||||
|
||||
$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=1 skip=67 iflag=direct
|
||||
dd: error reading '/dev/mapper/dust1': Input/output error
|
||||
0+0 records in
|
||||
0+0 records out
|
||||
0 bytes copied, 0.00040651 s, 0.0 kB/s
|
||||
|
||||
...and writing to the bad blocks will remove the blocks from the list,
|
||||
therefore emulating the "remap" behavior of hard disk drives::
|
||||
|
||||
$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
|
||||
128+0 records in
|
||||
128+0 records out
|
||||
|
||||
kernel: device-mapper: dust: block 60 removed from badblocklist by write
|
||||
kernel: device-mapper: dust: block 67 removed from badblocklist by write
|
||||
kernel: device-mapper: dust: block 72 removed from badblocklist by write
|
||||
kernel: device-mapper: dust: block 87 removed from badblocklist by write
|
||||
|
||||
Bad block add/remove error handling
|
||||
-----------------------------------
|
||||
|
||||
Attempting to add a bad block that already exists in the list will
|
||||
result in an "Invalid argument" error, as well as a helpful message::
|
||||
|
||||
$ sudo dmsetup message dust1 0 addbadblock 88
|
||||
device-mapper: message ioctl on dust1 failed: Invalid argument
|
||||
kernel: device-mapper: dust: block 88 already in badblocklist
|
||||
|
||||
Attempting to remove a bad block that doesn't exist in the list will
|
||||
result in an "Invalid argument" error, as well as a helpful message::
|
||||
|
||||
$ sudo dmsetup message dust1 0 removebadblock 87
|
||||
device-mapper: message ioctl on dust1 failed: Invalid argument
|
||||
kernel: device-mapper: dust: block 87 not found in badblocklist
|
||||
|
||||
Counting the number of bad blocks in the bad block list
|
||||
-------------------------------------------------------
|
||||
|
||||
To count the number of bad blocks configured in the device, run the
|
||||
following message command::
|
||||
|
||||
$ sudo dmsetup message dust1 0 countbadblocks
|
||||
|
||||
A message will print with the number of bad blocks currently
|
||||
configured on the device::
|
||||
|
||||
countbadblocks: 895 badblock(s) found
|
||||
|
||||
Querying for specific bad blocks
|
||||
--------------------------------
|
||||
|
||||
To find out if a specific block is in the bad block list, run the
|
||||
following message command::
|
||||
|
||||
$ sudo dmsetup message dust1 0 queryblock 72
|
||||
|
||||
The following message will print if the block is in the list::
|
||||
|
||||
dust_query_block: block 72 found in badblocklist
|
||||
|
||||
The following message will print if the block is not in the list::
|
||||
|
||||
dust_query_block: block 72 not found in badblocklist
|
||||
|
||||
The "queryblock" message command will work in both the "enabled"
|
||||
and "disabled" modes, allowing the verification of whether a block
|
||||
will be treated as "bad" without having to issue I/O to the device,
|
||||
or having to "enable" the bad block emulation.
|
||||
|
||||
Clearing the bad block list
|
||||
---------------------------
|
||||
|
||||
To clear the bad block list (without needing to individually run
|
||||
a "removebadblock" message command for every block), run the
|
||||
following message command::
|
||||
|
||||
$ sudo dmsetup message dust1 0 clearbadblocks
|
||||
|
||||
After clearing the bad block list, the following message will appear::
|
||||
|
||||
dust_clear_badblocks: badblocks cleared
|
||||
|
||||
If there were no bad blocks to clear, the following message will
|
||||
appear::
|
||||
|
||||
dust_clear_badblocks: no badblocks found
|
||||
|
||||
Listing the bad block list
|
||||
--------------------------
|
||||
|
||||
To list all bad blocks in the bad block list (using an example device
|
||||
with blocks 1 and 2 in the bad block list), run the following message
|
||||
command::
|
||||
|
||||
$ sudo dmsetup message dust1 0 listbadblocks
|
||||
1
|
||||
2
|
||||
|
||||
If there are no bad blocks in the bad block list, the command will
|
||||
execute with no output::
|
||||
|
||||
$ sudo dmsetup message dust1 0 listbadblocks
|
||||
|
||||
Message commands list
|
||||
---------------------
|
||||
|
||||
Below is a list of the messages that can be sent to a dust device:
|
||||
|
||||
Operations on blocks (requires a <blknum> argument)::
|
||||
|
||||
addbadblock <blknum>
|
||||
queryblock <blknum>
|
||||
removebadblock <blknum>
|
||||
|
||||
...where <blknum> is a block number within range of the device
|
||||
(corresponding to the block size of the device.)
|
||||
|
||||
Single argument message commands::
|
||||
|
||||
countbadblocks
|
||||
clearbadblocks
|
||||
listbadblocks
|
||||
disable
|
||||
enable
|
||||
quiet
|
||||
|
||||
Device removal
|
||||
--------------
|
||||
|
||||
When finished, remove the device via the "dmsetup remove" command::
|
||||
|
||||
$ sudo dmsetup remove dust1
|
||||
|
||||
Quiet mode
|
||||
----------
|
||||
|
||||
On test runs with many bad blocks, it may be desirable to avoid
|
||||
excessive logging (from bad blocks added, removed, or "remapped").
|
||||
This can be done by enabling "quiet mode" via the following message::
|
||||
|
||||
$ sudo dmsetup message dust1 0 quiet
|
||||
|
||||
This will suppress log messages from add / remove / removed by write
|
||||
operations. Log messages from "countbadblocks" or "queryblock"
|
||||
message commands will still print in quiet mode.
|
||||
|
||||
The status of quiet mode can be seen by running "dmsetup status"::
|
||||
|
||||
$ sudo dmsetup status dust1
|
||||
0 33552384 dust 252:17 fail_read_on_bad_block quiet
|
||||
|
||||
To disable quiet mode, send the "quiet" message again::
|
||||
|
||||
$ sudo dmsetup message dust1 0 quiet
|
||||
|
||||
$ sudo dmsetup status dust1
|
||||
0 33552384 dust 252:17 fail_read_on_bad_block verbose
|
||||
|
||||
(The presence of "verbose" indicates normal logging.)
|
||||
|
||||
"Why not...?"
|
||||
-------------
|
||||
|
||||
scsi_debug has a "medium error" mode that can fail reads on one
|
||||
specified sector (sector 0x1234, hardcoded in the source code), but
|
||||
it uses RAM for the persistent storage, which drastically decreases
|
||||
the potential device size.
|
||||
|
||||
dm-flakey fails all I/O from all block locations at a specified time
|
||||
frequency, and not a given point in time.
|
||||
|
||||
When a bad sector occurs on a hard disk drive, reads to that sector
|
||||
are failed by the device, usually resulting in an error code of EIO
|
||||
("I/O error") or ENODATA ("No data available"). However, a write to
|
||||
the sector may succeed, and result in the sector becoming readable
|
||||
after the device controller no longer experiences errors reading the
|
||||
sector (or after a reallocation of the sector). However, there may
|
||||
be bad sectors that occur on the device in the future, in a different,
|
||||
unpredictable location.
|
||||
|
||||
This target seeks to provide a device that can exhibit the behavior
|
||||
of a bad sector at a known sector location, at a known time, based
|
||||
on a large storage device (at least tens of gigabytes, not occupying
|
||||
system memory).
|
51
Documentation/admin-guide/device-mapper/dm-ebs.rst
Normal file
@ -0,0 +1,51 @@
|
||||
======
|
||||
dm-ebs
|
||||
======
|
||||
|
||||
|
||||
This target is similar to the linear target except that it emulates
|
||||
a smaller logical block size on a device with a larger logical block
|
||||
size. Its main purpose is to provide emulation of 512 byte sectors on
|
||||
devices that do not provide this emulation (i.e. 4K native disks).
|
||||
|
||||
Supported emulated logical block sizes 512, 1024, 2048 and 4096.
|
||||
|
||||
Underlying block size can be set to > 4K to test buffering larger units.
|
||||
|
||||
|
||||
Table parameters
|
||||
----------------
|
||||
<dev path> <offset> <emulated sectors> [<underlying sectors>]
|
||||
|
||||
Mandatory parameters:
|
||||
|
||||
<dev path>:
|
||||
Full pathname to the underlying block-device,
|
||||
or a "major:minor" device-number.
|
||||
<offset>:
|
||||
Starting sector within the device;
|
||||
has to be a multiple of <emulated sectors>.
|
||||
<emulated sectors>:
|
||||
Number of sectors defining the logical block size to be emulated;
|
||||
1, 2, 4, 8 sectors of 512 bytes supported.
|
||||
|
||||
Optional parameter:
|
||||
|
||||
<underyling sectors>:
|
||||
Number of sectors defining the logical block size of <dev path>.
|
||||
2^N supported, e.g. 8 = emulate 8 sectors of 512 bytes = 4KiB.
|
||||
If not provided, the logical block size of <dev path> will be used.
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
Emulate 1 sector = 512 bytes logical block size on /dev/sda starting at
|
||||
offset 1024 sectors with underlying devices block size automatically set:
|
||||
|
||||
ebs /dev/sda 1024 1
|
||||
|
||||
Emulate 2 sector = 1KiB logical block size on /dev/sda starting at
|
||||
offset 128 sectors, enforce 2KiB underlying device block size.
|
||||
This presumes 2KiB logical blocksize on /dev/sda or less to work:
|
||||
|
||||
ebs /dev/sda 128 2 4
|
74
Documentation/admin-guide/device-mapper/dm-flakey.rst
Normal file
@ -0,0 +1,74 @@
|
||||
=========
|
||||
dm-flakey
|
||||
=========
|
||||
|
||||
This target is the same as the linear target except that it exhibits
|
||||
unreliable behaviour periodically. It's been found useful in simulating
|
||||
failing devices for testing purposes.
|
||||
|
||||
Starting from the time the table is loaded, the device is available for
|
||||
<up interval> seconds, then exhibits unreliable behaviour for <down
|
||||
interval> seconds, and then this cycle repeats.
|
||||
|
||||
Also, consider using this in combination with the dm-delay target too,
|
||||
which can delay reads and writes and/or send them to different
|
||||
underlying devices.
|
||||
|
||||
Table parameters
|
||||
----------------
|
||||
|
||||
::
|
||||
|
||||
<dev path> <offset> <up interval> <down interval> \
|
||||
[<num_features> [<feature arguments>]]
|
||||
|
||||
Mandatory parameters:
|
||||
|
||||
<dev path>:
|
||||
Full pathname to the underlying block-device, or a
|
||||
"major:minor" device-number.
|
||||
<offset>:
|
||||
Starting sector within the device.
|
||||
<up interval>:
|
||||
Number of seconds device is available.
|
||||
<down interval>:
|
||||
Number of seconds device returns errors.
|
||||
|
||||
Optional feature parameters:
|
||||
|
||||
If no feature parameters are present, during the periods of
|
||||
unreliability, all I/O returns errors.
|
||||
|
||||
drop_writes:
|
||||
All write I/O is silently ignored.
|
||||
Read I/O is handled correctly.
|
||||
|
||||
error_writes:
|
||||
All write I/O is failed with an error signalled.
|
||||
Read I/O is handled correctly.
|
||||
|
||||
corrupt_bio_byte <Nth_byte> <direction> <value> <flags>:
|
||||
During <down interval>, replace <Nth_byte> of the data of
|
||||
each matching bio with <value>.
|
||||
|
||||
<Nth_byte>:
|
||||
The offset of the byte to replace.
|
||||
Counting starts at 1, to replace the first byte.
|
||||
<direction>:
|
||||
Either 'r' to corrupt reads or 'w' to corrupt writes.
|
||||
'w' is incompatible with drop_writes.
|
||||
<value>:
|
||||
The value (from 0-255) to write.
|
||||
<flags>:
|
||||
Perform the replacement only if bio->bi_opf has all the
|
||||
selected flags set.
|
||||
|
||||
Examples:
|
||||
|
||||
Replaces the 32nd byte of READ bios with the value 1::
|
||||
|
||||
corrupt_bio_byte 32 r 1 0
|
||||
|
||||
Replaces the 224th byte of REQ_META (=32) bios with the value 0::
|
||||
|
||||
corrupt_bio_byte 224 w 0 32
|
715
Documentation/admin-guide/device-mapper/dm-ima.rst
Normal file
@ -0,0 +1,715 @@
|
||||
======
|
||||
dm-ima
|
||||
======
|
||||
|
||||
For a given system, various external services/infrastructure tools
|
||||
(including the attestation service) interact with it - both during the
|
||||
setup and during rest of the system run-time. They share sensitive data
|
||||
and/or execute critical workload on that system. The external services
|
||||
may want to verify the current run-time state of the relevant kernel
|
||||
subsystems before fully trusting the system with business-critical
|
||||
data/workload.
|
||||
|
||||
Device mapper plays a critical role on a given system by providing
|
||||
various important functionalities to the block devices using various
|
||||
target types like crypt, verity, integrity etc. Each of these target
|
||||
types’ functionalities can be configured with various attributes.
|
||||
The attributes chosen to configure these target types can significantly
|
||||
impact the security profile of the block device, and in-turn, of the
|
||||
system itself. For instance, the type of encryption algorithm and the
|
||||
key size determines the strength of encryption for a given block device.
|
||||
|
||||
Therefore, verifying the current state of various block devices as well
|
||||
as their various target attributes is crucial for external services before
|
||||
fully trusting the system with business-critical data/workload.
|
||||
|
||||
IMA kernel subsystem provides the necessary functionality for
|
||||
device mapper to measure the state and configuration of
|
||||
various block devices -
|
||||
|
||||
- by device mapper itself, from within the kernel,
|
||||
- in a tamper resistant way,
|
||||
- and re-measured - triggered on state/configuration change.
|
||||
|
||||
Setting the IMA Policy:
|
||||
=======================
|
||||
For IMA to measure the data on a given system, the IMA policy on the
|
||||
system needs to be updated to have following line, and the system needs
|
||||
to be restarted for the measurements to take effect.
|
||||
|
||||
::
|
||||
|
||||
/etc/ima/ima-policy
|
||||
measure func=CRITICAL_DATA label=device-mapper template=ima-buf
|
||||
|
||||
The measurements will be reflected in the IMA logs, which are located at:
|
||||
|
||||
::
|
||||
|
||||
/sys/kernel/security/integrity/ima/ascii_runtime_measurements
|
||||
/sys/kernel/security/integrity/ima/binary_runtime_measurements
|
||||
|
||||
Then IMA ASCII measurement log has the following format:
|
||||
|
||||
::
|
||||
|
||||
<PCR> <TEMPLATE_DATA_DIGEST> <TEMPLATE_NAME> <TEMPLATE_DATA>
|
||||
|
||||
PCR := Platform Configuration Register, in which the values are registered.
|
||||
This is applicable if TPM chip is in use.
|
||||
|
||||
TEMPLATE_DATA_DIGEST := Template data digest of the IMA record.
|
||||
TEMPLATE_NAME := Template name that registered the integrity value (e.g. ima-buf).
|
||||
|
||||
TEMPLATE_DATA := <ALG> ":" <EVENT_DIGEST> <EVENT_NAME> <EVENT_DATA>
|
||||
It contains data for the specific event to be measured,
|
||||
in a given template data format.
|
||||
|
||||
ALG := Algorithm to compute event digest
|
||||
EVENT_DIGEST := Digest of the event data
|
||||
EVENT_NAME := Description of the event (e.g. 'dm_table_load').
|
||||
EVENT_DATA := The event data to be measured.
|
||||
|
||||
|
|
||||
|
||||
| *NOTE #1:*
|
||||
| The DM target data measured by IMA subsystem can alternatively
|
||||
be queried from userspace by setting DM_IMA_MEASUREMENT_FLAG with
|
||||
DM_TABLE_STATUS_CMD.
|
||||
|
||||
|
|
||||
|
||||
| *NOTE #2:*
|
||||
| The Kernel configuration CONFIG_IMA_DISABLE_HTABLE allows measurement of duplicate records.
|
||||
| To support recording duplicate IMA events in the IMA log, the Kernel needs to be configured with
|
||||
CONFIG_IMA_DISABLE_HTABLE=y.
|
||||
|
||||
Supported Device States:
|
||||
========================
|
||||
Following device state changes will trigger IMA measurements:
|
||||
|
||||
1. Table load
|
||||
#. Device resume
|
||||
#. Device remove
|
||||
#. Table clear
|
||||
#. Device rename
|
||||
|
||||
1. Table load:
|
||||
---------------
|
||||
When a new table is loaded in a device's inactive table slot,
|
||||
the device information and target specific details from the
|
||||
targets in the table are measured.
|
||||
|
||||
The IMA measurement log has the following format for 'dm_table_load':
|
||||
|
||||
::
|
||||
|
||||
EVENT_NAME := "dm_table_load"
|
||||
EVENT_DATA := <dm_version_str> ";" <device_metadata> ";" <table_load_data>
|
||||
|
||||
dm_version_str := "dm_version=" <N> "." <N> "." <N>
|
||||
Same as Device Mapper driver version.
|
||||
device_metadata := <device_name> "," <device_uuid> "," <device_major> "," <device_minor> ","
|
||||
<minor_count> "," <num_device_targets> ";"
|
||||
|
||||
device_name := "name=" <dm-device-name>
|
||||
device_uuid := "uuid=" <dm-device-uuid>
|
||||
device_major := "major=" <N>
|
||||
device_minor := "minor=" <N>
|
||||
minor_count := "minor_count=" <N>
|
||||
num_device_targets := "num_targets=" <N>
|
||||
dm-device-name := Name of the device. If it contains special characters like '\', ',', ';',
|
||||
they are prefixed with '\'.
|
||||
dm-device-uuid := UUID of the device. If it contains special characters like '\', ',', ';',
|
||||
they are prefixed with '\'.
|
||||
|
||||
table_load_data := <target_data>
|
||||
Represents the data (as name=value pairs) from various targets in the table,
|
||||
which is being loaded into the DM device's inactive table slot.
|
||||
target_data := <target_data_row> | <target_data><target_data_row>
|
||||
|
||||
target_data_row := <target_index> "," <target_begin> "," <target_len> "," <target_name> ","
|
||||
<target_version> "," <target_attributes> ";"
|
||||
target_index := "target_index=" <N>
|
||||
Represents nth target in the table (from 0 to N-1 targets specified in <num_device_targets>)
|
||||
If all the data for N targets doesn't fit in the given buffer - then the data that fits
|
||||
in the buffer (say from target 0 to x) is measured in a given IMA event.
|
||||
The remaining data from targets x+1 to N-1 is measured in the subsequent IMA events,
|
||||
with the same format as that of 'dm_table_load'
|
||||
i.e. <dm_version_str> ";" <device_metadata> ";" <table_load_data>.
|
||||
|
||||
target_begin := "target_begin=" <N>
|
||||
target_len := "target_len=" <N>
|
||||
target_name := Name of the target. 'linear', 'crypt', 'integrity' etc.
|
||||
The targets that are supported for IMA measurements are documented below in the
|
||||
'Supported targets' section.
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
target_attributes := Data containing comma separated list of name=value pairs of target specific attributes.
|
||||
|
||||
For instance, if a linear device is created with the following table entries,
|
||||
# dmsetup create linear1
|
||||
0 2 linear /dev/loop0 512
|
||||
2 2 linear /dev/loop0 512
|
||||
4 2 linear /dev/loop0 512
|
||||
6 2 linear /dev/loop0 512
|
||||
|
||||
Then IMA ASCII measurement log will have the following entry:
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
10 a8c5ff755561c7a28146389d1514c318592af49a ima-buf sha256:4d73481ecce5eadba8ab084640d85bb9ca899af4d0a122989252a76efadc5b72
|
||||
dm_table_load
|
||||
dm_version=4.45.0;
|
||||
name=linear1,uuid=,major=253,minor=0,minor_count=1,num_targets=4;
|
||||
target_index=0,target_begin=0,target_len=2,target_name=linear,target_version=1.4.0,device_name=7:0,start=512;
|
||||
target_index=1,target_begin=2,target_len=2,target_name=linear,target_version=1.4.0,device_name=7:0,start=512;
|
||||
target_index=2,target_begin=4,target_len=2,target_name=linear,target_version=1.4.0,device_name=7:0,start=512;
|
||||
target_index=3,target_begin=6,target_len=2,target_name=linear,target_version=1.4.0,device_name=7:0,start=512;
|
||||
|
||||
2. Device resume:
|
||||
------------------
|
||||
When a suspended device is resumed, the device information and the hash of the
|
||||
data from previous load of an active table are measured.
|
||||
|
||||
The IMA measurement log has the following format for 'dm_device_resume':
|
||||
|
||||
::
|
||||
|
||||
EVENT_NAME := "dm_device_resume"
|
||||
EVENT_DATA := <dm_version_str> ";" <device_metadata> ";" <active_table_hash> ";" <current_device_capacity> ";"
|
||||
|
||||
dm_version_str := As described in the 'Table load' section above.
|
||||
device_metadata := As described in the 'Table load' section above.
|
||||
active_table_hash := "active_table_hash=" <table_hash_alg> ":" <table_hash>
|
||||
Rerpresents the hash of the IMA data being measured for the
|
||||
active table for the device.
|
||||
table_hash_alg := Algorithm used to compute the hash.
|
||||
table_hash := Hash of the (<dm_version_str> ";" <device_metadata> ";" <table_load_data> ";")
|
||||
as described in the 'dm_table_load' above.
|
||||
Note: If the table_load data spans across multiple IMA 'dm_table_load'
|
||||
events for a given device, the hash is computed combining all the event data
|
||||
i.e. (<dm_version_str> ";" <device_metadata> ";" <table_load_data> ";")
|
||||
across all those events.
|
||||
current_device_capacity := "current_device_capacity=" <N>
|
||||
|
||||
For instance, if a linear device is resumed with the following command,
|
||||
#dmsetup resume linear1
|
||||
|
||||
then IMA ASCII measurement log will have an entry with:
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
10 56c00cc062ffc24ccd9ac2d67d194af3282b934e ima-buf sha256:e7d12c03b958b4e0e53e7363a06376be88d98a1ac191fdbd3baf5e4b77f329b6
|
||||
dm_device_resume
|
||||
dm_version=4.45.0;
|
||||
name=linear1,uuid=,major=253,minor=0,minor_count=1,num_targets=4;
|
||||
active_table_hash=sha256:4d73481ecce5eadba8ab084640d85bb9ca899af4d0a122989252a76efadc5b72;current_device_capacity=8;
|
||||
|
||||
3. Device remove:
|
||||
------------------
|
||||
When a device is removed, the device information and a sha256 hash of the
|
||||
data from an active and inactive table are measured.
|
||||
|
||||
The IMA measurement log has the following format for 'dm_device_remove':
|
||||
|
||||
::
|
||||
|
||||
EVENT_NAME := "dm_device_remove"
|
||||
EVENT_DATA := <dm_version_str> ";" <device_active_metadata> ";" <device_inactive_metadata> ";"
|
||||
<active_table_hash> "," <inactive_table_hash> "," <remove_all> ";" <current_device_capacity> ";"
|
||||
|
||||
dm_version_str := As described in the 'Table load' section above.
|
||||
device_active_metadata := Device metadata that reflects the currently loaded active table.
|
||||
The format is same as 'device_metadata' described in the 'Table load' section above.
|
||||
device_inactive_metadata := Device metadata that reflects the inactive table.
|
||||
The format is same as 'device_metadata' described in the 'Table load' section above.
|
||||
active_table_hash := Hash of the currently loaded active table.
|
||||
The format is same as 'active_table_hash' described in the 'Device resume' section above.
|
||||
inactive_table_hash := Hash of the inactive table.
|
||||
The format is same as 'active_table_hash' described in the 'Device resume' section above.
|
||||
remove_all := "remove_all=" <yes_no>
|
||||
yes_no := "y" | "n"
|
||||
current_device_capacity := "current_device_capacity=" <N>
|
||||
|
||||
For instance, if a linear device is removed with the following command,
|
||||
#dmsetup remove l1
|
||||
|
||||
then IMA ASCII measurement log will have the following entry:
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
10 790e830a3a7a31590824ac0642b3b31c2d0e8b38 ima-buf sha256:ab9f3c959367a8f5d4403d6ce9c3627dadfa8f9f0e7ec7899299782388de3840
|
||||
dm_device_remove
|
||||
dm_version=4.45.0;
|
||||
device_active_metadata=name=l1,uuid=,major=253,minor=2,minor_count=1,num_targets=2;
|
||||
device_inactive_metadata=name=l1,uuid=,major=253,minor=2,minor_count=1,num_targets=1;
|
||||
active_table_hash=sha256:4a7e62efaebfc86af755831998b7db6f59b60d23c9534fb16a4455907957953a,
|
||||
inactive_table_hash=sha256:9d79c175bc2302d55a183e8f50ad4bafd60f7692fd6249e5fd213e2464384b86,remove_all=n;
|
||||
current_device_capacity=2048;
|
||||
|
||||
4. Table clear:
|
||||
----------------
|
||||
When an inactive table is cleared from the device, the device information and a sha256 hash of the
|
||||
data from an inactive table are measured.
|
||||
|
||||
The IMA measurement log has the following format for 'dm_table_clear':
|
||||
|
||||
::
|
||||
|
||||
EVENT_NAME := "dm_table_clear"
|
||||
EVENT_DATA := <dm_version_str> ";" <device_inactive_metadata> ";" <inactive_table_hash> ";" <current_device_capacity> ";"
|
||||
|
||||
dm_version_str := As described in the 'Table load' section above.
|
||||
device_inactive_metadata := Device metadata that was captured during the load time inactive table being cleared.
|
||||
The format is same as 'device_metadata' described in the 'Table load' section above.
|
||||
inactive_table_hash := Hash of the inactive table being cleared from the device.
|
||||
The format is same as 'active_table_hash' described in the 'Device resume' section above.
|
||||
current_device_capacity := "current_device_capacity=" <N>
|
||||
|
||||
For instance, if a linear device's inactive table is cleared,
|
||||
#dmsetup clear l1
|
||||
|
||||
then IMA ASCII measurement log will have an entry with:
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
10 77d347408f557f68f0041acb0072946bb2367fe5 ima-buf sha256:42f9ca22163fdfa548e6229dece2959bc5ce295c681644240035827ada0e1db5
|
||||
dm_table_clear
|
||||
dm_version=4.45.0;
|
||||
name=l1,uuid=,major=253,minor=2,minor_count=1,num_targets=1;
|
||||
inactive_table_hash=sha256:75c0dc347063bf474d28a9907037eba060bfe39d8847fc0646d75e149045d545;current_device_capacity=1024;
|
||||
|
||||
5. Device rename:
|
||||
------------------
|
||||
When an device's NAME or UUID is changed, the device information and the new NAME and UUID
|
||||
are measured.
|
||||
|
||||
The IMA measurement log has the following format for 'dm_device_rename':
|
||||
|
||||
::
|
||||
|
||||
EVENT_NAME := "dm_device_rename"
|
||||
EVENT_DATA := <dm_version_str> ";" <device_active_metadata> ";" <new_device_name> "," <new_device_uuid> ";" <current_device_capacity> ";"
|
||||
|
||||
dm_version_str := As described in the 'Table load' section above.
|
||||
device_active_metadata := Device metadata that reflects the currently loaded active table.
|
||||
The format is same as 'device_metadata' described in the 'Table load' section above.
|
||||
new_device_name := "new_name=" <dm-device-name>
|
||||
dm-device-name := Same as <dm-device-name> described in 'Table load' section above
|
||||
new_device_uuid := "new_uuid=" <dm-device-uuid>
|
||||
dm-device-uuid := Same as <dm-device-uuid> described in 'Table load' section above
|
||||
current_device_capacity := "current_device_capacity=" <N>
|
||||
|
||||
E.g 1: if a linear device's name is changed with the following command,
|
||||
#dmsetup rename linear1 --setuuid 1234-5678
|
||||
|
||||
then IMA ASCII measurement log will have an entry with:
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
10 8b0423209b4c66ac1523f4c9848c9b51ee332f48 ima-buf sha256:6847b7258134189531db593e9230b257c84f04038b5a18fd2e1473860e0569ac
|
||||
dm_device_rename
|
||||
dm_version=4.45.0;
|
||||
name=linear1,uuid=,major=253,minor=2,minor_count=1,num_targets=1;new_name=linear1,new_uuid=1234-5678;
|
||||
current_device_capacity=1024;
|
||||
|
||||
E.g 2: if a linear device's name is changed with the following command,
|
||||
# dmsetup rename linear1 linear=2
|
||||
|
||||
then IMA ASCII measurement log will have an entry with:
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
10 bef70476b99c2bdf7136fae033aa8627da1bf76f ima-buf sha256:8c6f9f53b9ef9dc8f92a2f2cca8910e622543d0f0d37d484870cb16b95111402
|
||||
dm_device_rename
|
||||
dm_version=4.45.0;
|
||||
name=linear1,uuid=1234-5678,major=253,minor=2,minor_count=1,num_targets=1;
|
||||
new_name=linear\=2,new_uuid=1234-5678;
|
||||
current_device_capacity=1024;
|
||||
|
||||
Supported targets:
|
||||
==================
|
||||
|
||||
Following targets are supported to measure their data using IMA:
|
||||
|
||||
1. cache
|
||||
#. crypt
|
||||
#. integrity
|
||||
#. linear
|
||||
#. mirror
|
||||
#. multipath
|
||||
#. raid
|
||||
#. snapshot
|
||||
#. striped
|
||||
#. verity
|
||||
|
||||
1. cache
|
||||
---------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'cache' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <metadata_mode> "," <cache_metadata_device> ","
|
||||
<cache_device> "," <cache_origin_device> "," <writethrough> "," <writeback> ","
|
||||
<passthrough> "," <no_discard_passdown> ";"
|
||||
|
||||
target_name := "target_name=cache"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
metadata_mode := "metadata_mode=" <cache_metadata_mode>
|
||||
cache_metadata_mode := "fail" | "ro" | "rw"
|
||||
cache_device := "cache_device=" <cache_device_name_string>
|
||||
cache_origin_device := "cache_origin_device=" <cache_origin_device_string>
|
||||
writethrough := "writethrough=" <yes_no>
|
||||
writeback := "writeback=" <yes_no>
|
||||
passthrough := "passthrough=" <yes_no>
|
||||
no_discard_passdown := "no_discard_passdown=" <yes_no>
|
||||
yes_no := "y" | "n"
|
||||
|
||||
E.g.
|
||||
When a 'cache' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'cache' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;name=cache1,uuid=cache_uuid,major=253,minor=2,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=28672,target_name=cache,target_version=2.2.0,metadata_mode=rw,
|
||||
cache_metadata_device=253:4,cache_device=253:3,cache_origin_device=253:5,writethrough=y,writeback=n,
|
||||
passthrough=n,metadata2=y,no_discard_passdown=n;
|
||||
|
||||
|
||||
2. crypt
|
||||
---------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'crypt' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <allow_discards> "," <same_cpu_crypt> ","
|
||||
<submit_from_crypt_cpus> "," <no_read_workqueue> "," <no_write_workqueue> ","
|
||||
<iv_large_sectors> "," <iv_large_sectors> "," [<integrity_tag_size> ","] [<cipher_auth> ","]
|
||||
[<sector_size> ","] [<cipher_string> ","] <key_size> "," <key_parts> ","
|
||||
<key_extra_size> "," <key_mac_size> ";"
|
||||
|
||||
target_name := "target_name=crypt"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
allow_discards := "allow_discards=" <yes_no>
|
||||
same_cpu_crypt := "same_cpu_crypt=" <yes_no>
|
||||
submit_from_crypt_cpus := "submit_from_crypt_cpus=" <yes_no>
|
||||
no_read_workqueue := "no_read_workqueue=" <yes_no>
|
||||
no_write_workqueue := "no_write_workqueue=" <yes_no>
|
||||
iv_large_sectors := "iv_large_sectors=" <yes_no>
|
||||
integrity_tag_size := "integrity_tag_size=" <N>
|
||||
cipher_auth := "cipher_auth=" <string>
|
||||
sector_size := "sector_size=" <N>
|
||||
cipher_string := "cipher_string="
|
||||
key_size := "key_size=" <N>
|
||||
key_parts := "key_parts=" <N>
|
||||
key_extra_size := "key_extra_size=" <N>
|
||||
key_mac_size := "key_mac_size=" <N>
|
||||
yes_no := "y" | "n"
|
||||
|
||||
E.g.
|
||||
When a 'crypt' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'crypt' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;
|
||||
name=crypt1,uuid=crypt_uuid1,major=253,minor=0,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=1953125,target_name=crypt,target_version=1.23.0,
|
||||
allow_discards=y,same_cpu=n,submit_from_crypt_cpus=n,no_read_workqueue=n,no_write_workqueue=n,
|
||||
iv_large_sectors=n,cipher_string=aes-xts-plain64,key_size=32,key_parts=1,key_extra_size=0,key_mac_size=0;
|
||||
|
||||
3. integrity
|
||||
-------------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'integrity' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <dev_name> "," <start>
|
||||
<tag_size> "," <mode> "," [<meta_device> ","] [<block_size> ","] <recalculate> ","
|
||||
<allow_discards> "," <fix_padding> "," <fix_hmac> "," <legacy_recalculate> ","
|
||||
<journal_sectors> "," <interleave_sectors> "," <buffer_sectors> ";"
|
||||
|
||||
target_name := "target_name=integrity"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
dev_name := "dev_name=" <device_name_str>
|
||||
start := "start=" <N>
|
||||
tag_size := "tag_size=" <N>
|
||||
mode := "mode=" <integrity_mode_str>
|
||||
integrity_mode_str := "J" | "B" | "D" | "R"
|
||||
meta_device := "meta_device=" <meta_device_str>
|
||||
block_size := "block_size=" <N>
|
||||
recalculate := "recalculate=" <yes_no>
|
||||
allow_discards := "allow_discards=" <yes_no>
|
||||
fix_padding := "fix_padding=" <yes_no>
|
||||
fix_hmac := "fix_hmac=" <yes_no>
|
||||
legacy_recalculate := "legacy_recalculate=" <yes_no>
|
||||
journal_sectors := "journal_sectors=" <N>
|
||||
interleave_sectors := "interleave_sectors=" <N>
|
||||
buffer_sectors := "buffer_sectors=" <N>
|
||||
yes_no := "y" | "n"
|
||||
|
||||
E.g.
|
||||
When a 'integrity' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'integrity' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;
|
||||
name=integrity1,uuid=,major=253,minor=1,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=7856,target_name=integrity,target_version=1.10.0,
|
||||
dev_name=253:0,start=0,tag_size=32,mode=J,recalculate=n,allow_discards=n,fix_padding=n,
|
||||
fix_hmac=n,legacy_recalculate=n,journal_sectors=88,interleave_sectors=32768,buffer_sectors=128;
|
||||
|
||||
|
||||
4. linear
|
||||
----------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'linear' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <device_name> <,> <start> ";"
|
||||
|
||||
target_name := "target_name=linear"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
device_name := "device_name=" <linear_device_name_str>
|
||||
start := "start=" <N>
|
||||
|
||||
E.g.
|
||||
When a 'linear' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'linear' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;
|
||||
name=linear1,uuid=linear_uuid1,major=253,minor=2,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=28672,target_name=linear,target_version=1.4.0,
|
||||
device_name=253:1,start=2048;
|
||||
|
||||
5. mirror
|
||||
----------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'mirror' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <nr_mirrors> ","
|
||||
<mirror_device_data> "," <handle_errors> "," <keep_log> "," <log_type_status> ";"
|
||||
|
||||
target_name := "target_name=mirror"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
nr_mirrors := "nr_mirrors=" <NR>
|
||||
mirror_device_data := <mirror_device_row> | <mirror_device_data><mirror_device_row>
|
||||
mirror_device_row is repeated <NR> times - for <NR> described in <nr_mirrors>.
|
||||
mirror_device_row := <mirror_device_name> "," <mirror_device_status>
|
||||
mirror_device_name := "mirror_device_" <X> "=" <mirror_device_name_str>
|
||||
where <X> ranges from 0 to (<NR> -1) - for <NR> described in <nr_mirrors>.
|
||||
mirror_device_status := "mirror_device_" <X> "_status=" <mirror_device_status_char>
|
||||
where <X> ranges from 0 to (<NR> -1) - for <NR> described in <nr_mirrors>.
|
||||
mirror_device_status_char := "A" | "F" | "D" | "S" | "R" | "U"
|
||||
handle_errors := "handle_errors=" <yes_no>
|
||||
keep_log := "keep_log=" <yes_no>
|
||||
log_type_status := "log_type_status=" <log_type_status_str>
|
||||
yes_no := "y" | "n"
|
||||
|
||||
E.g.
|
||||
When a 'mirror' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'mirror' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;
|
||||
name=mirror1,uuid=mirror_uuid1,major=253,minor=6,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=2048,target_name=mirror,target_version=1.14.0,nr_mirrors=2,
|
||||
mirror_device_0=253:4,mirror_device_0_status=A,
|
||||
mirror_device_1=253:5,mirror_device_1_status=A,
|
||||
handle_errors=y,keep_log=n,log_type_status=;
|
||||
|
||||
6. multipath
|
||||
-------------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'multipath' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <nr_priority_groups>
|
||||
["," <pg_state> "," <priority_groups> "," <priority_group_paths>] ";"
|
||||
|
||||
target_name := "target_name=multipath"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
nr_priority_groups := "nr_priority_groups=" <NPG>
|
||||
priority_groups := <priority_groups_row>|<priority_groups_row><priority_groups>
|
||||
priority_groups_row := "pg_state_" <X> "=" <pg_state_str> "," "nr_pgpaths_" <X> "=" <NPGP> ","
|
||||
"path_selector_name_" <X> "=" <string> "," <priority_group_paths>
|
||||
where <X> ranges from 0 to (<NPG> -1) - for <NPG> described in <nr_priority_groups>.
|
||||
pg_state_str := "E" | "A" | "D"
|
||||
<priority_group_paths> := <priority_group_paths_row> | <priority_group_paths_row><priority_group_paths>
|
||||
priority_group_paths_row := "path_name_" <X> "_" <Y> "=" <string> "," "is_active_" <X> "_" <Y> "=" <is_active_str>
|
||||
"fail_count_" <X> "_" <Y> "=" <N> "," "path_selector_status_" <X> "_" <Y> "=" <path_selector_status_str>
|
||||
where <X> ranges from 0 to (<NPG> -1) - for <NPG> described in <nr_priority_groups>,
|
||||
and <Y> ranges from 0 to (<NPGP> -1) - for <NPGP> described in <priority_groups_row>.
|
||||
is_active_str := "A" | "F"
|
||||
|
||||
E.g.
|
||||
When a 'multipath' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'multipath' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;
|
||||
name=mp,uuid=,major=253,minor=0,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=2097152,target_name=multipath,target_version=1.14.0,nr_priority_groups=2,
|
||||
pg_state_0=E,nr_pgpaths_0=2,path_selector_name_0=queue-length,
|
||||
path_name_0_0=8:16,is_active_0_0=A,fail_count_0_0=0,path_selector_status_0_0=,
|
||||
path_name_0_1=8:32,is_active_0_1=A,fail_count_0_1=0,path_selector_status_0_1=,
|
||||
pg_state_1=E,nr_pgpaths_1=2,path_selector_name_1=queue-length,
|
||||
path_name_1_0=8:48,is_active_1_0=A,fail_count_1_0=0,path_selector_status_1_0=,
|
||||
path_name_1_1=8:64,is_active_1_1=A,fail_count_1_1=0,path_selector_status_1_1=;
|
||||
|
||||
7. raid
|
||||
--------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'raid' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <raid_type> "," <raid_disks> "," <raid_state>
|
||||
<raid_device_status> ["," journal_dev_mode] ";"
|
||||
|
||||
target_name := "target_name=raid"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
raid_type := "raid_type=" <raid_type_str>
|
||||
raid_disks := "raid_disks=" <NRD>
|
||||
raid_state := "raid_state=" <raid_state_str>
|
||||
raid_state_str := "frozen" | "reshape" |"resync" | "check" | "repair" | "recover" | "idle" |"undef"
|
||||
raid_device_status := <raid_device_status_row> | <raid_device_status_row><raid_device_status>
|
||||
<raid_device_status_row> is repeated <NRD> times - for <NRD> described in <raid_disks>.
|
||||
raid_device_status_row := "raid_device_" <X> "_status=" <raid_device_status_str>
|
||||
where <X> ranges from 0 to (<NRD> -1) - for <NRD> described in <raid_disks>.
|
||||
raid_device_status_str := "A" | "D" | "a" | "-"
|
||||
journal_dev_mode := "journal_dev_mode=" <journal_dev_mode_str>
|
||||
journal_dev_mode_str := "writethrough" | "writeback" | "invalid"
|
||||
|
||||
E.g.
|
||||
When a 'raid' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'raid' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;
|
||||
name=raid_LV1,uuid=uuid_raid_LV1,major=253,minor=12,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=2048,target_name=raid,target_version=1.15.1,
|
||||
raid_type=raid10,raid_disks=4,raid_state=idle,
|
||||
raid_device_0_status=A,
|
||||
raid_device_1_status=A,
|
||||
raid_device_2_status=A,
|
||||
raid_device_3_status=A;
|
||||
|
||||
|
||||
8. snapshot
|
||||
------------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'snapshot' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <snap_origin_name> ","
|
||||
<snap_cow_name> "," <snap_valid> "," <snap_merge_failed> "," <snapshot_overflowed> ";"
|
||||
|
||||
target_name := "target_name=snapshot"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
snap_origin_name := "snap_origin_name=" <string>
|
||||
snap_cow_name := "snap_cow_name=" <string>
|
||||
snap_valid := "snap_valid=" <yes_no>
|
||||
snap_merge_failed := "snap_merge_failed=" <yes_no>
|
||||
snapshot_overflowed := "snapshot_overflowed=" <yes_no>
|
||||
yes_no := "y" | "n"
|
||||
|
||||
E.g.
|
||||
When a 'snapshot' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'snapshot' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;
|
||||
name=snap1,uuid=snap_uuid1,major=253,minor=13,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=4096,target_name=snapshot,target_version=1.16.0,
|
||||
snap_origin_name=253:11,snap_cow_name=253:12,snap_valid=y,snap_merge_failed=n,snapshot_overflowed=n;
|
||||
|
||||
9. striped
|
||||
-----------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'striped' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <stripes> "," <chunk_size> ","
|
||||
<stripe_data> ";"
|
||||
|
||||
target_name := "target_name=striped"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
stripes := "stripes=" <NS>
|
||||
chunk_size := "chunk_size=" <N>
|
||||
stripe_data := <stripe_data_row>|<stripe_data><stripe_data_row>
|
||||
stripe_data_row := <stripe_device_name> "," <stripe_physical_start> "," <stripe_status>
|
||||
stripe_device_name := "stripe_" <X> "_device_name=" <stripe_device_name_str>
|
||||
where <X> ranges from 0 to (<NS> -1) - for <NS> described in <stripes>.
|
||||
stripe_physical_start := "stripe_" <X> "_physical_start=" <N>
|
||||
where <X> ranges from 0 to (<NS> -1) - for <NS> described in <stripes>.
|
||||
stripe_status := "stripe_" <X> "_status=" <stripe_status_str>
|
||||
where <X> ranges from 0 to (<NS> -1) - for <NS> described in <stripes>.
|
||||
stripe_status_str := "D" | "A"
|
||||
|
||||
E.g.
|
||||
When a 'striped' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'striped' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;
|
||||
name=striped1,uuid=striped_uuid1,major=253,minor=5,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=640,target_name=striped,target_version=1.6.0,stripes=2,chunk_size=64,
|
||||
stripe_0_device_name=253:0,stripe_0_physical_start=2048,stripe_0_status=A,
|
||||
stripe_1_device_name=253:3,stripe_1_physical_start=2048,stripe_1_status=A;
|
||||
|
||||
10. verity
|
||||
----------
|
||||
The 'target_attributes' (described as part of EVENT_DATA in 'Table load'
|
||||
section above) has the following data format for 'verity' target.
|
||||
|
||||
::
|
||||
|
||||
target_attributes := <target_name> "," <target_version> "," <hash_failed> "," <verity_version> ","
|
||||
<data_device_name> "," <hash_device_name> "," <verity_algorithm> "," <root_digest> ","
|
||||
<salt> "," <ignore_zero_blocks> "," <check_at_most_once> ["," <root_hash_sig_key_desc>]
|
||||
["," <verity_mode>] ";"
|
||||
|
||||
target_name := "target_name=verity"
|
||||
target_version := "target_version=" <N> "." <N> "." <N>
|
||||
hash_failed := "hash_failed=" <hash_failed_str>
|
||||
hash_failed_str := "C" | "V"
|
||||
verity_version := "verity_version=" <verity_version_str>
|
||||
data_device_name := "data_device_name=" <data_device_name_str>
|
||||
hash_device_name := "hash_device_name=" <hash_device_name_str>
|
||||
verity_algorithm := "verity_algorithm=" <verity_algorithm_str>
|
||||
root_digest := "root_digest=" <root_digest_str>
|
||||
salt := "salt=" <salt_str>
|
||||
salt_str := "-" <verity_salt_str>
|
||||
ignore_zero_blocks := "ignore_zero_blocks=" <yes_no>
|
||||
check_at_most_once := "check_at_most_once=" <yes_no>
|
||||
root_hash_sig_key_desc := "root_hash_sig_key_desc="
|
||||
verity_mode := "verity_mode=" <verity_mode_str>
|
||||
verity_mode_str := "ignore_corruption" | "restart_on_corruption" | "panic_on_corruption" | "invalid"
|
||||
yes_no := "y" | "n"
|
||||
|
||||
E.g.
|
||||
When a 'verity' target is loaded, then IMA ASCII measurement log will have an entry
|
||||
similar to the following, depicting what 'verity' attributes are measured in EVENT_DATA
|
||||
for 'dm_table_load' event.
|
||||
(converted from ASCII to text for readability)
|
||||
|
||||
dm_version=4.45.0;
|
||||
name=test-verity,uuid=,major=253,minor=2,minor_count=1,num_targets=1;
|
||||
target_index=0,target_begin=0,target_len=1953120,target_name=verity,target_version=1.8.0,hash_failed=V,
|
||||
verity_version=1,data_device_name=253:1,hash_device_name=253:0,verity_algorithm=sha256,
|
||||
root_digest=29cb87e60ce7b12b443ba6008266f3e41e93e403d7f298f8e3f316b29ff89c5e,
|
||||
salt=e48da609055204e89ae53b655ca2216dd983cf3cb829f34f63a297d106d53e2d,
|
||||
ignore_zero_blocks=n,check_at_most_once=n;
|
125
Documentation/admin-guide/device-mapper/dm-init.rst
Normal file
@ -0,0 +1,125 @@
|
||||
================================
|
||||
Early creation of mapped devices
|
||||
================================
|
||||
|
||||
It is possible to configure a device-mapper device to act as the root device for
|
||||
your system in two ways.
|
||||
|
||||
The first is to build an initial ramdisk which boots to a minimal userspace
|
||||
which configures the device, then pivot_root(8) in to it.
|
||||
|
||||
The second is to create one or more device-mappers using the module parameter
|
||||
"dm-mod.create=" through the kernel boot command line argument.
|
||||
|
||||
The format is specified as a string of data separated by commas and optionally
|
||||
semi-colons, where:
|
||||
|
||||
- a comma is used to separate fields like name, uuid, flags and table
|
||||
(specifies one device)
|
||||
- a semi-colon is used to separate devices.
|
||||
|
||||
So the format will look like this::
|
||||
|
||||
dm-mod.create=<name>,<uuid>,<minor>,<flags>,<table>[,<table>+][;<name>,<uuid>,<minor>,<flags>,<table>[,<table>+]+]
|
||||
|
||||
Where::
|
||||
|
||||
<name> ::= The device name.
|
||||
<uuid> ::= xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ""
|
||||
<minor> ::= The device minor number | ""
|
||||
<flags> ::= "ro" | "rw"
|
||||
<table> ::= <start_sector> <num_sectors> <target_type> <target_args>
|
||||
<target_type> ::= "verity" | "linear" | ... (see list below)
|
||||
|
||||
The dm line should be equivalent to the one used by the dmsetup tool with the
|
||||
`--concise` argument.
|
||||
|
||||
Target types
|
||||
============
|
||||
|
||||
Not all target types are available as there are serious risks in allowing
|
||||
activation of certain DM targets without first using userspace tools to check
|
||||
the validity of associated metadata.
|
||||
|
||||
======================= =======================================================
|
||||
`cache` constrained, userspace should verify cache device
|
||||
`crypt` allowed
|
||||
`delay` allowed
|
||||
`era` constrained, userspace should verify metadata device
|
||||
`flakey` constrained, meant for test
|
||||
`linear` allowed
|
||||
`log-writes` constrained, userspace should verify metadata device
|
||||
`mirror` constrained, userspace should verify main/mirror device
|
||||
`raid` constrained, userspace should verify metadata device
|
||||
`snapshot` constrained, userspace should verify src/dst device
|
||||
`snapshot-origin` allowed
|
||||
`snapshot-merge` constrained, userspace should verify src/dst device
|
||||
`striped` allowed
|
||||
`switch` constrained, userspace should verify dev path
|
||||
`thin` constrained, requires dm target message from userspace
|
||||
`thin-pool` constrained, requires dm target message from userspace
|
||||
`verity` allowed
|
||||
`writecache` constrained, userspace should verify cache device
|
||||
`zero` constrained, not meant for rootfs
|
||||
======================= =======================================================
|
||||
|
||||
If the target is not listed above, it is constrained by default (not tested).
|
||||
|
||||
Examples
|
||||
========
|
||||
An example of booting to a linear array made up of user-mode linux block
|
||||
devices::
|
||||
|
||||
dm-mod.create="lroot,,,rw, 0 4096 linear 98:16 0, 4096 4096 linear 98:32 0" root=/dev/dm-0
|
||||
|
||||
This will boot to a rw dm-linear target of 8192 sectors split across two block
|
||||
devices identified by their major:minor numbers. After boot, udev will rename
|
||||
this target to /dev/mapper/lroot (depending on the rules). No uuid was assigned.
|
||||
|
||||
An example of multiple device-mappers, with the dm-mod.create="..." contents
|
||||
is shown here split on multiple lines for readability::
|
||||
|
||||
dm-linear,,1,rw,
|
||||
0 32768 linear 8:1 0,
|
||||
32768 1024000 linear 8:2 0;
|
||||
dm-verity,,3,ro,
|
||||
0 1638400 verity 1 /dev/sdc1 /dev/sdc2 4096 4096 204800 1 sha256
|
||||
ac87db56303c9c1da433d7209b5a6ef3e4779df141200cbd7c157dcb8dd89c42
|
||||
5ebfe87f7df3235b80a117ebc4078e44f55045487ad4a96581d1adb564615b51
|
||||
|
||||
Other examples (per target):
|
||||
|
||||
"crypt"::
|
||||
|
||||
dm-crypt,,8,ro,
|
||||
0 1048576 crypt aes-xts-plain64
|
||||
babebabebabebabebabebabebabebabebabebabebabebabebabebabebabebabe 0
|
||||
/dev/sda 0 1 allow_discards
|
||||
|
||||
"delay"::
|
||||
|
||||
dm-delay,,4,ro,0 409600 delay /dev/sda1 0 500
|
||||
|
||||
"linear"::
|
||||
|
||||
dm-linear,,,rw,
|
||||
0 32768 linear /dev/sda1 0,
|
||||
32768 1024000 linear /dev/sda2 0,
|
||||
1056768 204800 linear /dev/sda3 0,
|
||||
1261568 512000 linear /dev/sda4 0
|
||||
|
||||
"snapshot-origin"::
|
||||
|
||||
dm-snap-orig,,4,ro,0 409600 snapshot-origin 8:2
|
||||
|
||||
"striped"::
|
||||
|
||||
dm-striped,,4,ro,0 1638400 striped 4 4096
|
||||
/dev/sda1 0 /dev/sda2 0 /dev/sda3 0 /dev/sda4 0
|
||||
|
||||
"verity"::
|
||||
|
||||
dm-verity,,4,ro,
|
||||
0 1638400 verity 1 8:1 8:2 4096 4096 204800 1 sha256
|
||||
fb1a5a0f00deb908d8b53cb270858975e76cf64105d412ce764225d53b8f3cfd
|
||||
51934789604d1b92399c52e7cb149d1b3a1b74bbbcb103b2a0aaacbed5c08584
|
292
Documentation/admin-guide/device-mapper/dm-integrity.rst
Normal file
@ -0,0 +1,292 @@
|
||||
============
|
||||
dm-integrity
|
||||
============
|
||||
|
||||
The dm-integrity target emulates a block device that has additional
|
||||
per-sector tags that can be used for storing integrity information.
|
||||
|
||||
A general problem with storing integrity tags with every sector is that
|
||||
writing the sector and the integrity tag must be atomic - i.e. in case of
|
||||
crash, either both sector and integrity tag or none of them is written.
|
||||
|
||||
To guarantee write atomicity, the dm-integrity target uses journal, it
|
||||
writes sector data and integrity tags into a journal, commits the journal
|
||||
and then copies the data and integrity tags to their respective location.
|
||||
|
||||
The dm-integrity target can be used with the dm-crypt target - in this
|
||||
situation the dm-crypt target creates the integrity data and passes them
|
||||
to the dm-integrity target via bio_integrity_payload attached to the bio.
|
||||
In this mode, the dm-crypt and dm-integrity targets provide authenticated
|
||||
disk encryption - if the attacker modifies the encrypted device, an I/O
|
||||
error is returned instead of random data.
|
||||
|
||||
The dm-integrity target can also be used as a standalone target, in this
|
||||
mode it calculates and verifies the integrity tag internally. In this
|
||||
mode, the dm-integrity target can be used to detect silent data
|
||||
corruption on the disk or in the I/O path.
|
||||
|
||||
There's an alternate mode of operation where dm-integrity uses bitmap
|
||||
instead of a journal. If a bit in the bitmap is 1, the corresponding
|
||||
region's data and integrity tags are not synchronized - if the machine
|
||||
crashes, the unsynchronized regions will be recalculated. The bitmap mode
|
||||
is faster than the journal mode, because we don't have to write the data
|
||||
twice, but it is also less reliable, because if data corruption happens
|
||||
when the machine crashes, it may not be detected.
|
||||
|
||||
When loading the target for the first time, the kernel driver will format
|
||||
the device. But it will only format the device if the superblock contains
|
||||
zeroes. If the superblock is neither valid nor zeroed, the dm-integrity
|
||||
target can't be loaded.
|
||||
|
||||
To use the target for the first time:
|
||||
|
||||
1. overwrite the superblock with zeroes
|
||||
2. load the dm-integrity target with one-sector size, the kernel driver
|
||||
will format the device
|
||||
3. unload the dm-integrity target
|
||||
4. read the "provided_data_sectors" value from the superblock
|
||||
5. load the dm-integrity target with the target size
|
||||
"provided_data_sectors"
|
||||
6. if you want to use dm-integrity with dm-crypt, load the dm-crypt target
|
||||
with the size "provided_data_sectors"
|
||||
|
||||
|
||||
Target arguments:
|
||||
|
||||
1. the underlying block device
|
||||
|
||||
2. the number of reserved sector at the beginning of the device - the
|
||||
dm-integrity won't read of write these sectors
|
||||
|
||||
3. the size of the integrity tag (if "-" is used, the size is taken from
|
||||
the internal-hash algorithm)
|
||||
|
||||
4. mode:
|
||||
|
||||
D - direct writes (without journal)
|
||||
in this mode, journaling is
|
||||
not used and data sectors and integrity tags are written
|
||||
separately. In case of crash, it is possible that the data
|
||||
and integrity tag doesn't match.
|
||||
J - journaled writes
|
||||
data and integrity tags are written to the
|
||||
journal and atomicity is guaranteed. In case of crash,
|
||||
either both data and tag or none of them are written. The
|
||||
journaled mode degrades write throughput twice because the
|
||||
data have to be written twice.
|
||||
B - bitmap mode - data and metadata are written without any
|
||||
synchronization, the driver maintains a bitmap of dirty
|
||||
regions where data and metadata don't match. This mode can
|
||||
only be used with internal hash.
|
||||
R - recovery mode - in this mode, journal is not replayed,
|
||||
checksums are not checked and writes to the device are not
|
||||
allowed. This mode is useful for data recovery if the
|
||||
device cannot be activated in any of the other standard
|
||||
modes.
|
||||
|
||||
5. the number of additional arguments
|
||||
|
||||
Additional arguments:
|
||||
|
||||
journal_sectors:number
|
||||
The size of journal, this argument is used only if formatting the
|
||||
device. If the device is already formatted, the value from the
|
||||
superblock is used.
|
||||
|
||||
interleave_sectors:number
|
||||
The number of interleaved sectors. This values is rounded down to
|
||||
a power of two. If the device is already formatted, the value from
|
||||
the superblock is used.
|
||||
|
||||
meta_device:device
|
||||
Don't interleave the data and metadata on the device. Use a
|
||||
separate device for metadata.
|
||||
|
||||
buffer_sectors:number
|
||||
The number of sectors in one buffer. The value is rounded down to
|
||||
a power of two.
|
||||
|
||||
The tag area is accessed using buffers, the buffer size is
|
||||
configurable. The large buffer size means that the I/O size will
|
||||
be larger, but there could be less I/Os issued.
|
||||
|
||||
journal_watermark:number
|
||||
The journal watermark in percents. When the size of the journal
|
||||
exceeds this watermark, the thread that flushes the journal will
|
||||
be started.
|
||||
|
||||
commit_time:number
|
||||
Commit time in milliseconds. When this time passes, the journal is
|
||||
written. The journal is also written immediately if the FLUSH
|
||||
request is received.
|
||||
|
||||
internal_hash:algorithm(:key) (the key is optional)
|
||||
Use internal hash or crc.
|
||||
When this argument is used, the dm-integrity target won't accept
|
||||
integrity tags from the upper target, but it will automatically
|
||||
generate and verify the integrity tags.
|
||||
|
||||
You can use a crc algorithm (such as crc32), then integrity target
|
||||
will protect the data against accidental corruption.
|
||||
You can also use a hmac algorithm (for example
|
||||
"hmac(sha256):0123456789abcdef"), in this mode it will provide
|
||||
cryptographic authentication of the data without encryption.
|
||||
|
||||
When this argument is not used, the integrity tags are accepted
|
||||
from an upper layer target, such as dm-crypt. The upper layer
|
||||
target should check the validity of the integrity tags.
|
||||
|
||||
recalculate
|
||||
Recalculate the integrity tags automatically. It is only valid
|
||||
when using internal hash.
|
||||
|
||||
journal_crypt:algorithm(:key) (the key is optional)
|
||||
Encrypt the journal using given algorithm to make sure that the
|
||||
attacker can't read the journal. You can use a block cipher here
|
||||
(such as "cbc(aes)") or a stream cipher (for example "chacha20"
|
||||
or "ctr(aes)").
|
||||
|
||||
The journal contains history of last writes to the block device,
|
||||
an attacker reading the journal could see the last sector numbers
|
||||
that were written. From the sector numbers, the attacker can infer
|
||||
the size of files that were written. To protect against this
|
||||
situation, you can encrypt the journal.
|
||||
|
||||
journal_mac:algorithm(:key) (the key is optional)
|
||||
Protect sector numbers in the journal from accidental or malicious
|
||||
modification. To protect against accidental modification, use a
|
||||
crc algorithm, to protect against malicious modification, use a
|
||||
hmac algorithm with a key.
|
||||
|
||||
This option is not needed when using internal-hash because in this
|
||||
mode, the integrity of journal entries is checked when replaying
|
||||
the journal. Thus, modified sector number would be detected at
|
||||
this stage.
|
||||
|
||||
block_size:number
|
||||
The size of a data block in bytes. The larger the block size the
|
||||
less overhead there is for per-block integrity metadata.
|
||||
Supported values are 512, 1024, 2048 and 4096 bytes. If not
|
||||
specified the default block size is 512 bytes.
|
||||
|
||||
sectors_per_bit:number
|
||||
In the bitmap mode, this parameter specifies the number of
|
||||
512-byte sectors that corresponds to one bitmap bit.
|
||||
|
||||
bitmap_flush_interval:number
|
||||
The bitmap flush interval in milliseconds. The metadata buffers
|
||||
are synchronized when this interval expires.
|
||||
|
||||
allow_discards
|
||||
Allow block discard requests (a.k.a. TRIM) for the integrity device.
|
||||
Discards are only allowed to devices using internal hash.
|
||||
|
||||
fix_padding
|
||||
Use a smaller padding of the tag area that is more
|
||||
space-efficient. If this option is not present, large padding is
|
||||
used - that is for compatibility with older kernels.
|
||||
|
||||
fix_hmac
|
||||
Improve security of internal_hash and journal_mac:
|
||||
|
||||
- the section number is mixed to the mac, so that an attacker can't
|
||||
copy sectors from one journal section to another journal section
|
||||
- the superblock is protected by journal_mac
|
||||
- a 16-byte salt stored in the superblock is mixed to the mac, so
|
||||
that the attacker can't detect that two disks have the same hmac
|
||||
key and also to disallow the attacker to move sectors from one
|
||||
disk to another
|
||||
|
||||
legacy_recalculate
|
||||
Allow recalculating of volumes with HMAC keys. This is disabled by
|
||||
default for security reasons - an attacker could modify the volume,
|
||||
set recalc_sector to zero, and the kernel would not detect the
|
||||
modification.
|
||||
|
||||
The journal mode (D/J), buffer_sectors, journal_watermark, commit_time and
|
||||
allow_discards can be changed when reloading the target (load an inactive
|
||||
table and swap the tables with suspend and resume). The other arguments
|
||||
should not be changed when reloading the target because the layout of disk
|
||||
data depend on them and the reloaded target would be non-functional.
|
||||
|
||||
|
||||
Status line:
|
||||
|
||||
1. the number of integrity mismatches
|
||||
2. provided data sectors - that is the number of sectors that the user
|
||||
could use
|
||||
3. the current recalculating position (or '-' if we didn't recalculate)
|
||||
|
||||
|
||||
The layout of the formatted block device:
|
||||
|
||||
* reserved sectors
|
||||
(they are not used by this target, they can be used for
|
||||
storing LUKS metadata or for other purpose), the size of the reserved
|
||||
area is specified in the target arguments
|
||||
|
||||
* superblock (4kiB)
|
||||
* magic string - identifies that the device was formatted
|
||||
* version
|
||||
* log2(interleave sectors)
|
||||
* integrity tag size
|
||||
* the number of journal sections
|
||||
* provided data sectors - the number of sectors that this target
|
||||
provides (i.e. the size of the device minus the size of all
|
||||
metadata and padding). The user of this target should not send
|
||||
bios that access data beyond the "provided data sectors" limit.
|
||||
* flags
|
||||
SB_FLAG_HAVE_JOURNAL_MAC
|
||||
- a flag is set if journal_mac is used
|
||||
SB_FLAG_RECALCULATING
|
||||
- recalculating is in progress
|
||||
SB_FLAG_DIRTY_BITMAP
|
||||
- journal area contains the bitmap of dirty
|
||||
blocks
|
||||
* log2(sectors per block)
|
||||
* a position where recalculating finished
|
||||
* journal
|
||||
The journal is divided into sections, each section contains:
|
||||
|
||||
* metadata area (4kiB), it contains journal entries
|
||||
|
||||
- every journal entry contains:
|
||||
|
||||
* logical sector (specifies where the data and tag should
|
||||
be written)
|
||||
* last 8 bytes of data
|
||||
* integrity tag (the size is specified in the superblock)
|
||||
|
||||
- every metadata sector ends with
|
||||
|
||||
* mac (8-bytes), all the macs in 8 metadata sectors form a
|
||||
64-byte value. It is used to store hmac of sector
|
||||
numbers in the journal section, to protect against a
|
||||
possibility that the attacker tampers with sector
|
||||
numbers in the journal.
|
||||
* commit id
|
||||
|
||||
* data area (the size is variable; it depends on how many journal
|
||||
entries fit into the metadata area)
|
||||
|
||||
- every sector in the data area contains:
|
||||
|
||||
* data (504 bytes of data, the last 8 bytes are stored in
|
||||
the journal entry)
|
||||
* commit id
|
||||
|
||||
To test if the whole journal section was written correctly, every
|
||||
512-byte sector of the journal ends with 8-byte commit id. If the
|
||||
commit id matches on all sectors in a journal section, then it is
|
||||
assumed that the section was written correctly. If the commit id
|
||||
doesn't match, the section was written partially and it should not
|
||||
be replayed.
|
||||
|
||||
* one or more runs of interleaved tags and data.
|
||||
Each run contains:
|
||||
|
||||
* tag area - it contains integrity tags. There is one tag for each
|
||||
sector in the data area
|
||||
* data area - it contains data sectors. The number of data sectors
|
||||
in one run must be a power of two. log2 of this value is stored
|
||||
in the superblock.
|