OpenBSD/sgi on octane2 - mplock周りで落ちるバグについて

__cpu_simple_lock後にきちんとロックされているか確かめるコードを念の為書いて走らせてみた。
が、そこは問題ないようである。

こんなん:

//#if defined(MP_LOCKDEBUG)
#ifndef DDB
#error "MP_LOCKDEBUG requires DDB"
#endif

extern void Debugger(void);
extern int db_printf(const char *, ...)
    __attribute__((__format__(__kprintf__,1,2)));

/* CPU-dependent timing, needs this to be settable from ddb. */
extern int __mp_lock_spinout;
//#endif

static __inline void
__mp_lock(struct __mp_lock *lock)
{
	int s = spllock();

	if (lock->mpl_cpu != cpu_number()) {
#ifndef MP_LOCKDEBUG
		__cpu_simple_lock(&lock->mpl_lock);
#else
		{
			int got_it;
			do {
				int ticks = __mp_lock_spinout;

				do {
					got_it = __cpu_simple_lock_try(
					    &lock->mpl_lock);
				} while (!got_it && ticks-- > 0);
				if (!got_it) {
 					db_printf(
					    "__mp_lock(0x%x): lock spun out",
					    lock);
					Debugger();
				}
			} while (!got_it);
		}
		if (lock->mpl_lock != __SIMPLELOCK_LOCKED) 
			{
				db_printf("[%s:%s:%d] lock->mpl_lock != __SIMPLELOCK_LOCKED\n", __FILE__, __func__, __LINE__);
				Debugger();
			}
#endif
		lock->mpl_cpu = cpu_number();
	}
	lock->mpl_count++;
	splx(s);
}

/*
 * Try to acquire the lock, if another cpu has it, fill it in the
 * call-by-reference cpu parameter.  Return true if acquired.
 */
static __inline int
__mp_lock_try(struct __mp_lock *lock, cpuid_t *cpu)
{
	int s = spllock();

	if (lock->mpl_cpu != cpu_number()) {
		if (!__cpu_simple_lock_try(&lock->mpl_lock)) {
			*cpu = lock->mpl_cpu;
			splx(s);
			return 0;
		}
		lock->mpl_cpu = cpu_number();
		if (lock->mpl_lock != __SIMPLELOCK_LOCKED) 
			{
				db_printf("[%s:%s:%d] lock->mpl_lock != __SIMPLELOCK_LOCKED\n", __FILE__, __func__, __LINE__);
				Debugger();
			}
	}
	lock->mpl_count++;
	splx(s);
	return 1;
}

static __inline void
__mp_unlock(struct __mp_lock *lock)
{
	int s = spllock();

#ifdef MP_LOCKDEBUG
	if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
		db_printf("__mp_unlock(0x%x): releasing not locked lock\n",
		    lock);
		Debugger();
	}
#endif

	if (--lock->mpl_count == 0) {
		lock->mpl_cpu = LK_NOCPU;
		__cpu_simple_unlock(&lock->mpl_lock);
		if (lock->mpl_lock != __SIMPLELOCK_UNLOCKED)
			{
				db_printf("[%s:%s:%d] lock->mpl_lock != __SIMPLELOCK_UNLOCKED\n", __FILE__, __func__, __LINE__);
				Debugger();
			}
	}
	splx(s);
}

static __inline int
__mp_release_all(struct __mp_lock *lock) {
	int s = spllock();
	int rv = lock->mpl_count;

#ifdef MP_LOCKDEBUG
	if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
		db_printf(
		    "__mp_release_all(0x%x): releasing not locked lock\n",
		    lock);
		Debugger();
	}
#endif

	lock->mpl_cpu = LK_NOCPU;
	lock->mpl_count = 0;
	__cpu_simple_unlock(&lock->mpl_lock);
	if (lock->mpl_lock != __SIMPLELOCK_UNLOCKED)
		{
			db_printf("[%s:%s:%d] lock->mpl_lock != __SIMPLELOCK_LOCKED\n", __FILE__, __func__, __LINE__);
			Debugger();
		}
	splx(s);
	return (rv);
}

とすると、やはりSCHED_LOCK周りに問題があって初期化されていないのにlockする・unlockする、或いはlockされていないのにunlockする、などの操作が行われていると考えざるを得ない。
・・・それって、sgiなコードの問題?kernel genericなんじゃね?

と思い、やっぱり問題を解決せずに回避する方向へ走ってみる。
試しに以下の4つをコメントアウト&リビルド。

#option         DIAGNOSTIC
#option         DEBUG
#option         MP_LOCKDEBUG
#option         LOCKDEBUG

なんとか起動成功。おk。取り合えずこの状態でSMP対応を続行しよう。

>> bootp()192.168.3.1:bsd
Setting $netaddr to 192.168.3.2 (from server )
Obtaining bsd from server
5848320+492712 entry: 0xa800000020020000
ARCS64 Firmware Version 64.0
Found SGI-IP30, setting up.
Initial setup done, switching console.
cpu_id:0
Copyright (c) 1982, 1986, 1989, 1991, 1993
        The Regents of the University of California.  All rights reserved.
Copyright (c) 1995-2009 OpenBSD. All rights reserved.  http://www.OpenBSD.org

OpenBSD 4.5-current (OCTANE_RAMDISK) #0: Fri May  8 18:02:19 JST 2009

real mem = 1073741824 (1024MB)
rsvd mem = 1064960 (1MB)
avail mem = 1013821440 (966MB)
mainbus0 at root
cpu0 at mainbus0: MIPS R12000 CPU rev 3.5 400 MHz with R10000 FPU rev 0.0
cpu0: cache L1-I 32KB D 32KB 2 way, L2 2048KB 2 way
clock0 at mainbus0: ticker on int5 using count register
xbow0 at mainbus0: XBow revision 5
xheart0 at xbow0 widget 8: Heart revision 6
onewire0 at xheart0
owserial0 at onewire0 family 0x0b sn 0000004d74fa
owserial0: "PM20400MHZ" p/n 030-1476-001, serial KWL381
"Odyssey" revision 2 at xbow0 widget 11 not configured
xbridge0 at xbow0 widget 15: Bridge revision 4
pci0 at xbridge0 bus 0
isp0 at pci0 dev 0 function 0 "QLogic ISP1020" rev 0x05: irq 0
isp0: invalid NVRAM header
scsibus0 at isp0: 16 targets, initiator 7
sd0 at scsibus0 targ 1 lun 0: <QUANTUM, ATLAS_V__9_SCA, 0238> SCSI3 0/direct fixed
sd0: 8682MB, 512 bytes/sec, 17781964 sec total
isp1 at pci0 dev 1 function 0 "QLogic ISP1020" rev 0x05: irq 1
isp1: invalid NVRAM header
scsibus1 at isp1: 16 targets, initiator 7
ioc0 at pci0 dev 2 function 0 "SGI IOC3" rev 0x01
onewire1 at ioc0
owmac0 at onewire1 family 0x09 sn 000002d29696
owmac0: Ethernet Address 08:00:69:13:67:82
owserial1 at onewire1 family 0x0b sn 0000004d4ee4
owserial1: "FP1" p/n 030-0891-003, serial LMR447
owserial2 at onewire1 family 0x0b sn 0000004e12fb
owserial2: "PWR.SPPLY.ER" p/n 060-0035-002, serial AAE0420107
ioc0: superio irq 4, ethernet irq 2
com0 at ioc0 base 0x00020178: ns16550a, 16 byte fifo
com0: console
com1 at ioc0 base 0x00020170: ns16550a, 16 byte fifo
"SGI Rad1" rev 0xc0 at pci0 dev 3 function 0 not configured
rd0: fixed, 8192 blocks
boot device: sd0
root on rd0a swap on rd0b dump on rd0b
WARNING: No TOD clock, believing file system.
WARNING: CHECK AND RESET THE DATE!
erase ^?, werase ^W, kill ^U, intr ^C, status ^T
(I)nstall, (U)pgrade or (S)hell?

追記:
起動はしてるんだが、入力を受け付けない。
なんでだろう。もしかしたら死んでしまっているのかもしれない。
ちなみに同じソースコードをoption MULTIPROCESSOR無しでビルドした場合、問題なくShellを立ち上げる事が可能である事を確認した。

追記2:
もっかいやったらここで死亡。
不安定なようだ。
本当にoption MULTIPROCESSORなしの時に再現しないか、再確認してみよう。

boot device: sd0
root on rd0a swap on rd0b dump on rd0b
WARNING: No TOD clock, believing file system.
WARNING: CHECK AND RESET THE DATE!
erase ^?, werase ^W, kill ^U, intr ^C, status ^T
(I)nstall, (U)pgrade or (S)hell?
(I)nstall, (U)pgrade or (S)hell?
(I)nstall, (U)pgrade or (S)hell?
(I)nstall, (U)pgrade or (S)hell? s
#
#
#
#
# ls /bin
cat      cp       df       expr     ln       mt       rm       sync
chgrp    cpio     ed       hostname ls       mv       sh       tar
chmod    dd       eject    ksh      mkdir    pax      stty
#

追記3:
やっぱりoption MULTIPROCESSORなしでは落ちないね。
mp_lock周りなんだろうか・・・?