Age | Commit message (Collapse) | Author |
|
Rename THREAD_RESCHEDULE to THREAD_YIELD and thread_reschedule to
thread_yield for better clarity, and add the thread_schedule inline
function that checks for the THREAD_YIELD flag before calling
thread_yield (yielding only checks if preemption is enabled).
|
|
|
|
Refer to scheduling class data instead of context.
|
|
Address 0 is commonly used to report allocation errors, in particular to
the kmem module, which itself returns NULL on failure.
|
|
|
|
|
|
The kernel image is loaded where the kernel space ends. The previous end
address left 2 MiB to the kernel image. Since boot stacks are now statically
allocated, a kernel configured for a large number of processors would
overflow the area reserved for the kernel image. Reduce the kernel space
end address so that 64 MiB are now available for the kernel image.
|
|
This minor change groups the reset/commit and register/unregister functions
together for better discoverability.
|
|
This change makes reset requests write both the per-processor flag as well as
the checkpoint bitmap atomically, and adjusts the module logic accordingly.
It fixes a race between checkpoint reset and system timer interrupts where
the timer interrupt would make the local processor commit its checkpoint
although it can't be reliably determined that it reached a checkpoint since
the last global checkpoint, because the reset interrupt wasn't received yet.
This problem would rarely happen on real hardware because of the near-instant
handling of IPIs, but it was observed on virtual machines.
|
|
Intuitively, registering the first processor should trigger a global
checkpoint to get the lockless synchronization system started. It is
possible, however, that this case occurs frequently on idle systems,
where processors are normally not registered, and only perform load
balancing. It can also happen that a processor determines itself as
the only registered one whereas reset interrupts have not yet been
processed, in which case a global checkpoint should just not occur.
The real condition for a global checkpoint is the number of pending
checkpoints reaching 0.
|
|
Move code handling the unregistration of the last processor in the global
checkpoint processing function, where list management actually occurs.
|
|
Not strictly required, but makes things simpler at virtually no cost.
|
|
|
|
Keep a local copy of a processor registration state to avoid acquiring the
global lock when attempting to commit a checkpoint from an unregistered
processor.
|
|
|
|
|
|
Processor affinity can be set before a thread is created, but currently not
changed afterwards.
|
|
|
|
GCC already assumes the condition code register (eflags) is always
clobbered on this architecture.
|
|
Using complete names instead of forging them actually helps clarity.
|
|
|
|
|
|
This reverts a change brought when reworking slab lists handling that made
the allocator store slabs in LIFO order, whatever their reference count.
While it's fine for free slabs, it actually increased fragmentation for
partial slabs.
|
|
The kernel task was inserted instead of the newly created task on task
creation (!). Fix that dumb mistake. In addition, insert the new task at
the end of the task list.
|
|
This change increases clarity.
|
|
Not a necessary change, but done for consistency.
|
|
The correct type for run queue or processor identifiers is unsigned int.
The signed variant was used because of the bitmap interface, but there will
never be enough processors to trigger a problem with it, while using signed
integers can quickly mess things up.
|
|
Although the dinstinction between those and the public interface was already
easy to make, it's a bit more consistent and elegant this way.
|
|
Balancer threads use their own version of thread_sleep because they have to
keep the run queue locked after pulling threads, otherwise remote balancers
might pull threads from a run queue right before a scheduling decision is
made, possibly putting the run queue in a state where only expired threads
remain.
Although this might be relaxed in the future, this is how it's currently
done, and a clear note in the main balancer function definitely helps against
breaking that part.
|
|
Not required nor used, but done for consistency.
|
|
|
|
|
|
This module provides lockless synchronization so that reads can safely occur
during updates, without holding a lock. It is based on passive serialization
as described in US patent 4809168, and achieves a goal similar to Linux RCU
(Read-Copy Update).
|
|
The upcoming lockless synchronization implementation requires the idle loop
to report when it's about to enter/leave the idle state. Preemption must be
disabled to accomplish that.
|
|
The idle loop is being reworked and requires this change.
|
|
These inter-processor interrupts will be used by the upcoming llsync module
implementing lockless synchronization.
|
|
|
|
|
|
|
|
|
|
|
|
Rename sched_policy to policy.
|
|
|
|
|
|
|
|
The memory barrier semantics of locks already provide all the required
ordering when checking for pinned threads.
|
|
|
|
Don't enforce strong ordering of partial slabs. Separating partial slabs
from free slabs is already effective against fragmentation, and sorting
would sometimes cause pathological scalability issues. In addition, store
new slabs (whether free or partial) in LIFO order for better cache usage.
|
|
|
|
As it's done for other modules, this separation makes the public interface
easy to identify.
|