Unix.Environment.Mod 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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 (status = Running) & (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. IF status # Running THEN
  55. WHILE Queues.Dequeue (item, sleepingQueue) DO Activities.Resume (item(Activities.Activity)) END;
  56. END;
  57. END Enqueue;
  58. PROCEDURE {C} TimerThread (): ADDRESS;
  59. BEGIN {UNCOOPERATIVE, UNCHECKED}
  60. Activities.CallVirtual (TickLoop, NIL, Activities.CreateVirtualProcessor ());
  61. RETURN NIL;
  62. END TimerThread;
  63. PROCEDURE TickLoop (argument: ADDRESS);
  64. VAR item: Queues.Item;
  65. BEGIN
  66. WHILE status = Running DO
  67. Unix.ThrSleep (1);
  68. WHILE Queues.Dequeue (item, sleepingQueue) DO
  69. Activities.Resume (item(Activities.Activity));
  70. END;
  71. END;
  72. WHILE Queues.Dequeue (item, sleepingQueue) DO
  73. Activities.Resume (item(Activities.Activity));
  74. END;
  75. END TickLoop;
  76. PROCEDURE Allocate- (size: SIZE): ADDRESS;
  77. VAR result, address: ADDRESS;
  78. BEGIN {UNCOOPERATIVE, UNCHECKED}
  79. result := Unix.malloc (size);
  80. IF result = NIL THEN RETURN NIL END;
  81. FOR address := result TO result + size - 1 DO SYSTEM.PUT8 (address, 0) END;
  82. RETURN result;
  83. END Allocate;
  84. PROCEDURE Deallocate- (address: ADDRESS);
  85. BEGIN {UNCOOPERATIVE, UNCHECKED}
  86. Unix.free (address);
  87. END Deallocate;
  88. PROCEDURE GetInit- (n: SIZE; VAR val: LONGINT);
  89. BEGIN val := 0;
  90. END GetInit;
  91. PROCEDURE GetString- (CONST name: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
  92. BEGIN {UNCOOPERATIVE, UNCHECKED}
  93. result := "";
  94. END GetString;
  95. PROCEDURE StoreActivity-;
  96. BEGIN {UNCOOPERATIVE, UNCHECKED}
  97. Unix.WriteKey (activity, SYSTEM.GetActivity ());
  98. END StoreActivity;
  99. PROCEDURE RestoreActivity-;
  100. BEGIN {UNCOOPERATIVE, UNCHECKED}
  101. SYSTEM.SetActivity(SYSTEM.VAL(Activities.Activity,Unix.ReadKey (activity)));
  102. END RestoreActivity;
  103. PROCEDURE TrapHandler ( sig: LONGINT; mc: Unix.Mcontext );
  104. PROCEDURE Trap EXTERN "Runtime.Trap" (number: SIZE);
  105. BEGIN
  106. RestoreActivity;
  107. Trap (sig);
  108. END TrapHandler;
  109. PROCEDURE Initialize-;
  110. BEGIN {UNCOOPERATIVE, UNCHECKED}
  111. clock := Timer.GetCounter ();
  112. milliseconds := Timer.GetFrequency () DIV 1000;
  113. activity := Unix.NewKey ();
  114. Unix.HandleSignal(Unix.SIGSEGV);
  115. Unix.InstallTrap (TrapHandler);
  116. END Initialize;
  117. PROCEDURE Terminate-;
  118. BEGIN {UNCOOPERATIVE, UNCHECKED}
  119. END Terminate;
  120. BEGIN
  121. Trace.String ("Build "); Trace.String (SYSTEM.Date); Trace.String (" (");
  122. Trace.String (Unix.Version); Trace.String (", GC, ");
  123. Trace.Int (Processors.count, 0); Trace.String (" CPU");
  124. IF Processors.count > 1 THEN Trace.Char ('s') END; Trace.String (", ");
  125. Trace.Int (SIZE OF ADDRESS * 8, 0); Trace.String ("-bit)"); Trace.Ln;
  126. ASSERT (Unix.pthread_create (ADDRESS OF timer, NIL, TimerThread, NIL) = 0);
  127. END Environment.