# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" "POT-Creation-Date: 2025-05-01 19:56-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Title = #: documentation/content/en/books/arch-handbook/smp/_index.adoc:1 #: documentation/content/en/books/arch-handbook/smp/_index.adoc:14 #, no-wrap msgid "SMPng Design Document" msgstr "" #. type: YAML Front Matter: title #: documentation/content/en/books/arch-handbook/smp/_index.adoc:1 #, no-wrap msgid "Chapter 8. SMPng Design Document" msgstr "" #. type: Title == #: documentation/content/en/books/arch-handbook/smp/_index.adoc:52 #, no-wrap msgid "Introduction" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:55 msgid "" "This document presents the current design and implementation of the SMPng " "Architecture. First, the basic primitives and tools are introduced. Next, a " "general architecture for the FreeBSD kernel's synchronization and execution " "model is laid out. Then, locking strategies for specific subsystems are " "discussed, documenting the approaches taken to introduce fine-grained " "synchronization and parallelism for each subsystem. Finally, detailed " "implementation notes are provided to motivate design choices, and make the " "reader aware of important implications involving the use of specific " "primitives." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:57 msgid "" "This document is a work-in-progress, and will be updated to reflect on-going " "design and implementation activities associated with the SMPng Project. Many " "sections currently exist only in outline form, but will be fleshed out as " "work proceeds. Updates or suggestions regarding the document may be directed " "to the document editors." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:63 msgid "" "The goal of SMPng is to allow concurrency in the kernel. The kernel is " "basically one rather large and complex program. To make the kernel multi-" "threaded we use some of the same tools used to make other programs multi-" "threaded. These include mutexes, shared/exclusive locks, semaphores, and " "condition variables. For the definitions of these and other SMP-related " "terms, please see the crossref:smp[smp-glossary, Glossary] section of this " "article." msgstr "" #. type: Title == #: documentation/content/en/books/arch-handbook/smp/_index.adoc:65 #, no-wrap msgid "Basic Tools and Locking Fundamentals" msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:67 #, no-wrap msgid "Atomic Instructions and Memory Barriers" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:70 msgid "" "There are several existing treatments of memory barriers and atomic " "instructions, so this section will not include a lot of detail. To put it " "simply, one can not go around reading variables without a lock if a lock is " "used to protect writes to that variable. This becomes obvious when you " "consider that memory barriers simply determine relative order of memory " "operations; they do not make any guarantee about timing of memory " "operations. That is, a memory barrier does not force the contents of a CPU's " "local cache or store buffer to flush. Instead, the memory barrier at lock " "release simply ensures that all writes to the protected data will be visible " "to other CPU's or devices if the write to release the lock is visible. The " "CPU is free to keep that data in its cache or store buffer as long as it " "wants. However, if another CPU performs an atomic instruction on the same " "datum, the first CPU must guarantee that the updated value is made visible " "to the second CPU along with any other operations that memory barriers may " "require." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:72 msgid "" "For example, assuming a simple model where data is considered visible when " "it is in main memory (or a global cache), when an atomic instruction is " "triggered on one CPU, other CPU's store buffers and caches must flush any " "writes to that same cache line along with any pending operations behind a " "memory barrier." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:74 msgid "" "This requires one to take special care when using an item protected by " "atomic instructions. For example, in the sleep mutex implementation, we have " "to use an `atomic_cmpset` rather than an `atomic_set` to turn on the " "`MTX_CONTESTED` bit. The reason is that we read the value of `mtx_lock` into " "a variable and then make a decision based on that read. However, the value " "we read may be stale, or it may change while we are making our decision. " "Thus, when the `atomic_set` executed, it may end up setting the bit on " "another value than the one we made the decision on. Thus, we have to use an " "`atomic_cmpset` to set the value only if the value we made the decision on " "is up-to-date and valid." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:76 msgid "" "Finally, atomic instructions only allow one item to be updated or read. If " "one needs to atomically update several items, then a lock must be used " "instead. For example, if two counters must be read and have values that are " "consistent relative to each other, then those counters must be protected by " "a lock rather than by separate atomic instructions." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:77 #, no-wrap msgid "Read Locks Versus Write Locks" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:80 msgid "" "Read locks do not need to be as strong as write locks. Both types of locks " "need to ensure that the data they are accessing is not stale. However, only " "write access requires exclusive access. Multiple threads can safely read a " "value. Using different types of locks for reads and writes can be " "implemented in a number of ways." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:82 msgid "" "First, sx locks can be used in this manner by using an exclusive lock when " "writing and a shared lock when reading. This method is quite straightforward." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:84 msgid "" "A second method is a bit more obscure. You can protect a datum with multiple " "locks. Then for reading that data you simply need to have a read lock of one " "of the locks. However, to write to the data, you need to have a write lock " "of all of the locks. This can make writing rather expensive but can be " "useful when data is accessed in various ways. For example, the parent " "process pointer is protected by both the `proctree_lock` sx lock and the per-" "process mutex. Sometimes the proc lock is easier as we are just checking to " "see who a parent of a process is that we already have locked. However, other " "places such as `inferior` need to walk the tree of processes via parent " "pointers and locking each process would be prohibitive as well as a pain to " "guarantee that the condition you are checking remains valid for both the " "check and the actions taken as a result of the check." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:85 #, no-wrap msgid "Locking Conditions and Results" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:88 msgid "" "If you need a lock to check the state of a variable so that you can take an " "action based on the state you read, you can not just hold the lock while " "reading the variable and then drop the lock before you act on the value you " "read. Once you drop the lock, the variable can change rendering your " "decision invalid. Thus, you must hold the lock both while reading the " "variable and while performing the action as a result of the test." msgstr "" #. type: Title == #: documentation/content/en/books/arch-handbook/smp/_index.adoc:90 #, no-wrap msgid "General Architecture and Design" msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:92 #, no-wrap msgid "Interrupt Handling" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:95 msgid "" "Following the pattern of several other multi-threaded UNIX(R) kernels, " "FreeBSD deals with interrupt handlers by giving them their own thread " "context. Providing a context for interrupt handlers allows them to block on " "locks. To help avoid latency, however, interrupt threads run at real-time " "kernel priority. Thus, interrupt handlers should not execute for very long " "to avoid starving other kernel threads. In addition, since multiple handlers " "may share an interrupt thread, interrupt handlers should not sleep or use a " "sleepable lock to avoid starving another interrupt handler." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:97 msgid "" "The interrupt threads currently in FreeBSD are referred to as heavyweight " "interrupt threads. They are called this because switching to an interrupt " "thread involves a full context switch. In the initial implementation, the " "kernel was not preemptive and thus interrupts that interrupted a kernel " "thread would have to wait until the kernel thread blocked or returned to " "userland before they would have an opportunity to run." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:99 msgid "" "To deal with the latency problems, the kernel in FreeBSD has been made " "preemptive. Currently, we only preempt a kernel thread when we release a " "sleep mutex or when an interrupt comes in. However, the plan is to make the " "FreeBSD kernel fully preemptive as described below." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:101 msgid "" "Not all interrupt handlers execute in a thread context. Instead, some " "handlers execute directly in primary interrupt context. These interrupt " "handlers are currently misnamed \"fast\" interrupt handlers since the " "`INTR_FAST` flag used in earlier versions of the kernel is used to mark " "these handlers. The only interrupts which currently use these types of " "interrupt handlers are clock interrupts and serial I/O device interrupts. " "Since these handlers do not have their own context, they may not acquire " "blocking locks and thus may only use spin mutexes." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:103 msgid "" "Finally, there is one optional optimization that can be added in MD code " "called lightweight context switches. Since an interrupt thread executes in a " "kernel context, it can borrow the vmspace of any process. Thus, in a " "lightweight context switch, the switch to the interrupt thread does not " "switch vmspaces but borrows the vmspace of the interrupted thread. In order " "to ensure that the vmspace of the interrupted thread does not disappear out " "from under us, the interrupted thread is not allowed to execute until the " "interrupt thread is no longer borrowing its vmspace. This can happen when " "the interrupt thread either blocks or finishes. If an interrupt thread " "blocks, then it will use its own context when it is made runnable again. " "Thus, it can release the interrupted thread." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:105 msgid "" "The cons of this optimization are that they are very machine specific and " "complex and thus only worth the effort if their is a large performance " "improvement. At this point it is probably too early to tell, and in fact, " "will probably hurt performance as almost all interrupt handlers will " "immediately block on Giant and require a thread fix-up when they block. " "Also, an alternative method of interrupt handling has been proposed by Mike " "Smith that works like so:" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:107 msgid "" "Each interrupt handler has two parts: a predicate which runs in primary " "interrupt context and a handler which runs in its own thread context." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:108 msgid "" "If an interrupt handler has a predicate, then when an interrupt is " "triggered, the predicate is run. If the predicate returns true then the " "interrupt is assumed to be fully handled and the kernel returns from the " "interrupt. If the predicate returns false or there is no predicate, then the " "threaded handler is scheduled to run." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:110 msgid "" "Fitting light weight context switches into this scheme might prove rather " "complicated. Since we may want to change to this scheme at some point in the " "future, it is probably best to defer work on light weight context switches " "until we have settled on the final interrupt handling architecture and " "determined how light weight context switches might or might not fit into it." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:111 #, no-wrap msgid "Kernel Preemption and Critical Sections" msgstr "" #. type: Title ==== #: documentation/content/en/books/arch-handbook/smp/_index.adoc:113 #, no-wrap msgid "Kernel Preemption in a Nutshell" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:116 msgid "" "Kernel preemption is fairly simple. The basic idea is that a CPU should " "always be doing the highest priority work available. Well, that is the ideal " "at least. There are a couple of cases where the expense of achieving the " "ideal is not worth being perfect." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:118 msgid "" "Implementing full kernel preemption is very straightforward: when you " "schedule a thread to be executed by putting it on a run queue, you check to " "see if its priority is higher than the currently executing thread. If so, " "you initiate a context switch to that thread." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:120 msgid "" "While locks can protect most data in the case of a preemption, not all of " "the kernel is preemption safe. For example, if a thread holding a spin mutex " "preempted and the new thread attempts to grab the same spin mutex, the new " "thread may spin forever as the interrupted thread may never get a chance to " "execute. Also, some code such as the code to assign an address space number " "for a process during `exec` on the Alpha needs to not be preempted as it " "supports the actual context switch code. Preemption is disabled for these " "code sections by using a critical section." msgstr "" #. type: Title ==== #: documentation/content/en/books/arch-handbook/smp/_index.adoc:121 #, no-wrap msgid "Critical Sections" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:124 msgid "" "The responsibility of the critical section API is to prevent context " "switches inside of a critical section. With a fully preemptive kernel, every " "`setrunqueue` of a thread other than the current thread is a preemption " "point. One implementation is for `critical_enter` to set a per-thread flag " "that is cleared by its counterpart. If `setrunqueue` is called with this " "flag set, it does not preempt regardless of the priority of the new thread " "relative to the current thread. However, since critical sections are used in " "spin mutexes to prevent context switches and multiple spin mutexes can be " "acquired, the critical section API must support nesting. For this reason the " "current implementation uses a nesting count instead of a single per-thread " "flag." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:126 msgid "" "In order to minimize latency, preemptions inside of a critical section are " "deferred rather than dropped. If a thread that would normally be preempted " "to is made runnable while the current thread is in a critical section, then " "a per-thread flag is set to indicate that there is a pending preemption. " "When the outermost critical section is exited, the flag is checked. If the " "flag is set, then the current thread is preempted to allow the higher " "priority thread to run." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:128 msgid "" "Interrupts pose a problem with regards to spin mutexes. If a low-level " "interrupt handler needs a lock, it needs to not interrupt any code needing " "that lock to avoid possible data structure corruption. Currently, providing " "this mechanism is piggybacked onto critical section API by means of the " "`cpu_critical_enter` and `cpu_critical_exit` functions. Currently this API " "disables and re-enables interrupts on all of FreeBSD's current platforms. " "This approach may not be purely optimal, but it is simple to understand and " "simple to get right. Theoretically, this second API need only be used for " "spin mutexes that are used in primary interrupt context. However, to make " "the code simpler, it is used for all spin mutexes and even all critical " "sections. It may be desirable to split out the MD API from the MI API and " "only use it in conjunction with the MI API in the spin mutex implementation. " "If this approach is taken, then the MD API likely would need a rename to " "show that it is a separate API." msgstr "" #. type: Title ==== #: documentation/content/en/books/arch-handbook/smp/_index.adoc:129 #, no-wrap msgid "Design Tradeoffs" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:132 msgid "" "As mentioned earlier, a couple of trade-offs have been made to sacrifice " "cases where perfect preemption may not always provide the best performance." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:134 msgid "" "The first trade-off is that the preemption code does not take other CPUs " "into account. Suppose we have a two CPU's A and B with the priority of A's " "thread as 4 and the priority of B's thread as 2. If CPU B makes a thread " "with priority 1 runnable, then in theory, we want CPU A to switch to the new " "thread so that we will be running the two highest priority runnable threads. " "However, the cost of determining which CPU to enforce a preemption on as " "well as actually signaling that CPU via an IPI along with the " "synchronization that would be required would be enormous. Thus, the current " "code would instead force CPU B to switch to the higher priority thread. Note " "that this still puts the system in a better position as CPU B is executing a " "thread of priority 1 rather than a thread of priority 2." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:136 msgid "" "The second trade-off limits immediate kernel preemption to real-time " "priority kernel threads. In the simple case of preemption defined above, a " "thread is always preempted immediately (or as soon as a critical section is " "exited) if a higher priority thread is made runnable. However, many threads " "executing in the kernel only execute in a kernel context for a short time " "before either blocking or returning to userland. Thus, if the kernel " "preempts these threads to run another non-realtime kernel thread, the kernel " "may switch out the executing thread just before it is about to sleep or " "execute. The cache on the CPU must then adjust to the new thread. When the " "kernel returns to the preempted thread, it must refill all the cache " "information that was lost. In addition, two extra context switches are " "performed that could be avoided if the kernel deferred the preemption until " "the first thread blocked or returned to userland. Thus, by default, the " "preemption code will only preempt immediately if the higher priority thread " "is a real-time priority thread." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:138 msgid "" "Turning on full kernel preemption for all kernel threads has value as a " "debugging aid since it exposes more race conditions. It is especially useful " "on UP systems were many races are hard to simulate otherwise. Thus, there is " "a kernel option `FULL_PREEMPTION` to enable preemption for all kernel " "threads that can be used for debugging purposes." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:139 #, no-wrap msgid "Thread Migration" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:142 msgid "" "Simply put, a thread migrates when it moves from one CPU to another. In a " "non-preemptive kernel this can only happen at well-defined points such as " "when calling `msleep` or returning to userland. However, in the preemptive " "kernel, an interrupt can force a preemption and possible migration at any " "time. This can have negative affects on per-CPU data since with the " "exception of `curthread` and `curpcb` the data can change whenever you " "migrate. Since you can potentially migrate at any time this renders " "unprotected per-CPU data access rather useless. Thus it is desirable to be " "able to disable migration for sections of code that need per-CPU data to be " "stable." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:144 msgid "" "Critical sections currently prevent migration since they do not allow " "context switches. However, this may be too strong of a requirement to " "enforce in some cases since a critical section also effectively blocks " "interrupt threads on the current processor. As a result, another API has " "been provided to allow the current thread to indicate that if it preempted " "it should not migrate to another CPU." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:146 msgid "" "This API is known as thread pinning and is provided by the scheduler. The " "API consists of two functions: `sched_pin` and `sched_unpin`. These " "functions manage a per-thread nesting count `td_pinned`. A thread is pinned " "when its nesting count is greater than zero and a thread starts off unpinned " "with a nesting count of zero. Each scheduler implementation is required to " "ensure that pinned threads are only executed on the CPU that they were " "executing on when the `sched_pin` was first called. Since the nesting count " "is only written to by the thread itself and is only read by other threads " "when the pinned thread is not executing but while `sched_lock` is held, then " "`td_pinned` does not need any locking. The `sched_pin` function increments " "the nesting count and `sched_unpin` decrements the nesting count. Note that " "these functions only operate on the current thread and bind the current " "thread to the CPU it is executing on at the time. To bind an arbitrary " "thread to a specific CPU, the `sched_bind` and `sched_unbind` functions " "should be used instead." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:147 #, no-wrap msgid "Callouts" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:150 msgid "" "The `timeout` kernel facility permits kernel services to register functions " "for execution as part of the `softclock` software interrupt. Events are " "scheduled based on a desired number of clock ticks, and callbacks to the " "consumer-provided function will occur at approximately the right time." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:152 msgid "" "The global list of pending timeout events is protected by a global spin " "mutex, `callout_lock`; all access to the timeout list must be performed with " "this mutex held. When `softclock` is woken up, it scans the list of pending " "timeouts for those that should fire. In order to avoid lock order reversal, " "the `softclock` thread will release the `callout_lock` mutex when invoking " "the provided `timeout` callback function. If the `CALLOUT_MPSAFE` flag was " "not set during registration, then Giant will be grabbed before invoking the " "callout, and then released afterwards. The `callout_lock` mutex will be re-" "grabbed before proceeding. The `softclock` code is careful to leave the list " "in a consistent state while releasing the mutex. If `DIAGNOSTIC` is enabled, " "then the time taken to execute each function is measured, and a warning is " "generated if it exceeds a threshold." msgstr "" #. type: Title == #: documentation/content/en/books/arch-handbook/smp/_index.adoc:154 #, no-wrap msgid "Specific Locking Strategies" msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:156 #, no-wrap msgid "Credentials" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:159 msgid "" "`struct ucred` is the kernel's internal credential structure, and is " "generally used as the basis for process-driven access control within the " "kernel. BSD-derived systems use a \"copy-on-write\" model for credential " "data: multiple references may exist for a credential structure, and when a " "change needs to be made, the structure is duplicated, modified, and then the " "reference replaced. Due to wide-spread caching of the credential to " "implement access control on open, this results in substantial memory " "savings. With a move to fine-grained SMP, this model also saves " "substantially on locking operations by requiring that modification only " "occur on an unshared credential, avoiding the need for explicit " "synchronization when consuming a known-shared credential." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:161 msgid "" "Credential structures with a single reference are considered mutable; shared " "credential structures must not be modified or a race condition is risked. A " "mutex, `cr_mtxp` protects the reference count of `struct ucred` so as to " "maintain consistency. Any use of the structure requires a valid reference " "for the duration of the use, or the structure may be released out from under " "the illegitimate consumer." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:163 msgid "" "The `struct ucred` mutex is a leaf mutex and is implemented via a mutex pool " "for performance reasons." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:165 msgid "" "Usually, credentials are used in a read-only manner for access control " "decisions, and in this case `td_ucred` is generally preferred because it " "requires no locking. When a process' credential is updated the `proc` lock " "must be held across the check and update operations thus avoid races. The " "process credential `p_ucred` must be used for check and update operations to " "prevent time-of-check, time-of-use races." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:167 msgid "" "If system call invocations will perform access control after an update to " "the process credential, the value of `td_ucred` must also be refreshed to " "the current process value. This will prevent use of a stale credential " "following a change. The kernel automatically refreshes the `td_ucred` " "pointer in the thread structure from the process `p_ucred` whenever a " "process enters the kernel, permitting use of a fresh credential for kernel " "access control." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:168 #, no-wrap msgid "File Descriptors and File Descriptor Tables" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:171 msgid "Details to follow." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:172 #, no-wrap msgid "Jail Structures" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:175 msgid "" "`struct prison` stores administrative details pertinent to the maintenance " "of jails created using the man:jail[2] API. This includes the per-jail " "hostname, IP address, and related settings. This structure is reference-" "counted since pointers to instances of the structure are shared by many " "credential structures. A single mutex, `pr_mtx` protects read and write " "access to the reference count and all mutable variables inside the struct " "jail. Some variables are set only when the jail is created, and a valid " "reference to the `struct prison` is sufficient to read these values. The " "precise locking of each entry is documented via comments in [.filename]#sys/" "jail.h#." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:176 #, no-wrap msgid "MAC Framework" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:179 msgid "" "The TrustedBSD MAC Framework maintains data in a variety of kernel objects, " "in the form of `struct label`. In general, labels in kernel objects are " "protected by the same lock as the remainder of the kernel object. For " "example, the `v_label` label in `struct vnode` is protected by the vnode " "lock on the vnode." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:181 msgid "" "In addition to labels maintained in standard kernel objects, the MAC " "Framework also maintains a list of registered and active policies. The " "policy list is protected by a global mutex (`mac_policy_list_lock`) and a " "busy count (also protected by the mutex). Since many access control checks " "may occur in parallel, entry to the framework for a read-only access to the " "policy list requires holding the mutex while incrementing (and later " "decrementing) the busy count. The mutex need not be held for the duration of " "the MAC entry operation--some operations, such as label operations on file " "system objects--are long-lived. To modify the policy list, such as during " "policy registration and de-registration, the mutex must be held and the " "reference count must be zero, to prevent modification of the list while it " "is in use." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:183 msgid "" "A condition variable, `mac_policy_list_not_busy`, is available to threads " "that need to wait for the list to become unbusy, but this condition variable " "must only be waited on if the caller is holding no other locks, or a lock " "order violation may be possible. The busy count, in effect, acts as a form " "of shared/exclusive lock over access to the framework: the difference is " "that, unlike with an sx lock, consumers waiting for the list to become " "unbusy may be starved, rather than permitting lock order problems with " "regards to the busy count and other locks that may be held on entry to (or " "inside) the MAC Framework." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:184 #, no-wrap msgid "Modules" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:187 msgid "" "For the module subsystem there exists a single lock that is used to protect " "the shared data. This lock is a shared/exclusive (SX) lock and has a good " "chance of needing to be acquired (shared or exclusively), therefore there " "are a few macros that have been added to make access to the lock more easy. " "These macros can be located in [.filename]#sys/module.h# and are quite basic " "in terms of usage. The main structures protected under this lock are the " "`module_t` structures (when shared) and the global `modulelist_t` structure, " "modules. One should review the related source code in [.filename]#kern/" "kern_module.c# to further understand the locking strategy." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:188 #, no-wrap msgid "Newbus Device Tree" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:191 msgid "" "The newbus system will have one sx lock. Readers will hold a shared (read) " "lock (man:sx_slock[9]) and writers will hold an exclusive (write) lock " "(man:sx_xlock[9]). Internal functions will not do locking at all. Externally " "visible ones will lock as needed. Those items that do not matter if the race " "is won or lost will not be locked, since they tend to be read all over the " "place (e.g., man:device_get_softc[9]). There will be relatively few changes " "to the newbus data structures, so a single lock should be sufficient and not " "impose a performance penalty." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:192 #, no-wrap msgid "Pipes" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:195 #: documentation/content/en/books/arch-handbook/smp/_index.adoc:217 msgid "..." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:196 #, no-wrap msgid "Processes and Threads" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:199 msgid "process hierarchy" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:201 msgid "proc locks, references" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:203 msgid "" "thread-specific copies of proc entries to freeze during system calls, " "including td_ucred" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:205 msgid "inter-process operations" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:207 msgid "process groups and sessions" msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:208 #, no-wrap msgid "Scheduler" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:211 msgid "" "Lots of references to `sched_lock` and notes pointing at specific primitives " "and related magic elsewhere in the document." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:212 #, no-wrap msgid "Select and Poll" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:215 msgid "" "The `select` and `poll` functions permit threads to block waiting on events " "on file descriptors--most frequently, whether or not the file descriptors " "are readable or writable." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:218 #, no-wrap msgid "SIGIO" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:221 msgid "" "The SIGIO service permits processes to request the delivery of a SIGIO " "signal to its process group when the read/write status of specified file " "descriptors changes. At most one process or process group is permitted to " "register for SIGIO from any given kernel object, and that process or group " "is referred to as the owner. Each object supporting SIGIO registration " "contains pointer field that is `NULL` if the object is not registered, or " "points to a `struct sigio` describing the registration. This field is " "protected by a global mutex, `sigio_lock`. Callers to SIGIO maintenance " "functions must pass in this field \"by reference\" so that local register " "copies of the field are not made when unprotected by the lock." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:223 msgid "" "One `struct sigio` is allocated for each registered object associated with " "any process or process group, and contains back-pointers to the object, " "owner, signal information, a credential, and the general disposition of the " "registration. Each process or progress group contains a list of registered " "`struct sigio` structures, `p_sigiolst` for processes, and `pg_sigiolst` for " "process groups. These lists are protected by the process or process group " "locks respectively. Most fields in each `struct sigio` are constant for the " "duration of the registration, with the exception of the `sio_pgsigio` field " "which links the `struct sigio` into the process or process group list. " "Developers implementing new kernel objects supporting SIGIO will, in " "general, want to avoid holding structure locks while invoking SIGIO " "supporting functions, such as `fsetown` or `funsetown` to avoid defining a " "lock order between structure locks and the global SIGIO lock. This is " "generally possible through use of an elevated reference count on the " "structure, such as reliance on a file descriptor reference to a pipe during " "a pipe operation." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:224 #, no-wrap msgid "Sysctl" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:227 msgid "" "The `sysctl` MIB service is invoked from both within the kernel and from " "userland applications using a system call. At least two issues are raised in " "locking: first, the protection of the structures maintaining the namespace, " "and second, interactions with kernel variables and functions that are " "accessed by the sysctl interface. Since sysctl permits the direct export " "(and modification) of kernel statistics and configuration parameters, the " "sysctl mechanism must become aware of appropriate locking semantics for " "those variables. Currently, sysctl makes use of a single global sx lock to " "serialize use of `sysctl`; however, it is assumed to operate under Giant and " "other protections are not provided. The remainder of this section speculates " "on locking and semantic changes to sysctl." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:229 msgid "" "Need to change the order of operations for sysctl's that update values from " "read old, copyin and copyout, write new to copyin, lock, read old and write " "new, unlock, copyout. Normal sysctl's that just copyout the old value and " "set a new value that they copyin may still be able to follow the old model. " "However, it may be cleaner to use the second model for all of the sysctl " "handlers to avoid lock operations." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:231 msgid "" "To allow for the common case, a sysctl could embed a pointer to a mutex in " "the SYSCTL_FOO macros and in the struct. This would work for most sysctl's. " "For values protected by sx locks, spin mutexes, or other locking strategies " "besides a single sleep mutex, SYSCTL_PROC nodes could be used to get the " "locking right." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:232 #, no-wrap msgid "Taskqueue" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:235 msgid "" "The taskqueue's interface has two basic locks associated with it in order to " "protect the related shared data. The `taskqueue_queues_mutex` is meant to " "serve as a lock to protect the `taskqueue_queues` TAILQ. The other mutex " "lock associated with this system is the one in the `struct taskqueue` data " "structure. The use of the synchronization primitive here is to protect the " "integrity of the data in the `struct taskqueue`. It should be noted that " "there are no separate macros to assist the user in locking down his/her own " "work since these locks are most likely not going to be used outside of " "[.filename]#kern/subr_taskqueue.c#." msgstr "" #. type: Title == #: documentation/content/en/books/arch-handbook/smp/_index.adoc:237 #, no-wrap msgid "Implementation Notes" msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:239 #, no-wrap msgid "Sleep Queues" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:242 msgid "" "A sleep queue is a structure that holds the list of threads asleep on a wait " "channel. Each thread that is not asleep on a wait channel carries a sleep " "queue structure around with it. When a thread blocks on a wait channel, it " "donates its sleep queue structure to that wait channel. Sleep queues " "associated with a wait channel are stored in a hash table." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:244 msgid "" "The sleep queue hash table holds sleep queues for wait channels that have at " "least one blocked thread. Each entry in the hash table is called a " "sleepqueue chain. The chain contains a linked list of sleep queues and a " "spin mutex. The spin mutex protects the list of sleep queues as well as the " "contents of the sleep queue structures on the list. Only one sleep queue is " "associated with a given wait channel. If multiple threads block on a wait " "channel than the sleep queues associated with all but the first thread are " "stored on a list of free sleep queues in the master sleep queue. When a " "thread is removed from the sleep queue it is given one of the sleep queue " "structures from the master queue's free list if it is not the only thread " "asleep on the queue. The last thread is given the master sleep queue when it " "is resumed. Since threads may be removed from the sleep queue in a different " "order than they are added, a thread may depart from a sleep queue with a " "different sleep queue structure than the one it arrived with." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:246 msgid "" "The `sleepq_lock` function locks the spin mutex of the sleep queue chain " "that maps to a specific wait channel. The `sleepq_lookup` function looks in " "the hash table for the master sleep queue associated with a given wait " "channel. If no master sleep queue is found, it returns `NULL`. The " "`sleepq_release` function unlocks the spin mutex associated with a given " "wait channel." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:248 msgid "" "A thread is added to a sleep queue via the `sleepq_add`. This function " "accepts the wait channel, a pointer to the mutex that protects the wait " "channel, a wait message description string, and a mask of flags. The sleep " "queue chain should be locked via `sleepq_lock` before this function is " "called. If no mutex protects the wait channel (or it is protected by Giant), " "then the mutex pointer argument should be `NULL`. The flags argument " "contains a type field that indicates the kind of sleep queue that the thread " "is being added to and a flag to indicate if the sleep is interruptible " "(`SLEEPQ_INTERRUPTIBLE`). Currently there are only two types of sleep " "queues: traditional sleep queues managed via the `msleep` and `wakeup` " "functions (`SLEEPQ_MSLEEP`) and condition variable sleep queues " "(`SLEEPQ_CONDVAR`). The sleep queue type and lock pointer argument are used " "solely for internal assertion checking. Code that calls `sleepq_add` should " "explicitly unlock any interlock protecting the wait channel after the " "associated sleepqueue chain has been locked via `sleepq_lock` and before " "blocking on the sleep queue via one of the waiting functions." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:250 msgid "" "A timeout for a sleep is set by invoking `sleepq_set_timeout`. The function " "accepts the wait channel and the timeout time as a relative tick count as " "its arguments. If a sleep should be interrupted by arriving signals, the " "`sleepq_catch_signals` function should be called as well. This function " "accepts the wait channel as its only parameter. If there is already a signal " "pending for this thread, then `sleepq_catch_signals` will return a signal " "number; otherwise, it will return 0." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:252 msgid "" "Once a thread has been added to a sleep queue, it blocks using one of the " "`sleepq_wait` functions. There are four wait functions depending on whether " "or not the caller wishes to use a timeout or have the sleep aborted by " "caught signals or an interrupt from the userland thread scheduler. The " "`sleepq_wait` function simply waits until the current thread is explicitly " "resumed by one of the wakeup functions. The `sleepq_timedwait` function " "waits until either the thread is explicitly resumed or the timeout set by an " "earlier call to `sleepq_set_timeout` expires. The `sleepq_wait_sig` function " "waits until either the thread is explicitly resumed or its sleep is aborted. " "The `sleepq_timedwait_sig` function waits until either the thread is " "explicitly resumed, the timeout set by an earlier call to " "`sleepq_set_timeout` expires, or the thread's sleep is aborted. All of the " "wait functions accept the wait channel as their first parameter. In " "addition, the `sleepq_timedwait_sig` function accepts a second boolean " "parameter to indicate if the earlier call to `sleepq_catch_signals` found a " "pending signal." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:254 msgid "" "If the thread is explicitly resumed or is aborted by a signal, then a value " "of zero is returned by the wait function to indicate a successful sleep. If " "the thread is resumed by either a timeout or an interrupt from the userland " "thread scheduler then an appropriate errno value is returned instead. Note " "that since `sleepq_wait` can only return 0 it does not return anything and " "the caller should assume a successful sleep. Also, if a thread's sleep times " "out and is aborted simultaneously then `sleepq_timedwait_sig` will return an " "error indicating that a timeout occurred. If an error value of 0 is returned " "and either `sleepq_wait_sig` or `sleepq_timedwait_sig` was used to block, " "then the function `sleepq_calc_signal_retval` should be called to check for " "any pending signals and calculate an appropriate return value if any are " "found. The signal number returned by the earlier call to " "`sleepq_catch_signals` should be passed as the sole argument to " "`sleepq_calc_signal_retval`." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:256 msgid "" "Threads asleep on a wait channel are explicitly resumed by the " "`sleepq_broadcast` and `sleepq_signal` functions. Both functions accept the " "wait channel from which to resume threads, a priority to raise resumed " "threads to, and a flags argument to indicate which type of sleep queue is " "being resumed. The priority argument is treated as a minimum priority. If a " "thread being resumed already has a higher priority (numerically lower) than " "the priority argument then its priority is not adjusted. The flags argument " "is used for internal assertions to ensure that sleep queues are not being " "treated as the wrong type. For example, the condition variable functions " "should not resume threads on a traditional sleep queue. The " "`sleepq_broadcast` function resumes all threads that are blocked on the " "specified wait channel while `sleepq_signal` only resumes the highest " "priority thread blocked on the wait channel. The sleep queue chain should " "first be locked via the `sleepq_lock` function before calling these " "functions." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:258 msgid "" "A sleeping thread may have its sleep interrupted by calling the " "`sleepq_abort` function. This function must be called with `sched_lock` held " "and the thread must be queued on a sleep queue. A thread may also be removed " "from a specific sleep queue via the `sleepq_remove` function. This function " "accepts both a thread and a wait channel as an argument and only awakens the " "thread if it is on the sleep queue for the specified wait channel. If the " "thread is not on a sleep queue or it is on a sleep queue for a different " "wait channel, then this function does nothing." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:259 #, no-wrap msgid "Turnstiles" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:262 msgid "Compare/contrast with sleep queues." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:264 msgid "Lookup/wait/release. - Describe TDF_TSNOBLOCK race." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:266 msgid "Priority propagation." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:267 #, no-wrap msgid "Details of the Mutex Implementation" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:270 msgid "" "Should we require mutexes to be owned for mtx_destroy() since we can not " "safely assert that they are unowned by anyone else otherwise?" msgstr "" #. type: Title ==== #: documentation/content/en/books/arch-handbook/smp/_index.adoc:271 #, no-wrap msgid "Spin Mutexes" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:274 msgid "Use a critical section..." msgstr "" #. type: Title ==== #: documentation/content/en/books/arch-handbook/smp/_index.adoc:275 #, no-wrap msgid "Sleep Mutexes" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:278 msgid "Describe the races with contested mutexes" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:280 msgid "" "Why it is safe to read mtx_lock of a contested mutex when holding the " "turnstile chain lock." msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:281 #, no-wrap msgid "Witness" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:284 msgid "What does it do" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:286 msgid "How does it work" msgstr "" #. type: Title == #: documentation/content/en/books/arch-handbook/smp/_index.adoc:288 #, no-wrap msgid "Miscellaneous Topics" msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:290 #, no-wrap msgid "Interrupt Source and ICU Abstractions" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:293 msgid "struct isrc" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:295 msgid "pic drivers" msgstr "" #. type: Title === #: documentation/content/en/books/arch-handbook/smp/_index.adoc:296 #, no-wrap msgid "Other Random Questions/Topics" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:299 msgid "Should we pass an interlock into `sema_wait`?" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:301 msgid "Should we have non-sleepable sx locks?" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:303 msgid "Add some info about proper use of reference counts." msgstr "" #. type: Title == #: documentation/content/en/books/arch-handbook/smp/_index.adoc:308 #, no-wrap msgid "Glossary" msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:311 #, no-wrap msgid "atomic" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:313 msgid "" "An operation is atomic if all of its effects are visible to other CPUs " "together when the proper access protocol is followed. In the degenerate case " "are atomic instructions provided directly by machine architectures. At a " "higher level, if several members of a structure are protected by a lock, " "then a set of operations are atomic if they are all performed while holding " "the lock without releasing the lock in between any of the operations." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:315 msgid "See Also operation." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:316 #, no-wrap msgid "block" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:318 msgid "" "A thread is blocked when it is waiting on a lock, resource, or condition. " "Unfortunately this term is a bit overloaded as a result." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:320 #: documentation/content/en/books/arch-handbook/smp/_index.adoc:357 msgid "See Also sleep." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:321 #, no-wrap msgid "critical section" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:323 msgid "" "A section of code that is not allowed to be preempted. A critical section is " "entered and exited using the man:critical_enter[9] API." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:324 #, no-wrap msgid "MD" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:326 msgid "Machine dependent." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:328 msgid "See Also MI." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:329 #, no-wrap msgid "memory operation" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:331 msgid "A memory operation reads and/or writes to a memory location." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:332 #, no-wrap msgid "MI" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:334 msgid "Machine independent." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:336 msgid "See Also MD." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:337 #, no-wrap msgid "operation" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:339 msgid "See memory operation." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:340 #, no-wrap msgid "primary interrupt context" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:342 msgid "" "Primary interrupt context refers to the code that runs when an interrupt " "occurs. This code can either run an interrupt handler directly or schedule " "an asynchronous interrupt thread to execute the interrupt handlers for a " "given interrupt source." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:343 #, no-wrap msgid "realtime kernel thread" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:345 msgid "" "A high priority kernel thread. Currently, the only realtime priority kernel " "threads are interrupt threads." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:347 msgid "See Also thread." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:348 #, no-wrap msgid "sleep" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:350 msgid "" "A thread is asleep when it is blocked on a condition variable or a sleep " "queue via msleep or tsleep." msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:352 msgid "See Also block." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:353 #, no-wrap msgid "sleepable lock" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:355 msgid "" "A sleepable lock is a lock that can be held by a thread which is asleep. " "Lockmgr locks and sx locks are currently the only sleepable locks in " "FreeBSD. Eventually, some sx locks such as the allproc and proctree locks " "may become non-sleepable locks." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:358 #, no-wrap msgid "thread" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:360 msgid "" "A kernel thread represented by a struct thread. Threads own locks and hold a " "single execution context." msgstr "" #. type: Labeled list #: documentation/content/en/books/arch-handbook/smp/_index.adoc:361 #, no-wrap msgid "wait channel" msgstr "" #. type: Plain text #: documentation/content/en/books/arch-handbook/smp/_index.adoc:363 msgid "A kernel virtual address that threads may sleep on." msgstr ""