Windows.Oberon.Kernel.Mod 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE Kernel IN Oberon;
  3. (** AUTHOR "pjm"; PURPOSE "Oberon for Aos kernel"; *)
  4. IMPORT Machine IN A2, KernelLog IN A2, Modules IN A2, (* Machine, *) Objects IN A2, Kernel IN A2,(* Traps, *) Clock IN A2, Kernel32 IN A2, Types;
  5. CONST
  6. LittleEndian* = TRUE; (** byte order of basic types *)
  7. LsbIs0* = TRUE; (** bit order of SET type *)
  8. (*
  9. CONST
  10. (* timer *)
  11. TimeUnit* = Kernel.Second; (* timer ticks per second, returned by GetTimer *) (* not a constant! *)
  12. *)
  13. TYPE
  14. (*Name* = Modules.Name; (* module name *)
  15. Proc* = Modules.TerminationHandler;
  16. Cmd* = Modules.Command;
  17. Module* = Modules.Module; (* module descriptor *)
  18. ModuleDesc* = Modules.ModuleDesc;*)
  19. (*TrapHandler* = PROCEDURE (err, fp, pc, pf: LONGINT);*)
  20. Finalizer* = Kernel.Finalizer;
  21. (*MilliTimer* = Kernel.MilliTimer;*)
  22. OberonFinalizer = OBJECT
  23. VAR fin: Finalizer; next: OberonFinalizer; obj: ANY;
  24. PROCEDURE Finalize(obj: ANY);
  25. BEGIN (* assume only one finalization thread, so don't need to protect globals here *)
  26. DEC(NfinalizeAlive); INC(NfinalizeDead);
  27. SELF.obj := obj; (* anchor object *)
  28. next := finalizeRoot; finalizeRoot := SELF (* add to list, to be called by Oberon *)
  29. END Finalize;
  30. END OberonFinalizer;
  31. VAR
  32. (* exported variables *)
  33. version*: ARRAY 64 OF CHAR;
  34. (*break* : BOOLEAN;*) (** has ctrl-break been pressed? *) (* for Input *)
  35. (*inGC*: BOOLEAN;*) (* executing inside GC? *) (* for Input *)
  36. (*copro*: BOOLEAN;*) (* is a coprocessor present? *) (* for Reals *)
  37. (*modules* : Modules.Module;*) (** fake list of modules *) (* for Compiler *)
  38. shutdown*: LONGINT;
  39. (*
  40. (*StackOrg* : LONGINT;*) (** highest address on stack (single-process system) *)
  41. (*bt*: LONGINT;*) (** boot table *)
  42. (*tspeed*: LONGINT;*) (** =0: no tracing, >0: tspeed = speed of com output, <0: -tspeed = screen segment *)
  43. (*tbase*: INTEGER;*) (** trace base port, 3F8H=com1, 2F8H=com2, etc. *)
  44. (*EnableGC*, DisableGC*: Proc;*) (** Enable or Disable the GC *)
  45. (*timer*: Proc;*) (** for internal use *)
  46. (*runtime*: ARRAY 5 OF LONGINT;*) (** for internal use *)
  47. *)
  48. lockedBy: ANY;
  49. level: LONGINT;
  50. oberon: ANY;
  51. finalizeRoot: OberonFinalizer; (* finalizers that have to be executed by Oberon *)
  52. NfinalizeAlive, NfinalizeDead: LONGINT;
  53. finalizers: Kernel.FinalizedCollection; (* collection for all Oberon finalizers *)
  54. isEXE-: BOOLEAN;
  55. lock-: LONGINT;
  56. hInstance- : ADDRESS;
  57. (** -- Low-level tracing support -- *)
  58. (** WriteChar - Write a character to the trace output *)
  59. PROCEDURE WriteChar*(c: CHAR);
  60. BEGIN
  61. KernelLog.Char(c)
  62. END WriteChar;
  63. (** WriteString - Write a string *)
  64. PROCEDURE WriteString*(s: ARRAY OF CHAR);
  65. BEGIN
  66. KernelLog.String(s)
  67. END WriteString;
  68. (** WriteLn - Skip to the next line on trace output *)
  69. PROCEDURE WriteLn*;
  70. BEGIN
  71. KernelLog.Ln
  72. END WriteLn;
  73. (** WriteInt - Write "x" as a decimal number. "w" is the field width. *)
  74. PROCEDURE WriteInt*(x, w: LONGINT);
  75. BEGIN
  76. KernelLog.Int(x, w)
  77. END WriteInt;
  78. (** WriteHex - Write "x" as a hexadecimal number. The absolute value of "w" is the field width. If "w" is negative, two hex digits are printed (x MOD 100H), otherwise 8 digits are printed. *)
  79. PROCEDURE WriteHex*(x, w: LONGINT);
  80. BEGIN
  81. KernelLog.Hex(x, w)
  82. END WriteHex;
  83. (** WriteMemory - Display a block of memory. *)
  84. PROCEDURE WriteMemory*(adr, size: LONGINT);
  85. BEGIN
  86. KernelLog.Memory(adr, size)
  87. END WriteMemory;
  88. (* -- Trap handling -- *)
  89. (*(** GetMod - Return the loaded module that contains code address pc. *)
  90. PROCEDURE GetMod*(pc : LONGINT): Module;
  91. BEGIN
  92. RETURN Modules.ModuleByAdr(pc)
  93. END GetMod;*)
  94. (*(** InstallTrap - Install the trap handler *)
  95. PROCEDURE InstallTrap*(p: TrapHandler);
  96. BEGIN
  97. handler := p
  98. END InstallTrap;*)
  99. (*(** InstallLoop - Install procedure to which control is transferred after a trap *)
  100. PROCEDURE InstallLoop*(p: Proc);
  101. BEGIN
  102. loop := p
  103. END InstallLoop;*)
  104. (*(** -- Interrupt handling -- *)*)
  105. (*(** InstallIP - Install interrupt handler & enable IRQ if necessary.
  106. "p" must be defined as a normal "PROCEDURE p;". On entry to p interrupts
  107. are disabled and may be enabled with SYSTEM.STI(). At exit from p the
  108. state of interrupts are restored. The acknowledgement of a hardware interrupt
  109. is done by the Kernel. No end-of-interrupt has to be signalled explicitly in
  110. procedure p. IRQs are mapped starting at interrupt Kernel.IRQ.
  111. At entry to procedure p the stack is as follows:
  112. 56 EFLAGS''
  113. 52 CS''
  114. 48 EIP'' (IRETD from glue code)
  115. 44 errorcode
  116. 40 intnum <-- ESP'
  117. 36 EAX
  118. 32 ECX
  119. 28 EDX
  120. 24 EBX
  121. 20 ESP'
  122. 16 EBP
  123. 12 ESI
  124. 08 EDI
  125. 04 EIP' (RET from p)
  126. 00 EBP' <-- EBP
  127. xx locals <-- ESP
  128. Interrupt priorities (highest to lowest):
  129. IRQ Common use
  130. 00 Timer
  131. 01 Keyboard
  132. 08 RT clock
  133. 09 EGA/VGA retrace
  134. 10 Ethernet or other card
  135. 11 card
  136. 12 PS/2 mouse or card
  137. 13 DMA/copro
  138. 14 Hard disk
  139. 15 card or IRQ error
  140. 03 COM2/4
  141. 04 COM1/3
  142. 05 card
  143. 06 Diskette
  144. 07 LPT1 or IRQ error
  145. *)
  146. PROCEDURE InstallIP*(p: Proc; i: INTEGER);
  147. BEGIN
  148. END InstallIP;*)
  149. (*(** RemoveIP - Uninstall interrupt handler & disable IRQ if necessary *)
  150. PROCEDURE RemoveIP*(p: Proc; i: INTEGER);
  151. BEGIN
  152. END RemoveIP;*)
  153. (** -- Memory/Object management -- *)
  154. (*
  155. (** Available - Return the size in bytes of the remaining free heap space *)
  156. PROCEDURE Available*(): LONGINT;
  157. BEGIN
  158. RETURN 0
  159. END Available;
  160. (** LargestAvailable - Return the size in bytes of the largest free available memory block.
  161. Allocating objects with a size greater than this size will cause the memory allocation to fail. *)
  162. PROCEDURE LargestAvailable*(): LONGINT;
  163. BEGIN
  164. RETURN 0
  165. END LargestAvailable;
  166. *)
  167. (** Used - Return the size in bytes of the amount of memory currently in use in the heap (not implemented on Aos). *)
  168. PROCEDURE Used*(): LONGINT;
  169. BEGIN
  170. RETURN 0
  171. END Used;
  172. (** GC - Immediately activate the garbage collector (on Aos, call the Oberon-based finalizers). *)
  173. PROCEDURE GC*;
  174. VAR of: OberonFinalizer;
  175. BEGIN
  176. (*
  177. Heaps.GC;
  178. *)
  179. CheckOberonLock; (* must hold Oberon lock *)
  180. WHILE finalizeRoot # NIL DO
  181. of := finalizeRoot; finalizeRoot := of.next; DEC(NfinalizeDead);
  182. of.fin(of.obj) (* call Oberon finalizer *)
  183. END
  184. END GC;
  185. (*(** NewDMA - Allocate memory correctly aligned for byte or word DMA in device drivers.
  186. "adr" returns the virtual and "phys" the physical address of the memory. To deallocate,
  187. call with size = -(size of block) and adr = virtual address of block. Max size=64k. *)
  188. PROCEDURE NewDMA*(size: LONGINT; VAR adr, phys: LONGINT);
  189. BEGIN
  190. END NewDMA;*)
  191. (*
  192. (** MapPhysical - Map a physical memory area into the virtual address space. {physAdr, size MOD PS = 0} *)
  193. PROCEDURE MapPhysical*(physAdr, size: LONGINT; VAR virtAdr: LONGINT);
  194. BEGIN
  195. Machine.MapPhysical(physAdr, size, virtAdr)
  196. END MapPhysical;
  197. *)
  198. (*
  199. (** DisableTracing - Disable the GC tracing of a record field of the specified type. For internal use only. *)
  200. PROCEDURE DisableTracing*(recadr, fldadr: LONGINT);
  201. BEGIN
  202. (*KernelLog.String("DisableTracing"); KernelLog.Hex(recadr, 9); KernelLog.Hex(fldadr, 9);
  203. KernelLog.Ln*)
  204. END DisableTracing;
  205. *)
  206. (** RegisterObject - Register a record for finalization. basic = FALSE *)
  207. PROCEDURE RegisterObject*(obj: ANY; fin: Finalizer; basic: BOOLEAN);
  208. VAR of: OberonFinalizer; type: Types.Type;
  209. BEGIN
  210. (*
  211. Heaps.RegisterObject(obj,fin,basic);
  212. *)
  213. IF Machine.debug THEN
  214. IF obj # NIL THEN type := Types.TypeOf(obj)
  215. END;
  216. KernelLog.String("kernel.RegisterObject: ");
  217. IF type # NIL THEN
  218. KernelLog.String(type.mod.name); KernelLog.String("."); KernelLog.String(type.name);
  219. END;
  220. KernelLog.Ln;
  221. END;
  222. NEW(of); of.fin := fin; INC(NfinalizeAlive);
  223. finalizers.Add(obj, of.Finalize);
  224. (* when obj unreachable, Aos GC calls of.Finalizer, which will enqueue obj for calling by GC in this module, which is called by Oberon.Collect and periodically by the Oberon loop *)
  225. END RegisterObject;
  226. (*
  227. (** InstallTermHandler - Install a procedure to execute when a module is freed. Normally used to uninstall
  228. interrupt handlers or tasks and perform other cleanup duties. *)
  229. PROCEDURE InstallTermHandler* (h: Modules.TerminationHandler);
  230. BEGIN
  231. Modules.InstallTermHandler(h)
  232. END InstallTermHandler;
  233. *)
  234. (** -- Clock/Timer -- *)
  235. (** GetClock - Return current time and date *)
  236. PROCEDURE GetClock*(VAR time, date: LONGINT);
  237. BEGIN
  238. Clock.Get(time, date)
  239. END GetClock;
  240. (** SetClock - Set current time and date *)
  241. PROCEDURE SetClock*(time, date: LONGINT);
  242. BEGIN
  243. Clock.Set(time, date)
  244. END SetClock;
  245. (*
  246. (** GetTimer - Return "ticks" since initialisation (Kernel.TimeUnit ticks per second) *)
  247. PROCEDURE GetTimer*(): LONGINT;
  248. BEGIN
  249. RETURN Kernel.GetTicks();
  250. END GetTimer;
  251. (** SetTimer - Set timer to expire in approximately "ms" milliseconds. *)
  252. PROCEDURE SetTimer*(VAR t: MilliTimer; ms: LONGINT);
  253. BEGIN
  254. Kernel.SetTimer(t, ms)
  255. END SetTimer;
  256. (** Expired - Test if a timer has expired. Interrupts must be on. *)
  257. PROCEDURE Expired*(VAR t: MilliTimer): BOOLEAN;
  258. BEGIN
  259. RETURN Kernel.Expired(t)
  260. END Expired;
  261. *)
  262. (** -- Miscellaneous -- *)
  263. (** GetConfig - Return value of configuration string. Returns empty val if name not found. *)
  264. PROCEDURE GetConfig*(name: ARRAY OF CHAR; VAR val: ARRAY OF CHAR);
  265. BEGIN
  266. Machine.GetConfig(name, val)
  267. END GetConfig;
  268. (* ------------------------------------------------------------------------------------------------*)
  269. (* Shutdown - Terminate Oberon after executing all module terminators. If code = 1, perform an APM power-down, if code = 2, perform a soft reboot, or else just switch off interrupts and loop endlessly. *)
  270. PROCEDURE Shutdown*(code: LONGINT);
  271. BEGIN
  272. shutdown := code;
  273. Modules.Shutdown(code)
  274. END Shutdown;
  275. (*
  276. (** Idle - Called when system is idle. *)
  277. PROCEDURE Idle*(code: LONGINT); (* code currently unused *)
  278. BEGIN
  279. Objects.Yield
  280. END Idle;
  281. *)
  282. (*
  283. PROCEDURE TerminateInLock;
  284. BEGIN
  285. BEGIN {EXCLUSIVE}
  286. IF lockedBy = Objects.ActiveObject() THEN (* if we held it, release the lock *)
  287. lockedBy := NIL; level := 0 (* allow Oberon.Loop to re-acquire lock *)
  288. END
  289. END;
  290. Objects.Terminate (* fixme: should really call CurrentProcess().restartEIP *)
  291. END TerminateInLock;
  292. *)
  293. (* Handle exception that occurred while holding Oberon lock. *)
  294. (*
  295. PROCEDURE ExceptionInLock(p: Objects.Process; VAR int: Machine.State; VAR exc: Machine.ExceptionState; VAR return: BOOLEAN);
  296. VAR proc: PROCEDURE;
  297. BEGIN
  298. IF p.obj # oberon THEN (* similar to Traps.Exception *)
  299. Traps.Show(p, int, exc, TRUE);
  300. INCL(int.FLAGS, Machine.IFBit); (* enable interrupts on return *)
  301. int.EBP := 0; int.ESP := p.restartSP; (* reset stack *)
  302. proc := TerminateInLock; int.EIP := SYSTEM.VAL(LONGINT, proc); (* terminate *)
  303. return := TRUE (* return to TerminateInLock procedure at user level *)
  304. ELSE
  305. lockedBy := NIL; level := 0 (* Oberon.Loop will re-acquire lock *)
  306. END
  307. END ExceptionInLock;
  308. *)
  309. (** Acquire the Oberon lock (and replace exception handler). *)
  310. PROCEDURE LockOberon*;
  311. (*
  312. VAR me: ANY;
  313. BEGIN {EXCLUSIVE}
  314. me := Objects.ActiveObject();
  315. IF lockedBy = me THEN
  316. ASSERT(level # -1); (* overflow *)
  317. INC(level)
  318. ELSE
  319. AWAIT(lockedBy = NIL);
  320. lockedBy := me; level := 1;
  321. Objects.SetExceptionHandler(ExceptionInLock) (* assume no other exception handler is present *)
  322. END
  323. *)
  324. END LockOberon;
  325. (** Release the Oberon lock (and remove exception handler). *)
  326. PROCEDURE UnlockOberon*;
  327. (*
  328. BEGIN {EXCLUSIVE}
  329. ASSERT(lockedBy = Objects.ActiveObject()); (* must hold lock *)
  330. DEC(level);
  331. IF level = 0 THEN
  332. Objects.SetExceptionHandler(NIL);
  333. lockedBy := NIL
  334. END
  335. *)
  336. END UnlockOberon;
  337. (** Check if the oberon lock is held by the current process. *)
  338. PROCEDURE CheckOberonLock*;
  339. VAR me: ANY; ok: BOOLEAN;
  340. BEGIN
  341. RETURN; (* disable *)
  342. BEGIN {EXCLUSIVE}
  343. me := Objects.ActiveObject();
  344. ok := (me = oberon) OR (lockedBy = me);
  345. END;
  346. IF ~ok THEN HALT(MAX(INTEGER)+1) END (* to do: halt here *)
  347. END CheckOberonLock;
  348. BEGIN
  349. (*Heaps.RegisterObject := RegisterObject; *) oberon := Objects.ActiveObject();
  350. lockedBy := NIL; level := 0; finalizeRoot := NIL; NEW(finalizers);
  351. COPY(Machine.version, version);
  352. (*shutdown := 0;*)
  353. KernelLog.Enter; WriteString("ETH Oberon / "); WriteString(version); KernelLog.Exit;
  354. (*AosScope.Init;*)
  355. (*modules := NIL;*)
  356. (*break := FALSE; inGC := TRUE;*) (* set inGC = TRUE to disable hard break *)
  357. (*copro := TRUE;*)
  358. isEXE := Kernel32.isEXE;
  359. lock := 0;
  360. hInstance := Kernel32.hInstance;
  361. END Kernel.
  362. (*
  363. 28.04.98 pjm First version
  364. *)