#ifndef _SYS_INDEFINITE2_H_
#define _SYS_INDEFINITE2_H_
#ifndef _SYS_INDEFINITE_H_
#include <sys/indefinite.h>
#endif
#ifndef _SYS_GLOBALDATA_H_
#include <sys/globaldata.h>
#endif
static __inline void
indefinite_init(indefinite_info_t *info, void *lock_addr, const char *ident,
char now, char type)
{
info->lock_addr = lock_addr;
info->ident = ident;
info->secs = 0;
info->count = 0;
info->reported = now;
if (tsc_frequency) {
info->type = type;
} else {
info->type = 0;
info->base = 0;
}
if (now && info->ident) {
mycpu->gd_cnt.v_lock_addr = lock_addr;
mycpu->gd_cnt.v_lock_name[0] = info->type;
strncpy(mycpu->gd_cnt.v_lock_name + 1, info->ident,
sizeof(mycpu->gd_cnt.v_lock_name) - 2);
}
}
static __inline int
indefinite_check(indefinite_info_t *info)
{
tsc_uclock_t delta;
const char *str;
int doreport;
#ifdef _KERNEL_VIRTUAL
vkernel_yield();
#else
cpu_pause();
#endif
if (info->type == 0)
return FALSE;
if (info->count == INDEF_INFO_START) {
if (indefinite_uses_rdtsc)
info->base = rdtsc();
else
info->base = ticks;
if (info->reported == 0 && info->ident) {
mycpu->gd_cnt.v_lock_addr = info->lock_addr;
mycpu->gd_cnt.v_lock_name[0] = info->type;
strncpy(mycpu->gd_cnt.v_lock_name + 1, info->ident,
sizeof(mycpu->gd_cnt.v_lock_name) - 2);
info->reported = 1;
}
}
if ((++info->count & 127) != 127)
return FALSE;
info->count = 128;
if (indefinite_uses_rdtsc)
delta = rdtsc() - info->base;
else
delta = ticks - info->base;
#if defined(INVARIANTS)
if (lock_test_mode > 0) {
--lock_test_mode;
print_backtrace(8);
}
#endif
doreport = 0;
if (indefinite_uses_rdtsc) {
if (delta >= tsc_frequency) {
info->secs += delta / tsc_frequency;
info->base += delta;
mycpu->gd_cnt.v_lock_colls += 1000000U;
doreport = 1;
}
} else {
if (delta >= hz) {
info->secs += delta / hz;
info->base += delta;
mycpu->gd_cnt.v_lock_colls += 1000000U;
doreport = 1;
}
}
if (doreport) {
switch(info->type) {
case 's':
str = "spin_lock_sh";
break;
case 'S':
str = "spin_lock_ex";
break;
case 'm':
str = "mutex_sh";
break;
case 'M':
str = "mutex_ex";
break;
case 'l':
str = "lock_sh";
break;
case 'L':
str = "lock_ex";
break;
case 't':
str = "token";
break;
default:
str = "lock(?)";
break;
}
kprintf("%s: %s, indefinite wait (%d secs)!\n",
str, info->ident, info->secs);
if (panicstr)
return TRUE;
#if defined(INVARIANTS)
if (lock_test_mode) {
print_backtrace(-1);
return TRUE;
}
#endif
#if defined(INVARIANTS)
if (info->secs == 11 &&
(info->type == 's' || info->type == 'S')) {
print_backtrace(-1);
}
#endif
if (info->secs == 60 &&
(info->type == 's' || info->type == 'S')) {
panic("%s: %s, indefinite wait!", str, info->ident);
}
}
return FALSE;
}
static __inline void
indefinite_done(indefinite_info_t *info)
{
tsc_uclock_t delta;
globaldata_t gd;
if (info->type && info->count > INDEF_INFO_START) {
gd = mycpu;
if (indefinite_uses_rdtsc) {
delta = rdtsc() - info->base;
delta = delta * 1000000U / tsc_frequency;
gd->gd_cnt.v_lock_colls += delta;
} else {
delta = ticks - info->base;
delta = delta * 1000000U / hz;
gd->gd_cnt.v_lock_colls += delta;
}
}
info->type = 0;
}
#endif