28 #if !defined( INC_INOSKERNEL_H )
29 #define INC_INOSKERNEL_H
53 #ifdef INOS_TIMINIG_CHECKS
54 void DebugTimingFailureDetected(
CINOSTask* apTask, uint32 auTaskLoggerPattern,
55 const char* apFailureText, uint32 auDiff, uint32 auMaxAllowed);
57 void PriorityInversionDetected(
const char* apMsg,
CINOSTask* apTask,
const char* apSyncObjName, uint32 auType);
63 #ifdef INOS_TIMINIG_CHECKS_DISABLEINTERRUPTS
64 extern uint32 g_uMaxIrqDisabledTicks;
67 void INOSEnableInterrupts(uint32 aMask);
68 uint32 INOSDisableInterrupts();
69 uint32 INOSDisableAllInterrupts();
72 uint32 INOSCoreLock();
75 inline uint32 INOSCoreLock()
77 return INOSDisableInterrupts();
81 return INOSDisableInterrupts();
86 void INOSCoreUnlock(uint32 auMsr);
89 inline void INOSCoreUnlock(uint32 auMsr)
91 INOSEnableInterrupts(auMsr);
93 inline void INOSCoreUnlock(
SINOSCoreLock& aLock, uint32 auMsr)
95 INOSEnableInterrupts(auMsr);
98 uint32 INOSSpinLock(uint32* apLock);
99 void INOSSpinUnlock(uint32* apLock);
104 #define INOSOptimizationBarrier() \
105 asm volatile ("" ::: "memory");
107 #define INOSOptimizationBarrier()
110 void INOSMemoryBarrier();
112 uintnbr INOSReqSem(
void* aAddress, uintnbr aNumber);
113 uintnbr INOSRelSem(
void* aAddress);
122 class CTaskListLocker
135 CTaskListLocker m_TaskListLock;
137 TINOSDoubleLinkedList<CINOSTask>* m_pTaskList;
142 explicit CSafeTaskList(TINOSDoubleLinkedList<CINOSTask>* apTaskList);
147 long GetItemsInContainer();
163 m_uMsr = INOSDisableInterrupts();
169 INOSEnableInterrupts(m_uMsr);
175 INOSEnableInterrupts(m_uMsr);
198 : m_pCoreLock(&aCoreLock)
200 m_uMsr = INOSCoreLock(*m_pCoreLock);
205 INOSCoreUnlock(*m_pCoreLock, m_uMsr);
210 INOSCoreUnlock(*m_pCoreLock, m_uMsr);
211 m_pCoreLock =
nullptr;
243 eCnsPriorityNumber = 32,
244 eCnsPriorityLowest = eCnsPriorityNumber-1,
246 eCnsStackSizeDefault = 0,
247 eCnsTimeSliceNone = 0xffffffff,
248 eCnsTimeSliceDefault = 100,
249 eCnsLogEntriesMin = 2048,
250 eCnsLogEntriesMax = 16*1024*1024,
251 eCnsLogEntriesSmall = 2048,
252 eCnsLogEntriesMedium = 65536,
253 eCnsLogEntriesLarge = 131072
260 eLogTypePreemption = 0,
263 eLogTypeResumeDispatch = 3,
264 eLogTypeRelinquish = 4,
265 eLogTypeChangePriority = 5,
266 eLogTypeTestpoint = 6,
267 eLogTypeTiminigIssue = 7,
288 static constexpr uint32 AsciiToUint32(
const char (&s)[5]) {
289 #ifdef INOS_BIG_ENDIAN
290 return (uint32(s[0]) << 24) | (uint32(s[1]) << 16) | (uint32(s[2]) << 8) | uint32(s[3]);
292 return (uint32(s[3]) << 24) | (uint32(s[2]) << 16) | (uint32(s[1]) << 8) | uint32(s[0]);
295 #if defined(INOS_TASK_LOGGER_EXTENDED)
296 static constexpr uint64 AsciiToUint64(
const char (&s)[9]) {
297 return *((uint64*) s);
306 eTskStatePureSuspended = 1,
313 eFlgCommandNone = 0x00000000,
314 eFlgCommandForeign = 0x00000001,
315 eFlgCommandShutdown = 0x00000002,
332 friend void Suspend(uint32 auTaskState, uint32 auFlags);
412 friend void Schedule(uint32 auCoreId);
423 friend void Exit(uint32 auExitCode);
446 virtual void AddIdle(
void* apFunction,
void* apObject);
451 void AddFinalyse(
void* apFunction,
void* apObject);
486 {
return m_iKernelState; };
495 friend void Preemption();
499 friend class CINOSHwTarget;
501 friend class CSafeTaskList;
502 friend void _suspend();
514 void ReadConfigSettings();
518 void Idle () INOS_COMPILE_NONOPTIMIZED;
530 static
void Create ();
534 static
void Startup ();
544 #if defined(INOS_TASK_LOGGER_EXTENDED)
552 uint64 DoLogging(uint8 aeLogType, uint8 aeSubType, uint64 auData) INOS_OCRAM;
559 inline uint64 DoLogging(uint8 aeLogType,
class CINOSTask* apTask) INOS_OCRAM
561 return DoLogging(aeLogType, 0, uintptr(apTask));
563 inline uint64 DoLogging(uint8 aeLogType, uint8 aeSubType,
class CINOSTask* apTask) INOS_OCRAM
565 return DoLogging(aeLogType, aeSubType, uintptr(apTask));
575 uint64 DoLogging(uint8 aeLogType, uint32 auData);
582 inline uint64 DoLogging(uint8 aeLogType,
class CINOSTask* apTask)
584 return DoLogging(aeLogType, inos_ptr_to_uint32(apTask));
592 inline CINOSTask* ActualLoggedTask() INOS_OCRAM
605 void AddTask(
CINOSTask* apTask, uint32 auParentId = 0);
610 class CINOSTask* GetHighestPriorityTask()
618 return m_pHead[inos_getlsb32(m_uReady)];
625 virtual uint32 CreateTask(
CINOSTask* apTask)
640 void AttachTask(
CINOSTask* apTask, uint32 auParentId = 0);
649 virtual void DestroyTask(
CINOSTask* apTask)
655 virtual void SetTaskName(
CINOSTask* apTask)
665 void ShutdownChildren();
670 return apTask == m_pTskMain;
675 return &m_sSyncStartup;
678 void SetStartupCallResult(
class CMcResult* apResult);
680 class CMcResult* GetStartupCallResult();
685 CINOSTask* FindTask(
const char* aTaskname);
689 void DisallowTaskListChanges();
692 void AllowTaskListChanges();
694 CSafeTaskList GetTaskList()
695 {
return CSafeTaskList(m_pTaskList); };
697 {
return mUpdateId; };
702 void DoTimingMeasurement();
704 virtual void PrepareTaskStack(
CINOSTask* apTask)=0;
706 virtual uint32 SingleStep(
CINOSTask* apTask)=0;
707 virtual uint32 RangeStep(
CINOSTask* apTask, uintptr auFrom, uintptr auTo)=0;
708 virtual uint32 Halt(
CINOSTask* apTask)=0;
711 virtual uint32 GetPC(
CINOSTask* apTask, uintnbr* aValue)=0;
712 virtual uint32 PutPC(
CINOSTask* apTask, uintnbr aValue)=0;
713 virtual uint32 GetLR(
CINOSTask* apTask, uintnbr* aValue)=0;
714 virtual uint32 GetSPR(
CINOSTask* apTask, uint32 aNumber, uint32* aValue)=0;
715 virtual uint32 PutSPR(
CINOSTask* apTask, uint32 aNumber, uint32 aValue)=0;
716 virtual uint32 GetSPRs(
CINOSTask* apTask, uint32* aResult)=0;
717 virtual uint32 GetSPRsGdb(
CINOSTask* apTask, uint32* aResult)=0;
719 virtual uint32 GetGPR(
CINOSTask* apTask, uint32 aNumber, uint32* aValue)=0;
720 virtual uint32 PutGPR(
CINOSTask* apTask, uint32 aNumber, uint32 aValue)=0;
722 virtual uint32 GetGPRs(
CINOSTask* apTask, uint32* aResult,
bool abNative)=0;
724 virtual uint32 GetFPR(
CINOSTask* apTask, uint32 aNumber,
double* aValue)=0;
725 virtual uint32 PutFPR(
CINOSTask* apTask, uint32 aNumber,
double aValue)=0;
726 virtual uint32 GetFPRs(
CINOSTask* apTask,
double* aResult)=0;
728 virtual uint32 GetTaskData(
CINOSTask* apTask, uint32 aDataDef, uintnbr* aResult, uint32& aLength)=0;
729 virtual uint32 PutTaskData(
CINOSTask* apTask, uint32 aDataDef, uint32* aData, uint32 aLength)=0;
733 virtual const char* GetTargetDescription() = 0;
737 virtual uint32 GetGdbRegsSize(
CINOSTask* apTask, uint32& auSize) = 0;
741 virtual uint32 GetGdbRegs(
CINOSTask* apTask,
void* apData)=0;
745 virtual uint32 PutGdbReg(
CINOSTask* apTask,
const uint32 auRegister,
const void* apData, uint32 auDataLength)=0;
751 static void Finalyse();
755 void MaskInterrupts()
757 #if defined(INOS_ARCH_ARM)
758 m_uIrqMask = 0x000000c0;
760 m_uIrqMask = 0xffff7fff;
769 eStaBootingCore0 = 0,
770 eStaBootingCore1 = 1,
771 eStaBootingCore2 = 2,
772 eStaBootingCore3 = 3,
773 eStaBootingCore4 = 4,
774 eStaBootingCore5 = 5,
775 eStaBootingCore6 = 6,
776 eStaBootingCore7 = 7,
777 eStaBootingCore8 = 8,
778 eStaBootingCore9 = 9,
779 eStaBootingCore10 = 10,
780 eStaBootingCore11 = 11,
781 eStaBootingCore12 = 12,
782 eStaBootingCore13 = 13,
783 eStaBootingCore14 = 14,
784 eStaBootingCore15 = 15,
785 eStaSyncTimebase = 64,
789 static int32 m_iKernelState;
796 CINOSTask* m_pHead[eCnsPriorityNumber+1];
805 uint64 m_uIdleCount = 0;
810 static uint8 m_uCoreShift;
812 static uint32 m_uCoreMask;
814 std::atomic<uint32> m_uTskIdCnt = {1};
822 static CINOSTask* GetTask(uint32 auTaskId);
826 static bool IsTaskValid(
CINOSTask* apTask);
831 CINCOObject* m_pRegister;
833 CINCOObject* m_pTask;
835 TINOSDoubleLinkedList<CINOSTask>* m_pTaskList;
844 uint32 m_uDisallowTaskListChangesCntr;
852 friend class CINOSTestpoint;
853 friend class CINCODataLogger;
854 friend class CINOSMcTargetKernelLogger;
855 friend class CINOSKernelLoggerTest;
858 uint32 LoggerCreate(uint32 auEntries);
860 uint32 LoggerDestroy();
862 uint32 LoggerStart(uint8 auType);
864 uint32 LoggerStart(uint8 auType, uint64 auTicks);
867 uint32 iLoggerStop();
869 uint32 LoggerCancel();
870 uint32 iLoggerCancel();
872 uint32 LoggerGetState();
874 void TriggerOccured(uint8 auType, uint8 auPercent);
875 void TriggerOccured(uint8 auType, uint8 auPercent, uint64 auTimeStamp);
876 void iTriggerOccured(uint8 auType, uint8 auPercent, uint64 auTimeStamp);
878 #if defined(INOS_TASK_LOGGER_EXTENDED)
879 struct SINOSKernelLoggerEntry
888 struct SINOSKernelLoggerEntry
901 #if defined(INOS_TASK_LOGGER_EXTENDED)
902 } m_eLogVersion = eLogExtended;
904 } m_eLogVersion = eLogStandard;
911 } m_eLogState = eLogStaIdle;
913 uint32 m_uLogEntries{};
917 uint64 m_uLogIndexWrt{};
919 uint64 m_uLogIndexStp{};
921 uint32 m_uLogIndexWrtMask{};
923 uint64 m_uLogTriggerTicks{};
925 SINOSKernelLoggerEntry* m_pLogBuffer{};
927 uint8 m_uLogTriggerPercent = 50;
929 uint8 m_uLogTriggerType{DF_INOS_LOG_TRIGGER_TYPE_UNKNOWN};
933 char m_cLogTriggerTask[64]{};
935 uintnbr m_uLogActualTask{};
938 uint64 m_uLogTicks{};
942 struct SINOSKernelCallback* m_pFirstIdle;
944 static struct SINOSKernelCallback* m_pFinalyseFst;
946 static struct SINOSKernelCallback* m_pFinalyseLst;
948 static struct SINOSKernelCallback* m_pFirstRunning;
960 void Suspend(uint32 auTaskState=1, uint32 auFlags=0);
962 void Resume(
class CINOSTask* apTask, uint32 auFlags=0);
963 void Resume(
tTaskId aidTask, uint32 auFlags=0);
964 void Ready(
class CINOSTask* apTask, uint32 auFlags=0);
965 void Ready(
tTaskId aidTask, uint32 auFlags=0);
967 extern void Suspend(uint32 auTaskState, uint32 auFlags);
969 extern void Goodbye();
970 extern void Resume(
class CINOSTask* apTask, uint32 auFlags);
971 extern void Resume(
tTaskId aidTask, uint32 auFlags);
972 extern void Ready(
class CINOSTask* apTask, uint32 auFlags);
973 extern void Ready(
tTaskId aidTask, uint32 auFlags);
974 extern uint32 SwitchCore(uint32 auCoreId);
975 extern void Schedule();
976 extern void Schedule(uint32 auCoreId);
977 extern void Exit(uint32 auExitCode);
978 extern void Relinquish();
979 extern void Preemption();
980 extern void ChangePriority(uint32 auPriority);
981 #if defined(INOS_WINDOWS)
982 extern long _Sleep(
long aTime);
983 #define Sleep(aTime) _Sleep(aTime)
985 extern long Sleep(
long aTime);
995 #if defined(INOS_CPU_CORTEXA9)
997 #include <inoskernel_cortexa9.h>
998 #elif defined(INOS_CPU_ARMV8)
1000 #include <inoskernel_armv8.h>
1001 #elif defined(INOS_CPU_P50XX)
1003 #include <inoskernel_p50xx.h>
1004 #elif defined(INOS_CPU_P2020)
1006 #include <inoskernel_p2020.h>
1007 #elif defined(INOS_CPU_PPC750)
1009 #include <inoskernel_ppc750.h>
1010 #elif defined(INOS_DESKTOP)
1012 #include <inoskernel_desktop.h>
1022 extern uint8 __cpu_cores_real;
1023 return __cpu_cores_real;
1026 extern uint8 __cpu_cores_virtual;
1027 return __cpu_cores_virtual;
1032 return GetCoreId() == 0;
1037 extern uint32 __cpu_coreid_primary;
1038 return __cpu_coreid_primary;
1043 extern uint32 __cpu_coreid_primary;
1044 return GetCoreId(
true) == __cpu_coreid_primary;
1056 struct SINOSCoreSync
1062 ePointInternal0 = 0,
1063 ePointInternal1 = 1,
1064 ePointInternal2 = 2,
1065 ePointInternal3 = 3,
1066 ePointInternal4 = 4,
1067 ePointInternal5 = 5,
1068 ePointInternal6 = 6,
1069 ePointInternal7 = 7,
1070 ePointInternal8 = 8,
1071 ePointDataLogger = 9,
1094 #if defined(INOS_DESKTOP)
1098 while (__sync_lock_test_and_set(m_CoreLock.GetAddr(), 1));
1104 #if defined(INOS_DESKTOP)
1108 __sync_lock_release(m_CoreLock.GetAddr());
1119 for (uint32 i=0; i<ePointLast+1; i++) {
1121 __sync_fetch_and_or(m_CoreDone[i].GetAddr(), m_CoreMask.GetValue());
1127 __sync_fetch_and_or(m_CoreMask.GetAddr(), (1<<GetCoreId()));
1132 __sync_fetch_and_and(m_CoreMask.GetAddr(), ~(1<<GetCoreId()));
1142 return __atomic_load_n(m_CoreMask.GetAddr(), __ATOMIC_SEQ_CST);
1153 uint32 uCoreDone = __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1155 bool bIsFirst = (uCoreDone == m_CoreMask.GetValue());
1172 uint32 uCoreDone = __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1174 return (uCoreDone == (uint32) (1<<GetCoreId()));
1179 INOS_INLINE bool IsCore(uint32 auPointIndex, uint32 auCoreId)
1182 if (GetCoreId() == auCoreId) {
1188 volatile uint32* p = m_CoreDone[auPointIndex].GetAddr();
1190 while (*p & (1<<auCoreId));
1193 __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1203 __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1215 #endif // INC_INOSKERNEL_h