提交 da450a4f 创建 作者: Austin Clements's avatar Austin Clements

Support static construction of lockstat-enabled locks

This works by lazily allocating a lock's klockstat structure when the lock is first acquired.
上级 b6308520
#pragma once #pragma once
#include "lockstat.h" #include "lockstat.h"
#if LOCKSTAT
extern klockstat klockstat_lazy;
#endif
// Mutual exclusion lock. // Mutual exclusion lock.
struct spinlock { struct spinlock {
u32 locked; // Is the lock held? u32 locked; // Is the lock held?
...@@ -29,16 +33,15 @@ struct spinlock { ...@@ -29,16 +33,15 @@ struct spinlock {
#endif #endif
{ } { }
// Create a spinlock without lockstat tracking. This is constexpr, // Create a spinlock. This is constexpr, so it can be used for
// so it can be used for global spinlocks without incurring a static // global spinlocks without incurring a static constructor.
// constructor. constexpr spinlock(const char *name, bool lockstat = false)
constexpr spinlock(const char *name)
: locked(0) : locked(0)
#if SPINLOCK_DEBUG #if SPINLOCK_DEBUG
, name(name), cpu(nullptr), pcs{} , name(name), cpu(nullptr), pcs{}
#endif #endif
#if LOCKSTAT #if LOCKSTAT
, stat(nullptr) , stat(lockstat ? nullptr : &klockstat_lazy)
#endif #endif
{ } { }
}; };
......
...@@ -13,8 +13,14 @@ ...@@ -13,8 +13,14 @@
#include "major.h" #include "major.h"
#if LOCKSTAT #if LOCKSTAT
// The klockstat structure pointed to by spinlocks that want lockstat,
// but have never been acquired.
struct klockstat klockstat_lazy("<lazy>");
static int lockstat_enable; static int lockstat_enable;
void lockstat_init(struct spinlock *lk, bool lazy);
static inline struct cpulockstat * static inline struct cpulockstat *
mylockstat(struct spinlock *lk) mylockstat(struct spinlock *lk)
{ {
...@@ -49,8 +55,11 @@ locking(struct spinlock *lk) ...@@ -49,8 +55,11 @@ locking(struct spinlock *lk)
#endif #endif
#if LOCKSTAT #if LOCKSTAT
if (lockstat_enable && lk->stat != nullptr) if (lockstat_enable && lk->stat != nullptr) {
if (lk->stat == &klockstat_lazy)
lockstat_init(lk, true);
mylockstat(lk)->locking_ts = rdtsc(); mylockstat(lk)->locking_ts = rdtsc();
}
#endif #endif
mtlock(lk); mtlock(lk);
...@@ -128,12 +137,21 @@ klockstat::klockstat(const char *name) : ...@@ -128,12 +137,21 @@ klockstat::klockstat(const char *name) :
}; };
void void
lockstat_init(struct spinlock *lk) lockstat_init(struct spinlock *lk, bool lazy)
{ {
lk->stat = new klockstat(lk->name); klockstat *ls = new klockstat(lk->name);
if (lk->stat == 0) if (!ls)
return; return;
if (lazy) {
if (!__sync_bool_compare_and_swap(&lk->stat, &klockstat_lazy, ls)) {
delete ls;
return;
}
} else {
lk->stat = ls;
}
acquire(&lockstat_lock); acquire(&lockstat_lock);
LIST_INSERT_HEAD(&lockstat_list, lk->stat, link); LIST_INSERT_HEAD(&lockstat_list, lk->stat, link);
release(&lockstat_lock); release(&lockstat_lock);
...@@ -256,7 +274,7 @@ initlock(struct spinlock *lk, const char *name, int lockstat) ...@@ -256,7 +274,7 @@ initlock(struct spinlock *lk, const char *name, int lockstat)
#if LOCKSTAT #if LOCKSTAT
lk->stat = (struct klockstat*) nullptr; lk->stat = (struct klockstat*) nullptr;
if (lockstat) if (lockstat)
lockstat_init(lk); lockstat_init(lk, false);
#endif #endif
lk->locked = 0; lk->locked = 0;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论