Unix.Environment.Mod 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. (* Runtime environment for Unix *)
  2. (* Copyright (C) Florian Negele *)
  3. MODULE Environment;
  4. IMPORT SYSTEM, Activities, Counters, Unix, Processors, Queues, Timer, Trace;
  5. CONST IsNative* = FALSE;
  6. CONST Running* = 0; ShuttingDown* = 1; Rebooting* = 2;
  7. VAR status* := 0: WORD;
  8. VAR clock: Timer.Counter;
  9. VAR milliseconds: Timer.Counter;
  10. VAR sleepingQueue: Queues.Queue;
  11. VAR activity: Unix.Key_t;
  12. VAR timer: Unix.Thread_t;
  13. PROCEDURE {NORETURN} Abort-;
  14. BEGIN {UNCOOPERATIVE, UNCHECKED}
  15. IF Activities.GetCurrentActivity () # NIL THEN Activities.TerminateCurrentActivity END;
  16. Exit (1);
  17. END Abort;
  18. PROCEDURE Shutdown*;
  19. BEGIN {UNCOOPERATIVE, UNCHECKED}
  20. IF CAS (status, Running, ShuttingDown) # Running THEN RETURN END;
  21. Trace.StringLn ("system: shutting down...");
  22. END Shutdown;
  23. PROCEDURE Reboot*;
  24. BEGIN {UNCOOPERATIVE, UNCHECKED}
  25. Shutdown;
  26. ASSERT (CAS (status, ShuttingDown, Rebooting) = ShuttingDown);
  27. END Reboot;
  28. PROCEDURE {NORETURN} Exit- (status: WORD);
  29. BEGIN {UNCOOPERATIVE, UNCHECKED}
  30. Trace.String ("system: exiting to Unix"); Trace.Ln;
  31. Unix.exit (status);
  32. END Exit;
  33. PROCEDURE Clock- (): LONGINT;
  34. BEGIN {UNCOOPERATIVE, UNCHECKED}
  35. RETURN LONGINT ((Timer.GetCounter () - clock) / milliseconds);
  36. END Clock;
  37. PROCEDURE Sleep- (milliseconds: LONGINT);
  38. VAR nextActivity: Activities.Activity;
  39. BEGIN {UNCOOPERATIVE, UNCHECKED}
  40. INC (milliseconds, Clock ());
  41. Counters.Inc (Activities.awaiting);
  42. WHILE Clock () - milliseconds < 0 DO
  43. IF Activities.Select (nextActivity, Activities.IdlePriority) THEN
  44. Activities.SwitchTo (nextActivity, Enqueue, NIL);
  45. Activities.FinalizeSwitch;
  46. END;
  47. END;
  48. Counters.Dec (Activities.awaiting);
  49. END Sleep;
  50. PROCEDURE Enqueue (previous {UNTRACED}: Activities.Activity; argument: ADDRESS);
  51. VAR item: Queues.Item;
  52. BEGIN {UNCOOPERATIVE, UNCHECKED}
  53. Queues.Enqueue (previous, sleepingQueue);
  54. END Enqueue;
  55. PROCEDURE TimerThread;
  56. BEGIN {UNCOOPERATIVE, UNCHECKED}
  57. Activities.CallVirtual (TickLoop, NIL, Activities.CreateVirtualProcessor ());
  58. Unix.pthread_exit (0);
  59. END TimerThread;
  60. PROCEDURE TickLoop (argument: ADDRESS);
  61. VAR item: Queues.Item;
  62. BEGIN
  63. WHILE status = Running DO
  64. Unix.ThrSleep (1);
  65. WHILE Queues.Dequeue (item, sleepingQueue) DO
  66. Activities.Resume (item(Activities.Activity));
  67. END;
  68. END;
  69. END TickLoop;
  70. PROCEDURE Allocate- (size: SIZE): ADDRESS;
  71. VAR result, address: ADDRESS;
  72. BEGIN {UNCOOPERATIVE, UNCHECKED}
  73. result := Unix.malloc (size);
  74. IF result = NIL THEN RETURN NIL END;
  75. FOR address := result TO result + size - 1 DO SYSTEM.PUT8 (address, 0) END;
  76. RETURN result;
  77. END Allocate;
  78. PROCEDURE Deallocate- (address: ADDRESS);
  79. BEGIN {UNCOOPERATIVE, UNCHECKED}
  80. Unix.free (address);
  81. END Deallocate;
  82. PROCEDURE GetInit- (n: SIZE; VAR val: LONGINT);
  83. BEGIN val := 0;
  84. END GetInit;
  85. PROCEDURE GetString- (CONST name: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
  86. BEGIN {UNCOOPERATIVE, UNCHECKED}
  87. result := "";
  88. END GetString;
  89. PROCEDURE StoreActivity-;
  90. BEGIN {UNCOOPERATIVE, UNCHECKED}
  91. Unix.WriteKey (activity, SYSTEM.GetActivity ());
  92. END StoreActivity;
  93. PROCEDURE RestoreActivity-;
  94. BEGIN {UNCOOPERATIVE, UNCHECKED}
  95. SYSTEM.SetActivity(SYSTEM.VAL(Activities.Activity,Unix.ReadKey (activity)));
  96. END RestoreActivity;
  97. PROCEDURE Initialize-;
  98. BEGIN {UNCOOPERATIVE, UNCHECKED}
  99. clock := Timer.GetCounter ();
  100. milliseconds := Timer.GetFrequency () DIV 1000;
  101. activity := Unix.NewKey ();
  102. END Initialize;
  103. PROCEDURE Terminate-;
  104. BEGIN {UNCOOPERATIVE, UNCHECKED}
  105. END Terminate;
  106. BEGIN
  107. Trace.String ("Build "); Trace.String (SYSTEM.Date); Trace.String (" (Unix, ");
  108. Trace.String ("GC, ");
  109. Trace.Int (Processors.count, 0); Trace.String (" CPU");
  110. IF Processors.count > 1 THEN Trace.Char ('s') END; Trace.String (", ");
  111. Trace.Int (SIZE OF ADDRESS * 8, 0); Trace.String ("-bit)"); Trace.Ln;
  112. ASSERT (Unix.pthread_create (ADDRESS OF timer, NIL, TimerThread, NIL) = 0);
  113. END Environment.