PROCESS.MOD 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * PROCESS.MOD - Multi-process support *
  5. * *
  6. * COPYRIGHT (C) 1987..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. (*# call(seg_name => PROCESS) *)
  11. (*# module(implementation=>off) *)
  12. (*# check(stack=>off,
  13. index=>off,
  14. range=>off,
  15. overflow=>off,
  16. nil_ptr=>off) *)
  17. (*# call(o_a_copy=>off) *)
  18. IMPLEMENTATION MODULE Process;
  19. (*%F _OS2 *)
  20. FROM Storage IMPORT ALLOCATE;
  21. IMPORT SYSTEM, Storage, Lib, CoreSig, CoreProc;
  22. TYPE
  23. SIGNAL = POINTER TO SigRec;
  24. (* change to task descriptor *)
  25. SigRec = RECORD
  26. count : INTEGER;
  27. waiting : CoreProc.Task;
  28. END;
  29. PROCEDURE QInsert(T: CoreProc.Task; VAR Q: CoreProc.Task);
  30. (* inserts task after last task in Q with greater or equal priority *)
  31. VAR
  32. q,qb : CoreProc.Task;
  33. BEGIN
  34. q := Q;
  35. qb := NIL;
  36. WHILE (q<>NIL)AND(T^.priority<=q^.priority) DO
  37. qb := q;
  38. q := q^.next;
  39. END;
  40. IF qb=NIL THEN
  41. Q := T;
  42. ELSE
  43. qb^.next := T;
  44. END;
  45. T^.next := q;
  46. END QInsert;
  47. PROCEDURE AddReadyProcess(T: CoreProc.Task);
  48. (* adds new process to ready list
  49. NB gets added ahead of current process if at same priority
  50. *)
  51. VAR
  52. mp : SYSTEM.PROCESS;
  53. oldcp : CoreProc.Task;
  54. ie : CARDINAL;
  55. BEGIN
  56. ie := SYSTEM.GetFlags(); SYSTEM.DI;
  57. IF CoreProc._cp=NIL THEN
  58. QInsert(T,CoreProc._cp); (* add new process *)
  59. ELSE
  60. oldcp := CoreProc._cp; (* remove current process *)
  61. CoreProc._cp := CoreProc._cp^.next;
  62. QInsert(T,CoreProc._cp); (* add new process *)
  63. QInsert(oldcp,CoreProc._cp); (* add current process *)
  64. END;
  65. mp := CoreProc._cp^.cor;
  66. SYSTEM.TRANSFER (mp,mp);
  67. SYSTEM.SetFlags(ie);
  68. END AddReadyProcess;
  69. PROCEDURE StartProcess(P:PROC;N,Pr:CARDINAL);
  70. VAR
  71. np : CoreProc.Task;
  72. BEGIN
  73. INC(Pr);
  74. IF N < 32000 THEN
  75. INC(N, 512); (* FP Overhead *)
  76. END; (*IF*)
  77. Storage.ALLOCATE(np,SIZE(CoreProc.TaskDescriptor));
  78. Storage.ALLOCATE(np^.wsp,N);
  79. np^.priority := Pr;
  80. np^.wspsize := N;
  81. SYSTEM.NEWPROCESS(P,np^.wsp,N,np^.cor);
  82. AddReadyProcess(np);
  83. END StartProcess;
  84. (* new stop me procedure *)
  85. PROCEDURE StopProcess;
  86. VAR
  87. t0 : CoreProc.Task;
  88. mp : SYSTEM.PROCESS;
  89. ie : CARDINAL;
  90. BEGIN
  91. CoreProc._ProcIds[CoreProc._getTID()-1] := 0;
  92. ie := SYSTEM.GetFlags(); SYSTEM.DI;
  93. t0 := CoreProc._cp ;
  94. CoreProc._cp := CoreProc._cp^.next;
  95. Storage.DEALLOCATE(t0^.wsp,t0^.wspsize);
  96. Storage.DEALLOCATE(t0,SIZE(CoreProc.TaskDescriptor));
  97. mp := CoreProc._cp^.cor;
  98. SYSTEM.TRANSFER (mp,mp);
  99. SYSTEM.SetFlags(ie);
  100. END StopProcess;
  101. PROCEDURE SEND(s: SIGNAL);
  102. VAR
  103. t0 : CoreProc.Task;
  104. ie : CARDINAL;
  105. BEGIN
  106. ie := SYSTEM.GetFlags(); SYSTEM.DI;
  107. IF s^.count <> MAX(INTEGER) THEN
  108. INC(s^.count);
  109. IF s^.count <= 0 THEN (* somebody waiting *)
  110. t0 := s^.waiting;
  111. s^.waiting := t0^.next;
  112. AddReadyProcess(t0);
  113. END;
  114. END;
  115. SYSTEM.SetFlags(ie);
  116. END SEND;
  117. PROCEDURE Notify(s: SIGNAL);
  118. VAR
  119. t0 : CoreProc.Task;
  120. ie : CARDINAL;
  121. BEGIN
  122. ie := SYSTEM.GetFlags(); SYSTEM.DI;
  123. IF s^.count < 0 THEN (* somebody waiting *)
  124. INC(s^.count);
  125. t0 := s^.waiting;
  126. s^.waiting := t0^.next;
  127. (* add to waiting q *)
  128. t0^.nextdue := CoreProc._wq;
  129. CoreProc._wq := t0;
  130. END;
  131. SYSTEM.SetFlags(ie);
  132. END Notify;
  133. PROCEDURE WAIT (s: SIGNAL);
  134. VAR
  135. t0 : CoreProc.Task;
  136. mp : SYSTEM.PROCESS;
  137. ie : CARDINAL;
  138. BEGIN (* insert CoreProc._cp in queue s *)
  139. ie := SYSTEM.GetFlags(); SYSTEM.DI;
  140. DEC(s^.count);
  141. IF s^.count < 0 THEN (* wait *)
  142. t0 := CoreProc._cp;
  143. CoreProc._cp := CoreProc._cp^.next;
  144. QInsert(t0,s^.waiting);
  145. mp := CoreProc._cp^.cor;
  146. SYSTEM.TRANSFER (mp,mp);
  147. END;
  148. SYSTEM.SetFlags(ie);
  149. END WAIT;
  150. PROCEDURE Awaited(s: SIGNAL) : BOOLEAN;
  151. BEGIN
  152. RETURN (s^.count<0);
  153. END Awaited;
  154. PROCEDURE Init(VAR s: SIGNAL);
  155. BEGIN
  156. NEW(s);
  157. s^.waiting := NIL;
  158. s^.count := 0;
  159. END Init;
  160. PROCEDURE CheckTimeQ;
  161. VAR
  162. ta,tb,tn : CoreProc.Task;
  163. BEGIN
  164. ta := CoreProc._dq;
  165. tb := NIL;
  166. WHILE ta <> NIL DO
  167. tn := ta^.nextdue;
  168. IF ta^.due = CoreProc._SchedTime THEN
  169. IF tb = NIL THEN CoreProc._dq := tn ELSE tb^.nextdue := tn END;
  170. ta^.nextdue := CoreProc._wq;
  171. CoreProc._wq := ta;
  172. ELSE
  173. tb := ta;
  174. END;
  175. ta := tn;
  176. END;
  177. END CheckTimeQ;
  178. PROCEDURE Slice;
  179. (* Clears waiting queue *)
  180. (* Then schedules next ready process if it is of equal priority *)
  181. VAR
  182. nextt,oldt,ta : CoreProc.Task;
  183. BEGIN
  184. IF CoreProc._LockNestMonster = 0 THEN
  185. (* move waiting queue to the ready queue *)
  186. (* set up by CheckTimeQueue *)
  187. WHILE CoreProc._wq <> NIL DO
  188. ta := CoreProc._wq; CoreProc._wq := CoreProc._wq^.nextdue;
  189. QInsert(ta,CoreProc._cp);
  190. END;
  191. (* now do slice *)
  192. nextt := CoreProc._cp^.next;
  193. IF (nextt <> NIL) AND (nextt^.priority = CoreProc._cp^.priority) THEN (* slice *)
  194. oldt := CoreProc._cp; CoreProc._cp := nextt;
  195. QInsert(oldt,CoreProc._cp); (* insert old CoreProc._cp at end of processes *)
  196. END;
  197. END;
  198. END Slice;
  199. MODULE SS[1]; (* IRQ 1: timer interrupt *)
  200. IMPORT SYSTEM;
  201. IMPORT CoreProc,Slice,CheckTimeQ;
  202. EXPORT Scheduler;
  203. PROCEDURE Scheduler;
  204. VAR
  205. nextt,
  206. oldt : CoreProc.Task;
  207. op,np : SYSTEM.PROCESS;
  208. Int8 : PROC;
  209. TYPE
  210. code = ARRAY[0..2] OF SHORTCARD;
  211. CONST
  212. Int8code = code(0CDH,08H,0CBH); (* INT 08H / RETF *)
  213. BEGIN
  214. SYSTEM.DI;
  215. Int8 := PROC(ADR(Int8code));
  216. CoreProc.Stop := FALSE;
  217. CoreProc._SchedTime := 0;
  218. LOOP
  219. np := CoreProc._cp^.cor;
  220. LOOP
  221. SYSTEM.IOTRANSFER(op,np,8);
  222. Int8;
  223. INC(CoreProc._SchedTime);
  224. IF CoreProc.Stop THEN EXIT END;
  225. CheckTimeQ;
  226. Slice;
  227. np := CoreProc._cp^.cor;
  228. END;
  229. CoreProc.Stop := FALSE;
  230. SYSTEM.TRANSFER(op,np); (* no return until restarted *)
  231. END;
  232. END Scheduler;
  233. END SS;
  234. PROCEDURE Idler; (* always on CoreProc._cp chain *)
  235. VAR
  236. i : CARDINAL;
  237. BEGIN
  238. LOOP INC(i);
  239. END;
  240. END Idler;
  241. PROCEDURE StartScheduler;
  242. VAR
  243. ie : CARDINAL;
  244. BEGIN
  245. ie := SYSTEM.GetFlags(); SYSTEM.DI;
  246. IF NOT CoreProc._Started THEN
  247. CoreProc._Started := TRUE;
  248. IF CoreProc._SchedStack = NIL THEN (* first time *)
  249. Storage.ALLOCATE( CoreProc._SchedStack, 1024 );
  250. SYSTEM.NEWPROCESS( Scheduler, CoreProc._SchedStack, 1024, CoreProc._SchedProc );
  251. END;
  252. SYSTEM.TRANSFER( CoreProc._cp^.cor, CoreProc._SchedProc );
  253. END;
  254. SYSTEM.SetFlags(ie);
  255. END StartScheduler;
  256. PROCEDURE StopScheduler;
  257. VAR
  258. ie : CARDINAL;
  259. BEGIN
  260. ie := SYSTEM.GetFlags();
  261. IF CoreProc._Started THEN
  262. SYSTEM.EI ;
  263. CoreProc._Started := FALSE;
  264. CoreProc.Stop := TRUE;
  265. WHILE CoreProc.Stop DO END;
  266. END;
  267. SYSTEM.SetFlags(ie);
  268. END StopScheduler;
  269. PROCEDURE Delay(T: CARDINAL);
  270. (* Waits T time slices *)
  271. (* 0 will swap to next process of equal priority, without delaying *)
  272. VAR
  273. mp : SYSTEM.PROCESS;
  274. ie : CARDINAL;
  275. BEGIN
  276. IF NOT CoreProc._Started THEN RETURN END;
  277. ie := SYSTEM.GetFlags(); SYSTEM.DI;
  278. IF T = 0 THEN
  279. mp := CoreProc._cp^.cor;
  280. Slice;
  281. IF mp = CoreProc._cp^.cor THEN
  282. SYSTEM.SetFlags(ie);
  283. RETURN
  284. END; (* no other processes ready *)
  285. ELSE
  286. CoreProc._cp^.due := CoreProc._SchedTime + T;
  287. CoreProc._cp^.nextdue := CoreProc._dq;
  288. CoreProc._dq := CoreProc._cp;
  289. CoreProc._cp := CoreProc._cp^.next;
  290. END;
  291. mp := CoreProc._cp^.cor;
  292. SYSTEM.TRANSFER(mp,mp);
  293. SYSTEM.SetFlags(ie);
  294. END Delay;
  295. PROCEDURE Lock;
  296. (* Critical region lock - prevents timeslicing *)
  297. (* may be nested *)
  298. BEGIN
  299. INC(CoreProc._LockNestMonster);
  300. END Lock;
  301. PROCEDURE Unlock;
  302. (* Unlock procedure, always paired with a call to Lock.
  303. Will de-schedule current process if there are ready processes
  304. of equal priority *)
  305. VAR
  306. ie : CARDINAL;
  307. BEGIN
  308. ie := SYSTEM.GetFlags(); SYSTEM.DI;
  309. IF CoreProc._LockNestMonster <= 1 THEN
  310. CoreProc._LockNestMonster := 0; Delay(0);
  311. ELSE
  312. DEC(CoreProc._LockNestMonster);
  313. END;
  314. SYSTEM.SetFlags(ie);
  315. END Unlock;
  316. BEGIN
  317. IF CoreProc._proc_init = FALSE THEN
  318. SYSTEM.initprocess();
  319. CoreProc._dq := NIL;
  320. CoreProc._wq := NIL;
  321. Storage.ALLOCATE(CoreProc._cp, SIZE(CoreProc.TaskDescriptor));
  322. IF CoreProc._cp = NIL THEN
  323. CoreSig._FatalError(CoreSig._FatalErrorPos(), 044H);
  324. END;
  325. CoreProc._cp^.next := NIL;
  326. CoreProc._cp^.priority := 2;
  327. CoreProc._cp^.cor := SYSTEM.CurrentProcess();
  328. CoreProc._NextThread:=2;
  329. StartProcess( Idler, 512, MAX(CARDINAL));
  330. CoreProc._SchedStack := NIL;
  331. CoreProc._Started := FALSE;
  332. CoreProc._LockNestMonster := 0;
  333. CoreProc._exit_proc:=StopScheduler;
  334. END;
  335. CoreProc._core_lock:=Lock;
  336. CoreProc._core_unlock:=Unlock;
  337. CoreProc._core_delay := Delay;
  338. (*%E *)
  339. (*%T _OS2 *)
  340. IMPORT Storage, Lib, Str, Dos, CoreProc, CoreSig;
  341. FROM Storage IMPORT ALLOCATE;
  342. TYPE
  343. SIGNAL = POINTER TO SigRec;
  344. SigRec = RECORD
  345. count : INTEGER;
  346. sem : LONGCARD;
  347. END;
  348. PROCEDURE ErrorNamed ( IOR : CARDINAL; Code: CARDINAL; Msg: ARRAY OF CHAR);
  349. VAR
  350. s : ARRAY[0..100] OF CHAR;
  351. BEGIN
  352. IF IOR#0 THEN
  353. Lib.RunTimeError(CoreSig._FatalErrorPos(), Code, Msg);
  354. END;
  355. END ErrorNamed;
  356. PROCEDURE StartScheduler;
  357. VAR i : [0..MaxProcess];
  358. BEGIN
  359. Lock;
  360. FOR i := 1 TO MaxProcess DO
  361. IF CoreProc._ProcIds[i] # 0 THEN ErrorNamed(Dos.ResumeThread(CoreProc._ProcIds[i]), 0C0H, 'DosResumeThread') END;
  362. END;
  363. CoreProc._Started := TRUE;
  364. Unlock;
  365. END StartScheduler;
  366. PROCEDURE StartProcess(P: PROC; N: CARDINAL; Pr: CARDINAL);
  367. VAR
  368. ID: CARDINAL;
  369. BEGIN
  370. Lock;
  371. DEC(Pr);
  372. INC(CoreProc._LastProc);
  373. IF CoreProc._LastProc = MaxProcess THEN
  374. ErrorNamed(0, 0C0H, 'StartProcess');
  375. END;
  376. IF N < 32000 THEN
  377. INC(N, 512); (* FP Overhead *)
  378. END;
  379. ID := CoreProc._dosbeginthread(P, N, NIL);
  380. IF ID < 0 THEN
  381. Lib.RunTimeError(CoreSig._FatalErrorPos(), 0C1H, Lib.NilStr);
  382. END;
  383. CoreProc._ProcIds[ID-1] := ID;
  384. ErrorNamed(Dos.SetPrty(2,0,INTEGER(Pr),ID), 0C2H, 'DosSetPrty');
  385. IF NOT CoreProc._Started THEN
  386. ErrorNamed(Dos.SuspendThread(ID), 0C3H, 'DosSuspendThread');
  387. END;
  388. Unlock;
  389. END StartProcess;
  390. PROCEDURE StopProcess();
  391. BEGIN
  392. CoreProc._ProcIds[CoreProc._getTID()-1] := 0;
  393. CoreProc._dosendthread();
  394. END StopProcess;
  395. PROCEDURE StopScheduler();
  396. BEGIN
  397. END StopScheduler;
  398. PROCEDURE SEND(s: SIGNAL);
  399. BEGIN
  400. Lock;
  401. IF s^.count < 0 THEN
  402. ErrorNamed(Dos.SemClear(FarADR(s^.sem)), 0C4H, 'DosSemClear');;
  403. END;
  404. INC(s^.count);
  405. Unlock;
  406. END SEND;
  407. PROCEDURE WAIT(s: SIGNAL);
  408. BEGIN
  409. Lock;
  410. DEC(s^.count);
  411. IF s^.count < 0 THEN
  412. Unlock;
  413. ErrorNamed(Dos.SemRequest(FarADR(s^.sem),-1), 0C5H, 'DosSemRequest');
  414. ELSE
  415. Unlock;
  416. END;
  417. END WAIT;
  418. PROCEDURE Notify(s: SIGNAL);
  419. BEGIN
  420. Lock;
  421. IF s^.count < 0 THEN
  422. ErrorNamed(Dos.SemClear(FarADR(s^.sem)), 0C6H, 'DosSemClear');
  423. INC(s^.count);
  424. END;
  425. Unlock;
  426. END Notify;
  427. PROCEDURE Awaited(s: SIGNAL) : BOOLEAN;
  428. BEGIN
  429. RETURN s^.count < 0;
  430. END Awaited;
  431. PROCEDURE Lock;
  432. VAR
  433. tid : CARDINAL ;
  434. BEGIN
  435. tid := CoreProc._getTID();
  436. IF (CoreProc._LockCount=0)OR(CoreProc._LockedThread<>tid) THEN
  437. IF Dos.SemRequest(FarADR(CoreProc._LockSem),-1)=0 THEN END;
  438. CoreProc._LockedThread := tid ;
  439. END;
  440. INC(CoreProc._LockCount);
  441. END Lock;
  442. PROCEDURE Unlock;
  443. BEGIN
  444. DEC(CoreProc._LockCount);
  445. IF CoreProc._LockCount=0 THEN
  446. IF Dos.SemClear(FarADR(CoreProc._LockSem))=0 THEN END;
  447. IF Dos.Sleep(0)=0 THEN END;
  448. END;
  449. END Unlock;
  450. PROCEDURE Init(VAR s: SIGNAL);
  451. BEGIN
  452. NEW(s);
  453. s^.sem := 0;
  454. ErrorNamed(Dos.SemSet(FarADR(s^.sem)), 0C7H, 'DosSemSet');
  455. s^.count := 0;
  456. END Init;
  457. PROCEDURE Delay(T: CARDINAL);
  458. BEGIN
  459. ErrorNamed(Dos.Sleep(LONGCARD(T)*50), 0C8H, 'DosSleep');
  460. END Delay;
  461. PROCEDURE Idler();
  462. END Idler;
  463. BEGIN
  464. CoreProc._Started := FALSE;
  465. CoreProc._LastProc := 0;
  466. CoreProc._LockCount := 0;
  467. CoreProc._LockSem := 0;
  468. CoreProc._LockedThread := 0 ;
  469. CoreProc._core_lock := Lock;
  470. CoreProc._core_unlock := Unlock;
  471. CoreProc._core_delay := Delay;
  472. CoreProc._NextThread:=2;
  473. (*%E *)
  474. END Process.
  475.