ã¿ã¤ãã¼å²è¾¼ã¿ã¨ããªã¨ã³ãã·ã§ã³
æåã«èªããªãã¹ã±ã¸ã¥ã¼ã©å¨ãããªã¨ãã¾ãã¯ã¿ã¤ãã¼å²è¾¼ã¿ã®æ±ããã追ã£ããããã¨ã«ããã
æ®éã®ãã«ãã¿ã¹ã¯OSã¯ããã»ã¹ããªã¨ã³ãã·ã§ã³ãæä¾ãã¦ãããã¤ã¾ãã10ããªç§å¨æã¨ãã§ã¿ã¤ãå²è¾¼ã¿ãçºçããã¦ãããã»ã¹ãåãæ¿ããï¼ããã«ã¹ã±ã¸ã¥ã¼ã©ãå¼ã³åºãï¼ãæ¬ç©ã®x86ã§ããã°i8253ã¨ããå²è¾¼ã¿æºã«ãªããã9vxã¯ã¦ã¼ã¶ããã»ã¹ã§ãããã¼ãã¦ã§ã¢ãç´æ¥å©ãããã«ã¯ãããªããããã®å¿ è¦ããªãã®ã§ãã·ã°ãã«ã§ä»£ç¨ãããå²è¾¼ã¿ã³ã³ããã¹ããã·ã°ãã«ã³ã³ããã¹ãã§å®è¡ãããã¨èããã°ããã
9vx/vx32.cã®setclock()ãè¦ãã¨ãsetitimer()é¢æ°ã使ã£ã¦ãããã¨ãããããITIMER_VIRTUALãªã®ã§ãããã»ã¹ã®ä»®æ³æéã§25ããªç§*1çµéããã¨ãSIGVTALRMãçºçããã
static void setclock(int start) { struct itimerval itv; /* Ask for clock tick to interrupt execution after ClockMillis ms. */ memset(&itv, 0, sizeof itv); if(start) itv.it_value.tv_usec = ClockMillis*1000; else itv.it_value.tv_usec = 0; setitimer(ITIMER_VIRTUAL, &itv, 0); }
ãããåããã·ã°ãã«ãã³ãã©ã¯ã¨ããã¨ãlibvx32/sig.cã®sighandler()é¢æ°ãããã ã
static void sighandler(int signo, siginfo_t *si, void *ucontext) { if (vx32_sighandler(signo, si, ucontext)){ // Back into the fire. return; } // vx32_sighandler thought that vx32 wasn't // running or otherwise didn't know what to do. // TODO: If there was a handler registered before us, call it? // If the signal is not important, ignore it. if (signo == SIGVTALRM || signo == SIGALRM) return;
vx32_sighandler()é¢æ°ã¯ã³ã³ããã¹ãã®ã»ã¼ãããªã¹ãã¢ãªã©ãå¿ è¦ãªOSä¾åã³ã¼ãã§ãMac OS Xã§ããã°darwin.cã§å®ç¾©ããã¦ãããSIGVTALRMã ãã«çç®ããã¨ãä»®æ³çãªIRQçªå·ã§ããVXIRQ_TIMERãä¾å¤è¦å ã«è¨å®ãã¦ããã
int vx32_sighandler(int signo, siginfo_t *si, void *v) { : int newtrap; switch(signo){ : case SIGVTALRM: newtrap = VXTRAP_IRQ + VXIRQ_TIMER; break; : emu->cpu_trap = newtrap; r = vxemu_sighandler(emu, ctx->ss.eip);
ï¼ãã®éã¯å¾ã§æ¸ãï¼
9vx/vx32.cã®vxproc_run()å¼åºããã復帰ãããæ»ãå¤ã¯VXTRAP_IRQ + VXIRQ_TIMERã
void touser(void *initsp) { : /* * User-mode execution loop. */ for(;;){ : setsigsegv(1); setclock(1); rc = vxproc_run(vp); setclock(0); setsigsegv(0); : proc2ureg(vp, &u); u.trap = rc; trap(&u); ureg2proc(&u, vp); } }
ããã¦ã9vx/trap.cã®trap()é¢æ°ãå¼ã°ããæçµçã«ã¹ã±ã¸ã¥ã¼ã©ã§ããsched()é¢æ°ãå¼ã°ããã
void trap(Ureg *ureg) { char buf[ERRMAX]; int vno; vno = ureg->trap; switch(vno){ : case VXTRAP_IRQ+VXIRQ_TIMER: sched(); break;
sched()é¢æ°ããªã¿ã¼ã³ããã¾ã§ãã·ã°ãã«ã³ã³ããã¹ãã§åãï¼siglongjmp()使ãã®ãã¨æã£ããã©éããªã
æåã«æ»ã£ã¦setclock()é¢æ°ãã©ãããå¼ã°ãããã¨ããã¨ãä¸ã§æ¢åºã ãtouser()é¢æ°ãããã¯ã«ã¼ãã«ç©ºéããã¦ã¼ã¶ç©ºéã«æ»ãã¨ãã«å¼ã°ããé¢æ°ã§ãã*2ãã§ãsetitimer()ã¯Plan9ã¦ã¼ã¶ããã»ã¹ãå®è¡ä¸ã ãè¨å®ããããã«ãã¦ããã
ã¾ããã·ã°ãã«ãã³ãã©ã®ç»é²ã¯ã9vx/main.cã®siginit()é¢æ°ããå¼ã°ãããvx32_siginit()é¢æ°(libvx32/sig.c)ã§è¡ãããã
*1:ClockMillisã¯25ã
*2:x86ã§ããã°ããã®é¢æ°ã®æå¾ã¯iretå½ä»¤ã«ãªããé¢é£ãã¦ãinitプロセス (カーネルコンテキスト)