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;
805 uint64 m_uIdleCount = 0;
806
808 uint8 m_uCoreId = 0;
810 static uint8 m_uCoreShift;
812 static uint32 m_uCoreMask;
814 std::atomic<uint32> m_uTskIdCnt = {1};
816 static CINOSTask* m_pTskPool[DF_INOS_MAX_CORES][DF_INOS_MAX_TASKS];
818 static CINOSMutex m_TskPoolLock;
819
822 static CINOSTask* GetTask(uint32 auTaskId);
823
826 static bool IsTaskValid(CINOSTask* apTask);
827
828 //--- compatibility ---------------------------------------------------
829
831 CINCOObject* m_pRegister;
833 CINCOObject* m_pTask;
835 TINOSDoubleLinkedList<CINOSTask>* m_pTaskList;
837 CINOSMutex* m_TaskListChangesLock;
839 uint32 mCount_1sec;
841 uint32 mUpdateId;
842 // count of current CINOSTask-list users (users are for example: INCO-
843 // dbg functions)
844 uint32 m_uDisallowTaskListChangesCntr;
846 CINOSSync m_sSyncStartup;
847
848 //--- logger ----------------------------------------------------------
849
850 // kernel logger members are private
851 friend class CINOSBus;
852 friend class CINOSTestpoint;
853 friend class CINCODataLogger;
854 friend class CINOSMcTargetKernelLogger;
855 friend class CINOSKernelLoggerTest;
856 private :
857 // create logger buffer
858 uint32 LoggerCreate(uint32 auEntries);
859 // destroy logger buffer
860 uint32 LoggerDestroy();
861 // start logger
862 uint32 LoggerStart(uint8 auType);
863 // start logger
864 uint32 LoggerStart(uint8 auType, uint64 auTicks);
865 // stop logger
866 uint32 LoggerStop();
867 uint32 iLoggerStop();
868 // cancel logger
869 uint32 LoggerCancel();
870 uint32 iLoggerCancel();
871 // get logger state
872 uint32 LoggerGetState();
873 // trigger occured
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);
877
878 #if defined(INOS_TASK_LOGGER_EXTENDED)
879 struct SINOSKernelLoggerEntry
880 {
881 uint16 m_uNext; // offset of next entry, usually sizeof(SINOSKernelLoggerEntry)
882 uint8 m_uType; // entry type
883 uint8 m_uSubType; // entry subtype
884 uint32 m_uTime; // lowest 32 bit of time base at log
885 uint64 m_uData; // log data
886 };
887 #else
888 struct SINOSKernelLoggerEntry
889 {
890 uint8 m_uType; // entry type
891 uint8 m_uReserved;// reserved for future use
892 uint16 m_uTime; // lowest 16 bit of time base at log
893 uint32 m_uData; // log data
894 };
895 #endif
896
898 enum ELogVersion {
899 eLogStandard = 0, // 0 - original
900 eLogExtended = 1, // 1 - extended
901 #if defined(INOS_TASK_LOGGER_EXTENDED)
902 } m_eLogVersion = eLogExtended;
903 #else
904 } m_eLogVersion = eLogStandard;
905 #endif
907 enum ELogState {
908 eLogStaIdle = 0, // 0 - idle
909 eLogStaWaiting = 1, // 1 - waiting for trigger
910 eLogStaRunning = 2, // 2 - running
911 } m_eLogState = eLogStaIdle;
913 uint32 m_uLogEntries{};
915 uint32 m_uLogSize{};
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};
931 CINOSTask* m_pLogTriggerTask{};
933 char m_cLogTriggerTask[64]{};
935 uintnbr m_uLogActualTask{};
936 #ifdef INOS_DESKTOP
938 uint64 m_uLogTicks{};
939 #endif
940
942 struct SINOSKernelCallback* m_pFirstIdle;
944 static struct SINOSKernelCallback* m_pFinalyseFst;
946 static struct SINOSKernelCallback* m_pFinalyseLst;
948 static struct SINOSKernelCallback* m_pFirstRunning;
949
950 //----------------------------------------------------------------------
952 //----------------------------------------------------------------------
953};
954
955//----------------------------------------------------------------------
957//----------------------------------------------------------------------
958
959/* gcc 10.x does not allow friends with default parameters */
960void Suspend(uint32 auTaskState=1, uint32 auFlags=0);
961void SuspendEx(uint32 auTaskState, SINOSCoreLock* apLock, CINOSTask* apTask = nullptr);
962void Resume(class CINOSTask* apTask, uint32 auFlags=0);
963void Resume(tTaskId aidTask, uint32 auFlags=0);
964void Ready(class CINOSTask* apTask, uint32 auFlags=0);
965void Ready(tTaskId aidTask, uint32 auFlags=0);
966
967extern void Suspend(uint32 auTaskState, uint32 auFlags);
968extern void SuspendEx(uint32 auTaskState, SINOSCoreLock* apLock, CINOSTask* apTask);
969extern void Goodbye();
970extern void Resume(class CINOSTask* apTask, uint32 auFlags);
971extern void Resume(tTaskId aidTask, uint32 auFlags);
972extern void Ready(class CINOSTask* apTask, uint32 auFlags);
973extern void Ready(tTaskId aidTask, uint32 auFlags);
974extern uint32 SwitchCore(uint32 auCoreId);
975extern void Schedule();
976extern void Schedule(uint32 auCoreId);
977extern void Exit(uint32 auExitCode);
978extern void Relinquish();
979extern void Preemption();
980extern void ChangePriority(uint32 auPriority);
981#if defined(INOS_WINDOWS)
982extern long _Sleep(long aTime);
983#define Sleep(aTime) _Sleep(aTime)
984#else
985extern long Sleep(long aTime);
986#endif
987extern CINOSTask* ActualTask();
988
989//------------------------------------------------------------------------------
990// target related includes
991//------------------------------------------------------------------------------
992
993INOS_INLINE uint8 GetCoreId(bool abReal = false);
994
995#if defined(INOS_CPU_CORTEXA9)
996 #include <cinostask.h>
997 #include <inoskernel_cortexa9.h>
998#elif defined(INOS_CPU_ARMV8)
999 #include <cinostask.h>
1000 #include <inoskernel_armv8.h>
1001#elif defined(INOS_CPU_P50XX)
1002 #include <cinostask.h>
1003 #include <inoskernel_p50xx.h>
1004#elif defined(INOS_CPU_P2020)
1005 #include <cinostask.h>
1006 #include <inoskernel_p2020.h>
1007#elif defined(INOS_CPU_PPC750)
1008 #include <cinostask.h>
1009 #include <inoskernel_ppc750.h>
1010#elif defined(INOS_DESKTOP)
1011 #include <cinostask.h>
1012 #include <inoskernel_desktop.h>
1013#endif
1014
1015//------------------------------------------------------------------------------
1016// cores
1017//------------------------------------------------------------------------------
1018
1019INOS_INLINE uint8 GetCores(bool abReal = false)
1020{
1021 if (abReal) {
1022 extern uint8 __cpu_cores_real;
1023 return __cpu_cores_real;
1024 }
1025 else {
1026 extern uint8 __cpu_cores_virtual;
1027 return __cpu_cores_virtual;
1028 }
1029}
1030INOS_INLINE bool IsCore0()
1031{
1032 return GetCoreId() == 0;
1033}
1034
1035INOS_INLINE uint8 GetPrimaryCoreId()
1036{
1037 extern uint32 __cpu_coreid_primary;
1038 return __cpu_coreid_primary;
1039}
1040
1041INOS_INLINE bool IsPrimaryCore()
1042{
1043 extern uint32 __cpu_coreid_primary;
1044 return GetCoreId(true) == __cpu_coreid_primary;
1045}
1046
1047INOS_INLINE tTaskId ActualTaskId()
1048{
1049 return tTaskId(ActualTask(), GetCoreId());
1050}
1051
1052//------------------------------------------------------------------------------
1053// core synchronisation
1054//------------------------------------------------------------------------------
1055
1056struct SINOSCoreSync
1057{
1058 enum {
1059 ePointFirst = 0,
1060 ePointLast = 13,
1061 // os specific points
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,
1072 // user specific points
1073 ePointUser0 = 10,
1074 ePointUser1 = 11,
1075 ePointUser2 = 12,
1076 ePointUser3 = 13,
1077 };
1078
1079 enum {
1080 eIsFirst,
1081 eIsLast,
1082 };
1084 SINOSCoreLock m_CoreMask;
1086 SINOSCoreLock m_CoreLock;
1089 SINOSCoreLock m_CoreDone[ePointLast+1];
1090
1092 INOS_INLINE void Lock()
1093 {
1094 #if defined(INOS_DESKTOP)
1095 // TODO
1096 #else
1097 // wait for lock
1098 while (__sync_lock_test_and_set(m_CoreLock.GetAddr(), 1));
1099 #endif
1100 }
1102 INOS_INLINE void Unlock()
1103 {
1104 #if defined(INOS_DESKTOP)
1105 // TODO
1106 #else
1107 // free lock
1108 __sync_lock_release(m_CoreLock.GetAddr());
1109 #endif
1110 }
1112 INOS_INLINE void Reset()
1113 {
1114 // IMPORTANT: We do NOT enter critical section here, as this leads to
1115 // deadlocks if a higher prio task/interrupt tries to get the
1116 // lock the core already owns ...
1117
1118 // reset done values
1119 for (uint32 i=0; i<ePointLast+1; i++) {
1120 // reset value
1121 __sync_fetch_and_or(m_CoreDone[i].GetAddr(), m_CoreMask.GetValue());
1122 } // end for
1123 }
1124
1125 INOS_INLINE void CoreAdd()
1126 {
1127 __sync_fetch_and_or(m_CoreMask.GetAddr(), (1<<GetCoreId()));
1128 }
1129
1130 INOS_INLINE void CoreRemove()
1131 {
1132 __sync_fetch_and_and(m_CoreMask.GetAddr(), ~(1<<GetCoreId()));
1133 }
1134
1135 INOS_INLINE uint32 CoreGetMask()
1136 {
1137 // IMPORTANT: We do NOT enter critical section here, as this leads to
1138 // deadlocks if a higher prio task/interrupt tries to get the
1139 // lock the core already owns ...
1140
1141 // add core to mask
1142 return __atomic_load_n(m_CoreMask.GetAddr(), __ATOMIC_SEQ_CST);
1143 }
1144
1147 INOS_INLINE bool IsFirst(uint32 auPointIndex)
1148 {
1149 // enter critical section
1150 Lock();
1151
1152 // done
1153 uint32 uCoreDone = __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1154 // lets check
1155 bool bIsFirst = (uCoreDone == m_CoreMask.GetValue());
1156
1157 // only unlock if I'm not the first
1158 if (!bIsFirst) {
1159 // exit critical section
1160 Unlock();
1161 }
1162
1163 // return result
1164 return bIsFirst;
1165 }
1166
1169 INOS_INLINE bool IsLast(uint32 auPointIndex)
1170 {
1171 // done
1172 uint32 uCoreDone = __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1173 // lets check
1174 return (uCoreDone == (uint32) (1<<GetCoreId()));
1175 }
1176
1179 INOS_INLINE bool IsCore(uint32 auPointIndex, uint32 auCoreId)
1180 {
1181 // ok ?
1182 if (GetCoreId() == auCoreId) {
1183 // yes
1184 return true;
1185 }
1186
1187 // locals
1188 volatile uint32* p = m_CoreDone[auPointIndex].GetAddr();
1189 // wait till the requested core did his job
1190 while (*p & (1<<auCoreId));
1191
1192 // done
1193 __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1194
1195 // return result
1196 return false;
1197 }
1198
1200 INOS_INLINE void Done(uint32 auPointIndex)
1201 {
1202 // done
1203 __sync_fetch_and_and(m_CoreDone[auPointIndex].GetAddr(), ~(1<<GetCoreId()));
1204 }
1205
1206};
1207
1208//----------------------------------------------------------------------
1210//----------------------------------------------------------------------
1211//------------------------------------------------------------------------------
1212// end of file
1213//------------------------------------------------------------------------------
1214
1215#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