Commit graph

50 commits

Author SHA1 Message Date
Jelle Raaijmakers
14fc05e912 Kernel: Verify mutex big lock behavior
These two methods are big lock specific, so verify our mutex' behavior.
2022-04-09 15:55:20 +02:00
Jelle Raaijmakers
bb02e9a7b9 Kernel: Unblock big lock waiters correctly
If the regular exclusive and shared lists were empty (which they
always should be for the big lock), we were not unblocking any waiters.
2022-04-09 15:55:20 +02:00
Jelle Raaijmakers
7826729ab2 Kernel: Track big lock blocked threads in separate list
When we lock a mutex, eventually `Thread::block` is invoked which could
in turn invoke `Process::big_lock().restore_exclusive_lock()`. This
would then try to add the current thread to a different blocked thread
list then the one in use for the original mutex being locked, and
because it's an intrusive list, the thread is removed from its original
list during the `.append()`. When the original mutex eventually
unblocks, we no longer have the thread in the intrusive blocked threads
list and we panic.

Solve this by making the big lock mutex special and giving it its own
blocked thread list. Because the process big lock is temporary and is
being actively removed from e.g. syscalls, it's a matter of time before
we can also remove the fix introduced by this commit.

Fixes issue #9401.
2022-04-06 18:27:19 +02:00
Andreas Kling
b28beb691e Kernel: Protect Mutex's thread lists with a spinlock 2022-04-05 14:44:50 +02:00
Idan Horowitz
086969277e Everywhere: Run clang-format 2022-04-01 21:24:45 +01:00
Andreas Kling
71792e4b3f Kernel: Make SpinlockProtected constructor forward all arguments
This allows you to instantiate SpinlockProtected<T> where T requires
constructor arguments.
2022-03-08 00:19:49 +01:00
Andreas Kling
b0e5406ae2 Kernel: Update terminology around Thread's "blocking mutex"
It's more accurate to say that we're blocking on a mutex, rather than
blocking on a lock. The previous terminology made sense when this code
was using something called Kernel::Lock, but since it was renamed to
Kernel::Mutex, this updates brings the language back in sync.
2022-01-30 16:21:59 +01:00
Idan Horowitz
e28af4a2fc Kernel: Stop using HashMap in Mutex
This commit removes the usage of HashMap in Mutex, thereby making Mutex
be allocation-free.

In order to achieve this several simplifications were made to Mutex,
removing unused code-paths and extra VERIFYs:
 * We no longer support 'upgrading' a shared lock holder to an
   exclusive holder when it is the only shared holder and it did not
   unlock the lock before relocking it as exclusive. NOTE: Unlike the
   rest of these changes, this scenario is not VERIFY-able in an
   allocation-free way, as a result the new LOCK_SHARED_UPGRADE_DEBUG
   debug flag was added, this flag lets Mutex allocate in order to
   detect such cases when debugging a deadlock.
 * We no longer support checking if a Mutex is locked by the current
   thread when the Mutex was not locked exclusively, the shared version
   of this check was not used anywhere.
 * We no longer support force unlocking/relocking a Mutex if the Mutex
   was not locked exclusively, the shared version of these functions
   was not used anywhere.
2022-01-29 16:45:39 +01:00
Andreas Kling
8f3b3af5ea Kernel: Remove no-longer-used Lockable template 2021-12-26 21:22:59 +01:00
Hendiadyoin1
e5cf395a54 Kernel: Collapse blocking logic for exclusive Mutex' restore_lock()
Clang-tidy pointed out that the `need_to_block = true;` block was
duplicate, and if we collapse these if statements, we should do so
fully.
2021-12-15 23:34:11 -08:00
Hendiadyoin1
1ad4a190b5 Kernel: Add implied auto-specifiers in Locking
As per clang-tidy.
2021-12-15 23:34:11 -08:00
Hendiadyoin1
a7209ca0f9 Kernel: Add missing includes in Locking 2021-12-15 23:34:11 -08:00
James Mintram
e8f09279d3 Kernel: Move spinlock into Arch
Spinlocks are tied to the platform they are built for, this is why they
have been moved into the Arch folder. They are still available via
"Locking/Spinlock.h"

An Aarch64 stub has been created
2021-10-15 21:48:45 +01:00
James Mintram
545ce5b595 Kernel: Add per platform Processor.h headers
The platform independent Processor.h file includes the shared processor
code and includes the specific platform header file.

All references to the Arch/x86/Processor.h file have been replaced with
a reference to Arch/Processor.h.
2021-10-14 01:23:08 +01:00
Brian Gianforcaro
fbb31b4519 Kernel: Disable lock rank enforcement by default for now
There are a few violations with signal handling that I won't be able to
fix it until later this week. So lets put lock rank enforcement under a
debug option for now so other folks don't hit these crashes until rank
enforcement is more fleshed out.
2021-09-14 18:31:16 +00:00
Ali Mohammad Pur
5a0cdb15b0 AK+Everywhere: Reduce the number of template parameters of IntrusiveList
This makes the user-facing type only take the node member pointer, and
lets the compiler figure out the other needed types from that.
2021-09-10 18:05:46 +03:00
Idan Horowitz
7bb3b2839e Kernel: Fix a typo in LockRank::Process's comment 2021-09-08 19:17:07 +03:00
Brian Gianforcaro
f6b1517426 Kernel/Locking: Add lock rank tracking to Spinlock/RecursiveSpinlock 2021-09-07 13:16:01 +02:00
Brian Gianforcaro
066b0590ec Kernel/Locking: Add lock rank tracking per thread to find deadlocks
This change adds a static lock hierarchy / ranking to the Kernel with
the goal of reducing / finding deadlocks when running with SMP enabled.

We have seen quite a few lock ordering deadlocks (locks taken in a
different order, on two different code paths). As we properly annotate
locks in the system, then these facilities will find these locking
protocol violations automatically

The `LockRank` enum documents the various locks in the system and their
rank. The implementation guarantees that a thread holding one or more
locks of a lower rank cannot acquire an additional lock with rank that
is greater or equal to any of the currently held locks.
2021-09-07 13:16:01 +02:00
Brian Gianforcaro
bb58a4d943 Kernel: Make all Spinlocks use u8 for storage, remove template
The default template argument is only used in one place, and it
looks like it was probably just an oversight. The rest of the Kernel
code all uses u8 as the type. So lets make that the default and remove
the unused template argument, as there doesn't seem to be a reason to
allow the size to be customizable.
2021-09-05 20:46:02 +02:00
Brian Gianforcaro
472454cded Kernel: Switch static_asserts of a type size to AK::AssertSize
This will provide better debug ability when the size comparison fails.
2021-09-05 20:08:57 +02:00
Brian Gianforcaro
9d1b27263f Kernel: Declare type aliases with "using" instead of "typedef"
This is the idiomatic way to declare type aliases in modern C++.
Flagged by Sonar Cloud as a "Code Smell", but I happen to agree
with this particular one. :^)
2021-09-05 09:48:43 +01:00
Andreas Kling
68bf6db673 Kernel: Rename Spinlock::is_owned_by_current_thread()
...to is_owned_by_current_processor(). As Tom pointed out, this is
much more accurate. :^)
2021-08-29 22:19:42 +02:00
Andreas Kling
0b4671add7 Kernel: {Mutex,Spinlock}::own_lock() => is_locked_by_current_thread()
Rename these API's to make it more clear what they are checking.
2021-08-29 12:53:11 +02:00
Andreas Kling
6ae60137d7 Kernel: Use StringView instead of C strings in Mutex 2021-08-29 02:21:01 +02:00
Andrew Kaster
72de228695 Kernel: Verify interrupts are disabled when interacting with Mutexes
This should help prevent deadlocks where a thread blocks on a Mutex
while interrupts are disabled, and makes it impossible for the holder of
the Mutex to make forward progress because it cannot be scheduled in.

Hide it behind a new debug macro LOCK_IN_CRITICAL_DEBUG for now, because
Ext2FS takes a series of Mutexes from the page fault handler, which
executes with interrupts disabled.
2021-08-28 20:53:38 +02:00
Andreas Kling
a8967388d3 Kernel: Remove unused ScopedLockRelease class 2021-08-23 02:17:02 +02:00
Andreas Kling
d60635cb9d Kernel: Convert Processor::in_irq() to static current_in_irq()
This closes the race window between Processor::current() and a context
switch happening before in_irq().
2021-08-23 00:02:09 +02:00
Andreas Kling
c922a7da09 Kernel: Rename ScopedSpinlock => SpinlockLocker
This matches MutexLocker, and doesn't sound like it's a lock itself.
2021-08-22 03:34:10 +02:00
Andreas Kling
55adace359 Kernel: Rename SpinLock => Spinlock 2021-08-22 03:34:10 +02:00
Andreas Kling
7d5d26b048 Kernel: Simplify SpinLockProtected<T>
Same treatment as MutexProtected<T>: inheritance and helper class is
removed, SpinLockProtected now holds a T and a SpinLock.
2021-08-22 03:34:09 +02:00
Andreas Kling
ed6f84c2c9 Kernel: Rename SpinLockProtectedValue<T> => SpinLockProtected<T> 2021-08-22 03:34:09 +02:00
Andreas Kling
532ffa7ddb Kernel: Simplify MutexProtected<T>
This patch removes the MutexContendedResource<T> helper class,
and MutexProtected<T> no longer inherits from T.
Instead, MutexProtected<T> simply has a T and a Mutex.

The LockedResource<T, LockMode> helper class is made a private nested
class in MutexProtected.
2021-08-22 03:34:09 +02:00
Andreas Kling
c2fc33becd Kernel: Rename ProtectedValue<T> => MutexProtected<T>
Let's make it obvious what we're protecting it with.
2021-08-22 03:34:09 +02:00
Andreas Kling
81d990b551 Kernel: Remove some unused classes from Kernel/Locking/ 2021-08-22 03:34:09 +02:00
Brian Gianforcaro
464dc42640 Kernel: Convert lock debug APIs to east const 2021-08-13 20:42:39 +02:00
Brian Gianforcaro
bffcb3e92a Kernel: Add lock debugging to ProtectedValue / RefCountedContended
Enable the LOCK_DEBUG functionality for these new APIs, as it looks
like we want to move the whole system to use this in the not so distant
future. :^)
2021-08-13 20:42:39 +02:00
Brian Gianforcaro
bea74f4b77 Kernel: Reduce LOCK_DEBUG ifdefs by utilizing Kernel::LockLocation
The LOCK_DEBUG conditional code is pretty ugly for a feature that we
only use rarely. We can remove a significant amount of this code by
utilizing a zero sized fake type when not building in LOCK_DEBUG mode.

This lets us keep the same API, but just let the compiler optimize it
away when don't actually care about the location the caller came from.
2021-08-13 20:42:39 +02:00
Brian Gianforcaro
6c18b4e558 Kernel: Introduce LockLocation abstraction from SourceLocation
Introduce a zero sized type to represent a SourceLocation, when we
don't want to compile with SourceLocation support.
2021-08-13 20:42:39 +02:00
Andreas Kling
7f50805903 Kernel/SMP: Fix RecursiveSpinLock remembering the wrong CPU when locking
We have to disable interrupts before capturing the current Processor*,
or we risk storing the wrong one if we get preempted and resume on a
different CPU.

Caught by the VERIFY in RecursiveSpinLock::unlock()
2021-08-11 12:34:55 +02:00
Andreas Kling
0a02496f04 Kernel/SMP: Change critical sections to not disable interrupts
Leave interrupts enabled so that we can still process IRQs. Critical
sections should only prevent preemption by another thread.

Co-authored-by: Tom <tomut@yahoo.com>
2021-08-10 02:49:37 +02:00
Andreas Kling
9babb92a4b Kernel/SMP: Make entering/leaving critical sections multi-processor safe
By making these functions static we close a window where we could get
preempted after calling Processor::current() and move to another
processor.

Co-authored-by: Tom <tomut@yahoo.com>
2021-08-10 02:49:37 +02:00
Jean-Baptiste Boric
75260bff92 Kernel: Introduce ProtectedValue
A protected value is a variable with enforced locking semantics. The
value is protected with a Mutex and can only be accessed through a
Locked object that holds a MutexLocker to said Mutex. Therefore, the
value itself cannot be accessed except through the proper locking
mechanism, which enforces correct locking semantics.

The Locked object has knowledge of shared and exclusive lock types and
will only return const-correct references and pointers. This should
help catch incorrect locking usage where a shared lock is acquired but
the user then modifies the locked value.

This is not a perfect solution because dereferencing the Locked object
returns the value, so the caller could defeat the protected value
semantics once it acquires a lock by keeping a pointer or a reference
to the value around. Then again, this is C++ and we can't protect
against malicious users from within the kernel anyways, but we can
raise the threshold above "didn't pay attention".
2021-08-07 11:48:00 +02:00
Jean-Baptiste Boric
39ceefa5dd Kernel: Implement contended, ref-counted resource framework
This is some syntaxic sugar to use a ContendedResource object with
reference counting. This effectively dissociates merely holding a
reference to an object and actually using the object in a way that
requires locking it against concurrent use.
2021-08-07 11:48:00 +02:00
Jean-Baptiste Boric
019ad8a507 Kernel: Introduce spin-locked contended and locked resource concepts 2021-08-07 11:48:00 +02:00
Jean-Baptiste Boric
3d684316c2 Kernel: Introduce contended and locked resource concepts 2021-08-07 11:48:00 +02:00
Jean-Baptiste Boric
aea98a85d1 Kernel: Move Lockable into its own header 2021-08-07 11:48:00 +02:00
Jean-Baptiste Boric
2c3b0baf76 Kernel: Move SpinLock.h into Locking/ 2021-08-07 11:48:00 +02:00
Jean-Baptiste Boric
f7f794e74a Kernel: Move Mutex into Locking/ 2021-08-07 11:48:00 +02:00
Jean-Baptiste Boric
479b07339c Kernel: Move LockMode into Locking/ 2021-08-07 11:48:00 +02:00