Nut Operating System  (Nos)
    How NOS work?
    Nos works under NOSS (Nos supervisor).  Nos are user-space
    functions (running in user-space).  NOSS is responsible to
    time-multiplex the Nos function (switchp, the task-switcher) execution
    and user functions execution.  Both are running is
    user-space.  The main function of NOSS is to issue a control to
    processor simulator (S2-machine) to run a number of instructions before
    returning to NOSS.  It does this by commanding the S2-machine
    simulator to run for a number of
    instructions and save its C-state.  The first thing Nos does is to
    run  task-switching (switchp) followed by running the user task (at
    restoreCstate).  This behaviour regards NOSS as an "interruptor" to
    S2-machine, i.e., S2-machine is running some process
    and NOSS "interrupts" it at a fixed interval to run "task-switching".
    
    Nos starts by executing "main" function which initialise global
    variables and creates processes to run user functions.   After
    this start-up, NOSS enters the main loop:
    
    while
        there is a task
        run switchp and at restore
        C-state, run user
        save C-state
    
    
    This is the code in nos for switchp:
    
    //
        status indicates how the process has been interrupted:
      //    
        time-out, block, end
      
      switchp
        if status is time-out or
        block
          if one-process
           
        runnable that process
          else
           
        set current process to ready
           
        runnable next process
        if status is end
          delete current
        process
          runnable next
        process
    
      
    runnable
        set process to running
        restore C-state 
    
    
    Most functions in Nos (switchp, wait, signal) must be atomic, that is,
    they must run to completion before allowing interruption to switch
    process.  This is achieved by adding two system calls to S2-machine:
    disable interrupt, enable interrupt.  In the S2-machine
    simulator executes a fixed number of instruction by
    checking the instruction count.  This is the main fetch-execute
    cycle of S2-machine (in fact most processor simulators are like this):
    
    run
        count = 0
        loop
          if count >
        limit break
          fetch an
        instruction
          execute the
        instruction
          count = count
        + 1
    
    
    To implement "interrupt", a flag (intflag) is used to disable the
    break.  This flag can be turned on/off by the system calls.
    
    run_with_interrupt
        count = 0
        loop
          if intflag == 1
            if
        count > limit break
          fetch an
        instruction
          execute the
        instruction
          count = count
        + 1
    
    
    The process control block contains C-state. C-state consists of fp, sp and
    pc.  Saving and restoring C-state are the act of transferring
    C-state between the S2-machine state and C-state of the
    process. NOSS does the restoring of C-state by running the code in
    user-space. This restoring will affect the flow of execution, as the
    instruction pointer (pc) is changed, it does a jump in the program. 
    Therefore, the precise point of time when this jump occurs is
    important.  There must not be any code following this jump. 
    This instruction must be the last instruction execute in the function
    (and it never returns to the caller).  As NOSS is responsible to
    run the task-switcher, it must save C-state.  Saving C-state can
    not be done in user-space as the precise state has been changed when
    trying to run the "saving state" function.  So, save-Cstate is
    done in the main loop of NOSS.  This gives the save-Cstate
    a special privilege (so called "kernel" in OS vocabulary).  It is
    implemented as a system call instruction in S2-machine.
    
    The system calls that support Nos are:
    
    20 disable interrupt
      21 enable interrupt
      22 get event
      23 block current process
      24 bootnos
    
    Example session
    A user program is written as (count) and integrated with nos in "main":
    
    //
        ---- application --------
      
      count (n)
        i = 0
        while (< i n)
          i = i + 1
          print(i)
      
      main()
        activep = 0
        sseg = 1000
        run (count(500))
        bootnos()
    
    
    The "run (count(500))"  creates a process to run "count(500)". 
    bootnos() starts the process running.
    
    To run NOSS, first compile user functions with NOS in nos.txt:
    
    e:\test>rz36
        nos.txt > nos-s.txt
    
    
    and assemble the S2 machine code, and copy it to obj.js 
    e:\test>as23 nos-s.txt
    e:\test>copy nos-s.obj obj.js
    
    Then run NOSS. This is shown on the output screen:
    
    
    1 2 3 4 5 6 7 8 9 10 11 12 13 14
      15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
     31 32 33 34 35 36 37 38 39
      40 41 42 43 44 45 46 47 48 49
    *
    50 51 52 53 54 55 56 57 58 59 60
      61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    . . .
    146 147 148 149 150 151 152 153
      154 155 156 157 158 159
    *
     160 161 162 163 164 165 166
      167 168 169 170 171 172 173 174 175 176 177 178 179
    . . .
     240 241 242 243 244 245 246
      247 248 249 250 251 252 253 254 255 256 257 258 259
     260 261 262 263 264 265 266
      267 268
    *
     269 270 271 272 273 274 275
      276 277 278 279 280 281 282 283 284 285 286 287 288
    . . .
    *
    487 488 489 490 491 492 493 494
      495 496 497 498 499 500
    *
    9345 clocks
    
    
    The "*" indicates the task-switching (every 1000 instructions). 
    
    last update 
    19 Jan 2013