-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
with Interfaces.C;
with Interfaces.C.Strings;
+with System.Multiprocessors;
with System.Tasking.Debug;
with System.OS_Primitives;
with System.Task_Info;
Unlock (L, Global_Lock => True);
-- No problem if we are interrupted here: if the condition is signaled,
- -- WaitForSingleObject will simply not block
+ -- WaitForSingleObject will simply not block.
if Rel_Time <= 0.0 then
Timed_Out := True;
Wait_Result := 0;
else
- if Rel_Time >= Duration (Time_Out_Max) / 1000 then
- Time_Out := Time_Out_Max;
- else
- Time_Out := DWORD (Rel_Time * 1000);
- end if;
+ Time_Out :=
+ (if Rel_Time >= Duration (Time_Out_Max) / 1000
+ then Time_Out_Max
+ else DWORD (Rel_Time * 1000));
Wait_Result := WaitForSingleObject (HANDLE (Cond.all), Time_Out);
pragma Import (C, Init_Float, "__gnat_init_float");
-- Properly initializes the FPU for x86 systems
+ procedure Get_Stack_Bounds (Base : Address; Limit : Address);
+ pragma Import (C, Get_Stack_Bounds, "__gnat_get_stack_bounds");
+ -- Get stack boundaries
begin
Specific.Set (Self_ID);
Init_Float;
Self_ID.Common.LL.Thread_Id := GetCurrentThreadId;
- Lock_RTS;
-
- for J in Known_Tasks'Range loop
- if Known_Tasks (J) = null then
- Known_Tasks (J) := Self_ID;
- Self_ID.Known_Tasks_Index := J;
- exit;
- end if;
- end loop;
-
- Unlock_RTS;
+ Get_Stack_Bounds
+ (Self_ID.Common.Compiler_Data.Pri_Stack_Info.Base'Address,
+ Self_ID.Common.Compiler_Data.Pri_Stack_Info.Limit'Address);
end Enter_Task;
--------------
Result : DWORD;
Entry_Point : PTHREAD_START_ROUTINE;
+ use type System.Multiprocessors.CPU_Range;
+
begin
pTaskParameter := To_Address (T);
T.Common.LL.Thread := hTask;
+ -- Note: it would be useful to initialize Thread_Id right away to avoid
+ -- a race condition in gdb where Thread_ID may not have the right value
+ -- yet, but GetThreadId is a Vista specific API, not available under XP:
+ -- T.Common.LL.Thread_Id := GetThreadId (hTask); so instead we set the
+ -- field to 0 to avoid having a random value. Thread_Id is initialized
+ -- in Enter_Task anyway.
+
+ T.Common.LL.Thread_Id := 0;
+
-- Step 3: set its priority (child has inherited priority from parent)
Set_Priority (T, Priority);
or else Get_Policy (Priority) = 'F'
then
-- Here we need Annex D semantics so we disable the NT priority
- -- boost. A priority boost is temporarily given by the system to a
- -- thread when it is taken out of a wait state.
+ -- boost. A priority boost is temporarily given by the system to
+ -- a thread when it is taken out of a wait state.
SetThreadPriorityBoost (hTask, DisablePriorityBoost => Win32.TRUE);
end if;
- -- Step 4: Handle Task_Info
+ -- Step 4: Handle pragma CPU and Task_Info
+
+ if T.Common.Base_CPU /= System.Multiprocessors.Not_A_Specific_CPU then
+
+ -- The CPU numbering in pragma CPU starts at 1 while the subprogram
+ -- to set the affinity starts at 0, therefore we must substract 1.
+
+ Result := SetThreadIdealProcessor
+ (hTask, ProcessorId (T.Common.Base_CPU) - 1);
+ pragma Assert (Result = 1);
- if T.Common.Task_Info /= null then
+ elsif T.Common.Task_Info /= null then
if T.Common.Task_Info.CPU /= Task_Info.Any_CPU then
Result := SetThreadIdealProcessor (hTask, T.Common.Task_Info.CPU);
pragma Assert (Result = 1);
end if;
end if;
- -- Step 5: Now, start it for good:
+ -- Step 5: Now, start it for good
Result := ResumeThread (hTask);
pragma Assert (Result = 1);
Discard : BOOL;
pragma Unreferenced (Discard);
+ Result : DWORD;
+
+ use type System.Multiprocessors.CPU_Range;
+
begin
Environment_Task_Id := Environment_Task;
OS_Primitives.Initialize;
Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
Environment_Task.Common.LL.Thread := GetCurrentThread;
+
+ -- Make environment task known here because it doesn't go through
+ -- Activate_Tasks, which does it for all other tasks.
+
+ Known_Tasks (Known_Tasks'First) := Environment_Task;
+ Environment_Task.Known_Tasks_Index := Known_Tasks'First;
+
Enter_Task (Environment_Task);
+
+ -- pragma CPU for the environment task
+
+ if Environment_Task.Common.Base_CPU /=
+ System.Multiprocessors.Not_A_Specific_CPU
+ then
+ -- The CPU numbering in pragma CPU starts at 1 while the subprogram
+ -- to set the affinity starts at 0, therefore we must substract 1.
+
+ Result :=
+ SetThreadIdealProcessor
+ (Environment_Task.Common.LL.Thread,
+ ProcessorId (Environment_Task.Common.Base_CPU) - 1);
+ pragma Assert (Result = 1);
+ end if;
end Initialize;
---------------------
procedure Finalize (S : in out Suspension_Object) is
Result : BOOL;
+
begin
-- Destroy internal mutex
procedure Suspend_Until_True (S : in out Suspension_Object) is
Result : DWORD;
Result_Bool : BOOL;
+
begin
SSL.Abort_Defer.all;