CS350 COS
COS
Loading...
Searching...
No Matches
spinlock.c File Reference
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <sys/kassert.h>
#include <sys/kconfig.h>
#include <sys/kdebug.h>
#include <sys/ktime.h>
#include <sys/mp.h>
#include <sys/spinlock.h>
#include <machine/atomic.h>
#include <machine/amd64.h>
#include <machine/amd64op.h>
Include dependency graph for spinlock.c:

Go to the source code of this file.

Functions

 LIST_HEAD (LockListHead, Spinlock)
 
void Spinlock_Init (Spinlock *lock, const char *name, uint64_t type)
 
void Spinlock_Destroy (Spinlock *lock)
 
void Spinlock_Lock (Spinlock *lock) __NO_LOCK_ANALYSIS
 
void Spinlock_Unlock (Spinlock *lock) __NO_LOCK_ANALYSIS
 
bool Spinlock_IsHeld (Spinlock *lock)
 
void Debug_Spinlocks (int argc, const char *argv[])
 
 REGISTER_DBGCMD (spinlocks, "Display list of spinlocks", Debug_Spinlocks)
 
void Debug_LockStack (int argc, const char *argv[])
 
 REGISTER_DBGCMD (lockstack, "Display stack of held spinlocks", Debug_LockStack)
 

Variables

Spinlock lockListLock
 

Function Documentation

◆ Debug_LockStack()

void Debug_LockStack ( int  argc,
const char *  argv[] 
)

Definition at line 152 of file spinlock.c.

153{
154 int c = CPU();
155 Spinlock *lock;
156
157 kprintf("Lock Stack:\n");
158 TAILQ_FOREACH(lock, &lockStack[c], lockStack) {
159 kprintf(" %s\n", lock->name);
160 }
161}
#define CPU
Definition: mp.h:7
int kprintf(const char *fmt,...)
Definition: printf.c:210
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:557
char name[SPINLOCK_NAMELEN]
Definition: spinlock.h:25
Here is the call graph for this function:

◆ Debug_Spinlocks()

void Debug_Spinlocks ( int  argc,
const char *  argv[] 
)

Definition at line 132 of file spinlock.c.

133{
134 Spinlock *lock;
135
137
138 kprintf("%-36s Locked CPU Count WaitTime LockTime\n", "Lock Name");
139 LIST_FOREACH(lock, &lockList, lockList)
140 {
141 kprintf("%-36s %6llu %3llu %8llu %12llu %12llu\n", lock->name,
142 lock->lock, lock->cpu, lock->count,
143 lock->waitTime, lock->lockTime);
144 }
145
147}
#define LIST_FOREACH(var, head, field)
Definition: queue.h:410
Spinlock lockListLock
Definition: spinlock.c:21
void Spinlock_Unlock(Spinlock *lock) __NO_LOCK_ANALYSIS
Definition: spinlock.c:109
void Spinlock_Lock(Spinlock *lock) __NO_LOCK_ANALYSIS
Definition: spinlock.c:75
uint64_t cpu
Definition: spinlock.h:18
uint64_t count
Definition: spinlock.h:19
volatile uint64_t lock
Definition: spinlock.h:17
uint64_t lockTime
Definition: spinlock.h:21
uint64_t waitTime
Definition: spinlock.h:22
Here is the call graph for this function:

◆ LIST_HEAD()

LIST_HEAD ( LockListHead  ,
Spinlock   
)

Definition at line 26 of file spinlock.c.

34{
35 int c;
36
37 for (c = 0; c < MAX_CPUS; c++) {
38 TAILQ_INIT(&lockStack[c]);
39 }
40}
#define MAX_CPUS
Definition: kconfig.h:8
#define TAILQ_INIT(head)
Definition: queue.h:597

◆ REGISTER_DBGCMD() [1/2]

REGISTER_DBGCMD ( lockstack  ,
"Display stack of held spinlocks"  ,
Debug_LockStack   
)

◆ REGISTER_DBGCMD() [2/2]

REGISTER_DBGCMD ( spinlocks  ,
"Display list of spinlocks"  ,
Debug_Spinlocks   
)

◆ Spinlock_Destroy()

void Spinlock_Destroy ( Spinlock lock)

Definition at line 61 of file spinlock.c.

62{
64 LIST_REMOVE(lock, lockList);
66}
#define LIST_REMOVE(elm, field)
Definition: queue.h:465
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Spinlock_Init()

void Spinlock_Init ( Spinlock lock,
const char *  name,
uint64_t  type 
)

Definition at line 43 of file spinlock.c.

44{
45 lock->lock = 0;
46 lock->cpu = 0;
47 lock->count = 0;
48 lock->rCount = 0;
49 lock->lockTime = 0;
50 lock->waitTime = 0;
51 lock->type = type;
52
53 strncpy(&lock->name[0], name, SPINLOCK_NAMELEN);
54
56 LIST_INSERT_HEAD(&lockList, lock, lockList);
58}
uint32_t type
Definition: multiboot.h:8
#define LIST_INSERT_HEAD(head, elm, field)
Definition: queue.h:451
#define SPINLOCK_NAMELEN
Definition: spinlock.h:10
char * strncpy(char *to, const char *from, size_t len)
Definition: string.c:34
uint64_t type
Definition: spinlock.h:24
uint64_t rCount
Definition: spinlock.h:20
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Spinlock_IsHeld()

bool Spinlock_IsHeld ( Spinlock lock)

Definition at line 126 of file spinlock.c.

127{
128 return (lock->cpu == CPU()) && (lock->lock == 1);
129}
Here is the caller graph for this function:

◆ Spinlock_Lock()

void Spinlock_Lock ( Spinlock lock)

Spinlock_Lock –

Spin until we acquire the spinlock. This will also disable interrupts to prevent deadlocking with interrupt handlers.

Definition at line 75 of file spinlock.c.

76{
77 uint64_t startTSC;
79
80 startTSC = Time_GetTSC();
81 while (atomic_swap_uint64(&lock->lock, 1) == 1)
82 {
83 if (lock->type == SPINLOCK_TYPE_RECURSIVE && lock->cpu == CPU()) {
84 break;
85 }
86 if ((Time_GetTSC() - startTSC) / ticksPerSecond > 1) {
87 kprintf("Spinlock_Lock(%s): waiting for over a second!\n", lock->name);
88 breakpoint();
89 }
90 }
91 lock->waitTime += Time_GetTSC() - startTSC;
92
93 lock->cpu = CPU();
94 lock->count++;
95
96 lock->rCount++;
97 if (lock->rCount == 1)
98 lock->lockedTSC = Time_GetTSC();
99
100 TAILQ_INSERT_TAIL(&lockStack[CPU()], lock, lockStack);
101}
static INLINE void breakpoint()
Definition: amd64op.h:29
static INLINE uint64_t atomic_swap_uint64(volatile uint64_t *dst, uint64_t newval)
Definition: atomic.h:15
void Critical_Enter()
Definition: critical.c:28
uint64_t ticksPerSecond
Definition: ktime.c:17
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:641
#define SPINLOCK_TYPE_RECURSIVE
Definition: spinlock.h:13
uint64_t lockedTSC
Definition: spinlock.h:23
uint64_t Time_GetTSC()
Definition: time.c:13
unsigned long uint64_t
Definition: types.h:13
Here is the call graph for this function:

◆ Spinlock_Unlock()

void Spinlock_Unlock ( Spinlock lock)

Spinlock_Unlock –

Release the spinlock. This will re-enable interrupts.

Definition at line 109 of file spinlock.c.

110{
111 ASSERT(lock->cpu == CPU());
112
113 TAILQ_REMOVE(&lockStack[CPU()], lock, lockStack);
114
115 lock->rCount--;
116 if (lock->rCount == 0) {
117 lock->cpu = 0;
118 lock->lockTime += Time_GetTSC() - lock->lockedTSC;
119 atomic_set_uint64(&lock->lock, 0);
120 }
121
123}
static void atomic_set_uint64(volatile uint64_t *dst, uint64_t newval)
Definition: atomic.h:24
void Critical_Exit()
Definition: critical.c:35
#define ASSERT(_x)
Definition: kassert.h:8
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:659
Here is the call graph for this function:

Variable Documentation

◆ lockListLock

Spinlock lockListLock
Initial value:
= {
0, 0, 0, 0, 0, 0, 0,
"SPINLOCK LIST",
}
#define SPINLOCK_TYPE_NORMAL
Definition: spinlock.h:12

Definition at line 21 of file spinlock.c.