Skip to content

Commit

Permalink
kernel: add comments to the implementation of spin lock
Browse files Browse the repository at this point in the history
  • Loading branch information
jjwang committed Sep 21, 2024
1 parent d66ba6a commit 374e3e2
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 11 deletions.
49 changes: 42 additions & 7 deletions kernel/base/lock.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
/**-----------------------------------------------------------------------------
@file lock.c
@brief Implementation of spin lock related functions
@details
@verbatim
There are a few atomic operations on the x86 processor that set and compare
memory or registers, that can be used as the basis of a spin lock.
See below implementation for details.
Note that when any task acquires spin lock, the system interrupts will be
disabled. When this task releases the corresponding spin lock, interrupts
will be enabled. So if some tasks acquire spin lock twice, it will block task
scheduler and system will fall into DEAD busy loop.
@endverbatim
**-----------------------------------------------------------------------------
*/


#include <base/lock.h>
#include <base/klog.h>

Expand All @@ -9,15 +31,22 @@ void lock_lock_impl(lock_t *s, const char *fn, const int ln)
asm volatile(
"pushfq;"
"cli;"
"lock btsl $0, %[lock];"
"jnc 2f;"
"1:"
"lock;" /* Make the next instruction atomic */
"btsl $0, %[lock];" /* The Bit Test and Set Long (btsl): the Carry Flag
* (CF) is set if the value of the 0th bit of
* register operand %[lock] before the instruction
* executes is 1, and in any case sets the 0th bit
* of %[lock] to 1. Here, $0 denotes an immediate
* operand with value zero. */
"jnc 2f;" /* Jump if Carry Flag is not set (zero) */
"1:" /* Loop to check %[lock] */
"pause;"
"btl $0, %[lock];"
"jc 1b;"
"lock btsl $0, %[lock];"
"lock;"
"btsl $0, %[lock];"
"jc 1b;"
"2:"
"2:" /* Get the lock which is free */
"pop %[flags]"
: [lock] "=m"((s)->lock), [flags] "=m"((s)->rflags)
:
Expand All @@ -29,11 +58,17 @@ void lock_release_impl(lock_t *s, const char *fn, const int ln)
(void)fn;
(void)ln;

/* The below Bit Test and Reset Long (btrl) instruction stores the value
* of the zeroth bit of the operand into the CF flag, and clears the bit
* in the memory operand.
*/
asm volatile("push %[flags];"
"lock btrl $0, %[lock];"
"popfq;"
"lock;"
"btrl $0, %[lock];"
"popfq;"
: [lock] "=m"((s)->lock)
: [flags] "m"((s)->rflags)
: "memory", "cc");
}


14 changes: 10 additions & 4 deletions kernel/base/lock.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
/**-----------------------------------------------------------------------------
@file lock.h
@brief Definition of lock related data structures and functions
@brief Definition of spin lock related data structures and functions
@details
@verbatim
e.g., lock new, lock and release.
Busy waiting is a technique in which a process repeatedly checks to see if a
condition is true (from Wikipedia).
Spinlock uses the above technique for the purpose of checking if a lock is
available.
Three functions are implemented here: init (new), acquire (lock) and release.
@endverbatim
Expand All @@ -17,7 +23,8 @@
#include <stdint.h>

typedef volatile struct {
int lock;
uint32_t lock; /* The value is zero if-and-only-if the lock is
* in the unlocked stated */
uint64_t rflags;
} lock_t;

Expand All @@ -28,4 +35,3 @@ typedef volatile struct {
void lock_lock_impl(lock_t *s, const char *fn, const int ln);
void lock_release_impl(lock_t *s, const char *fn, const int ln);


0 comments on commit 374e3e2

Please sign in to comment.