Windows.Processors.Mod 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. (* Windows runtime support for processors *)
  2. (* Copyright (C) Florian Negele *)
  3. MODULE Processors;
  4. IMPORT Kernel32;
  5. (** Indicates the maximal number of logical processors that are supported by the system. *)
  6. CONST Maximum* = MAX (SET) - MIN (SET) + 1;
  7. (** Holds the actual number of processors in the system. *)
  8. VAR count-: SIZE;
  9. VAR affinityMask: SET;
  10. VAR semaphore: Kernel32.HANDLE;
  11. VAR thread: ARRAY Maximum OF Kernel32.HANDLE;
  12. (** Returns the unique index of the processor executing this procedure call. *)
  13. PROCEDURE GetCurrentIndex- EXTERN "Activities.GetCurrentProcessorIndex" (): SIZE;
  14. (** Suspends the execution of the current processor. *)
  15. (** A suspended processor must be resumed by a call to the ResumeAnyProcessor procedure. *)
  16. PROCEDURE SuspendCurrentProcessor-;
  17. BEGIN {UNCOOPERATIVE, UNCHECKED}
  18. ASSERT (Kernel32.WaitForSingleObject (semaphore, Kernel32.Infinite) # Kernel32.WaitFailed);
  19. END SuspendCurrentProcessor;
  20. (** Resumes the execution of all suspended processors. *)
  21. PROCEDURE ResumeAllProcessors-;
  22. BEGIN {UNCOOPERATIVE, UNCHECKED}
  23. ASSERT (Kernel32.ReleaseSemaphore (semaphore, Maximum, NIL) # 0);
  24. END ResumeAllProcessors;
  25. (** Starts the execution of all available processors. *)
  26. PROCEDURE StartAll-;
  27. VAR i: SIZE;
  28. BEGIN {UNCOOPERATIVE, UNCHECKED}
  29. FOR i := 0 TO Maximum - 1 DO
  30. IF thread[i] # NIL THEN
  31. ASSERT (Kernel32.ResumeThread (thread[i]) # -1);
  32. END;
  33. END;
  34. END StartAll;
  35. (* Start routine for each Windows thread. *)
  36. PROCEDURE {WINAPI} Start (lpParameter {UNTRACED}: ANY): LONGINT;
  37. PROCEDURE Execute EXTERN "Activities.Execute" (procedure: PROCEDURE);
  38. PROCEDURE Idle EXTERN "Activities.Idle";
  39. BEGIN {UNCOOPERATIVE, UNCHECKED}
  40. Kernel32.InstallExceptionHandler;
  41. Execute (Idle);
  42. Kernel32.ExitThread(0);
  43. END Start;
  44. (** Initializes the module by enumerating all available processors. *)
  45. (** The number of concurrent threads corresponds to the number of slots in the affinity mask of the current process. *)
  46. PROCEDURE Initialize-;
  47. VAR systemAffinityMask: SET; i: SIZE; handle: Kernel32.HANDLE;
  48. BEGIN {UNCOOPERATIVE, UNCHECKED}
  49. semaphore := Kernel32.CreateSemaphore (NIL, 0, MAX (SIZE), NIL);
  50. ASSERT (semaphore # Kernel32.InvalidHandleValue);
  51. ASSERT (Kernel32.GetProcessAffinityMask (Kernel32.GetCurrentProcess (), ADDRESS OF affinityMask, ADDRESS OF systemAffinityMask) # 0);
  52. count := 0;
  53. FOR i := 0 TO Maximum - 1 DO
  54. IF i IN affinityMask THEN
  55. INC (count);
  56. IF count = 1 THEN
  57. handle := Kernel32.GetCurrentThread ();
  58. thread[i] := NIL;
  59. ELSE
  60. handle := Kernel32.CreateThread (NIL, 0, Start, NIL, {Kernel32.CreateSuspended}, NIL);
  61. ASSERT (handle # Kernel32.InvalidHandleValue);
  62. thread[i] := handle;
  63. END;
  64. ASSERT (Kernel32.SetThreadAffinityMask (handle, {i}) # {});
  65. ELSE
  66. thread[i] := NIL;
  67. END;
  68. END;
  69. END Initialize;
  70. (** Terminates the module and waits for all other processors to stop their execution. *)
  71. PROCEDURE Terminate-;
  72. VAR i: SIZE;
  73. BEGIN {UNCOOPERATIVE, UNCHECKED}
  74. FOR i := 0 TO Maximum - 1 DO
  75. IF thread[i] # NIL THEN
  76. ASSERT (Kernel32.WaitForSingleObject (thread[i], Kernel32.Infinite) # Kernel32.WaitFailed);
  77. ASSERT (Kernel32.CloseHandle (thread[i]) # 0);
  78. END;
  79. END;
  80. ASSERT (Kernel32.CloseHandle (semaphore) # 0);
  81. END Terminate;
  82. END Processors.