Skip to content

Commit

Permalink
introduced run modes in vamos
Browse files Browse the repository at this point in the history
  • Loading branch information
cnvogelg committed Dec 25, 2024
1 parent d17e4a9 commit c9a34bd
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 125 deletions.
8 changes: 6 additions & 2 deletions amitools/vamos/cfg/proc.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ def __init__(self, ini_prefix=None):
def_cfg = {
"process": {
"command": {
"binary": Value(str),
"args": ValueList(str, allow_split=False),
"shell": False,
"pure_ami_path": False,
"raw_arg": False,
"mode": Value(str, "proc"),
},
"stack": 8,
}
}
arg_cfg = {
"process": {
"command": {
"binary": Argument("bin", help="AmigaOS binary to run", order=1),
"args": Argument(
"args", nargs="*", help="AmigaOS binary arguments", order=2
),
Expand All @@ -40,6 +39,11 @@ def __init__(self, ini_prefix=None):
action="store_true",
help="pass a single unmodified argument string",
),
"mode": Argument(
"-M",
"--mode",
help="run mode. use 'list' for list of modes",
),
},
"stack": Argument(
"-s",
Expand Down
53 changes: 0 additions & 53 deletions amitools/vamos/lib/dos/Process.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from amitools.vamos.libstructs.dos import CLIStruct, DosPacketStruct, ProcessStruct
from amitools.vamos.libstructs.exec_ import MessageStruct, MinListStruct
from amitools.vamos.lib.dos import CommandLine
from amitools.vamos.log import log_proc
from amitools.vamos.machine.regs import (
REG_D0,
Expand All @@ -14,9 +13,6 @@
from amitools.vamos.machine import Code
from amitools.vamos.schedule import NativeTask
from amitools.vamos.task import Stack
import os

from .SysArgs import sys_args_to_ami_arg_str


NT_PROCESS = 13
Expand Down Expand Up @@ -381,52 +377,3 @@ def get_home_dir_lock(self):
lock_mgr = self.ctx.dos_lib.lock_mgr
lock_baddr = self.get_home_dir() >> 2
return lock_mgr.get_by_b_addr(lock_baddr)

# create main proc

@classmethod
def create_main_proc(cls, proc_cfg, dos_ctx):
# a single Amiga-like raw arg was passed
cmd_cfg = proc_cfg.command
if cmd_cfg.raw_arg:
# check args
if len(cmd_cfg.args) > 0:
log_proc.error("raw arg only allows a single argument!")
return None
# parse raw arg
cl = CommandLine()
res = cl.parse_line(cmd_cfg.binary)
if res != cl.LINE_OK:
log_proc.error("raw arg is invalid! (error %d)", res)
return None
binary = cl.get_cmd()
arg_str = cl.get_arg_str()
else:
# setup binary
binary = cmd_cfg.binary
if not cmd_cfg.pure_ami_path:
# if path exists on host system then make an ami path
if os.path.exists(binary):
sys_binary = binary
binary = dos_ctx.path_mgr.from_sys_path(binary)
if not binary:
log_proc.error("can't map binary: %s", sys_binary)
return None
# combine remaining args to arg_str
arg_str = sys_args_to_ami_arg_str(cmd_cfg.args)

# summary
stack_size = proc_cfg.stack * 1024
shell = proc_cfg.command.shell
log_proc.info("binary: '%s'", binary)
log_proc.info("args: '%s'", arg_str[:-1])
log_proc.info("stack: %d", stack_size)

cwd = str(dos_ctx.path_mgr.get_cwd())
proc = cls(
dos_ctx, binary, arg_str, stack_size=stack_size, shell=shell, cwd=cwd
)
if not proc.ok:
return None
log_proc.info("set main process: %s", proc)
return proc
2 changes: 2 additions & 0 deletions amitools/vamos/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# --- vamos loggers ---

log_main = logging.getLogger("main")
log_mode = logging.getLogger("mode")

log_mem = logging.getLogger("mem")
log_mem_map = logging.getLogger("mem_map")
Expand Down Expand Up @@ -36,6 +37,7 @@

loggers = [
log_main,
log_mode,
log_mem,
log_mem_map,
log_mem_alloc,
Expand Down
105 changes: 42 additions & 63 deletions amitools/vamos/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,56 +10,46 @@
from .libmgr import SetupLibManager
from .schedule import Scheduler
from .profiler import MainProfiler
from .lib.dos.Process import Process
from .mode import ModeContext, ModeSetup

RET_CODE_CONFIG_ERROR = 1000


def main(cfg_files=None, args=None, cfg_dict=None, profile=False):
def gen_task_list(cfg, dos_ctx, exec_ctx):
# setup main proc
proc_cfg = cfg.get_proc_dict().process
main_proc = Process.create_main_proc(proc_cfg, dos_ctx)
if not main_proc:
log_main.error("main proc setup failed!")
return None
return [main_proc]

exit_codes = main_run(gen_task_list, cfg_files, args, cfg_dict, profile)
if exit_codes is None:
return RET_CODE_CONFIG_ERROR

# exit
exit_code = exit_codes[0]
log_main.info("vamos is exiting: code=%d", exit_code)
return exit_code


def main_run(task_list_gen, cfg_files=None, args=None, cfg_dict=None, profile=False):
def main(
cfg_files=None,
args=None,
cfg_dict=None,
profile=False,
mode=None,
single_return_code=True,
):
"""vamos main entry point.
setup a vamos session and run it.
return the error code of the executed Amiga process.
task_list_gen: return list of tasks to run task_list_gen(cfg, task_ctx) -> [Task]
cfg_files(opt): list/tuple of config files. first found will be read
args(opt): None=read sys.argv, []=no args, list/tuple=args
cfg_dict(opt): pass options directly as a dictionary
mode: give the vamos run mode or auto select by config
single_return_code: if true then return only one int error code otherwise None or list
if an internal error occurred then return: None
otherwise and array with exit codes for each added task
"""
error_code = RET_CODE_CONFIG_ERROR if single_return_code else None

# --- parse config ---
mp = VamosMainParser()
if not mp.parse(cfg_files, args, cfg_dict):
return None
return error_code

# --- init logging ---
log_cfg = mp.get_log_dict().logging
if not log_setup(log_cfg):
log_help()
return None
return error_code

# setup main profiler
main_profiler = MainProfiler()
Expand All @@ -71,31 +61,31 @@ def main_run(task_list_gen, cfg_files=None, args=None, cfg_dict=None, profile=Fa
use_labels = mp.get_trace_dict().trace.labels
machine = Machine.from_cfg(machine_cfg, use_labels)
if not machine:
return None
return error_code

# setup memory map
mem_map_cfg = mp.get_machine_dict().memmap
mem_map = MemoryMap(machine)
if not mem_map.parse_config(mem_map_cfg):
log_main.error("memory map setup failed!")
return None
return error_code

# setup trace manager
trace_mgr_cfg = mp.get_trace_dict().trace
trace_mgr = TraceManager(machine)
if not trace_mgr.parse_config(trace_mgr_cfg):
log_main.error("tracing setup failed!")
return None
return error_code

# setup path manager
path_mgr = VamosPathManager()
try:
if not path_mgr.parse_config(mp.get_path_dict()):
log_main.error("path config failed!")
return None
return error_code
if not path_mgr.setup():
log_main.error("path setup failed!")
return None
return error_code

# setup scheduler
schedule_cfg = mp.get_schedule_dict().schedule
Expand Down Expand Up @@ -124,7 +114,7 @@ def runner(code, name=None):
)
if not slm.parse_config(lib_cfg):
log_main.error("lib manager setup failed!")
return RET_CODE_CONFIG_ERROR
return error_code
slm.setup()

# setup profiler
Expand All @@ -133,37 +123,24 @@ def runner(code, name=None):
# open base libs
slm.open_base_libs()

# generate tasks
task_list = task_list_gen(mp, slm.dos_ctx, slm.exec_ctx)
if task_list:
# add tasks to scheduler
for task in task_list:
sched_task = task.get_sched_task()
log_main.info("add task '%s'", sched_task.get_name())
scheduler.add_task(sched_task)

# --- main loop ---
# schedule tasks...
scheduler.schedule()

# pick up exit codes and free task
exit_codes = []
for task in task_list:
# return code is limited to 0-255
sched_task = task.get_sched_task()
exit_code = sched_task.get_exit_code() & 0xFF
log_main.info(
"done task '%s''. exit code=%d", sched_task.get_name(), exit_code
)
exit_codes.append(exit_code)

run_state = sched_task.get_run_result()
log_main.debug("run result: %r", run_state)

# free task
task.free()
# prepare mode context
proc_cfg = mp.get_proc_dict().process
exec_ctx = slm.exec_ctx
dos_ctx = slm.dos_ctx
mode_ctx = ModeContext(proc_cfg, exec_ctx, dos_ctx, scheduler, default_runtime)

# select mode via ModeSetup
if mode is None:
cmd_cfg = proc_cfg.command
mode = ModeSetup.select(cmd_cfg)

# run mode
if mode is None:
exit_code = error_code
else:
exit_codes = None
exit_code = mode.run(mode_ctx)
if single_return_code:
exit_code = exit_code[0]

# libs shutdown
slm.close_base_libs()
Expand All @@ -179,7 +156,9 @@ def runner(code, name=None):
mem_map.cleanup()
machine.cleanup()

return exit_codes
# exit
log_main.info("vamos is exiting: code=%r", exit_code)
return exit_code


def main_profile(
Expand Down
5 changes: 5 additions & 0 deletions amitools/vamos/mode/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .ctx import ModeContext
from .base import BaseMode
from .setup import ModeSetup
from .proc import ProcMode
from .test import TestMode
48 changes: 48 additions & 0 deletions amitools/vamos/mode/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from amitools.vamos.log import log_mode


class BaseMode:
"""base class for all modes"""

def __init__(self, name, gen_task_list_func):
self.name = name
self.gen_task_list_func = gen_task_list_func

def run(self, ctx):
log_mode.info("begin mode '%s'", self.name)

# generate tasks
task_list = self.gen_task_list_func(ctx)
if task_list is None:
return 0

# add tasks to scheduler
for task in task_list:
sched_task = task.get_sched_task()
log_mode.info("add task '%s'", sched_task.get_name())
ctx.scheduler.add_task(sched_task)

# --- main loop ---
# schedule tasks...
ctx.scheduler.schedule()

# pick up exit codes and free task
exit_codes = []
for task in task_list:
# return code is limited to 0-255
sched_task = task.get_sched_task()
exit_code = sched_task.get_exit_code() & 0xFF
log_mode.info(
"done task '%s''. exit code=%d", sched_task.get_name(), exit_code
)
exit_codes.append(exit_code)

run_state = sched_task.get_run_result()
log_mode.debug("run result: %r", run_state)

# free task
task.free()

# only return first code
log_mode.info("done mode '%s'. exit_code=%r", self.name, exit_codes)
return exit_codes
9 changes: 9 additions & 0 deletions amitools/vamos/mode/ctx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class ModeContext:
"""context shared with all modes"""

def __init__(self, proc_cfg, exec_ctx, dos_ctx, scheduler, def_runtime):
self.proc_cfg = proc_cfg
self.exec_ctx = exec_ctx
self.dos_ctx = dos_ctx
self.scheduler = scheduler
self.def_runtime = def_runtime
Loading

0 comments on commit c9a34bd

Please sign in to comment.