Unix.Objects.Mod 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE Objects; (** AUTHOR "pjm, G.F."; PURPOSE "Active object runtime support"; *)
  3. IMPORT S := SYSTEM, Trace, Glue, Unix, Machine, Heaps, Modules;
  4. CONST
  5. (*! Process flags, meaningless in Unix ports !!! *)
  6. PleaseHalt* = 10; (* Process requested to Halt itself soon *)
  7. Unbreakable*= 11; (* FINALLY shall not catch HALT exception (PleaseHalt is also set) *)
  8. SelfTermination*=12; (* Indicates the process has requested to terminate ifself (PleaseHalt is also set) *)
  9. Preempted* = 27; (* Has been preempted. *)
  10. Resistant* = 28; (* Can only be destroyed by itself *)
  11. MinPriority* = Unix.ThreadLow;
  12. Low* = Unix.ThreadLow + 1;
  13. Normal* = Unix.ThreadNormal;
  14. High* = Unix.ThreadHigh - 2;
  15. GCPriority* = Unix.ThreadHigh - 1;
  16. Realtime* = Unix.ThreadHigh;
  17. (* Process flag defined by compiler in OPC.CallRecBody *)
  18. Restart* = 0; (* Restart/Destroy process on exception *)
  19. (* Process modes (in UnixAos Running means Running or Ready!) *)
  20. Unknown* = 0; Ready* = 1; Running* = 2; AwaitingLock* = 3;
  21. AwaitingCond* = 4; AwaitingEvent* = 5; Terminated* = 6;
  22. Second* = 1000; (* frequency of ticks increments in Hz *)
  23. DefaultStacksize = 128*1024;
  24. AddrSize = SIZEOF( ADDRESS )
  25. VAR
  26. (* timer *)
  27. timerActivity : TimerActivity;
  28. timers : Timer;
  29. timerListMutex : Unix.Mutex_t;
  30. (* processes *)
  31. mainProcess : Process; (* runs the GC *)
  32. root- : Process; (*! Anchor of all instantiated threads in system *)
  33. stacksize: LONGINT; (* stack size of active objects, adjustable via boot parameter *)
  34. processList : Unix.Mutex_t;
  35. createProcess : Unix.Mutex_t;
  36. startProcess : Unix.Mutex_t;
  37. childrunning : Unix.Condition_t;
  38. newProcess: Process;
  39. nextPID: LONGINT;
  40. (* garbage colletion *)
  41. gcFinished: Unix.Condition_t; igc: Unix.Mutex_t;
  42. collect: BOOLEAN;
  43. finalizerCaller : FinalizerCaller;
  44. finCaller : Process;
  45. (* the dummy parameters assure proper stack alignment when compiled with
  46. option "\A" or "--darwinHost" *)
  47. mtxInit: PROCEDURE {REALTIME, C} ( dummy: LONGINT ): Unix.Mutex_t;
  48. mtxDestroy: PROCEDURE {REALTIME, C} ( mtx: Unix.Mutex_t );
  49. mtxLock: PROCEDURE {REALTIME, C} ( mtx: Unix.Mutex_t );
  50. mtxUnlock: PROCEDURE {REALTIME, C} ( mtx: Unix.Mutex_t );
  51. conInit: PROCEDURE {REALTIME, C} ( dummy: LONGINT ): Unix.Condition_t;
  52. conDestroy: PROCEDURE {REALTIME, C} ( cond: Unix.Condition_t );
  53. conWait: PROCEDURE {REALTIME, C} ( cond: Unix.Condition_t; mtx: Unix.Mutex_t );
  54. conSignal: PROCEDURE {REALTIME, C} ( cond: Unix.Condition_t );
  55. thrStart: PROCEDURE {REALTIME, C} ( p: PROCEDURE; stackLen: LONGINT ): Unix.Thread_t;
  56. thrThis: PROCEDURE {REALTIME, C} ( dummy: LONGINT ): Unix.Thread_t;
  57. thrSleep: PROCEDURE {REALTIME, C} ( ms: LONGINT );
  58. thrYield: PROCEDURE {REALTIME, C} ( dummy: LONGINT );
  59. thrExit: PROCEDURE {REALTIME, C} ( dummy: LONGINT );
  60. thrSuspend: PROCEDURE {REALTIME, C} ( t: Unix.Thread_t );
  61. thrResume: PROCEDURE {REALTIME, C} ( t: Unix.Thread_t );
  62. thrSetPriority: PROCEDURE {REALTIME, C} ( t: Unix.Thread_t; prio: LONGINT );
  63. thrGetPriority: PROCEDURE {REALTIME, C} ( t: Unix.Thread_t ): LONGINT;
  64. thrKill: PROCEDURE {REALTIME, C} ( t: Unix.Thread_t );
  65. TYPE
  66. CpuCyclesArray* = ARRAY Machine.MaxCPU OF HUGEINT;
  67. ProtectedObject = POINTER TO RECORD END;
  68. ObjectHeader = Heaps.ProtRecBlock;
  69. ProcessQueue = Heaps.ProcessQueue;
  70. EventHandler* = PROCEDURE {DELEGATE};
  71. Timer* = OBJECT
  72. VAR
  73. next: Timer;
  74. trigger: LONGINT;
  75. handler: EventHandler
  76. END Timer;
  77. TimerActivity = OBJECT
  78. VAR
  79. t, r: Timer; h: EventHandler; restart: BOOLEAN;
  80. PROCEDURE UpdateTicks;
  81. BEGIN {EXCLUSIVE}
  82. Machine.UpdateTicks
  83. END UpdateTicks;
  84. PROCEDURE Restart;
  85. BEGIN {EXCLUSIVE}
  86. restart := TRUE
  87. END Restart;
  88. BEGIN {ACTIVE, SAFE, PRIORITY(High)}
  89. restart := FALSE;
  90. LOOP
  91. t := timers;
  92. IF t # NIL THEN
  93. h := NIL; r := NIL;
  94. BEGIN {EXCLUSIVE}
  95. AWAIT( (Machine.ticks >= t.trigger) OR restart ); restart := FALSE;
  96. IF Machine.ticks >= t.trigger THEN
  97. h := t.handler; r := t
  98. END
  99. END;
  100. IF r # NIL THEN Remove( r ) END;
  101. IF h # NIL THEN (* not canceled *) h END
  102. ELSE
  103. BEGIN{EXCLUSIVE}
  104. AWAIT( restart ); restart := FALSE;
  105. END
  106. END
  107. END
  108. END TimerActivity;
  109. FinalizedCollection* = OBJECT (* base type for collection, extended in Kernel.Mod *)
  110. PROCEDURE RemoveAll*(obj: ANY); (** abstract *)
  111. BEGIN HALT(301) END RemoveAll;
  112. END FinalizedCollection;
  113. FinalizerNode* = POINTER TO RECORD (Heaps.FinalizerNode)
  114. c*: FinalizedCollection (* base type for collection containing object *)
  115. END;
  116. FinalizerCaller = OBJECT (* separate active object that calls finalizers *)
  117. VAR
  118. n: Heaps.FinalizerNode; start: BOOLEAN;
  119. PROCEDURE Start;
  120. BEGIN {EXCLUSIVE}
  121. start := TRUE
  122. END Start;
  123. BEGIN {ACTIVE, SAFE, PRIORITY(High)}
  124. finCaller := CurrentProcess( ); start := FALSE;
  125. LOOP
  126. BEGIN {EXCLUSIVE} AWAIT( start ) END;
  127. start := FALSE;
  128. LOOP
  129. n := Heaps.GetFinalizer();
  130. IF n = NIL THEN EXIT END;
  131. IF n IS FinalizerNode THEN
  132. n(FinalizerNode).c.RemoveAll(n.objStrong) (* remove it if it is not removed yet *)
  133. END;
  134. IF n.finalizer # NIL THEN
  135. n.finalizer(n.objStrong) (* may acquire locks *)
  136. END;
  137. END;
  138. Machine.ReleaseGC
  139. END
  140. END FinalizerCaller;
  141. Body = PROCEDURE ( self: ProtectedObject );
  142. Condition = PROCEDURE ( slink: ADDRESS ): BOOLEAN;
  143. Process* = OBJECT (Heaps.RootObject)
  144. VAR
  145. threadId : Unix.Thread_t;
  146. nextProcess- : Process; (* next in list of all processes *)
  147. stackBottom - : ADDRESS;
  148. SP- : ADDRESS; (* SP value at last NEW *)
  149. id- : LONGINT;
  150. body : Body;
  151. mode- : LONGINT;
  152. flags- : SET;
  153. priority- : LONGINT; (* only effective if Aos is running SUID root *)
  154. succ : Process; (* in ProcessQueue *)
  155. obj- : ProtectedObject; (* associated active object *)
  156. condition- : Condition; (* awaited process' condition *)
  157. condFP- : ADDRESS; (* awaited process' condition's context *)
  158. continue : Unix.Condition_t; (* gets signaled when condition yields true *)
  159. waitingOn- : ProtectedObject;
  160. procID- : LONGINT; (* processor ID where running, not used in UnixAos *)
  161. state- : Machine.State; (*! not used in UnixAos! *)
  162. state0 : ARRAY 2048 OF CHAR; (* thread state at body start, used for restart after trap *)
  163. context: ANY; (* commands cotext *)
  164. PROCEDURE FindRoots*;
  165. VAR sp, ptr: ADDRESS;
  166. BEGIN
  167. IF mode # Terminated THEN
  168. sp := SP;
  169. WHILE sp < stackBottom DO
  170. S.GET( sp, ptr );
  171. IF (ptr # 0) & (ptr MOD 8 = 0) THEN Heaps.AddCandidate( ptr ) END;
  172. INC( sp, AddrSize )
  173. END;
  174. END;
  175. Heaps.Mark( nextProcess )
  176. END FindRoots;
  177. PROCEDURE Cancel;
  178. VAR pt, t: Process; kt: Unix.Thread_t;
  179. BEGIN
  180. IF SELF = CurrentProcess() THEN Exit
  181. ELSE
  182. Machine.Acquire( Machine.X11 ); (* let the thread to be killed first finish its last I/O, if any *)
  183. mtxLock( processList );
  184. pt := NIL; t := root; kt := 0;
  185. WHILE (t # NIL ) & (t # SELF) DO pt := t; t := t.nextProcess END;
  186. IF t = SELF THEN
  187. kt := threadId;
  188. IF pt = NIL THEN root := t.nextProcess ELSE pt.nextProcess := t.nextProcess END;
  189. END;
  190. mtxUnlock( processList );
  191. IF kt # 0 THEN thrKill( kt ) END;
  192. Machine.Release( Machine.X11 );
  193. END
  194. END Cancel;
  195. PROCEDURE GetPriority( ): LONGINT;
  196. BEGIN
  197. RETURN thrGetPriority( threadId )
  198. END GetPriority;
  199. PROCEDURE SetPriority( prio: LONGINT );
  200. VAR pr: LONGINT;
  201. BEGIN
  202. pr := max( Machine.prioLow, min( prio, Machine.prioHigh ) );
  203. thrSetPriority( threadId, pr ); (* works only if SUID root *)
  204. priority := GetPriority( )
  205. END SetPriority;
  206. PROCEDURE & Initialize( obj: ProtectedObject; bodyProc: Body; prio: LONGINT; fl: SET; stacksize: LONGINT);
  207. VAR thr: Unix.Thread_t;
  208. BEGIN
  209. SELF.obj := obj; condition := NIL; continue := conInit(0);
  210. flags := fl;
  211. priority := prio;
  212. nextProcess := NIL;
  213. context := CurrentContext();
  214. IF root # NIL THEN
  215. newProcess := SELF;
  216. ASSERT( bodyProc # NIL );
  217. body := bodyProc;
  218. mtxLock( startProcess );
  219. thr := thrStart( BodyStarter, stacksize );
  220. conWait( childrunning, startProcess );
  221. mtxUnlock( startProcess );
  222. RegisterFinalizer( SELF, FinalizeProcess );
  223. ELSE
  224. (* first process *)
  225. stackBottom := Glue.stackBottom;
  226. SP := Machine.CurrentSP( );
  227. threadId := thrThis(0);
  228. id := 0; nextPID := 1;
  229. root := SELF;
  230. mainProcess := SELF;
  231. mode := Running;
  232. END;
  233. END Initialize;
  234. END Process;
  235. PROCEDURE BodyStarter;
  236. VAR p{UNTRACED}: Process; res: LONGINT; prevBP: ADDRESS;
  237. BEGIN
  238. mtxLock( startProcess );
  239. p := newProcess; newProcess := NIL;
  240. p.threadId := thrThis(0);
  241. p.id := nextPID; INC( nextPID );
  242. p.SP := Machine.CurrentSP( );
  243. p.stackBottom := Machine.CurrentBP( );
  244. S.GET( p.stackBottom, prevBP );
  245. S.PUT( prevBP, S.VAL( ADDRESS, 0 ) ); (* for terminating Reflection.StackTraceBack *)
  246. mtxLock( processList );
  247. p.nextProcess := root; root := p;
  248. mtxUnlock( processList );
  249. conSignal( childrunning );
  250. mtxUnlock( startProcess );
  251. p.SetPriority( p.priority );
  252. IF Restart IN p.flags THEN
  253. res := Unix.sigsetjmp( ADDRESSOF( p.state0[0] ), 1 );
  254. END;
  255. p.mode := Running;
  256. p.body( p.obj );
  257. p.mode := Terminated;
  258. Exit
  259. END BodyStarter;
  260. (*--------------------- create, lock, await, unlock -------------------------*)
  261. PROCEDURE InitProtHeader( hdr: ObjectHeader );
  262. BEGIN
  263. hdr.mtx := mtxInit( 0 ); hdr.enter := conInit( 0 ); hdr.lockedBy := NIL;
  264. END InitProtHeader;
  265. PROCEDURE CreateProcess*( body: Body; priority: LONGINT; flags: SET; obj: ProtectedObject );
  266. VAR p: Process; hdr: ObjectHeader;
  267. BEGIN
  268. mtxLock( createProcess );
  269. S.GET( S.VAL( ADDRESS, obj ) + Heaps.HeapBlockOffset, hdr ); InitProtHeader( hdr );
  270. IF priority = 0 THEN priority := Normal END;
  271. NEW( p, obj, body, priority, flags, stacksize ) ; (* execute BodyStarter as new (posix or solaris) thread *)
  272. mtxUnlock( createProcess );
  273. RegisterFinalizer( obj, FinalizeActiveObj )
  274. END CreateProcess;
  275. PROCEDURE Lock*( obj: ProtectedObject; exclusive: BOOLEAN );
  276. VAR hdr: ObjectHeader; p: Process;
  277. BEGIN
  278. ASSERT( exclusive ); (* shared not implemented yet *)
  279. S.GET( S.VAL( ADDRESS, obj ) + Heaps.HeapBlockOffset, hdr );
  280. p := CurrentProcess();
  281. p.mode := AwaitingLock;
  282. IF hdr.mtx = 0 THEN InitProtHeader( hdr ) END;
  283. mtxLock( hdr.mtx );
  284. WHILE hdr.lockedBy # NIL DO
  285. (* wait until threads with complied AWAIT conditions have left the monitor *)
  286. conWait( hdr.enter, hdr.mtx );
  287. END;
  288. p.mode := Running; hdr.lockedBy := p; p.waitingOn := NIL
  289. END Lock;
  290. PROCEDURE Await*( cond: Condition; slink: ADDRESS; obj: ProtectedObject; flags: SET );
  291. VAR hdr: ObjectHeader; p, c: Process;
  292. BEGIN
  293. IF 1 IN flags THEN (* compiler did not generate IF *)
  294. IF cond( slink ) THEN (* condition already true *) RETURN END
  295. END;
  296. S.GET( S.VAL( ADDRESS, obj ) + Heaps.HeapBlockOffset, hdr ); c := NIL;
  297. IF hdr.awaitingCond.head # NIL THEN c := FindCondition( hdr.awaitingCond ) END;
  298. p := CurrentProcess(); p.succ := NIL; p.condition := cond; p.condFP := slink;
  299. p.waitingOn := obj; p.mode := AwaitingCond;
  300. Put( hdr.awaitingCond, p );
  301. hdr.lockedBy := c;
  302. IF c # NIL THEN conSignal( c.continue ) ELSE conSignal( hdr.enter ) END;
  303. conWait( p.continue, hdr.mtx );
  304. p.mode := Running; hdr.lockedBy := p; p.waitingOn := NIL
  305. END Await;
  306. PROCEDURE Unlock*( obj: ProtectedObject; dummy: BOOLEAN );
  307. VAR hdr: ObjectHeader; c: Process;
  308. BEGIN
  309. S.GET( S.VAL( ADDRESS, obj ) + Heaps.HeapBlockOffset, hdr ); c := NIL;
  310. IF hdr.awaitingCond.head # NIL THEN c := FindCondition( hdr.awaitingCond ) END;
  311. hdr.lockedBy := c;
  312. IF c # NIL THEN conSignal( c.continue ) ELSE conSignal( hdr.enter ) END;
  313. mtxUnlock( hdr.mtx );
  314. END Unlock;
  315. PROCEDURE FindCondition( VAR q: ProcessQueue ): Process;
  316. VAR first, cand: Process;
  317. BEGIN
  318. Get( q, first );
  319. IF first.condition( first.condFP ) THEN RETURN first ELSE Put( q, first ) END;
  320. WHILE q.head # first DO
  321. Get( q, cand );
  322. IF cand.condition( cand.condFP ) THEN RETURN cand ELSE Put( q, cand ) END;
  323. END;
  324. RETURN NIL
  325. END FindCondition;
  326. PROCEDURE Get( VAR queue: ProcessQueue; VAR new: Process );
  327. VAR t: Process;
  328. BEGIN
  329. t := queue.head(Process);
  330. IF t # NIL THEN
  331. IF t = queue.tail THEN queue.head := NIL; queue.tail := NIL
  332. ELSE queue.head := t.succ; t.succ := NIL
  333. END
  334. END;
  335. new := t
  336. END Get;
  337. PROCEDURE Put( VAR queue: ProcessQueue; t: Process );
  338. BEGIN
  339. IF queue.head = NIL THEN queue.head := t ELSE queue.tail(Process).succ := t END;
  340. queue.tail := t
  341. END Put;
  342. (*-------------------------------------------------------------------------*)
  343. PROCEDURE Terminate*;
  344. BEGIN
  345. Exit
  346. END Terminate;
  347. PROCEDURE TerminateThis*( p: Process; unbreakable: BOOLEAN );
  348. BEGIN
  349. p.mode := Terminated;
  350. p.Cancel
  351. END TerminateThis;
  352. PROCEDURE SetPriority*( pri: LONGINT ); (* Set the current process' priority. *)
  353. VAR me: Process;
  354. BEGIN
  355. me := CurrentProcess();
  356. me.SetPriority( pri )
  357. END SetPriority;
  358. PROCEDURE Sleep*( ms: LONGINT );
  359. BEGIN
  360. thrSleep( ms )
  361. END Sleep;
  362. PROCEDURE Yield*; (* Relinquish control. *)
  363. BEGIN
  364. thrYield(0);
  365. END Yield;
  366. (* Return current process. (DEPRECATED, use ActiveObject) *)
  367. PROCEDURE CurrentProcess*( ): Process;
  368. VAR me: Unix.Thread_t; p: Process;
  369. BEGIN
  370. me := thrThis(0);
  371. mtxLock( processList );
  372. p := root;
  373. WHILE (p # NIL) & (p.threadId # me) DO p := p.nextProcess END;
  374. mtxUnlock( processList );
  375. RETURN p
  376. END CurrentProcess;
  377. PROCEDURE CurrentContext*(): ANY;
  378. VAR p: Process;
  379. BEGIN
  380. p := CurrentProcess();
  381. IF p # NIL THEN RETURN p.context
  382. ELSE RETURN NIL
  383. END;
  384. END CurrentContext;
  385. PROCEDURE SetContext*(context: ANY);
  386. VAR p: Process;
  387. BEGIN
  388. p := CurrentProcess();
  389. IF p # NIL THEN p.context := context END;
  390. END SetContext;
  391. (* Return the active object currently executing. *)
  392. PROCEDURE ActiveObject*( ): ANY;
  393. VAR p: Process;
  394. BEGIN
  395. p := CurrentProcess();
  396. RETURN p.obj
  397. END ActiveObject;
  398. (* Return stack bottom of process. For compatibility WinAos/UnixAos/NativeAos *)
  399. PROCEDURE GetStackBottom*(p: Process): ADDRESS;
  400. BEGIN
  401. RETURN p.stackBottom
  402. END GetStackBottom;
  403. PROCEDURE GetProcessID*( ): LONGINT;
  404. VAR p: Process;
  405. BEGIN
  406. p := CurrentProcess();
  407. RETURN p.id;
  408. END GetProcessID;
  409. PROCEDURE GetCpuCycles*( process : Process; VAR cpuCycles: CpuCyclesArray; all: BOOLEAN );
  410. VAR i: LONGINT;
  411. BEGIN
  412. ASSERT( process # NIL );
  413. FOR i := 0 TO Machine.MaxCPU-1 DO cpuCycles[i] := 0 END;
  414. END GetCpuCycles;
  415. (*-----------------------------------------------------------------------*)
  416. PROCEDURE min( a, b: LONGINT ): LONGINT;
  417. BEGIN
  418. IF a <= b THEN RETURN a ELSE RETURN b END
  419. END min;
  420. PROCEDURE max( a, b: LONGINT ): LONGINT;
  421. BEGIN
  422. IF a >= b THEN RETURN a ELSE RETURN b END
  423. END max;
  424. PROCEDURE RegisterFinalizer( obj: ANY; fin: Heaps.Finalizer );
  425. VAR n: Heaps.FinalizerNode;
  426. BEGIN
  427. NEW( n ); n.finalizer := fin; Heaps.AddFinalizer( obj, n );
  428. END RegisterFinalizer;
  429. PROCEDURE FinalizeActiveObj( obj: ANY );
  430. VAR p: Process;
  431. BEGIN
  432. mtxLock( processList );
  433. p := root;
  434. WHILE (p # NIL) & (p.obj # obj) DO p := p.nextProcess END;
  435. mtxUnlock( processList );
  436. IF (p # NIL) & (p.obj = obj) THEN
  437. p.mode := Terminated;
  438. conDestroy( p.continue ); p.continue := 0;
  439. FinalizeProtObject( obj );
  440. p.Cancel
  441. END;
  442. END FinalizeActiveObj;
  443. PROCEDURE FinalizeProtObject( obj: ANY );
  444. VAR hdr: ObjectHeader;
  445. BEGIN
  446. S.GET( S.VAL( ADDRESS, obj ) + Heaps.HeapBlockOffset, hdr );
  447. IF hdr.mtx # 0 THEN
  448. mtxDestroy( hdr.mtx ); hdr.mtx := 0
  449. END
  450. END FinalizeProtObject;
  451. PROCEDURE FinalizeProcess( obj: ANY );
  452. VAR p: Process;
  453. BEGIN
  454. p := obj(Process);
  455. IF p.continue # 0 THEN
  456. conDestroy( p.continue ); p.continue := 0
  457. END
  458. END FinalizeProcess;
  459. (* Terminate calling thread. *)
  460. PROCEDURE Exit;
  461. VAR prev, p, me: Process;
  462. BEGIN
  463. me := CurrentProcess();
  464. me.mode := Terminated;
  465. mtxLock( processList );
  466. prev := NIL; p := root;
  467. WHILE (p # NIL ) & (p # me) DO prev := p; p := p.nextProcess END;
  468. IF p = me THEN
  469. IF prev = NIL THEN root := p.nextProcess ELSE prev.nextProcess := p.nextProcess END;
  470. END;
  471. mtxUnlock( processList );
  472. thrExit(0)
  473. END Exit;
  474. PROCEDURE ExitTrap*;
  475. VAR p: Process;
  476. BEGIN
  477. p := CurrentProcess();
  478. (* restart the object body if it was given the SAFE flag *)
  479. IF Restart IN p.flags THEN
  480. Unix.siglongjmp( ADDRESSOF( p.state0[0] ), 1 )
  481. END;
  482. Exit
  483. END ExitTrap;
  484. (*---------------------------- Timer --------------------------------*)
  485. PROCEDURE Remove( t: Timer ); (* remove timer from list of active timers *)
  486. VAR p, x: Timer;
  487. BEGIN
  488. mtxLock( timerListMutex );
  489. t.trigger := 0; t.handler := NIL;
  490. IF timers # NIL THEN
  491. IF t = timers THEN
  492. timers := t.next
  493. ELSE
  494. p := timers; x := p.next;
  495. WHILE (x # NIL) & (x # t) DO p := x; x := p.next END;
  496. IF x = t THEN p.next := t.next END
  497. END;
  498. t.next := NIL
  499. END;
  500. mtxUnlock( timerListMutex )
  501. END Remove;
  502. PROCEDURE Insert( t: Timer );
  503. VAR p, x: Timer;
  504. BEGIN
  505. mtxLock( timerListMutex );
  506. p := NIL; x := timers;
  507. WHILE (x # NIL) & (x.trigger < t.trigger) DO p := x; x := p.next END;
  508. t.next := x;
  509. IF p = NIL THEN timers := t ELSE p.next := t END;
  510. mtxUnlock( timerListMutex )
  511. END Insert;
  512. PROCEDURE SetTimeout*( t: Timer; h: EventHandler; ms: LONGINT );
  513. BEGIN
  514. ASSERT( ( t # NIL) & ( h # NIL) );
  515. Remove( t );
  516. IF ms < 1 THEN ms := 1 END;
  517. t.trigger := Machine.ticks + ms; t.handler := h;
  518. Insert( t );
  519. timerActivity.Restart
  520. END SetTimeout;
  521. PROCEDURE SetTimeoutAt*( t: Timer; h: EventHandler; ms: LONGINT );
  522. BEGIN
  523. ASSERT( (t # NIL) & (h # NIL) );
  524. Remove( t );
  525. t.trigger := ms; t.handler := h;
  526. Insert( t );
  527. timerActivity.Restart
  528. END SetTimeoutAt;
  529. PROCEDURE CancelTimeout*( t: Timer );
  530. BEGIN
  531. Remove( t )
  532. END CancelTimeout;
  533. (*-------------------- Garbage Collection ------------------------------------*)
  534. (* called by WMProcessInfo to obtain the current state of a running process *)
  535. PROCEDURE UpdateProcessState*( p: Process );
  536. BEGIN
  537. (* update p.stat.{PC,BP,SP} *)
  538. END UpdateProcessState;
  539. PROCEDURE SuspendActivities;
  540. VAR t: Process;
  541. BEGIN
  542. t := root;
  543. WHILE t # NIL DO
  544. IF (t # mainProcess) & (t # finCaller) THEN thrSuspend( t.threadId ) END;
  545. t := t.nextProcess
  546. END;
  547. END SuspendActivities;
  548. PROCEDURE ResumeActivities;
  549. VAR t: Process;
  550. BEGIN
  551. t := root;
  552. WHILE t # NIL DO
  553. IF (t # mainProcess) & (t # finCaller) THEN thrResume( t.threadId ) END;
  554. t := t.nextProcess
  555. END;
  556. END ResumeActivities;
  557. PROCEDURE SaveSP; (* save current SP for usage by the GC *)
  558. VAR me: Unix.Thread_t; t: Process;
  559. BEGIN
  560. me := thrThis(0); t := root;
  561. WHILE (t # NIL ) & (t.threadId # me) DO t := t.nextProcess END;
  562. IF t # NIL THEN t.SP := Machine.CurrentSP( ) END
  563. END SaveSP;
  564. PROCEDURE InvokeGC;
  565. BEGIN
  566. IF Machine.AcquireGC() THEN (* gets released by FinalizerCaller *)
  567. collect := TRUE;
  568. conWait( gcFinished, igc )
  569. END;
  570. END InvokeGC;
  571. (*! GCLoop gets called as last procedure in BootConsole (main thread).
  572. The stack of the main thread is not limited by the boot parameter 'StackSize' !!
  573. *)
  574. PROCEDURE GCLoop*; (* Timer and GC activity *)
  575. BEGIN
  576. SetPriority( GCPriority );
  577. LOOP
  578. IF collect THEN
  579. collect := FALSE;
  580. Machine.Acquire( Machine.Heaps );
  581. SuspendActivities;
  582. Heaps.CollectGarbage( Modules.root );
  583. Machine.Release( Machine.Heaps );
  584. ResumeActivities;
  585. finalizerCaller.Start;
  586. conSignal( gcFinished );
  587. ELSE
  588. thrSleep( 10 );
  589. END;
  590. timerActivity.UpdateTicks
  591. END
  592. END GCLoop;
  593. PROCEDURE CurrentProcessTime*(): HUGEINT;
  594. BEGIN
  595. RETURN Machine.GetTimer()
  596. END CurrentProcessTime;
  597. PROCEDURE TimerFrequency*(): HUGEINT;
  598. BEGIN
  599. RETURN Machine.mhz * 1000000
  600. END TimerFrequency;
  601. (*----------------------------- initialization ----------------------------------*)
  602. PROCEDURE StartTimerActivity;
  603. BEGIN
  604. timerListMutex := mtxInit(0); timers := NIL;
  605. NEW( timerActivity );
  606. END StartTimerActivity;
  607. PROCEDURE GetStacksize;
  608. VAR str: ARRAY 32 OF CHAR; i: LONGINT;
  609. BEGIN
  610. Machine.GetConfig( "StackSize", str );
  611. IF str = "" THEN stacksize := DefaultStacksize
  612. ELSE
  613. i := 0; stacksize := Machine.StrToInt( i, str );
  614. stacksize := stacksize * 1024;
  615. END;
  616. IF Glue.debug # {} THEN
  617. Trace.String( "Stacksize of active objects = " );
  618. Trace.Int( stacksize DIV 1024, 0 ); Trace.StringLn( "K" )
  619. END;
  620. END GetStacksize;
  621. PROCEDURE Convert;
  622. VAR p: Process;
  623. BEGIN
  624. (* make current thread the first active object *)
  625. NEW( p, NIL, NIL, 0, {}, 0 );
  626. END Convert;
  627. PROCEDURE Init;
  628. BEGIN
  629. Unix.Dlsym( 0, "mtxInit", ADDRESSOF( mtxInit ) );
  630. Unix.Dlsym( 0, "mtxDestroy", ADDRESSOF( mtxDestroy ) );
  631. Unix.Dlsym( 0, "mtxLock", ADDRESSOF( mtxLock ) );
  632. Unix.Dlsym( 0, "mtxUnlock", ADDRESSOF( mtxUnlock ) );
  633. Unix.Dlsym( 0, "conInit", ADDRESSOF( conInit ) );
  634. Unix.Dlsym( 0, "conDestroy", ADDRESSOF( conDestroy ) );
  635. Unix.Dlsym( 0, "conWait", ADDRESSOF( conWait ) );
  636. Unix.Dlsym( 0, "conSignal", ADDRESSOF( conSignal ) );
  637. Unix.Dlsym( 0, "thrStart", ADDRESSOF( thrStart ) );
  638. Unix.Dlsym( 0, "thrThis", ADDRESSOF( thrThis ) );
  639. Unix.Dlsym( 0, "thrSleep", ADDRESSOF( thrSleep ) );
  640. Unix.Dlsym( 0, "thrYield", ADDRESSOF( thrYield ) );
  641. Unix.Dlsym( 0, "thrExit", ADDRESSOF( thrExit ) );
  642. Unix.Dlsym( 0, "thrSuspend", ADDRESSOF( thrSuspend ) );
  643. Unix.Dlsym( 0, "thrResume", ADDRESSOF( thrResume ) );
  644. Unix.Dlsym( 0, "thrGetPriority", ADDRESSOF( thrGetPriority ) );
  645. Unix.Dlsym( 0, "thrSetPriority", ADDRESSOF( thrSetPriority ) );
  646. Unix.Dlsym( 0, "thrKill", ADDRESSOF( thrKill ) );
  647. createProcess := mtxInit( 0 ); processList := mtxInit( 0 );
  648. startProcess := mtxInit(0); childrunning := conInit(0);
  649. collect := FALSE;
  650. igc := mtxInit( 0 ); gcFinished := conInit( 0 );
  651. GetStacksize;
  652. Convert;
  653. StartTimerActivity;
  654. NEW( finalizerCaller );
  655. Heaps.saveSP := SaveSP;
  656. Heaps.GC := InvokeGC;
  657. Heaps.InvokeGC := InvokeGC;
  658. END Init;
  659. VAR
  660. (* for compatibility and later extension *)
  661. TraceProcessHook*: PROCEDURE (prcoess: Process; pc, bp: ADDRESS; stacklow, stackhigh: ADDRESS);
  662. BEGIN
  663. TraceProcessHook := NIL;
  664. Init;
  665. END Objects.