forked from Hyperion/HyperionOS
moved stuff to src/ from test/ and made better build scripts
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
--:Minify:--
|
||||
local kernel = ...
|
||||
local tasks = {}
|
||||
local sys = {}
|
||||
local nextpid = 2
|
||||
kernel.exitMain=false
|
||||
|
||||
function sys.spawn(func, name, envars, args, tgid, fshandles)
|
||||
local id = nextpid
|
||||
nextpid = nextpid + 1
|
||||
tasks[tostring(id)] = {
|
||||
coro=coroutine.create(function()
|
||||
local ok, err = xpcall(func, debug.traceback, table.unpack(args or {}))
|
||||
if not ok then
|
||||
tasks[tostring(id)].status="Z"
|
||||
tasks[tostring(id)].exit=tostring(err)
|
||||
else
|
||||
tasks[tostring(id)].status="Z"
|
||||
tasks[tostring(id)].exit=err
|
||||
end
|
||||
end),
|
||||
name=name or "task"..tostring(id),
|
||||
envars=envars or {},
|
||||
args=args or {},
|
||||
status="R",
|
||||
pid=id,
|
||||
tgid=tgid or kernel.currentTask.tgid,
|
||||
user=kernel.user,
|
||||
uid=kernel.uid,
|
||||
fd=fshandles or {},
|
||||
exit="",
|
||||
sleep=0,
|
||||
ivs=0,
|
||||
vs=0,
|
||||
children={},
|
||||
parent=kernel.currentTask,
|
||||
siblings=kernel.currentTask.children,
|
||||
syscallReturn={},
|
||||
cwd=kernel.currentTask.cwd,
|
||||
term=kernel.currentTask.term,
|
||||
timeSlice=0,
|
||||
lastTime=0,
|
||||
totalTime=0,
|
||||
numRuns=0
|
||||
}
|
||||
table.insert(kernel.currentTask.children, tasks[tostring(id)])
|
||||
end
|
||||
|
||||
function sys.sleep(ms)
|
||||
kernel.currentTask.status="S"
|
||||
kernel.currentTask.sleep=kernel.computer:time()+ms
|
||||
coroutine.yield()
|
||||
end
|
||||
|
||||
kernel.syscalls["HPV_spawn"]=sys.spawn
|
||||
kernel.syscalls["HPV_sleep"]=sys.sleep
|
||||
kernel._G.sleep=function(...)coroutine.yield("syscall","HPV_sleep",...)end
|
||||
|
||||
local function reapDeadTasks()
|
||||
for pid, task in pairs(tasks) do
|
||||
if task.status == "Z" and not task.reapTime then
|
||||
task.coro = nil
|
||||
task.ivs = nil
|
||||
task.vs = nil
|
||||
task.args = nil
|
||||
task.envars = nil
|
||||
task.cwd = nil
|
||||
task.term = nil
|
||||
task.numRuns = nil
|
||||
task.totalTime = nil
|
||||
task.lastTime = nil
|
||||
task.timeSlice = nil
|
||||
task.syscallReturn = nil
|
||||
task.sleep = nil
|
||||
for k,v in pairs(task.fd) do
|
||||
kernel.vfs.close(v)
|
||||
end
|
||||
task.fd = nil
|
||||
task.reapTime = kernel.computer:time() + 30000
|
||||
elseif task.reapTime and kernel.computer:time() > task.reapTime then
|
||||
for _,child in ipairs(task.children) do
|
||||
child.parent = tasks["1"]
|
||||
child.siblings = tasks["1"].children
|
||||
table.insert(tasks["1"].children, child)
|
||||
end
|
||||
for i, sibling in ipairs(task.siblings) do
|
||||
if sibling.pid == task.pid then
|
||||
table.remove(task.siblings, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
tasks[pid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local alpha = 0.85
|
||||
local C_target = 0.01
|
||||
local Tmin = 0.0005
|
||||
local Tmax = 0.5
|
||||
local lambda_budget = 0.08
|
||||
local lambda_clamp = 0.03
|
||||
local lambda_var = 0.02
|
||||
local k_min = 0.5
|
||||
local k_max = 0.5
|
||||
local B = 0.01
|
||||
|
||||
function kernel.main()
|
||||
while not kernel.exitMain do
|
||||
local N = 0
|
||||
local Tmin_hit = 0
|
||||
local Tmax_hit = 0
|
||||
local totalTaskTime = 0
|
||||
local taskTimes = {}
|
||||
|
||||
for pid, task in pairs(tasks) do
|
||||
if task.status == "S" then
|
||||
if kernel.computer:time() >= task.sleep then
|
||||
task.status="R"
|
||||
task.sleep=0
|
||||
end
|
||||
end
|
||||
if task.status == "R" then
|
||||
kernel.currentTask = task
|
||||
kernel.vfs.cwd = task.cwd
|
||||
kernel.user = task.user
|
||||
kernel.uid = task.uid
|
||||
N = N + 1
|
||||
|
||||
-- assign adaptive time slice
|
||||
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
|
||||
|
||||
-- measure execution time
|
||||
local startTime = kernel.computer:time()
|
||||
local ret
|
||||
if kernel.config.preempt then
|
||||
ret = {coroutine.resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn))}
|
||||
else
|
||||
ret = {coroutine.resume(task.coro, table.unpack(task.syscallReturn))}
|
||||
end
|
||||
local elapsed = kernel.computer:time() - startTime
|
||||
task.lastTime = elapsed
|
||||
task.totalTime = (task.totalTime or 0) + elapsed
|
||||
task.numRuns = (task.numRuns or 0) + 1
|
||||
|
||||
taskTimes[#taskTimes + 1] = elapsed
|
||||
totalTaskTime = totalTaskTime + elapsed
|
||||
|
||||
if elapsed <= Tmin then Tmin_hit = Tmin_hit + 1 end
|
||||
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
||||
|
||||
-- handle task results
|
||||
if ret[1] == "error" then
|
||||
kernel.log("processHandlerException: "..ret[2])
|
||||
task.status = "Z"
|
||||
task.exit = "processHandlerException: "..ret[2]
|
||||
elseif ret[1] == "timeout" then
|
||||
task.ivs=task.ivs+1
|
||||
task.syscallReturn = {}
|
||||
elseif ret[1] == "success" then
|
||||
task.vs=task.vs+1
|
||||
if ret[2]=="syscall" then
|
||||
if kernel.syscalls[ret[3]] then
|
||||
if kernel.config.debugSyscalls then
|
||||
kernel.log("Task "..task.pid.." invoking syscall: "..ret[3], "DBUG")
|
||||
end
|
||||
local sysret = {xpcall(kernel.syscalls[ret[3]], debug.traceback, table.unpack(ret, 4))}
|
||||
if kernel.config.debugSyscalls then
|
||||
if not sysret[1] then
|
||||
kernel.log("Task "..task.pid.." syscall "..ret[3].." failed: "..tostring(sysret[2]))
|
||||
else
|
||||
kernel.log("Task "..task.pid.." syscall "..ret[3].." completed returning "..tostring(#sysret-1).." values", "DBUG")
|
||||
for i=2,#sysret do
|
||||
kernel.log(" retval["..tostring(i-1).."] = "..tostring(sysret[i]), "DBUG")
|
||||
end
|
||||
end
|
||||
end
|
||||
if not sysret[1] then
|
||||
task.syscallReturn={false, sysret[2]}
|
||||
else
|
||||
task.syscallReturn={true, table.unpack(sysret,2)}
|
||||
end
|
||||
else
|
||||
task.syscallReturn={false, "Unknown syscall: "..tostring(ret[3])}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
|
||||
local T_prev_var = 0
|
||||
for _, t in ipairs(taskTimes) do
|
||||
T_prev_var = T_prev_var + (t - T_prev_avg)^2
|
||||
end
|
||||
if N > 0 then T_prev_var = T_prev_var / N end
|
||||
|
||||
if N > 0 then
|
||||
local f_clamp = k_min*(Tmin_hit/N) - k_max*(Tmax_hit/N)
|
||||
local B_budget = (C_target * (N^(alpha-1))) / math.max(T_prev_avg, 1e-8)
|
||||
B = B + lambda_budget * (B_budget - B)
|
||||
+ lambda_clamp * f_clamp
|
||||
- lambda_var * T_prev_var
|
||||
end
|
||||
|
||||
-- clean up dead tasks
|
||||
reapDeadTasks()
|
||||
end
|
||||
end
|
||||
|
||||
kernel.tasks=tasks
|
||||
kernel.hpv=sys
|
||||
Reference in New Issue
Block a user