In advance, sorry for my bad english...

I write this program to create a CPU Monitor... But after many test with french purebasic community, it's appears that this code doesn't work with quad core. We can see that the result like this :
CPU0 : 210%
CPU1 : 222%
CPU2 : 254%
CPU3 : 228%
CPU TOTAL : 228%
If anyone have an idea on this problem, that will be very good.
Thanks by advance for your interest.
CPU Usage code
Structure SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
IdleTime.q
KernelTime.q
UserTime.q
DpcTime.q
InterruptTime.q
InterruptCount.q
EndStructure
#MaxCpus = 32
#SystemProcessorPerformanceInformation = 8
#SysProcPerfInfoLength = 48
#PROCESS_QUERY_INFORMATION = $400
#HUNDRED_NANOSEC = 10000000
Declare.l cpu_count()
Global Frequency.q, TimeStart.q
Global NumberOfProcessors = cpu_count()
Global Dim CpuInfo.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION(NumberOfProcessors)
Global Dim KernelTimesStart.d(NumberOfProcessors+1)
Global Dim UserTimesStart.d(NumberOfProcessors+1)
Global Dim IdleTimesStart.d(NumberOfProcessors+1)
Global Dim DpcTimesStart.d(NumberOfProcessors+1)
Global Dim InterruptTimesStart.d(NumberOfProcessors+1)
Global Dim KernelTimesStop.d(NumberOfProcessors+1)
Global Dim UserTimesStop.d(NumberOfProcessors+1)
Global Dim IdleTimesStop.d(NumberOfProcessors+1)
Global Dim DpcTimesStop.d(NumberOfProcessors+1)
Global Dim InterruptTimesStop.d(NumberOfProcessors+1)
Global Dim KernelTimesDelta.d(NumberOfProcessors+1)
Global Dim UserTimesDelta.d(NumberOfProcessors+1)
Global Dim IdleTimesDelta.d(NumberOfProcessors+1)
Global Dim CpuUsages.d(NumberOfProcessors+1)
Procedure.l cpu_count() ; Number of processors or cores
Protected SI.SYSTEM_INFO
GetSystemInfo_ (@SI)
ProcedureReturn SI\dwNumberOfProcessors
EndProcedure
Procedure.s TimeConvert(time.q)
hr.l = Round (time/36000000000, 0)
time = time-(hr*36000000000)
min.l = Round (time/600000000, 0)
time = time-(min*600000000)
sec.l = Round (time/10000000, 0)
time = time-(sec*10000000)
ms.l = Round (time/10000, 0)
ProcedureReturn Str (hr)+ ":" + RSet ( Str (min), 2, "0" )+ ":" + RSet ( Str (sec), 2, "0" )+ ":" + RSet ( Str (ms), 3, "0" )
EndProcedure
Procedure GetProcessorsTimes(start = #True )
Protected Lib
Lib = OpenLibrary ( #PB_Any , "ntdll.dll" )
If Lib
Function = GetFunction (Lib, "NtQuerySystemInformation" )
If CallFunctionFast (Function, #SystemProcessorPerformanceInformation , @CpuInfo(), #SysProcPerfInfoLength * #MaxCpus , @ret) = 0
If ret/ #SysProcPerfInfoLength = NumberOfProcessors
If start = #True
KernelTimesStart(NumberOfProcessors) = 0
IdleTimesStart(NumberOfProcessors) = 0
UserTimesStart(NumberOfProcessors) = 0
DpcTimesStart(NumberOfProcessors) = 0
InterruptTimesStart(NumberOfProcessors) = 0
For i = 0 To NumberOfProcessors - 1
KernelTimesStart(i) = CpuInfo(i)\KernelTime
IdleTimesStart(i) = CpuInfo(i)\IdleTime
UserTimesStart(i) = CpuInfo(i)\UserTime
DpcTimesStart(i) = CpuInfo(i)\DpcTime
InterruptTimesStart(i) = CpuInfo(i)\InterruptTime
KernelTimesStart(NumberOfProcessors) = KernelTimesStart(NumberOfProcessors) + CpuInfo(i)\KernelTime
IdleTimesStart(NumberOfProcessors) = IdleTimesStart(NumberOfProcessors) + CpuInfo(i)\IdleTime
UserTimesStart(NumberOfProcessors) = UserTimesStart(NumberOfProcessors) + CpuInfo(i)\UserTime
DpcTimesStart(NumberOfProcessors) = DpcTimesStart(NumberOfProcessors) + CpuInfo(i)\DpcTime
InterruptTimesStart(NumberOfProcessors) = InterruptTimesStart(NumberOfProcessors) + CpuInfo(i)\InterruptTime
Next
Else
KernelTimesStop(NumberOfProcessors) = 0
IdleTimesStop(NumberOfProcessors) = 0
UserTimesStop(NumberOfProcessors) = 0
DpcTimesStop(NumberOfProcessors) = 0
InterruptTimesStop(NumberOfProcessors) = 0
For i = 0 To NumberOfProcessors - 1
KernelTimesStop(i) = CpuInfo(i)\KernelTime
IdleTimesStop(i) = CpuInfo(i)\IdleTime
UserTimesStop(i) = CpuInfo(i)\UserTime
DpcTimesStop(i) = CpuInfo(i)\DpcTime
InterruptTimesStop(i) = CpuInfo(i)\InterruptTime
KernelTimesStop(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors) + CpuInfo(i)\KernelTime
IdleTimesStop(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors) + CpuInfo(i)\IdleTime
UserTimesStop(NumberOfProcessors) = UserTimesStop(NumberOfProcessors) + CpuInfo(i)\UserTime
DpcTimesStop(NumberOfProcessors) = DpcTimesStop(NumberOfProcessors) + CpuInfo(i)\DpcTime
InterruptTimesStop(NumberOfProcessors) = InterruptTimesStop(NumberOfProcessors) + CpuInfo(i)\InterruptTime
Next
EndIf
EndIf
EndIf
CloseLibrary (Lib)
EndIf
EndProcedure
Procedure refresh()
Protected CpuTime.d, CurTime.q, DiffTime.d
QueryPerformanceCounter_ (@CurTime)
GetProcessorsTimes( #False )
CpuUsages(NumberOfProcessors) = 0
For i = 0 To NumberOfProcessors - 1
KernelTimesDelta(i) = KernelTimesStop(i) - KernelTimesStart(i)
UserTimesDelta(i) = UserTimesStop(i) - UserTimesStart(i)
IdleTimesDelta(i) = IdleTimesStop(i) - IdleTimesStart(i)
CpuTime = (KernelTimesDelta(i) + UserTimesDelta(i) + IdleTimesDelta(i))
DiffTime = (CurTime - TimeStart) / Frequency
If DiffTime > 0 : CpuTime = ((CpuTime) / (DiffTime)) / NumberOfProcessors : EndIf
CpuUsages(i) = (100 * (1 - CpuTime / #HUNDRED_NANOSEC ))
If NumberOfProcessors = 1 : CpuUsages(i) = 100 + CpuUsages(i) : EndIf
If CpuUsages(i) < 0 : CpuUsages(i) = 0 : EndIf
; If CpuUsages(i) > (100/NumberOfProcessors) : CpuUsages(i) = (100/NumberOfProcessors) : EndIf
SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 2) ; Show percentage before adjusting to 100%
CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) + CpuUsages(i)
CpuUsages(i) = CpuUsages(i) * NumberOfProcessors
KernelTimesStart(i) = KernelTimesStop(i)
UserTimesStart(i) = UserTimesStop(i)
IdleTimesStart(i) = IdleTimesStop(i)
DpcTimesStart(i) = DpcTimesStop(i)
InterruptTimesStart(i) = InterruptTimesStop(i)
SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 1)
SetGadgetItemText (1, i, TimeConvert(KernelTimesStart(i)), 3)
SetGadgetItemText (1, i, TimeConvert(UserTimesStart(i)), 4)
SetGadgetItemText (1, i, TimeConvert(IdleTimesStart(i)), 5)
SetGadgetItemText (1, i, TimeConvert(DpcTimesStart(i)), 6)
SetGadgetItemText (1, i, TimeConvert(InterruptTimesStart(i)), 7)
Next
KernelTimesStart(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors)
UserTimesStart(NumberOfProcessors) = UserTimesStop(NumberOfProcessors)
IdleTimesStart(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors)
SetGadgetItemText (1, NumberOfProcessors, StrD (CpuUsages(NumberOfProcessors), 3), 1)
SetGadgetItemText (1, NumberOfProcessors, TimeConvert(KernelTimesStart(NumberOfProcessors)), 3)
SetGadgetItemText (1, NumberOfProcessors, TimeConvert(UserTimesStart(NumberOfProcessors)), 4)
SetGadgetItemText (1, NumberOfProcessors, TimeConvert(IdleTimesStart(NumberOfProcessors)), 5)
SetGadgetItemText (1, NumberOfProcessors, TimeConvert(DpcTimesStart(NumberOfProcessors)), 6)
SetGadgetItemText (1, NumberOfProcessors, TimeConvert(InterruptTimesStart(NumberOfProcessors)), 7)
TimeStart = CurTime
EndProcedure
QueryPerformanceFrequency_ (@Frequency)
QueryPerformanceCounter_ (@TimeStart)
GetProcessorsTimes()
Win = OpenWindow ( #PB_Any , 0, 0, 635, 140, "CPU Usage Multi-Processors" , #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget )
If IsWindow (Win) And CreateGadgetList ( WindowID (Win))
ListIconGadget (1, 10, 10, 615, 120, "CPU" , 75)
AddGadgetColumn (1, 1, "% Usage" , 60)
AddGadgetColumn (1, 2, "% (" + Str (100/NumberOfProcessors)+ ")" , 60)
AddGadgetColumn (1, 3, "Kernel Time" , 80)
AddGadgetColumn (1, 4, "User Time" , 80)
AddGadgetColumn (1, 5, "Idle Time" , 80)
AddGadgetColumn (1, 6, "Dpc Time" , 80)
AddGadgetColumn (1, 7, "Interrupt Time" , 80)
For i=0 To NumberOfProcessors-1
AddGadgetItem (1, -1, "CPU " + Str (i))
Next
AddGadgetItem (1, NumberOfProcessors, "CPU TOTAL" )
SetTimer_ ( WindowID (Win), 1, 1000, @refresh())
Repeat
Select WaitWindowEvent ()
Case #PB_Event_CloseWindow
Quit = 1
EndSelect
Until Quit = 1
KillTimer_ ( WindowID (Win), 1)
EndIf
Test code to change the processor's affinity
Declare set_affinity(CPU)
Declare cpu_count()
; Open the Task Manager
Shell_TrayWnd = FindWindow_ ( "Shell_TrayWnd" , NULL)
Result = SendMessage_ (Shell_TrayWnd, $111, 420, 0)
; Return name of process in task manager
ExeName.s = Space (255) : GetModuleFileName_ (0, @ExeName, 255)
Win = OpenWindow ( #PB_Any , 0, 0, 400, 200, "Multi-Core Test - " + GetFilePart (ExeName), #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget )
If Win And CreateGadgetList ( WindowID (Win))
TextGadget ( #PB_Any , 10, 10, 180, 20, "Number of processors : " + Str (cpu_count()))
CPU = 0
For X = 0 To cpu_count()-1
CheckBoxGadget (X, 10, (X*25)+30, 180, 20, "CPU " + Str (X))
CPU + Pow (2, X)
SetGadgetState (X, 1)
Next
set_affinity(CPU)
Repeat
Select WindowEvent () ; Just to use processors for multi-core test with WindowEvent
Case #PB_Event_Gadget
Event = EventGadget ()
CPU = 0
For X = 0 To cpu_count()-1
If GetGadgetState (X) = 1
CPU + Pow (2, X)
EndIf
Next
If CPU = 0
set_affinity(1)
SetGadgetState (0, 1)
Else
set_affinity(CPU)
EndIf
Case #PB_Event_CloseWindow
Quit = 1
EndSelect
Until Quit = 1
EndIf
ProcedureDLL.l cpu_count() ; Number of processors or cores
Protected SI.SYSTEM_INFO
GetSystemInfo_ (@SI)
ProcedureReturn SI\dwNumberOfProcessors
EndProcedure
Procedure get_affinity(mode = 0) ; Mode = 0 : Process, Mode = 1 : System
Protected lpProcessAffinityMask.l, lpSystemAffinityMask.l, hProcess.l
hProcess = GetCurrentProcess_ ()
GetProcessAffinityMask_ (hProcess,@lpProcessAffinityMask,@lpSystemAffinityMask)
If mode = 0
ProcedureReturn lpProcessAffinityMask
Else
ProcedureReturn lpSystemAffinityMask
EndIf
EndProcedure
Procedure set_affinity(CPU)
Protected lpProcessAffinityMask.l, lpSystemAffinityMask.l, hProcess.l
hProcess = GetCurrentProcess_ ()
succes = SetProcessAffinityMask_ (hProcess, CPU)
ProcedureReturn succes
EndProcedure