revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-pc / kernel / apic_heartbeat.c
blobcb3331418ec49436b072578563e7459650d05af3
1 /*
2 Copyright © 2017-2018, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 0
7 #include <aros/debug.h>
9 #include <aros/types/timespec_s.h>
10 #include <aros/asmcall.h>
11 #include <exec/execbase.h>
12 #include <exec/lists.h>
14 #define __AROS_KERNEL__
16 #include "exec_intern.h"
18 #include "kernel_intern.h"
20 #include "intservers.h"
23 * Unlike the VBlankServer, we might not run at a fixed 60Hz.
25 int APICHeartbeatServer(struct ExceptionContext *regs, struct KernelBase *KernelBase, struct ExecBase *SysBase)
27 struct PlatformData *pdata = KernelBase->kb_PlatformData;
28 struct APICData *apicData = pdata->kb_APIC;
29 #if defined(__AROSEXEC_SMP__)
30 IPTR __LAPICBase = apicData->lapicBase;
31 struct X86SchedulerPrivate *apicScheduleData;
32 tls_t *apicTLS;
33 #endif
34 UWORD current;
36 if (apicData->flags & APF_TIMER)
38 #if defined(__AROSEXEC_SMP__)
39 apicid_t cpuNum = core_APIC_GetNumber(apicData);
40 UQUAD now = RDTSC();
42 // Update LAPIC tick
43 apicData->cores[cpuNum].cpu_LAPICTick += APIC_REG(__LAPICBase, APIC_TIMER_ICR);
45 // Relaunch LAPIC timer
46 APIC_REG(__LAPICBase, APIC_TIMER_ICR) = (apicData->cores[cpuNum].cpu_TimerFreq + 500) / 1000;
48 if ((now - apicData->cores[cpuNum].cpu_LastCPULoadTime) > apicData->cores[cpuNum].cpu_TSCFreq)
50 struct Task *t;
51 UQUAD timeCur = now - apicData->cores[cpuNum].cpu_LastCPULoadTime;
53 /* Lock all lists to make sure we catch all the tasks */
54 KrnSpinLock(&PrivExecBase(SysBase)->TaskReadySpinLock, NULL, SPINLOCK_MODE_READ);
55 ForeachNode(&SysBase->TaskReady, t)
57 if (cpuNum == IntETask(t->tc_UnionETask.tc_ETask)->iet_CpuNumber)
59 IntETask(t->tc_UnionETask.tc_ETask)->iet_CpuUsage =
60 (IntETask(t->tc_UnionETask.tc_ETask)->iet_private2 << 32) / timeCur;
61 IntETask(t->tc_UnionETask.tc_ETask)->iet_private2 = 0;
64 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskReadySpinLock);
66 KrnSpinLock(&PrivExecBase(SysBase)->TaskWaitSpinLock, NULL, SPINLOCK_MODE_READ);
67 ForeachNode(&SysBase->TaskWait, t)
69 if (cpuNum == IntETask(t->tc_UnionETask.tc_ETask)->iet_CpuNumber)
71 IntETask(t->tc_UnionETask.tc_ETask)->iet_CpuUsage =
72 (IntETask(t->tc_UnionETask.tc_ETask)->iet_private2 << 32) / timeCur;
73 IntETask(t->tc_UnionETask.tc_ETask)->iet_private2 = 0;
76 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskWaitSpinLock);
78 KrnSpinLock(&PrivExecBase(SysBase)->TaskRunningSpinLock, NULL, SPINLOCK_MODE_READ);
79 ForeachNode(&PrivExecBase(SysBase)->TaskRunning, t)
81 if (cpuNum == IntETask(t->tc_UnionETask.tc_ETask)->iet_CpuNumber)
83 /*
84 TaskRunning list is different than others. Here the iet_private2 field is not yet updated,
85 so we have to update the CPU time in this place.
87 UQUAD time = IntETask(t->tc_UnionETask.tc_ETask)->iet_private2 +
88 now - IntETask(t->tc_UnionETask.tc_ETask)->iet_private1;
90 if (time < timeCur)
91 IntETask(t->tc_UnionETask.tc_ETask)->iet_CpuUsage = (time << 32) / timeCur;
92 else
93 IntETask(t->tc_UnionETask.tc_ETask)->iet_CpuUsage = 0xffffffff;
95 IntETask(t->tc_UnionETask.tc_ETask)->iet_private2 -= time;
98 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskRunningSpinLock);
100 KrnSpinLock(&PrivExecBase(SysBase)->TaskSpinningLock, NULL, SPINLOCK_MODE_READ);
101 ForeachNode(&PrivExecBase(SysBase)->TaskSpinning, t)
103 if (cpuNum == IntETask(t->tc_UnionETask.tc_ETask)->iet_CpuNumber)
105 IntETask(t->tc_UnionETask.tc_ETask)->iet_CpuUsage =
106 (IntETask(t->tc_UnionETask.tc_ETask)->iet_private2 << 32) / timeCur;
107 IntETask(t->tc_UnionETask.tc_ETask)->iet_private2 = 0;
110 KrnSpinUnLock(&PrivExecBase(SysBase)->TaskSpinningLock);
112 apicData->cores[cpuNum].cpu_Load =
113 ((apicData->cores[cpuNum].cpu_TSCFreq - apicData->cores[cpuNum].cpu_SleepTime) << 32) / timeCur;
115 D(bug("[Kernel:APIC.%03u] %s() cpu load %08x\n", cpuNum, __func__, (ULONG)apicData->cores[cpuNum].cpu_Load));
116 apicData->cores[cpuNum].cpu_SleepTime = 0;
117 apicData->cores[cpuNum].cpu_LastCPULoadTime = now;
120 D(bug("[Kernel:APIC.%03u] %s(), tick=%08x:%08x\n", cpuNum, __func__, (ULONG)(apicData->cores[cpuNum].cpu_LAPICTick >> 32),
121 (ULONG)(apicData->cores[cpuNum].cpu_LAPICTick & 0xffffffff)));
123 apicTLS = apicData->cores[cpuNum].cpu_TLS;
124 if ((apicTLS) && ((apicScheduleData = apicTLS->ScheduleData) != NULL))
126 if ((current = apicScheduleData->Elapsed))
128 if ((apicScheduleData->Elapsed = (current - apicScheduleData->Granularity)) == 0)
130 __AROS_ATOMIC_OR_L(apicScheduleData->ScheduleFlags, TLSSF_Quantum);
131 __AROS_ATOMIC_OR_L(apicScheduleData->ScheduleFlags, TLSSF_Switch);
135 #else
136 D(bug("[Kernel:APIC] %s()\n", __func__));
138 current = SCHEDELAPSED_GET;
139 if (current)
140 SCHEDELAPSED_SET(--current);
142 if (current == 0)
144 FLAG_SCHEDQUANTUM_SET;
145 FLAG_SCHEDSWITCH_SET;
147 #endif
150 return 1;