require '_h2ph_pre.ph';

no warnings qw(redefine misc);

unless(defined(&_SYS_LOCKSTAT_H_)) {
    eval 'sub _SYS_LOCKSTAT_H_ () {1;}' unless defined(&_SYS_LOCKSTAT_H_);
    if(defined(&_KERNEL_OPT)) {
	require './dev/opt_dtrace.ph';
	require 'lockstat.ph';
    }
    require 'sys/types.ph';
    require 'sys/ioccom.ph';
    require 'sys/lock.ph';
    require 'sys/queue.ph';
    require 'sys/time.ph';
    if(defined(&_KERNEL)  && defined(&__HAVE_CPU_COUNTER)) {
	require 'machine/cpu_counter.ph';
    }
    eval 'sub IOC_LOCKSTAT_GVERSION () { &_IOR(ord(\'L\'), 0, \'int\');}' unless defined(&IOC_LOCKSTAT_GVERSION);
    eval 'sub LS_VERSION () {5;}' unless defined(&LS_VERSION);
    eval 'sub IOC_LOCKSTAT_ENABLE () { &_IOW(ord(\'L\'), 1,  &lsenable_t);}' unless defined(&IOC_LOCKSTAT_ENABLE);
    eval 'sub LE_CALLSITE () {0x1;}' unless defined(&LE_CALLSITE);
    eval 'sub LE_ONE_CALLSITE () {0x2;}' unless defined(&LE_ONE_CALLSITE);
    eval 'sub LE_ONE_LOCK () {0x4;}' unless defined(&LE_ONE_LOCK);
    eval 'sub LE_LOCK () {0x8;}' unless defined(&LE_LOCK);
    eval 'sub IOC_LOCKSTAT_DISABLE () { &_IOR(ord(\'L\'), 2,  &lsdisable_t);}' unless defined(&IOC_LOCKSTAT_DISABLE);
    eval 'sub LB_SPIN () {0x1;}' unless defined(&LB_SPIN);
    eval 'sub LB_SLEEP1 () {0x2;}' unless defined(&LB_SLEEP1);
    eval 'sub LB_SLEEP2 () {0x3;}' unless defined(&LB_SLEEP2);
    eval 'sub LB_NEVENT () {0x3;}' unless defined(&LB_NEVENT);
    eval 'sub LB_EVENT_MASK () {0xff;}' unless defined(&LB_EVENT_MASK);
    eval 'sub LB_ADAPTIVE_MUTEX () {0x100;}' unless defined(&LB_ADAPTIVE_MUTEX);
    eval 'sub LB_SPIN_MUTEX () {0x200;}' unless defined(&LB_SPIN_MUTEX);
    eval 'sub LB_RWLOCK () {0x300;}' unless defined(&LB_RWLOCK);
    eval 'sub LB_NOPREEMPT () {0x400;}' unless defined(&LB_NOPREEMPT);
    eval 'sub LB_KERNEL_LOCK () {0x500;}' unless defined(&LB_KERNEL_LOCK);
    eval 'sub LB_MISC () {0x600;}' unless defined(&LB_MISC);
    eval 'sub LB_NLOCK () {0x600;}' unless defined(&LB_NLOCK);
    eval 'sub LB_LOCK_MASK () {0xff00;}' unless defined(&LB_LOCK_MASK);
    eval 'sub LB_LOCK_SHIFT () {8;}' unless defined(&LB_LOCK_SHIFT);
    eval 'sub LB_DTRACE () {0x10000;}' unless defined(&LB_DTRACE);
    if(defined(&_KERNEL)  && defined(&__HAVE_CPU_COUNTER)  && (defined(&NLOCKSTAT) ? &NLOCKSTAT : undef) > 0) {
	eval 'sub LOCKSTAT_EVENT {
	    my($flag, $lock, $type, $count, $time) = @_;
    	    eval q( &do {  &if ( &__predict_false($flag))  &lockstat_event(( &uintptr_t)($lock), ( &uintptr_t) &__builtin_return_address(0), ($type), ($count), ($time)); }  &while ( 0););
	}' unless defined(&LOCKSTAT_EVENT);
	eval 'sub LOCKSTAT_EVENT_RA {
	    my($flag, $lock, $type, $count, $time, $ra) = @_;
    	    eval q( &do {  &if ( &__predict_false($flag))  &lockstat_event(( &uintptr_t)($lock), ( &uintptr_t)$ra, ($type), ($count), ($time)); }  &while ( 0););
	}' unless defined(&LOCKSTAT_EVENT_RA);
	eval 'sub LOCKSTAT_TIMER {
	    my($name) = @_;
    	    eval q( &uint64_t $name = 0);
	}' unless defined(&LOCKSTAT_TIMER);
	eval 'sub LOCKSTAT_COUNTER {
	    my($name) = @_;
    	    eval q( &uint64_t $name = 0);
	}' unless defined(&LOCKSTAT_COUNTER);
	eval 'sub LOCKSTAT_FLAG {
	    my($name) = @_;
    	    eval q(\'int\' $name);
	}' unless defined(&LOCKSTAT_FLAG);
	eval 'sub LOCKSTAT_ENTER {
	    my($name) = @_;
    	    eval q($name =  &atomic_load_relaxed( &lockstat_enabled));
	}' unless defined(&LOCKSTAT_ENTER);
	eval 'sub LOCKSTAT_EXIT {
	    my($name) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_EXIT);
	eval 'sub LOCKSTAT_START_TIMER {
	    my($flag, $name) = @_;
    	    eval q( &do {  &if ( &__predict_false($flag)) ($name) -=  &cpu_counter(); }  &while ( 0));
	}' unless defined(&LOCKSTAT_START_TIMER);
	eval 'sub LOCKSTAT_STOP_TIMER {
	    my($flag, $name) = @_;
    	    eval q( &do {  &if ( &__predict_false($flag)) ($name) +=  &cpu_counter(); }  &while ( 0));
	}' unless defined(&LOCKSTAT_STOP_TIMER);
	eval 'sub LOCKSTAT_COUNT {
	    my($name, $inc) = @_;
    	    eval q( &do { ($name) += ($inc); }  &while ( 0));
	}' unless defined(&LOCKSTAT_COUNT);
    } else {
	eval 'sub LOCKSTAT_FLAG {
	    my($name) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_FLAG);
	eval 'sub LOCKSTAT_ENTER {
	    my($name) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_ENTER);
	eval 'sub LOCKSTAT_EXIT {
	    my($name) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_EXIT);
	eval 'sub LOCKSTAT_EVENT {
	    my($flag, $lock, $type, $count, $time) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_EVENT);
	eval 'sub LOCKSTAT_EVENT_RA {
	    my($flag, $lock, $type, $count, $time, $ra) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_EVENT_RA);
	eval 'sub LOCKSTAT_TIMER {
	    my($void) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_TIMER);
	eval 'sub LOCKSTAT_COUNTER {
	    my($void) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_COUNTER);
	eval 'sub LOCKSTAT_START_TIMER {
	    my($flag, $void) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_START_TIMER);
	eval 'sub LOCKSTAT_STOP_TIMER {
	    my($flag, $void) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_STOP_TIMER);
	eval 'sub LOCKSTAT_COUNT {
	    my($name, $int) = @_;
    	    eval q();
	}' unless defined(&LOCKSTAT_COUNT);
    }
    if(defined(&KDTRACE_HOOKS)) {
	eval 'sub KDTRACE_LOCKSTAT_ENABLED () { &lockstat_dtrace_enabled;}' unless defined(&KDTRACE_LOCKSTAT_ENABLED);
	eval 'sub LS_COMPRESS {
	    my($f) = @_;
    	    eval q((((($f) & 0x3) | ((($f) & 0x700) >> 6)) & ( &LS_NPROBES - 1)));
	}' unless defined(&LS_COMPRESS);
	eval 'sub LS_NPROBES () {0x20;}' unless defined(&LS_NPROBES);
    } else {
	eval 'sub KDTRACE_LOCKSTAT_ENABLED () {0;}' unless defined(&KDTRACE_LOCKSTAT_ENABLED);
    }
    if(defined(&_KERNEL)  && (defined(&NLOCKSTAT) ? &NLOCKSTAT : undef) > 0) {
	eval 'sub LOCKSTAT_ENABLED_UPDATE_BEGIN () {
	    eval q( &do {  &__cpu_simple_lock( &lockstat_enabled_lock); }  &while ( 0));
	}' unless defined(&LOCKSTAT_ENABLED_UPDATE_BEGIN);
	eval 'sub LOCKSTAT_ENABLED_UPDATE_END () {
	    eval q( &do {  &atomic_store_relaxed( &lockstat_enabled,  &lockstat_dev_enabled |  &KDTRACE_LOCKSTAT_ENABLED);  &__cpu_simple_unlock( &lockstat_enabled_lock); }  &while ( 0));
	}' unless defined(&LOCKSTAT_ENABLED_UPDATE_END);
    }
}
1;
