INOS
inoskernel.h
Go to the documentation of this file.
1//******************************************************************************
26//******************************************************************************
27
28#if !defined( INC_INOSKERNEL_H )
29#define INC_INOSKERNEL_H
30
31//------------------------------------------------------------------------------
32// includes
33//------------------------------------------------------------------------------
34
35#include <atomic>
36#include <inoslib.h>
37#include <inos_ccl.h>
38
39//------------------------------------------------------------------------------
41//------------------------------------------------------------------------------
42
43//------------------------------------------------------------------------------
44// forward declarations
45//------------------------------------------------------------------------------
46
47class CINOSSync;
48
49//------------------------------------------------------------------------------
50// functions
51//------------------------------------------------------------------------------
52
53#ifdef INOS_TIMINIG_CHECKS
54void DebugTimingFailureDetected(CINOSTask* apTask, uint32 auTaskLoggerPattern,
55 const char* apFailureText, uint32 auDiff, uint32 auMaxAllowed);
56#endif
57void PriorityInversionDetected(const char* apMsg, CINOSTask* apTask, const char* apSyncObjName, uint32 auType);
58
59//--------------------------------------------------------------------------
60// global variables
61//--------------------------------------------------------------------------
62
63#ifdef INOS_TIMINIG_CHECKS_DISABLEINTERRUPTS
64extern uint32 g_uMaxIrqDisabledTicks;
65#endif
66
67void INOSEnableInterrupts(uint32 aMask);
68uint32 INOSDisableInterrupts();
69uint32 INOSDisableAllInterrupts();
70
71#ifdef INOS_MULTICORE
72uint32 INOSCoreLock();
73uint32 INOSCoreLock(SINOSCoreLock& aLock);
74#else
75inline uint32 INOSCoreLock()
76{
77 return INOSDisableInterrupts();
78}
79inline uint32 INOSCoreLock(SINOSCoreLock& aLock)
80{
81 return INOSDisableInterrupts();
82}
83#endif
84
85#ifdef INOS_MULTICORE
86void INOSCoreUnlock(uint32 auMsr);
87void INOSCoreUnlock(SINOSCoreLock& aLock, uint32 auMsr);
88#else
89inline void INOSCoreUnlock(uint32 auMsr)
90{
91 INOSEnableInterrupts(auMsr);
92}
93inline void INOSCoreUnlock(SINOSCoreLock& aLock, uint32 auMsr)
94{
95 INOSEnableInterrupts(auMsr);
96}
97#endif
98uint32 INOSSpinLock(uint32* apLock);
99void INOSSpinUnlock(uint32* apLock);
100
101//-----------------------------------------------------------------------------
102//
103#ifndef _MSC_VER
104 #define INOSOptimizationBarrier() \
105 asm volatile ("" ::: "memory");
106#else
107 #define INOSOptimizationBarrier()
108#endif
109
110void INOSMemoryBarrier();
111
112uintnbr INOSReqSem(void* aAddress, uintnbr aNumber);
113uintnbr INOSRelSem(void* aAddress);
114
115//------------------------------------------------------------------------------
116//--- class CSafeTaskList -----------------------------------------------------
117//------------------------------------------------------------------------------
118
122class CTaskListLocker
123{
124 public:
125 CTaskListLocker();
126 ~CTaskListLocker();
127};
128
129
133class CSafeTaskList
134{
135 CTaskListLocker m_TaskListLock;
137 TINOSDoubleLinkedList<CINOSTask>* m_pTaskList;
138 public:
142 explicit CSafeTaskList(TINOSDoubleLinkedList<CINOSTask>* apTaskList);
145 CINOSTask* Next(CListNode*& apListNode);
147 long GetItemsInContainer();
148};
149
150//------------------------------------------------------------------------------
151//--- class CINOSIrqLock ------------------------------------------------------
152//------------------------------------------------------------------------------
153
155class CINOSIrqLock
156{
157 //--- user interface ---------------------------------------------------
158
159 // constructor / destructor
160 public :
161 // disable interrupts
162 CINOSIrqLock() {
163 m_uMsr = INOSDisableInterrupts();
164 m_bLocked = true;
165 }
166 // enable interrupts
167 ~CINOSIrqLock() {
168 if (m_bLocked) {
169 INOSEnableInterrupts(m_uMsr);
170 }
171 }
172 // enable interrupts early (before destructor is called)
173 void EarlyUnlock() {
174 if (m_bLocked) {
175 INOSEnableInterrupts(m_uMsr);
176 m_bLocked = false;
177 }
178 }
179
180 //--- internals --------------------------------------------------------
181
182 // protected members
183 protected :
184 uint32 m_uMsr;
185 bool m_bLocked;
186};
187
188//------------------------------------------------------------------------------
189//--- class CINOSCoreLock ------------------------------------------------------
190//------------------------------------------------------------------------------
191
193class CINOSCoreLock
194{
195 public :
196 // lock core
197 explicit CINOSCoreLock(SINOSCoreLock& aCoreLock)
198 : m_pCoreLock(&aCoreLock)
199 {
200 m_uMsr = INOSCoreLock(*m_pCoreLock);
201 }
202 // release core lock
203 ~CINOSCoreLock() {
204 if( m_pCoreLock ) {
205 INOSCoreUnlock(*m_pCoreLock, m_uMsr);
206 }
207 }
208 void EarlyUnlock() {
209 if( m_pCoreLock ) {
210 INOSCoreUnlock(*m_pCoreLock, m_uMsr);
211 m_pCoreLock = nullptr;
212 }
213 }
214
215 private :
216 SINOSCoreLock* m_pCoreLock;
217 uint32 m_uMsr;
218};
219
220//------------------------------------------------------------------------------
222//------------------------------------------------------------------------------
223
224//------------------------------------------------------------------------------
225// class definition
226//------------------------------------------------------------------------------
227//
229{
230 //--- user interface -------------------------------------------------------
231
232 // public member functions
233 public :
234
235 //----------------------------------------------------------------------
237 //----------------------------------------------------------------------
238
242 enum {
243 eCnsPriorityNumber = 32,
244 eCnsPriorityLowest = eCnsPriorityNumber-1,
245 eCnsPriorityHighest = DF_INOS_TASK_PRIO_HIGHEST,
246 eCnsStackSizeDefault = 0,
247 eCnsTimeSliceNone = 0xffffffff,
248 eCnsTimeSliceDefault = 100,
249 eCnsLogEntriesMin = 2048,
250 eCnsLogEntriesMax = 16*1024*1024,
251 eCnsLogEntriesSmall = 2048,
252 eCnsLogEntriesMedium = 65536, // requires 500 KByte
253 eCnsLogEntriesLarge = 131072 // requires 1 MByte
254 };
255
259 enum {
260 eLogTypePreemption = 0,
261 eLogTypeSuspend = 1,
262 eLogTypeResume = 2,
263 eLogTypeResumeDispatch = 3,
264 eLogTypeRelinquish = 4,
265 eLogTypeChangePriority = 5,
266 eLogTypeTestpoint = 6,
267 eLogTypeTiminigIssue = 7,
268 eLogTypeEnd = 15,
269 };
270
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]);
291 #else
292 return (uint32(s[3]) << 24) | (uint32(s[2]) << 16) | (uint32(s[1]) << 8) | uint32(s[0]);
293 #endif
294 }
295 #if defined(INOS_TASK_LOGGER_EXTENDED)
296 static constexpr uint64 AsciiToUint64(const char (&s)[9]) {
297 return *((uint64*) s);
298 }
299 #endif
300
304 enum {
305 eTskStateReady = 0,
306 eTskStatePureSuspended = 1,
307 };
308
312 enum {
313 eFlgCommandNone = 0x00000000,
314 eFlgCommandForeign = 0x00000001,
315 eFlgCommandShutdown = 0x00000002,
316 };
317
318 //----------------------------------------------------------------------
320 //----------------------------------------------------------------------
321
332 friend void Suspend(uint32 auTaskState, uint32 auFlags);
333
352 friend void SuspendEx(uint32 auTaskState, SINOSCoreLock* apLock, CINOSTask* apTask);
353
357 friend void Goodbye();
358
364 friend void Resume(class CINOSTask* apTask, uint32 auFlags);
365
371 friend void Resume(tTaskId aidTask, uint32 auFlags);
372
379 friend void Ready(class CINOSTask* apTask, uint32 auFlags);
380
387 friend void Ready(tTaskId aidTask, uint32 auFlags);
388
393 friend uint32 SwitchCore(uint32 auCoreId);
394
402 friend void Schedule();
403
412 friend void Schedule(uint32 auCoreId);
413
418 friend void Relinquish();
419
423 friend void Exit(uint32 auExitCode);
424
430 friend void ChangePriority(uint32 auPriority);
431
435 friend class CINOSTask* ActualTask();
436
446 virtual void AddIdle(void* apFunction, void* apObject);
447
451 void AddFinalyse(void* apFunction, void* apObject);
452
458 void AddBootedCallback(void* apFunction, void* apObject);
459
485 static int32 GetKernelState()
486 { return m_iKernelState; };
487
488 //----------------------------------------------------------------------
490 //----------------------------------------------------------------------
491
495 friend void Preemption();
496
497 //--- internals --------------------------------------------------------
498
499 friend class CINOSHwTarget;
500 friend class CINOSTask;
501 friend class CSafeTaskList;
502 friend void _suspend();
503
504 // protected methods
505 public :
508 CINOSKernel ();
509
511 virtual ~CINOSKernel () {}
512
514 void ReadConfigSettings();
515
518 void Idle () INOS_COMPILE_NONOPTIMIZED;
519
522 void DoIdle ();
523
526 void Main ();
527
530 static void Create ();
531
534 static void Startup ();
535
538 void Shutdown();
539
542 void Cleanup();
543
544 #if defined(INOS_TASK_LOGGER_EXTENDED)
545
552 uint64 DoLogging(uint8 aeLogType, uint8 aeSubType, uint64 auData) INOS_OCRAM;
553
559 inline uint64 DoLogging(uint8 aeLogType, class CINOSTask* apTask) INOS_OCRAM
560 {
561 return DoLogging(aeLogType, 0, uintptr(apTask));
562 }
563 inline uint64 DoLogging(uint8 aeLogType, uint8 aeSubType, class CINOSTask* apTask) INOS_OCRAM
564 {
565 return DoLogging(aeLogType, aeSubType, uintptr(apTask));
566 }
567
568 #else
569
575 uint64 DoLogging(uint8 aeLogType, uint32 auData);
576
582 inline uint64 DoLogging(uint8 aeLogType, class CINOSTask* apTask)
583 {
584 return DoLogging(aeLogType, inos_ptr_to_uint32(apTask));
585 }
586
587 #endif
588
592 inline CINOSTask* ActualLoggedTask() INOS_OCRAM
593 {
594 return (CINOSTask*) m_uLogActualTask;
595 }
596
599 void Register ();
600
605 void AddTask(CINOSTask* apTask, uint32 auParentId = 0);
606
610 class CINOSTask* GetHighestPriorityTask()
611 {
612 // any task ready ?
613 if (0 == m_uReady)
614 // no -> return idle
615 return m_pTskIdle;
616 else
617 // yes -> get highest prio
618 return m_pHead[inos_getlsb32(m_uReady)];
619 }
620
625 virtual uint32 CreateTask(CINOSTask* apTask)
626 { return 0; };
627
630 void RequireTaskId(CINOSTask* apTask);
631
634 void ReleaseTaskId(CINOSTask* apTask);
635
640 void AttachTask(CINOSTask* apTask, uint32 auParentId = 0);
641
644 void DetachTask(CINOSTask* apTask);
645
649 virtual void DestroyTask(CINOSTask* apTask)
650 { };
651
655 virtual void SetTaskName(CINOSTask* apTask)
656 { };
657
661 void RemoveTask(CINOSTask* apTask);
662
665 void ShutdownChildren();
666
668 bool IsStartup(CINOSTask* apTask)
669 {
670 return apTask == m_pTskMain;
671 }
673 CINOSSync* GetStartupSync()
674 {
675 return &m_sSyncStartup;
676 }
678 void SetStartupCallResult(class CMcResult* apResult);
680 class CMcResult* GetStartupCallResult();
681
683 CINOSTask* FindTask(uintid aTaskId);
685 CINOSTask* FindTask(const char* aTaskname);
686
689 void DisallowTaskListChanges();
692 void AllowTaskListChanges();
693
694 CSafeTaskList GetTaskList()
695 { return CSafeTaskList(m_pTaskList); };
696 uint32 GetUpdateId()
697 { return mUpdateId; };
698
699 virtual CINOSTask* Setup();
700
701 // to be called every 1ms
702 void DoTimingMeasurement();
703
704 virtual void PrepareTaskStack(CINOSTask* apTask)=0;
705
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;
709 virtual uint32 Run(CINOSTask* apTask)=0;
710
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;
718
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;
723
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;
727
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;
730
733 virtual const char* GetTargetDescription() = 0;
734
737 virtual uint32 GetGdbRegsSize(CINOSTask* apTask, uint32& auSize) = 0;
738
741 virtual uint32 GetGdbRegs(CINOSTask* apTask, void* apData)=0;
742
745 virtual uint32 PutGdbReg(CINOSTask* apTask, const uint32 auRegister, const void* apData, uint32 auDataLength)=0;
746
747 // private members
748 private :
751 static void Finalyse();
752
755 void MaskInterrupts()
756 {
757 #if defined(INOS_ARCH_ARM)
758 m_uIrqMask = 0x000000c0;
759 #else
760 m_uIrqMask = 0xffff7fff;
761 #endif
762 }
763
764 // public members
765 public :
767 enum {
768 eStaPreboot = -1,
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,
786 eStaFinalyse = 65,
787 eStaRunning = 66,
788 };
789 static int32 m_iKernelState;
791 static CINOSKernel* m_pInstance[DF_INOS_MAX_CORES];
792
794 uint32 m_uReady;
796 CINOSTask* m_pHead[eCnsPriorityNumber+1];
798 uintnbr m_uIrqMask;
799
801 CINOSTask* m_pTskIdle;
803 CINOSTask* m_pTskMain;
804
806 uint8 m_uCoreId = 0;
808 static uint8 m_uCoreShift;
810 static uint32 m_uCoreMask;
812 std::atomic<uint32> m_uTskIdCnt = {1};
814 static CINOSTask* m_pTskPool[DF_INOS_MAX_CORES][DF_INOS_MAX_TASKS];
816 static CINOSMutex m_TskPoolLock;
817
820 static CINOSTask* GetTask(uint32 auTaskId);
821
824 static bool IsTaskValid(CINOSTask* apTask);
825
826 //--- compatibility ---------------------------------------------------
827
829 CINCOObject* m_pRegister;
831 CINCOObject* m_pTask;
833 TINOSDoubleLinkedList<CINOSTask>* m_pTaskList;
835 CINOSMutex* m_TaskListChangesLock;
837 uint32 mCount_1sec;
839 uint32 mUpdateId;
840 // count of current CINOSTask-list users (users are for example: INCO-
841 // dbg functions)
842 uint32 m_uDisallowTaskListChangesCntr;
844 CINOSSync m_sSyncStartup;
845
846 //--- logger ----------------------------------------------------------
847
848 // kernel logger members are private
849 friend class CINOSBus;
850 friend class CINOSTestpoint;
851 friend class CINCODataLogger;
852 friend class CINOSMcTargetKernelLogger;
853 friend class CINOSKernelLoggerTest;
854 private :
855 // create logger buffer
856 uint32 LoggerCreate(uint32 auEntries);
857 // destroy logger buffer
858 uint32 LoggerDestroy();
859 // start logger
860 uint32 LoggerStart(uint8 auType);
861 // start logger
862 uint32 LoggerStart(uint8 auType, uint64 auTicks);
863 // stop logger
864 uint32 LoggerStop();
865 uint32 iLoggerStop();
866 // cancel logger
867 uint32 LoggerCancel();
868 uint32 iLoggerCancel();
869 // get logger state
870 uint32 LoggerGetState();
871 // trigger occured
872 void TriggerOccured(uint8 auType, uint8 auPercent);
873 void TriggerOccured(uint8 auType, uint8 auPercent, uint64 auTimeStamp);
874 void iTriggerOccured(uint8 auType, uint8 auPercent, uint64 auTimeStamp);
875
876 #if defined(INOS_TASK_LOGGER_EXTENDED)
877 struct SINOSKernelLoggerEntry
878 {
879 uint16 m_uNext; // offset of next entry, usually sizeof(SINOSKernelLoggerEntry)
880 uint8 m_uType; // entry type
881 uint8 m_uSubType; // entry subtype
882 uint32 m_uTime; // lowest 32 bit of time base at log
883 uint64 m_uData; // log data
884 };
885 #else
886 struct SINOSKernelLoggerEntry
887 {
888 uint8 m_uType; // entry type
889 uint8 m_uReserved;// reserved for future use
890 uint16 m_uTime; // lowest 16 bit of time base at log
891 uint32 m_uData; // log data
892 };
893 #endif
894
896 enum ELogVersion {
897 eLogStandard = 0, // 0 - original
898 eLogExtended = 1, // 1 - extended
899 #if defined(INOS_TASK_LOGGER_EXTENDED)
900 } m_eLogVersion = eLogExtended;
901 #else
902 } m_eLogVersion = eLogStandard;
903 #endif
905 enum ELogState {
906 eLogStaIdle = 0, // 0 - idle
907 eLogStaWaiting = 1, // 1 - waiting for trigger
908 eLogStaRunning = 2, // 2 - running
909 } m_eLogState = eLogStaIdle;
911 uint32 m_uLogEntries{};
913 uint32 m_uLogSize{};
915 uint64 m_uLogIndexWrt{};
917 uint64 m_uLogIndexStp{};
919 uint32 m_uLogIndexWrtMask{};
921 uint64 m_uLogTriggerTicks{};
923 SINOSKernelLoggerEntry* m_pLogBuffer{};
925 uint8 m_uLogTriggerPercent = 50;
927 uint8 m_uLogTriggerType{DF_INOS_LOG_TRIGGER_TYPE_UNKNOWN};
929 CINOSTask* m_pLogTriggerTask{};
931 char m_cLogTriggerTask[64]{};
933 uintnbr m_uLogActualTask{};
934 #ifdef INOS_DESKTOP
936 uint64 m_uLogTicks{};
937 #endif
938
940 struct SINOSKernelCallback* m_pFirstIdle;
942 static struct SINOSKernelCallback* m_pFinalyseFst;
944 static struct SINOSKernelCallback* m_pFinalyseLst;
946 static struct SINOSKernelCallback* m_pFirstRunning;
947
948 //----------------------------------------------------------------------
950 //----------------------------------------------------------------------
951};
952
953//----------------------------------------------------------------------
955//----------------------------------------------------------------------
956
957/* gcc 10.x does not allow friends with default parameters */
958void Suspend(uint32 auTaskState=1, uint32 auFlags=0);
959void SuspendEx(uint32 auTaskState, SINOSCoreLock* apLock, CINOSTask* apTask = nullptr);
960void Resume(class CINOSTask* apTask, uint32 auFlags=0);
961void Resume(tTaskId aidTask, uint32 auFlags=0);
962void Ready(class CINOSTask* apTask, uint32 auFlags=0);
963void Ready(tTaskId aidTask, uint32 auFlags=0);
964
965extern void Suspend(uint32 auTaskState, uint32 auFlags);
966extern void SuspendEx(uint32 auTaskState, SINOSCoreLock* apLock, CINOSTask* apTask);
967extern void Goodbye();
968extern void Resume(class CINOSTask* apTask, uint32 auFlags);
969extern void Resume(tTaskId aidTask, uint32 auFlags);
970extern void Ready(class CINOSTask* apTask, uint32 auFlags);
971extern void Ready(tTaskId aidTask, uint32 auFlags);
972extern uint32 SwitchCore(uint32 auCoreId);
973extern void Schedule();
974extern void Schedule(uint32 auCoreId);
975extern void Exit(uint32 auExitCode);
976extern void Relinquish();
977extern void Preemption();
978extern void ChangePriority(uint32 auPriority);
979#if defined(INOS_WINDOWS)
980extern long _Sleep(long aTime);
981#define Sleep(aTime) _Sleep(aTime)
982#else
983extern long Sleep(long aTime);
984#endif
985extern CINOSTask* ActualTask();
986
987//------------------------------------------------------------------------------
988// target related includes
989//------------------------------------------------------------------------------
990
991INOS_INLINE uint8 GetCoreId(bool abReal = false);
992
993#if defined(INOS_CPU_CORTEXA9)
994 #include <cinostask.h>
995 #include <inoskernel_cortexa9.h>
996#elif defined(INOS_CPU_ARMV8)
997 #include <cinostask.h>
998 #include <inoskernel_armv8.h>
999#elif defined(INOS_CPU_P50XX)
1000 #include <cinostask.h>
1001 #include <inoskernel_p50xx.h>
1002#elif defined(INOS_CPU_P2020)
1003 #include <cinostask.h>
1004 #include <inoskernel_p2020.h>
1005#elif defined(INOS_CPU_PPC750)
1006 #include <cinostask.h>
1007 #include <inoskernel_ppc750.h>
1008#elif defined(INOS_DESKTOP)
1009 #include <cinostask.h>
1010 #include <inoskernel_desktop.h>
1011#endif
1012
1013//------------------------------------------------------------------------------
1014// cores
1015//------------------------------------------------------------------------------
1016
1017INOS_INLINE uint8 GetCores(bool abReal = false)
1018{
1019 if (abReal) {
1020 extern uint8 __cpu_cores_real;
1021 return __cpu_cores_real;
1022 }
1023 else {
1024 extern uint8 __cpu_cores_virtual;
1025 return __cpu_cores_virtual;
1026 }
1027}
1028INOS_INLINE bool IsCore0()
1029{
1030 return GetCoreId() == 0;
1031}
1032
1033INOS_INLINE uint8 GetPrimaryCoreId()
1034{
1035 extern uint32 __cpu_coreid_primary;
1036 return __cpu_coreid_primary;
1037}
1038
1039INOS_INLINE bool IsPrimaryCore()
1040{
1041 extern uint32 __cpu_coreid_primary;
1042 return GetCoreId(true) == __cpu_coreid_primary;
1043}
1044
1045INOS_INLINE tTaskId ActualTaskId()
1046{
1047 return tTaskId(ActualTask(), GetCoreId());
1048}
1049
1050//------------------------------------------------------------------------------
1051// core synchronisation
1052//------------------------------------------------------------------------------
1053
1054struct SINOSCoreSync
1055{
1056 enum {
1057 ePointFirst = 0,
1058 ePointLast = 13,
1059 // os specific points
1060 ePointInternal0 = 0,
1061 ePointInternal1 = 1,
1062 ePointInternal2 = 2,
1063 ePointInternal3 = 3,
1064 ePointInternal4 = 4,
1065 ePointInternal5 = 5,
1066 ePointInternal6 = 6,
1067 ePointInternal7 = 7,
1068 ePointInternal8 = 8,
1069 ePointDataLogger = 9,
1070 // user specific points
1071 ePointUser0 = 10,
1072 ePointUser1 = 11,
1073 ePointUser2 = 12,
1074 ePointUser3 = 13,
1075 };
1076
1077 enum {
1078 eIsFirst,
1079 eIsLast,
1080 };
1082 SINOSCoreLock m_CoreMask;
1084 SINOSCoreLock m_CoreLock;
1087 SINOSCoreLock m_CoreDone[ePointLast+1];
1088
1090 INOS_INLINE void Lock()
1091 {
1092 #if defined(INOS_DESKTOP)
1093 // TODO
1094 #else
1095 // wait for lock
1096 while (__sync_lock_test_and_set(m_CoreLock.GetAddr(), 1));
1097 #endif
1098 }
1100 INOS_INLINE void Unlock()
1101 {
1102 #if defined(INOS_DESKTOP)
1103 // TODO
1104 #else
1105 // free lock
1106 __sync_lock_release(m_CoreLock.GetAddr());
1107 #endif
1108 }
1110 INOS_INLINE void Reset()
1111 {
1112 // IMPORTANT: We do NOT enter critical section here, as this leads to
1113 // deadlocks if a higher prio task/interrupt tries to get the
1114 // lock the core already owns ...
1115
1116 // reset done values
1117 for (uint32 i=0; i<ePointLast+1; i++) {
1118 // reset value
1119 __sync_fetch_and_or(m_CoreDone[i].GetAddr(), m_CoreMask.GetValue());
1120 } // end for
1121 }
1122
1123 INOS_INLINE void CoreAdd()
1124 {
1125 __sync_fetch_and_or(m_CoreMask.GetAddr(), (1<<GetCoreId()));
1126 }
1127
1128 INOS_INLINE void CoreRemove()
1129 {
1130 __sync_fetch_and_and(m_CoreMask.GetAddr(), ~(1<<GetCoreId()));
1131 }
1132
1133 INOS_INLINE uint32 CoreGetMask()
1134 {
1135 // IMPORTANT: We do NOT enter critical section here, as this leads to
1136 // deadlocks if a higher prio task/interrupt tries to get the
1137 // lock the core already owns ...
1138
1139 // add core to mask
1140 return __atomic_load_n(m_CoreMask.GetAddr(), __ATOMIC_SEQ_CST);
1141 }
1142
1145 INOS_INLINE bool IsFirst(uint32 auPointIndex)
1146 {
1147 // enter critical section
1148 Lock();
1149
1150 // done
1151 uint32 uCoreDone = __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1152 // lets check
1153 bool bIsFirst = (uCoreDone == m_CoreMask.GetValue());
1154
1155 // only unlock if I'm not the first
1156 if (!bIsFirst) {
1157 // exit critical section
1158 Unlock();
1159 }
1160
1161 // return result
1162 return bIsFirst;
1163 }
1164
1167 INOS_INLINE bool IsLast(uint32 auPointIndex)
1168 {
1169 // done
1170 uint32 uCoreDone = __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1171 // lets check
1172 return (uCoreDone == (uint32) (1<<GetCoreId()));
1173 }
1174
1177 INOS_INLINE bool IsCore(uint32 auPointIndex, uint32 auCoreId)
1178 {
1179 // ok ?
1180 if (GetCoreId() == auCoreId) {
1181 // yes
1182 return true;
1183 }
1184
1185 // locals
1186 volatile uint32* p = m_CoreDone[auPointIndex].GetAddr();
1187 // wait till the requested core did his job
1188 while (*p & (1<<auCoreId));
1189
1190 // done
1191 __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1192
1193 // return result
1194 return false;
1195 }
1196
1198 INOS_INLINE void Done(uint32 auPointIndex)
1199 {
1200 // done
1201 __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1202 }
1203
1204};
1205
1206//----------------------------------------------------------------------
1208//----------------------------------------------------------------------
1209//------------------------------------------------------------------------------
1210// end of file
1211//------------------------------------------------------------------------------
1212
1213#endif // INC_INOSKERNEL_h
The task module.
Definition cinosbus.h:563
Definition inoskernel.h:229
friend void Ready(tTaskId aidTask, uint32 auFlags)
Put given task into ready list but do not schedule. This method is normally used in conjunction with ...
friend void Schedule(uint32 auCoreId)
Do an explicite schedule or given core. This method is normally used in in conjunction with Ready In ...
friend void SuspendEx(uint32 auTaskState, SINOSCoreLock *apLock, CINOSTask *apTask)
Suspend current task from execution and release the given lock. The lock will be released completely,...
friend void ChangePriority(uint32 auPriority)
Change priority of current task and do a reschedule if necessary. For more info see section Priority.
friend void Exit(uint32 auExitCode)
Terminate actual task.
friend void Ready(class CINOSTask *apTask, uint32 auFlags)
Put given task into ready list but do not schedule. This method is normally used in conjunction with ...
friend void Resume(tTaskId aidTask, uint32 auFlags)
Resume given task and put it into ready list.
static int32 GetKernelState()
Get kernel state. Valid values are.
Definition inoskernel.h:485
friend void Relinquish()
Give other tasks with the same priority a chance to run. For more info see section Relinquish.
friend void Resume(class CINOSTask *apTask, uint32 auFlags)
Resume given task and put it into ready list.
friend uint32 SwitchCore(uint32 auCoreId)
Switch current task to the given core.
virtual void AddIdle(void *apFunction, void *apObject)
Add idle handler. The given function is called whenever the CPU goes into idle state IMPORTANT things...
end of doxygen exclude friend void Suspend(uint32 auTaskState, uint32 auFlags)
Suspend current task from execution. Note that upon Resume, the interrupt state will be restored to t...
friend void Schedule()
Do an explicite schedule. This method is normally used in in conjunction with Ready In case of using ...
void AddBootedCallback(void *apFunction, void *apObject)
Add kernel booted callback, it is called after the kernel has entered the running state....
void AddFinalyse(void *apFunction, void *apObject)
Add kernel finalyse callback, it is called after the kernel has booted all cores and just before it g...
friend void Goodbye()
Suspend current task from execution without saving its context.
friend class CINOSTask * ActualTask()
Return pointer to actual running task.
Definition cinosmutex.h:36
Definition inos_syn.h:67
Definition cinostask.h:52
CINOSTask * ActualTask()
#define DF_INOS_MAX_TASKS
Definition inosdefault.h:435
#define DF_INOS_TASK_PRIO_HIGHEST
Definition inosdefine.h:187
#define INOS_INLINE
Definition inosdefine.h:60
#define DF_INOS_MAX_CORES
Definition inosdefine.h:164
Definition inostype.h:258
Definition inostype.h:192