123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- (* Runtime environment for Unix *)
- (* Copyright (C) Florian Negele *)
- MODULE Environment;
- IMPORT SYSTEM, Activities, Counters, Unix, Processors, Queues, Timer, Trace;
- CONST IsNative* = FALSE;
- CONST Running* = 0; ShuttingDown* = 1; Rebooting* = 2;
- VAR status* := 0: WORD;
- VAR clock: Timer.Counter;
- VAR milliseconds: Timer.Counter;
- VAR sleepingQueue: Queues.Queue;
- VAR activity: Unix.Key_t;
- VAR timer: Unix.Thread_t;
- PROCEDURE {NORETURN} Abort-;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- IF Activities.GetCurrentActivity () # NIL THEN Activities.TerminateCurrentActivity END;
- Exit (1);
- END Abort;
- PROCEDURE Shutdown*;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- IF CAS (status, Running, ShuttingDown) # Running THEN RETURN END;
- Trace.StringLn ("system: shutting down...");
- END Shutdown;
- PROCEDURE Reboot*;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- Shutdown;
- ASSERT (CAS (status, ShuttingDown, Rebooting) = ShuttingDown);
- END Reboot;
- PROCEDURE {NORETURN} Exit- (status: WORD);
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- Trace.String ("system: exiting to Unix"); Trace.Ln;
- Unix.exit (status);
- END Exit;
- PROCEDURE Clock- (): LONGINT;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- RETURN LONGINT ((Timer.GetCounter () - clock) / milliseconds);
- END Clock;
- PROCEDURE Sleep- (milliseconds: LONGINT);
- VAR nextActivity: Activities.Activity;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- INC (milliseconds, Clock ());
- Counters.Inc (Activities.awaiting);
- WHILE Clock () - milliseconds < 0 DO
- IF Activities.Select (nextActivity, Activities.IdlePriority) THEN
- Activities.SwitchTo (nextActivity, Enqueue, NIL);
- Activities.FinalizeSwitch;
- END;
- END;
- Counters.Dec (Activities.awaiting);
- END Sleep;
- PROCEDURE Enqueue (previous {UNTRACED}: Activities.Activity; argument: ADDRESS);
- VAR item: Queues.Item;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- Queues.Enqueue (previous, sleepingQueue);
- END Enqueue;
- PROCEDURE TimerThread;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- Activities.CallVirtual (TickLoop, NIL, Activities.CreateVirtualProcessor ());
- Unix.pthread_exit (0);
- END TimerThread;
- PROCEDURE TickLoop (argument: ADDRESS);
- VAR item: Queues.Item;
- BEGIN
- WHILE status = Running DO
- Unix.ThrSleep (1);
- WHILE Queues.Dequeue (item, sleepingQueue) DO
- Activities.Resume (item(Activities.Activity));
- END;
- END;
- END TickLoop;
- PROCEDURE Allocate- (size: SIZE): ADDRESS;
- VAR result, address: ADDRESS;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- result := Unix.malloc (size);
- IF result = NIL THEN RETURN NIL END;
- FOR address := result TO result + size - 1 DO SYSTEM.PUT8 (address, 0) END;
- RETURN result;
- END Allocate;
- PROCEDURE Deallocate- (address: ADDRESS);
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- Unix.free (address);
- END Deallocate;
- PROCEDURE GetInit- (n: SIZE; VAR val: LONGINT);
- BEGIN val := 0;
- END GetInit;
- PROCEDURE GetString- (CONST name: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- result := "";
- END GetString;
- PROCEDURE StoreActivity-;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- Unix.WriteKey (activity, SYSTEM.GetActivity ());
- END StoreActivity;
- PROCEDURE RestoreActivity-;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- SYSTEM.SetActivity(SYSTEM.VAL(Activities.Activity,Unix.ReadKey (activity)));
- END RestoreActivity;
- PROCEDURE Initialize-;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- clock := Timer.GetCounter ();
- milliseconds := Timer.GetFrequency () DIV 1000;
- activity := Unix.NewKey ();
- END Initialize;
- PROCEDURE Terminate-;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- END Terminate;
- BEGIN
- Trace.String ("Build "); Trace.String (SYSTEM.Date); Trace.String (" (Unix, ");
- Trace.String ("GC, ");
- Trace.Int (Processors.count, 0); Trace.String (" CPU");
- IF Processors.count > 1 THEN Trace.Char ('s') END; Trace.String (", ");
- Trace.Int (SIZE OF ADDRESS * 8, 0); Trace.String ("-bit)"); Trace.Ln;
- ASSERT (Unix.pthread_create (ADDRESS OF timer, NIL, TimerThread, NIL) = 0);
- END Environment.
|