mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-27 04:48:05 +11:00
Somewhat smaller & less RAM-hungry kernel so the system is more usable.
This commit is contained in:
parent
89d8c7fd82
commit
fcabf5b853
26
README.md
26
README.md
@ -6,6 +6,32 @@ The first commit is after I got the installer working again after the new compre
|
|||||||
|
|
||||||
That's what the "SYSTEM HEROES" thing is about.
|
That's what the "SYSTEM HEROES" thing is about.
|
||||||
|
|
||||||
|
## Known Issues (That Aren't KittenOS NEO's Fault)
|
||||||
|
|
||||||
|
Touch calibration is off because OC's setPrecise seems to offset coordinates down and right by a character. OCEmu's does not. I consider this an OC bug. This is known to occur on at least `OpenComputers-MC1.12.2-1.7.2.67.jar`. If you want to check my routines, see sys-everest, search for the lowest instance of `"touch"`. Or just use OCEmu, which doesn't change anything when precise is set, and thus can't be doing anything different than the setPrecise(false) behavior.
|
||||||
|
|
||||||
|
Wide character support *may* encounter issues due to performance-saving tricks in some old OC versions. The 1.12.2 version being used at LimboCon doesn't have the issue, so it's been dealt with. Point is, not a KittenOS NEO bug if it happens.
|
||||||
|
|
||||||
|
## Known Issues (That Are KittenOS NEO's Fault But Aren't Really Fixable)
|
||||||
|
|
||||||
|
If you move a window over another window, that window has to rerender. The alternative is buffering the window. Since memory is a concern, that is not going to happen. Some windows are more expensive to render than others (`klogo` tries to use less RAM if the system is 192K, at the expense of disk access) - move the most expensive window out of the way, since once a window is top-most, moving it around is usually "free".
|
||||||
|
|
||||||
|
If the system runs out of memory, the kernel could crash, or alternatively the system goes into a limbo state. You're more or less doomed. Given that almost everything in Lua causes a memory allocation, I'm not exactly sure how I'd be supposed to fix this properly.
|
||||||
|
|
||||||
|
Any situation where the system fails to boot *may* be fixable with Safe Mode.
|
||||||
|
This includes if you copied a sufficiently large bit of text into the persistent clipboard, and now Icecap or Everest won't start.
|
||||||
|
The catch is, it wipes your settings. As the settings are always in RAM, and contain just about every *fixable* thing that can break your boot,
|
||||||
|
nuking them should bring you to defaults.
|
||||||
|
|
||||||
|
It seems to take just under a second for a key event to get through, yet drags are fine.
|
||||||
|
I don't know why this is, but I suspect the answer involves the timing of a `computer.pullSignal()` with no timeout.
|
||||||
|
If you particularly find performance important, and don't mind the energy costs, you can modify the `init.lua` to make it so that the kernel wakes up every tick.
|
||||||
|
|
||||||
|
And finally, just because a system can multitask somewhat on 192K doesn't mean it can do the impossible regarding memory usage.
|
||||||
|
Lesson learned: Cleaner design -> Higher memory usage.
|
||||||
|
So anyone who wants the design to be made even cleaner should probably reread this paragraph.
|
||||||
|
(In R0, editing the kernel causes 192K systems to fail to open filedialogs. I've fixed this in R1.)
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
At least in theory: "efficient. multi-tasking. clean. security-oriented".
|
At least in theory: "efficient. multi-tasking. clean. security-oriented".
|
||||||
|
182
code/init.lua
182
code/init.lua
@ -106,12 +106,12 @@ function wrapMeta(t)
|
|||||||
local t2 = {}
|
local t2 = {}
|
||||||
setmetatable(t2, {
|
setmetatable(t2, {
|
||||||
__index = function (a, k) return wrapMeta(t[k]) end,
|
__index = function (a, k) return wrapMeta(t[k]) end,
|
||||||
__newindex = function (a, k, v) end,
|
__newindex = error,
|
||||||
__pairs = function (a)
|
__pairs = function (a)
|
||||||
return function (x, key)
|
return function (x, key)
|
||||||
local k, v = next(t, k)
|
local k, v = next(t, k)
|
||||||
if k then return k, wrapMeta(v) end
|
if k then return k, wrapMeta(v) end
|
||||||
end, {}, nil
|
end, 9, nil
|
||||||
end,
|
end,
|
||||||
__ipairs = function (a)
|
__ipairs = function (a)
|
||||||
return function (x, key)
|
return function (x, key)
|
||||||
@ -119,7 +119,7 @@ function wrapMeta(t)
|
|||||||
if t[key] then
|
if t[key] then
|
||||||
return key, wrapMeta(t[key])
|
return key, wrapMeta(t[key])
|
||||||
end
|
end
|
||||||
end, {}, 0
|
end, 9, 0
|
||||||
end,
|
end,
|
||||||
__metatable = uniqueNEOProtectionObject
|
__metatable = uniqueNEOProtectionObject
|
||||||
-- Don't protect this table - it'll make things worse
|
-- Don't protect this table - it'll make things worse
|
||||||
@ -138,36 +138,17 @@ function ensureType(a, t)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ensurePathComponent(s)
|
function ensurePathComponent(s)
|
||||||
if not s:match("^[a-zA-Z0-9_%-%+%,%#%~%@%'%;%[%]%(%)%&%%%$%! %=%{%}%^]+") then error("chars disallowed") end
|
if not string.match(s, "^[a-zA-Z0-9_%-%+%,%#%~%@%'%;%[%]%(%)%&%%%$%! %=%{%}%^]+") then error("chars disallowed") end
|
||||||
if s == "." then error("single dot disallowed") end
|
if s == "." then error("single dot disallowed") end
|
||||||
if s == ".." then error("double dot disallowed") end
|
if s == ".." then error("double dot disallowed") end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ensurePath(s, r)
|
function ensurePath(s, r)
|
||||||
-- Filter filename for anything "worrying". Note / is allowed, see further filters
|
string.gsub(s, "[^/]+", ensurePathComponent)
|
||||||
if not s:match("^[a-zA-Z0-9_%-%+%,%#%~%@%'%;%[%]%(%)%&%%%$%! %=%{%}%^%/]+") then error("chars disallowed") end
|
|
||||||
if s:sub(1, r:len()) ~= r then error("base disallowed") end
|
if s:sub(1, r:len()) ~= r then error("base disallowed") end
|
||||||
if s:match("//") then error("// disallowed") end
|
if s:match("//") then error("// disallowed") end
|
||||||
if s:match("^%.%./") then error("../ disallowed") end
|
|
||||||
if s:match("/%.%./") then error("/../ disallowed") end
|
|
||||||
if s:match("/%.%.$") then error("/.. disallowed") end
|
|
||||||
if s:match("^%./") then error("./ disallowed") end
|
|
||||||
if s:match("/%./") then error("/./ disallowed") end
|
|
||||||
if s:match("/%.$") then error("/. disallowed") end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
wrapMath = wrapMeta(math)
|
|
||||||
wrapTable = wrapMeta(table)
|
|
||||||
wrapString = wrapMeta(string)
|
|
||||||
wrapUnicode = wrapMeta(unicode)
|
|
||||||
wrapCoroutine = wrapMeta(coroutine)
|
|
||||||
wrapOs = wrapMeta({
|
|
||||||
totalMemory = computer.totalMemory, freeMemory = computer.freeMemory,
|
|
||||||
energy = computer.energy, maxEnergy = computer.maxEnergy,
|
|
||||||
clock = os.clock, date = os.date, difftime = os.difftime,
|
|
||||||
time = os.time, uptime = computer.uptime
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Use with extreme care.
|
-- Use with extreme care.
|
||||||
-- (A process killing itself will actually survive until the next yield... before any of the death events have run.)
|
-- (A process killing itself will actually survive until the next yield... before any of the death events have run.)
|
||||||
function termProc(pid, reason)
|
function termProc(pid, reason)
|
||||||
@ -218,7 +199,7 @@ function distEvent(pid, s, ...)
|
|||||||
if not v then
|
if not v then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not (v.access["s." .. s] or v.access["k.root"]) then
|
if not (s:sub(1, 2) == "k." or v.access["s." .. s] or v.access["k.root"]) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Schedule the timer to carry the event.
|
-- Schedule the timer to carry the event.
|
||||||
@ -243,57 +224,6 @@ function lister(pfx)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function baseProcEnv()
|
|
||||||
local pe = {
|
|
||||||
_VERSION = _VERSION,
|
|
||||||
math = wrapMath,
|
|
||||||
table = wrapTable,
|
|
||||||
string = wrapString,
|
|
||||||
unicode = wrapUnicode,
|
|
||||||
coroutine = wrapCoroutine,
|
|
||||||
os = wrapOs,
|
|
||||||
-- Note raw-methods are gone - these can interfere with the metatable safeties.
|
|
||||||
require = loadLibraryInner,
|
|
||||||
assert = assert, ipairs = ipairs,
|
|
||||||
load = load, next = next,
|
|
||||||
pairs = pairs, pcall = pcall,
|
|
||||||
xpcall = xpcall, select = select,
|
|
||||||
type = type, error = error,
|
|
||||||
tonumber = tonumber, tostring = tostring,
|
|
||||||
setmetatable = setmetatable, getmetatable = function (n)
|
|
||||||
local mt = getmetatable(n)
|
|
||||||
if mt == uniqueNEOProtectionObject then return "NEO-Protected Object" end
|
|
||||||
return mt
|
|
||||||
end,
|
|
||||||
rawset = function (t, i, v)
|
|
||||||
local mt = getmetatable(n)
|
|
||||||
if mt == uniqueNEOProtectionObject then error("NEO-Protected Object") end
|
|
||||||
return rawset(t, i, v)
|
|
||||||
end, rawget = rawget, rawlen = rawlen, rawequal = rawequal,
|
|
||||||
neo = {
|
|
||||||
emergency = emergencyFunction,
|
|
||||||
readBufSize = readBufSize,
|
|
||||||
wrapMeta = wrapMeta,
|
|
||||||
listProcs = function ()
|
|
||||||
local n = {}
|
|
||||||
for k, v in pairs(processes) do
|
|
||||||
table.insert(n, {k, v.pkg, v.cpuUsage})
|
|
||||||
end
|
|
||||||
return n
|
|
||||||
end,
|
|
||||||
listApps = lister("apps/"),
|
|
||||||
listLibs = lister("libs/"),
|
|
||||||
totalIdleTime = function () return idleTime end,
|
|
||||||
ensurePath = ensurePath,
|
|
||||||
ensurePathComponent = ensurePathComponent,
|
|
||||||
ensureType = ensureType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pe._G = pe
|
|
||||||
pe._ENV = pe
|
|
||||||
return pe
|
|
||||||
end
|
|
||||||
|
|
||||||
function loadLibraryInner(library)
|
function loadLibraryInner(library)
|
||||||
ensureType(library, "string")
|
ensureType(library, "string")
|
||||||
library = "libs/" .. library .. ".lua"
|
library = "libs/" .. library .. ".lua"
|
||||||
@ -313,6 +243,87 @@ function loadLibraryInner(library)
|
|||||||
return nil, r
|
return nil, r
|
||||||
end
|
end
|
||||||
|
|
||||||
|
wrapMath = wrapMeta(math)
|
||||||
|
wrapTable = wrapMeta(table)
|
||||||
|
wrapString = wrapMeta(string)
|
||||||
|
wrapUnicode = wrapMeta(unicode)
|
||||||
|
wrapCoroutine = wrapMeta(coroutine)
|
||||||
|
wrapOs = wrapMeta({
|
||||||
|
totalMemory = computer.totalMemory, freeMemory = computer.freeMemory,
|
||||||
|
energy = computer.energy, maxEnergy = computer.maxEnergy,
|
||||||
|
clock = os.clock, date = os.date, difftime = os.difftime,
|
||||||
|
time = os.time, uptime = computer.uptime
|
||||||
|
})
|
||||||
|
wrapDebug = wrapMeta(debug)
|
||||||
|
|
||||||
|
baseProcEnvCore = {
|
||||||
|
_VERSION = _VERSION,
|
||||||
|
math = wrapMath,
|
||||||
|
table = wrapTable,
|
||||||
|
string = wrapString,
|
||||||
|
unicode = wrapUnicode,
|
||||||
|
coroutine = wrapCoroutine,
|
||||||
|
os = wrapOs,
|
||||||
|
debug = wrapDebug,
|
||||||
|
require = loadLibraryInner,
|
||||||
|
assert = assert, ipairs = ipairs,
|
||||||
|
load = load,
|
||||||
|
next = function (t, k)
|
||||||
|
local mt = getmetatable(t)
|
||||||
|
if mt == uniqueNEOProtectionObject then error("NEO-Protected Object") end
|
||||||
|
return next(t, k)
|
||||||
|
end,
|
||||||
|
pairs = pairs, pcall = pcall,
|
||||||
|
xpcall = xpcall, select = select,
|
||||||
|
type = type, error = error,
|
||||||
|
tonumber = tonumber, tostring = tostring,
|
||||||
|
setmetatable = setmetatable, getmetatable = function (n)
|
||||||
|
local mt = getmetatable(n)
|
||||||
|
if mt == uniqueNEOProtectionObject then return "NEO-Protected Object" end
|
||||||
|
return mt
|
||||||
|
end,
|
||||||
|
rawset = function (t, i, v)
|
||||||
|
local mt = getmetatable(t)
|
||||||
|
if mt == uniqueNEOProtectionObject then error("NEO-Protected Object") end
|
||||||
|
return rawset(t, i, v)
|
||||||
|
end, rawget = rawget, rawlen = rawlen, rawequal = rawequal,
|
||||||
|
}
|
||||||
|
baseProcNeo = {
|
||||||
|
emergency = emergencyFunction,
|
||||||
|
readBufSize = readBufSize,
|
||||||
|
wrapMeta = wrapMeta,
|
||||||
|
listProcs = function ()
|
||||||
|
local n = {}
|
||||||
|
for k, v in pairs(processes) do
|
||||||
|
table.insert(n, {k, v.pkg, v.cpuUsage})
|
||||||
|
end
|
||||||
|
return n
|
||||||
|
end,
|
||||||
|
listApps = lister("apps/"),
|
||||||
|
listLibs = lister("libs/"),
|
||||||
|
totalIdleTime = function () return idleTime end,
|
||||||
|
ensurePath = ensurePath,
|
||||||
|
ensurePathComponent = ensurePathComponent,
|
||||||
|
ensureType = ensureType
|
||||||
|
}
|
||||||
|
|
||||||
|
baseProcEnvMT = {
|
||||||
|
__index = baseProcEnvCore,
|
||||||
|
__metatable = uniqueNEOProtectionObject
|
||||||
|
}
|
||||||
|
baseProcNeoMT = {
|
||||||
|
__index = baseProcNeo,
|
||||||
|
__metatable = uniqueNEOProtectionObject
|
||||||
|
}
|
||||||
|
|
||||||
|
function baseProcEnv()
|
||||||
|
local pe = setmetatable({}, baseProcEnvMT)
|
||||||
|
pe.neo = setmetatable({}, baseProcNeoMT)
|
||||||
|
pe._G = pe
|
||||||
|
pe._ENV = pe
|
||||||
|
return pe
|
||||||
|
end
|
||||||
|
|
||||||
-- These two are hooks for k.root level applications to change policy.
|
-- These two are hooks for k.root level applications to change policy.
|
||||||
-- Only a k.root application is allowed to do this for obvious reasons.
|
-- Only a k.root application is allowed to do this for obvious reasons.
|
||||||
function securityPolicy(pid, proc, perm, req)
|
function securityPolicy(pid, proc, perm, req)
|
||||||
@ -500,7 +511,6 @@ function start(pkg, ...)
|
|||||||
end
|
end
|
||||||
local env = baseProcEnv()
|
local env = baseProcEnv()
|
||||||
env.neo.pid = pid
|
env.neo.pid = pid
|
||||||
env.neo.dead = false
|
|
||||||
env.neo.executeAsync = startFromUser
|
env.neo.executeAsync = startFromUser
|
||||||
env.neo.execute = function (...)
|
env.neo.execute = function (...)
|
||||||
return osExecuteCore(function () end, ...)
|
return osExecuteCore(function () end, ...)
|
||||||
@ -538,16 +548,7 @@ function start(pkg, ...)
|
|||||||
end
|
end
|
||||||
proc.co = coroutine.create(function (...) local r = {xpcall(appfunc, debug.traceback, ...)} if not r[1] then error(table.unpack(r, 2)) end return table.unpack(r, 2) end)
|
proc.co = coroutine.create(function (...) local r = {xpcall(appfunc, debug.traceback, ...)} if not r[1] then error(table.unpack(r, 2)) end return table.unpack(r, 2) end)
|
||||||
proc.pkg = pkg
|
proc.pkg = pkg
|
||||||
proc.access = {
|
proc.access = {}
|
||||||
-- These permissions are the "critical set".
|
|
||||||
["s.k.securityresponse"] = true,
|
|
||||||
["s.k.timer"] = true,
|
|
||||||
["s.k.procnew"] = true,
|
|
||||||
["s.k.procdie"] = true,
|
|
||||||
-- Used when a registration is updated, in particular, as this signifies "readiness"
|
|
||||||
["s.k.registration"] = true,
|
|
||||||
["s.k.deregistration"] = true
|
|
||||||
}
|
|
||||||
proc.denied = {}
|
proc.denied = {}
|
||||||
-- You are dead. Not big surprise.
|
-- You are dead. Not big surprise.
|
||||||
proc.deathCBs = {function () pcall(function () env.neo.dead = true end) end}
|
proc.deathCBs = {function () pcall(function () env.neo.dead = true end) end}
|
||||||
@ -571,15 +572,14 @@ while true do
|
|||||||
for i = 1, 16 do
|
for i = 1, 16 do
|
||||||
tmr = nil
|
tmr = nil
|
||||||
local now = computer.uptime()
|
local now = computer.uptime()
|
||||||
local breaking = false -- Used when a process dies - in this case it's assumed OC just did something drastic
|
local didAnything = false -- for early exit
|
||||||
local didAnything = false
|
|
||||||
local k = 1
|
local k = 1
|
||||||
while timers[k] do
|
while timers[k] do
|
||||||
local v = timers[k]
|
local v = timers[k]
|
||||||
if v[1] <= now then
|
if v[1] <= now then
|
||||||
table.remove(timers, k)
|
table.remove(timers, k)
|
||||||
if v[2](table.unpack(v, 3)) then
|
if v[2](table.unpack(v, 3)) then
|
||||||
breaking = true
|
didAnything = false -- to break
|
||||||
tmr = 0.05
|
tmr = 0.05
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@ -593,8 +593,6 @@ while true do
|
|||||||
k = k + 1
|
k = k + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if breaking then break end
|
|
||||||
-- If the system didn't make any progress, then we're waiting for a signal (this includes timers)
|
|
||||||
if not didAnything then break end
|
if not didAnything then break end
|
||||||
end
|
end
|
||||||
now = computer.uptime() -- the above probably took a while
|
now = computer.uptime() -- the above probably took a while
|
||||||
|
Loading…
Reference in New Issue
Block a user