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周りなんだろうか・・・?