101 lines
2.1 KiB
C
101 lines
2.1 KiB
C
|
|
#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>
|
|
|
|
Spinlock lockListLock = { 0, 0, 0, 0, 0, 0, "SPINLOCK LIST" };
|
|
LIST_HEAD(LockListHead, Spinlock) lockList = LIST_HEAD_INITIALIZER(lockList);
|
|
|
|
extern uint64_t ticksPerSecond;
|
|
|
|
void
|
|
Spinlock_Init(Spinlock *lock, const char *name)
|
|
{
|
|
lock->lock = 0;
|
|
lock->cpu = 0;
|
|
lock->count = 0;
|
|
lock->lockTime = 0;
|
|
lock->waitTime = 0;
|
|
|
|
strncpy(&lock->name[0], name, SPINLOCK_NAMELEN);
|
|
|
|
Spinlock_Lock(&lockListLock);
|
|
LIST_INSERT_HEAD(&lockList, lock, lockList);
|
|
Spinlock_Unlock(&lockListLock);
|
|
}
|
|
|
|
void
|
|
Spinlock_Destroy(Spinlock *lock)
|
|
{
|
|
Spinlock_Lock(&lockListLock);
|
|
LIST_REMOVE(lock, lockList);
|
|
Spinlock_Unlock(&lockListLock);
|
|
}
|
|
|
|
void
|
|
Spinlock_Lock(Spinlock *lock)
|
|
{
|
|
uint64_t startTSC;
|
|
Critical_Enter();
|
|
|
|
startTSC = Time_GetTSC();
|
|
while (atomic_swap_uint64(&lock->lock, 1) == 1)
|
|
{
|
|
if ((Time_GetTSC() - startTSC) / ticksPerSecond > 1) {
|
|
kprintf("Spinlock_Lock(%s): waiting for over a second!\n", lock->name);
|
|
}
|
|
}
|
|
lock->waitTime += Time_GetTSC() - startTSC;
|
|
|
|
lock->cpu = CPU();
|
|
lock->count++;
|
|
lock->lockedTSC = Time_GetTSC();
|
|
}
|
|
|
|
void
|
|
Spinlock_Unlock(Spinlock *lock)
|
|
{
|
|
lock->cpu = 0;
|
|
lock->lockTime += Time_GetTSC() - lock->lockedTSC;
|
|
|
|
atomic_set_uint64(&lock->lock, 0);
|
|
|
|
Critical_Exit();
|
|
}
|
|
|
|
bool
|
|
Spinlock_IsHeld(Spinlock *lock)
|
|
{
|
|
return (lock->cpu == CPU()) && (lock->lock == 1);
|
|
}
|
|
|
|
void
|
|
Debug_Spinlocks(int argc, const char *argv[])
|
|
{
|
|
Spinlock *lock;
|
|
|
|
Spinlock_Lock(&lockListLock);
|
|
|
|
kprintf("%-36s Locked CPU Count WaitTime LockTime\n", "Lock Name");
|
|
LIST_FOREACH(lock, &lockList, lockList)
|
|
{
|
|
kprintf("%-36s %6llu %3llu %8llu %12llu %12llu\n", lock->name,
|
|
lock->lock, lock->cpu, lock->count,
|
|
lock->waitTime, lock->lockTime);
|
|
}
|
|
|
|
Spinlock_Unlock(&lockListLock);
|
|
}
|
|
|
|
REGISTER_DBGCMD(spinlocks, "Display list of spinlocks", Debug_Spinlocks);
|
|
|