do
local tTasks,nPid,nTimeout,cPid = {},1,0.25,0 -- table of tasks, next process ID, default event timeout, current PID
function os.spawn(f,n) -- function string -- number -- creates a process from function *f* with name *n*
 tTasks[nPid] = {
  c=coroutine.create(function()
   local rt = {pcall(f)}
   if not rt[1] then
    syslog(rt[2])
   end
   computer.pushSignal("process_finished",os.pid(),table.unpack(rt))
  end), -- actual coroutine
  n=n, -- process name
  p=nPid, -- process PID
  P=cPid, -- parent PID
  t=0, -- CPU time
  T=0, -- total uptime
  E=nTimeout, -- event timeout
  e={} -- environment variables
 }
 if tTasks[cPid] then
  for k,v in pairs(tTasks[cPid].e) do
   tTasks[nPid].e[k] = tTasks[nPid].e[k] or v
  end
 end
 nPid = nPid + 1
 return nPid - 1
end
function os.kill(pid) -- number -- -- removes process *pid* from the task list
 tTasks[pid] = nil
end
function os.pid() -- -- number -- returns the current process' PID
 return cPid
end
function os.tasks() -- -- table -- returns a table of process IDs
 local rt = {}
 for k,v in pairs(tTasks) do
  rt[#rt+1] = k
 end
 return rt
end
function os.taskInfo(pid) -- number -- table -- returns info on process *pid* as a table with name and parent values
 pid = pid or os.pid()
 if not tTasks[pid] then return false end
 return {name=tTasks[pid].n,parent=tTasks[pid].P,cputime=tTasks[pid].t,iotime=tTasks[pid].T}
end
function os.sched() -- the actual scheduler function
 os.sched = nil
 local sTimeout = nTimeout
 while #tTasks > 0 do
  local tEv = {computer.pullSignal(sTimeout)}
  sTimeout = nTimeout
  for k,v in pairs(tTasks) do
   if coroutine.status(v.c) ~= "dead" then
    cPid = k
    local sT, sC = os.clock(), computer.uptime()
    coroutine.resume(v.c,table.unpack(tEv))
    v.t, v.T = v.t + os.clock() - sT, v.T + computer.uptime() - sC
    sTimeout=math.min(sTimeout, v.E)
   else
    tTasks[k] = nil
   end
  end
  sTimeout = nTimeout
 end
end
function os.setenv(k,v) -- set's the current process' environment variable *k* to *v*, which is passed to children
 if tTasks[cPid] then
  tTasks[cPid].e[k] = v
 end
end
function os.getenv(k) -- gets a process' *k* environment variable
 if tTasks[cPid] then
  return tTasks[cPid].e[k]
 end
end
function os.getTimeout()
 return tTasks[cPid].E
end
function os.setTimeout(n,pid)
 assert(type(n) == "number" and n >= 0)
 tTasks[pid or cPid].E = n
 return true
end
end