割り込み処理の実装 (システム関数手動) default tip
authorissei@issei.org
Sat Jun 30 20:49:23 2007 +0900 (18 months ago)
changeset 495adb98ac47e73
parent 494b3c8c862cece
割り込み処理の実装 (システム関数手動)
tool/src/cscript/code/cscvm_main.cc
tool/src/cscript/code/parser.y
tool/src/cscript/code/vm.cc
tool/src/cscript/code/vm.h
tool/src/cscript/code/vm_cast.h
tool/src/cscript/cscript/cscript.sch
tool/src/cscript/cscript/system.sch
tool/src/cscript/mk/cscript.mak
tool/src/cscript/sample/intr.sch
tool/src/cscript/sample/intr.scs
--- a/tool/src/cscript/code/cscvm_main.cc Mon Jun 25 17:01:05 2007 +0900
+++ b/tool/src/cscript/code/cscvm_main.cc Sat Jun 30 20:49:23 2007 +0900
@@ -31,10 +31,14 @@
#include "vm_sys_ud.h"
#define CSCR_HANDLE_TEST
+#define CSCR_INTRRUPT_TEST
#ifdef CSCR_HANDLE_TEST
#include "scr_sys_test_pl.h"
#endif // CSCR_HANDLE_TEST
+#ifdef CSCR_INTRRUPT_TEST
+#include "../sample/intr.sch"
+#endif // CSCR_INTRRUPT_TEST
CSCRIPT_NAMESPACE_USING
@@ -103,6 +107,11 @@ int main(int argc, char** argv)
PlayerImpl player;
vm.setScrArgH(0, &player);
#endif // CSCR_HANDLE_TEST
+#ifdef CSCR_INTRRUPT_TEST
+ vm.run();
+ vm.intr(SAMPLE_INTR_1);
+ vm.intr(SAMPLE_INTR_2);
+#endif
int run_count = 0;
while (vm.run())
--- a/tool/src/cscript/code/parser.y Mon Jun 25 17:01:05 2007 +0900
+++ b/tool/src/cscript/code/parser.y Sat Jun 30 20:49:23 2007 +0900
@@ -833,8 +833,8 @@ node_primary_expression:
CodeGenEntry const* e = NULL;
if ((sym_f = p_comp->findFunction(id)) != NULL) {
- if (sym_f->getCast() != Cast::THREAD) {
- yyerror(std::string("variable or thread function expected [" + id + "]"));
+ if (sym_f->getCast() != Cast::THREAD && sym_f->getCast() != Cast::INTERRUPT) {
+ yyerror(std::string("variable or thread/intrrupt function expected [" + id + "]"));
$$ = Cast::ERROR;
} else {
_genPUSH(p_comp, sym_f->getAddr());
--- a/tool/src/cscript/code/vm.cc Mon Jun 25 17:01:05 2007 +0900
+++ b/tool/src/cscript/code/vm.cc Sat Jun 30 20:49:23 2007 +0900
@@ -44,10 +44,6 @@
# define CSCR_VM_DPRINTF(fmt, ...)
#endif
-#ifndef FRAMES_PER_SEC
-# define FRAMES_PER_SEC (60.0f) // 1秒間の標準実行回数
-#endif
-
CSCRIPT_NAMESPACE_BEGIN
ANON_NAMESPACE_BEGIN
@@ -97,6 +93,7 @@ class VMThread
{
public:
typedef vm_int_t Id;
+ static Id const IntrId = -1;
typedef std::set<Id> TChildIdList;
struct ICtxVirtualMachine
@@ -195,6 +192,7 @@ public:
void setScrArgH(int idx, vm_handle_t h);
bool run();
+ bool intr(vm_intr_t intr_no);
STATE getState() const { return m_common_reg.sw; }
protected:
@@ -215,7 +213,6 @@ protected:
// ISyscallVM
virtual void scr_sysPass(vm_int_t n);
- virtual void scr_sysPassSec(vm_float_t sec);
virtual void scr_sysExit();
virtual vm_int_t scr_sysGetArgI(vm_int_t idx);
virtual vm_float_t scr_sysGetArgF(vm_int_t idx);
@@ -225,7 +222,7 @@ protected:
virtual void scr_sysThreadKillAll();
virtual void scr_sysThreadWait(vm_int_t tid);
virtual void scr_sysThreadWaitAll();
- virtual void scr_sysIntrRegister(vm_int_t intrno, vm_taddr_t intr_main);
+ virtual void scr_sysIntrRegister(vm_intr_t intr_no, vm_taddr_t intr_addr);
#ifndef NDEBUG
virtual void scr_sysDbStackDump();
virtual void scr_sysDbTest(vm_int_t i, vm_float_t f) {}
@@ -274,13 +271,17 @@ private:
}
~VMThreadResHolder()
{
- m_vm_impl._set_cur_thread();
+ m_vm_impl._reset_cur_thread();
}
private:
VirtualMachine::Impl& m_vm_impl;
};
friend struct VMThreadResHolder;
+
+ // 割り込みマップ
+ typedef std::map<vm_intr_t, vm_taddr_t> VMIntrMap;
+ VMIntrMap m_intr_map;
u m_sys_args[CSCR_VM_SYSARG_MAX]; // C++側からVM起動時に渡されるパラメタ
VMThread::Id m_thread_id_next;
@@ -294,9 +295,16 @@ private:
sysno <= CSCR_VM_SYSNO_SYSFUNC_INTERNAL_END;
}
- void _set_cur_thread(VMThread* thread = NULL)
+ void _set_cur_thread(VMThread* thread)
{
+ assert(m_cur_thread == NULL);
m_cur_thread = thread;
+ }
+
+ void _reset_cur_thread()
+ {
+ assert(m_cur_thread != NULL);
+ m_cur_thread = NULL;
}
VMThread::Id _get_thread_id() const
@@ -733,6 +741,52 @@ bool VirtualMachine::Impl::run()
return m_common_reg.sw == STATE_OK;
}
+bool VirtualMachine::Impl::intr(vm_intr_t intr_no)
+{
+ if (m_common_reg.sw != STATE_OK) {
+ CSCR_VM_DPRINTF("intr : invalid vm state : %d\n", m_common_reg.sw);
+ return false;
+ }
+
+ VMIntrMap::const_iterator i = m_intr_map.find(intr_no);
+ if (i == m_intr_map.end()) {
+ CSCR_VM_DPRINTF("intr : intr_no not registerd [%d]\n", intr_no);
+ return false;
+ }
+ vm_taddr_t intr_addr = i->second;
+
+ VMThread thread(0, VMThread::IntrId);
+ thread.thr_stack.resize(VM_STACK_SIZE);
+
+ VMThreadResHolder holder(*this, thread);
+ VMThread::Regs& regs = _get_thread_regs();
+ regs.pc = intr_addr; // intr_addr
+ _push(1); // addr of INST_halt
+ assert(CSCR_VM_TWORD_OPCODE_GET(m_code[1]) == INST_halt);
+
+ for (int loop_count = 0; !regs.halt && regs.sleep == 0; ++m_common_reg.tick) {
+ if (0 < VM_LOOP_COUNT_MAX && VM_LOOP_COUNT_MAX < loop_count++) {
+ m_common_reg.sw = STATE_INFINITE_LOOP;
+ return false;
+ }
+ if (m_code_size <= regs.pc) {
+ m_common_reg.sw = STATE_CODE_FAULT;
+ return false;
+ }
+ _exec1(m_code[regs.pc++]);
+ if (m_common_reg.sw != STATE_OK)
+ return false;
+ }
+
+ if (_get_thread_regs().sleep > 0) {
+ // 割り込み処理では sysSleep() 呼び出し不可
+ m_common_reg.sw = STATE_INVALID_SYSCALL;
+ return false;
+ }
+
+ return true;
+}
+
vm_int_t VirtualMachine::Impl::_opr_int(vm_tword_oprand_t oprand)
{
switch (D_GET_OPRAND(oprand)) {
@@ -912,13 +966,6 @@ void VirtualMachine::Impl::scr_sysPass(v
_get_thread_regs().sleep = n;
}
-void VirtualMachine::Impl::scr_sysPassSec(vm_float_t sec)
-{
- assert(sec > 0);
- if (sec > 0.0f)
- _get_thread_regs().sleep = static_cast<int>(FRAMES_PER_SEC / sec);
-}
-
void VirtualMachine::Impl::scr_sysExit()
{
assert(m_cur_thread != NULL);
@@ -1007,9 +1054,11 @@ void VirtualMachine::Impl::scr_sysThread
_rollbackExec();
}
-void VirtualMachine::Impl::scr_sysIntrRegister(vm_int_t intrno, vm_taddr_t intr_main)
+void VirtualMachine::Impl::scr_sysIntrRegister(vm_intr_t intr_no, vm_taddr_t intr_addr)
{
- // TODO
+ if (m_intr_map.find(intr_no) != m_intr_map.end())
+ CSCR_VM_DPRINTF("sysIntrRegister : overreide intr : %d\n", intr_no);
+ m_intr_map[intr_no] = intr_addr;
}
#ifndef NDEBUG
@@ -1140,6 +1189,11 @@ bool VirtualMachine::run()
return m_impl->run();
}
+bool VirtualMachine::intr(vm_intr_t intr_no)
+{
+ return m_impl->intr(intr_no);
+}
+
VirtualMachine::STATE VirtualMachine::getState() const
{
return m_impl->getState();
--- a/tool/src/cscript/code/vm.h Mon Jun 25 17:01:05 2007 +0900
+++ b/tool/src/cscript/code/vm.h Sat Jun 30 20:49:23 2007 +0900
@@ -107,11 +107,19 @@ public:
/*
* 仮想マシンを実行する
*
- * 戻り値
+ * @return
* 実行継続中の場合は ture, そうでない場合は false
* 正常終了/エラー終了の区別は getState() の戻り値を見て判断すること
*/
bool run();
+
+ /*
+ * 仮想マシンに割り込みをかける
+ *
+ * @param intr_no
+ * 割り込み番号
+ */
+ bool intr(vm_intr_t intr_no);
/**
* 仮想マシン状態を取得する
--- a/tool/src/cscript/code/vm_cast.h Mon Jun 25 17:01:05 2007 +0900
+++ b/tool/src/cscript/code/vm_cast.h Sat Jun 30 20:49:23 2007 +0900
@@ -62,6 +62,7 @@ typedef float vm_float_t;
typedef float vm_float_t;
typedef void* vm_handle_t;
typedef boost::uint16_t vm_sysno_t;
+typedef boost::int32_t vm_intr_t; /// sys_intr_t
#define CSCR_VM_TWORD_SYSCALL_SYSNO_GET(x) static_cast<vm_sysno_t>(((x) & 0x0000ffff))
#define CSCR_VM_TWORD_SYSCALL_ARGSIZE_GET(x) (((x) >> 16) & 0xff)
#define CSCR_VM_SYSCALL_ARGSIZE_MAX (255)
--- a/tool/src/cscript/cscript/cscript.sch Mon Jun 25 17:01:05 2007 +0900
+++ b/tool/src/cscript/cscript/cscript.sch Sat Jun 30 20:49:23 2007 +0900
@@ -33,6 +33,11 @@
// システム引数の数
#define CSCR_VM_SYSARG_MAX (4)
+
+// 1秒間の run() 実行回数
+#ifndef CSCR_VM_FRAMES_PER_SEC
+# define CSCR_VM_FRAMES_PER_SEC (60.0f)
+#endif
// --------------------------------------------------------------------
// 内部システム関数
--- a/tool/src/cscript/cscript/system.sch Mon Jun 25 17:01:05 2007 +0900
+++ b/tool/src/cscript/cscript/system.sch Sat Jun 30 20:49:23 2007 +0900
@@ -2,6 +2,9 @@
* CScript システム関数
* $Id: system.sch 446 2007-06-05 11:18:59Z issei $
*/
+
+#ifndef CSCRIPT_SYSTEM_SCH__INCLUDED
+#define CSCRIPT_SYSTEM_SCH__INCLUDED
#include <cscript.sch>
@@ -59,7 +62,8 @@ __system[] void sysPass(int n);
@param sec
中断する時間 (秒)
*/
-__system[] void sysPassSec(float sec);
+#define sysPassSec(sec) sysPass((sec) / CSCR_VM_FRAMES_PER_SEC)
+
/**
実行を終了する
@@ -108,7 +112,7 @@ __system[] void sysThreadWaitAll();
// -------------------------------------------------------------------
// 割り込み処理
// -------------------------------------------------------------------
-__system[CSCR_VM_SYSNO_SYSFUNC_INTERNAL_INTERRUPT_BEGIN] void sysIntrRegister(sys_intr_t intrno, interrupt intr_main);
+__system[CSCR_VM_SYSNO_SYSFUNC_INTERNAL_INTERRUPT_BEGIN] void sysIntrRegister(sys_intr_t intr_no, interrupt intr_addr);
// -------------------------------------------------------------------
// デバッグ用システム関数
@@ -128,4 +132,6 @@ __system[] void sysDbTest(int i, float f
# define sysDbTest(i, f)
#endif
+#endif // CSCRIPT_SYSTEM_SCH__INCLUDED
+
// vim: syntax=c
--- a/tool/src/cscript/mk/cscript.mak Mon Jun 25 17:01:05 2007 +0900
+++ b/tool/src/cscript/mk/cscript.mak Sat Jun 30 20:49:23 2007 +0900
@@ -10,7 +10,7 @@ CSCRCFLAGS=
CSCRCFLAGS=
CPP= cpp
-CPPFLAGS= -nostdinc -undef -I ../cscript
+CPPFLAGS= -nostdinc -undef -I ../cscript -DCSCRIPT
SRCS= $(notdir $(wildcard *.scs))
DEPS= $(addsuffix .scd,$(basename $(SRCS)))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/src/cscript/sample/intr.sch Sat Jun 30 20:49:23 2007 +0900
@@ -0,0 +1,21 @@
+/*
+ * 割り込みテスト
+ * $Id: for.scs 444 2007-06-04 23:03:03Z issei $
+ */
+
+#ifndef SAMPLE_INTR_SCH__INCLUDED
+#define SAMPLE_INTR_SCH__INCLUDED
+
+#ifdef CSCRIPT
+# define INTR_TYPE_CAST (sys_intr_t)
+#else
+# define INTR_TYPE_CAST (CScript::vm_intr_t)
+#endif
+
+#define SAMPLE_INTR_1 (INTR_TYPE_CAST 1)
+#define SAMPLE_INTR_2 (INTR_TYPE_CAST 2)
+
+#endif // SAMPLE_INTR_SCH__INCLUDED
+
+// vim: syntax=c
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/src/cscript/sample/intr.scs Sat Jun 30 20:49:23 2007 +0900
@@ -0,0 +1,28 @@
+/*
+ * 割り込みテスト
+ * $Id: for.scs 444 2007-06-04 23:03:03Z issei $
+ */
+
+#include <system.sch>
+#include <stdfunc.sch>
+#include "intr.sch"
+
+interrupt testIntr1()
+{
+ sysPrintS("intr 1\n");
+}
+
+interrupt testIntr2()
+{
+ sysPrintS("intr 2\n");
+}
+
+void main()
+{
+ sysIntrRegister(SAMPLE_INTR_1, testIntr1);
+ sysIntrRegister(SAMPLE_INTR_2, testIntr2);
+ sysPass(1);
+}
+
+// vim: syntax=c
+