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 
47 class CINOSSync;
48 
49 //------------------------------------------------------------------------------
50 // functions
51 //------------------------------------------------------------------------------
52 
53 #ifdef INOS_TIMINIG_CHECKS
54 void DebugTimingFailureDetected(CINOSTask* apTask, uint32 auTaskLoggerPattern,
55  const char* apFailureText, uint32 auDiff, uint32 auMaxAllowed);
56 #endif
57 void PriorityInversionDetected(const char* apMsg, CINOSTask* apTask, const char* apSyncObjName, uint32 auType);
58 
59 //--------------------------------------------------------------------------
60 // global variables
61 //--------------------------------------------------------------------------
62 
63 #ifdef INOS_TIMINIG_CHECKS_DISABLEINTERRUPTS
64 extern uint32 g_uMaxIrqDisabledTicks;
65 #endif
66 
67 void INOSEnableInterrupts(uint32 aMask);
68 uint32 INOSDisableInterrupts();
69 uint32 INOSDisableAllInterrupts();
70 
71 #ifdef INOS_MULTICORE
72 uint32 INOSCoreLock();
73 uint32 INOSCoreLock(SINOSCoreLock& aLock);
74 #else
75 inline uint32 INOSCoreLock()
76 {
77  return INOSDisableInterrupts();
78 }
79 inline uint32 INOSCoreLock(SINOSCoreLock& aLock)
80 {
81  return INOSDisableInterrupts();
82 }
83 #endif
84 
85 #ifdef INOS_MULTICORE
86 void INOSCoreUnlock(uint32 auMsr);
87 void INOSCoreUnlock(SINOSCoreLock& aLock, uint32 auMsr);
88 #else
89 inline void INOSCoreUnlock(uint32 auMsr)
90 {
91  INOSEnableInterrupts(auMsr);
92 }
93 inline void INOSCoreUnlock(SINOSCoreLock& aLock, uint32 auMsr)
94 {
95  INOSEnableInterrupts(auMsr);
96 }
97 #endif
98 uint32 INOSSpinLock(uint32* apLock);
99 void 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 
110 void INOSMemoryBarrier();
111 
112 uintnbr INOSReqSem(void* aAddress, uintnbr aNumber);
113 uintnbr INOSRelSem(void* aAddress);
114 
115 //------------------------------------------------------------------------------
116 //--- class CSafeTaskList -----------------------------------------------------
117 //------------------------------------------------------------------------------
118 
122 class CTaskListLocker
123 {
124  public:
125  CTaskListLocker();
126  ~CTaskListLocker();
127 };
128 
129 
133 class 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 
155 class 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 
193 class 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
906 
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
937 
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 */
960 void Suspend(uint32 auTaskState=1, uint32 auFlags=0);
961 void SuspendEx(uint32 auTaskState, SINOSCoreLock* apLock, CINOSTask* apTask = nullptr);
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);
966 
967 extern void Suspend(uint32 auTaskState, uint32 auFlags);
968 extern void SuspendEx(uint32 auTaskState, SINOSCoreLock* apLock, CINOSTask* apTask);
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)
984 #else
985 extern long Sleep(long aTime);
986 #endif
987 extern CINOSTask* ActualTask();
988 
989 //------------------------------------------------------------------------------
990 // target related includes
991 //------------------------------------------------------------------------------
992 
993 INOS_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 
1019 INOS_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 }
1030 INOS_INLINE bool IsCore0()
1031 {
1032  return GetCoreId() == 0;
1033 }
1034 
1035 INOS_INLINE uint8 GetPrimaryCoreId()
1036 {
1037  extern uint32 __cpu_coreid_primary;
1038  return __cpu_coreid_primary;
1039 }
1040 
1041 INOS_INLINE bool IsPrimaryCore()
1042 {
1043  extern uint32 __cpu_coreid_primary;
1044  return GetCoreId(true) == __cpu_coreid_primary;
1045 }
1046 
1047 INOS_INLINE tTaskId ActualTaskId()
1048 {
1049  return tTaskId(ActualTask(), GetCoreId());
1050 }
1051 
1052 //------------------------------------------------------------------------------
1053 // core synchronisation
1054 //------------------------------------------------------------------------------
1055 
1056 struct 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
CINOSMutex
Definition: cinosmutex.h:35
CINOSBus
Definition: cinosbus.h:564
ActualTask
CINOSTask * ActualTask()
cinostask.h
The task module.
CINOSKernel::ActualTask
friend class CINOSTask * ActualTask()
Return pointer to actual running task.
DF_INOS_MAX_CORES
#define DF_INOS_MAX_CORES
Definition: inosdefine.h:164
CINOSKernel::AddFinalyse
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...
CINOSKernel
Definition: inoskernel.h:228
CINOSKernel::SwitchCore
friend uint32 SwitchCore(uint32 auCoreId)
Switch current task to the given core.
CINOSKernel::AddBootedCallback
void AddBootedCallback(void *apFunction, void *apObject)
Add kernel booted callback, it is called after the kernel has entered the running state....
CINOSKernel::Resume
friend void Resume(class CINOSTask *apTask, uint32 auFlags)
Resume given task and put it into ready list.
INOS_INLINE
#define INOS_INLINE
Definition: inosdefine.h:60
SINOSCoreLock
Definition: inostype.h:257
CINOSKernel::Exit
friend void Exit(uint32 auExitCode)
Terminate actual task.
CINOSKernel::ChangePriority
friend void ChangePriority(uint32 auPriority)
Change priority of current task and do a reschedule if necessary. For more info see section Priority.
CINOSKernel::GetKernelState
static int32 GetKernelState()
Get kernel state. Valid values are.
Definition: inoskernel.h:485
CINOSKernel::Schedule
friend void Schedule()
Do an explicite schedule. This method is normally used in in conjunction with Ready In case of using ...
tTaskId
Definition: inostype.h:192
CINOSKernel::Relinquish
friend void Relinquish()
Give other tasks with the same priority a chance to run. For more info see section Relinquish.
DF_INOS_TASK_PRIO_HIGHEST
#define DF_INOS_TASK_PRIO_HIGHEST
Definition: inosdefine.h:187
CINOSKernel::Goodbye
friend void Goodbye()
Suspend current task from execution without saving its context.
CINOSKernel::SuspendEx
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,...
CINOSKernel::Suspend
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...
DF_INOS_MAX_TASKS
#define DF_INOS_MAX_TASKS
Definition: inosdefault.h:443
CINOSKernel::Ready
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 ...
CINOSSync
Definition: inos_syn.h:66
CINOSKernel::AddIdle
virtual void AddIdle(void *apFunction, void *apObject)
Add idle handler. The given function is called whenever the CPU goes into idle state IMPORTANT things...
CINOSTask
Definition: cinostask.h:51