Choco OS  V.0.16.9.0
Join to the chocolate world
oc_thread.c
Go to the documentation of this file.
1 
27 #include <oc_thread.h>
28 #include <oc_object.h>
29 #include <oc_memman.h>
30 #include <oc_sys_lld.h>
31 #include <oc_system_cfg.h>
32 #include <oc_stdlib.h>
33 #include <oc_processman.h>
34 #include <oc_threadman.h>
35 #include <oc_intman.h>
36 #include <oc_mem_lld.h>
37 #include <oc_debug.h>
38 
44 #define _________________________________________TYPES_SECTION______________________________________________________________________________
45 
46 typedef struct
47 {
48  oC_Thread_RevertFunction_t Function;
49  void * Object;
50  uint32_t Parameter;
52 
53 typedef oC_Thread_FinishedFunction_t FinishedFunction_t;
54 
55 //==========================================================================================================================================
59 //==========================================================================================================================================
60 struct Thread_t
61 {
62  oC_ObjectControl_t ObjectControl;
64  oC_Thread_Priority_t Priority;
65  const char * Name;
66  oC_UInt_t * RedZone;
67  oC_UInt_t * RedZoneEnd;
68  void * RealStackStart;
70  void * StackStart;
71  oC_Int_t RealStackSize;
72  uint32_t * BlockedFlag;
73  uint32_t StateToUnblock;
74  uint32_t UnblockMask;
75  oC_Thread_Unblock_t Unblock;
76  oC_Timestamp_t TimeoutTimestamp;
77  oC_Time_t ExecutionTime;
78  uint32_t LastExecutionTick;
79  oC_Int_t StackSize;
80  oC_Thread_Function_t Function;
81  void * Parameter;
82  FinishedFunction_t FinishedFunction;
84  RevertAction_t ActionsToRevert[CFG_UINT8_MAX_ACTIONS_TO_REVERT];
85 };
86 
87 typedef bool (*CheckFunction_t)( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask );
88 
89 #undef _________________________________________TYPES_SECTION______________________________________________________________________________
90 
96 #define _________________________________________LOCAL_PROTOTYPES_SECTION___________________________________________________________________
97 
98 static void ThreadExitHandler( void );
99 static bool CheckUnblockedWhenEqual ( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask );
100 static bool CheckUnblockedWhenNotEqual ( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask );
101 static bool CheckUnblockedWhenSmaller ( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask );
102 static bool CheckUnblockedWhenGreater ( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask );
103 static bool CheckUnblockedWhenSmallerOrEqual( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask );
104 static bool CheckUnblockedWhenGreaterOrEqual( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask );
105 
106 #undef _________________________________________LOCAL_PROTOTYPES_SECTION___________________________________________________________________
107 
108 
114 #define _________________________________________VARIABLES_SECTION__________________________________________________________________________
115 
116 static const uint16_t NotUsedByteValue = 0xbeef;
117 static const CheckFunction_t CheckFunctions[] = {
118  CheckUnblockedWhenEqual ,
119  CheckUnblockedWhenNotEqual,
120  CheckUnblockedWhenSmaller ,
121  CheckUnblockedWhenGreater ,
122  CheckUnblockedWhenSmallerOrEqual ,
123  CheckUnblockedWhenGreaterOrEqual
124 };
125 
126 #undef _________________________________________VARIABLES_SECTION__________________________________________________________________________
127 
128 
134 #define _________________________________________INTERFACE_FUNCTIONS_SECTION________________________________________________________________
135 
138 
139 //==========================================================================================================================================
140 //==========================================================================================================================================
141 oC_Thread_t oC_Thread_New( oC_Thread_Priority_t Priority , oC_Int_t StackSize , void * Process , const char * Name , oC_Thread_Function_t Function , void * Parameter )
142 {
143  oC_Thread_t thread = NULL;
144 
146  {
147  Allocator_t allocator = NULL;
148  oC_Process_t process = Process;
149 
150  if(process == NULL)
151  {
152  process = oC_ProcessMan_GetCurrentProcess();
153  }
154 
155  if(oC_Process_IsCorrect(process) == false)
156  {
157  kdebuglog(oC_LogType_Error,"thread: process 0x%08X is not correct" , Process);
158  }
159 
160  allocator = oC_Process_GetAllocator(process);
161 
162  if(StackSize == 0)
163  {
164  StackSize = oC_ThreadMan_GetDefaultStackSize();
165  }
166 
167  StackSize = oC_MemMan_AlignSizeTo(StackSize,oC_MEM_LLD_STACK_ALIGNMENT);
168 
169  if(allocator)
170  {
171  thread = kmalloc(sizeof(struct Thread_t) , allocator , AllocationFlags_CanWait1Second | AllocationFlags_ZeroFill );
172 
173  if(thread)
174  {
175  oC_MemorySize_t redZoneSize = oC_ThreadMan_GetRedZoneSize();
176  oC_UInt_t minimumContextSize = oC_SYS_LLD_GetMinimumContextSize(StackSize + redZoneSize);
177  void * realStack = kamalloc(minimumContextSize , allocator , AllocationFlags_CanWait1Second , oC_MEM_LLD_STACK_ALIGNMENT );
178  void * endStack = (void*)(((oC_UInt_t)realStack) + minimumContextSize);
179 
180  /* Filling a stack with special value for checking if all stack is used */
181  for(uint16_t * stack = (uint16_t*)realStack; stack < ((uint16_t*)endStack) ; stack++ )
182  {
183  *stack = NotUsedByteValue;
184  }
185 
186  if(realStack)
187  {
188  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
189 
190  thread->ObjectControl = oC_CountObjectControl(thread,oC_ObjectId_Thread);
191  thread->Name = Name;
192  thread->Priority = Priority + oC_Process_GetPriority(process);
193  thread->BlockedFlag = NULL;
194  thread->TimeoutTimestamp = 0;
195  thread->ExecutionTime = 0;
196  thread->RealStackSize = minimumContextSize;
197  thread->StackSize = StackSize;
198  thread->Process = process;
199  thread->Function = Function;
200  thread->Parameter = Parameter;
201  thread->RealStackStart = realStack;
202 
204  {
205  // 0x00000000 - ,----------------------------------------.
206  // | RED ZONE |
207  // |----------------------------------------|
208  // | STACK |
209  // 0xFFFFFFFF - '----------------------------------------'
210  thread->RedZone = realStack;
211  thread->Context = oC_MemMan_AlignAddressTo((void*)(((oC_UInt_t)realStack) + redZoneSize),oC_MEM_LLD_STACK_ALIGNMENT);
212  }
213  else
214  {
215  // 0x00000000 - ,----------------------------------------.
216  // | STACK |
217  // |----------------------------------------|
218  // | RED ZONE |
219  // 0xFFFFFFFF - '----------------------------------------'
220  thread->RedZone = (void*)(((oC_UInt_t)realStack) + StackSize);
221  thread->Context = realStack;
222  }
223 
224  thread->StackStart = thread->Context;
225  thread->RedZoneEnd = oC_MemMan_AlignAddressTo((void*)(((oC_UInt_t)thread->RedZone) + redZoneSize),oC_MEM_LLD_STACK_ALIGNMENT);
226 
227  errorCode = oC_SYS_LLD_InitializeContext(&thread->Context,StackSize,Function,Parameter,ThreadExitHandler);
228 
229  if(errorCode == oC_ErrorCode_ModuleNotStartedYet)
230  {
232  errorCode = oC_SYS_LLD_InitializeContext(&thread->Context,StackSize,Function,Parameter,ThreadExitHandler);
233  }
234 
235  if(oC_ErrorOccur(errorCode))
236  {
237  oC_SaveError("Thread: Cannot initialize context" , errorCode);
238 
239  if(!kfree(realStack , AllocationFlags_CanWait1Second) ||
240  !kfree(thread , AllocationFlags_CanWait1Second)
241  )
242  {
243  oC_SaveError("Thread: Cannot release memory" , oC_ErrorCode_AllocationError);
244  }
245  thread = NULL;
246  }
247  }
248  else
249  {
250  bool stackReleased = kfree(realStack,0);
251 
252  oC_SaveIfFalse("Stack" , stackReleased || realStack == NULL, oC_ErrorCode_ReleaseError);
253  if(!kfree(thread,AllocationFlags_CanWait1Second))
254  {
255  oC_SaveError("Thread: Cannot release memory" , oC_ErrorCode_AllocationError);
256  }
257  thread = NULL;
258  }
259  }
260  }
261 
262  }
263 
264  return thread;
265 }
266 
267 //==========================================================================================================================================
271 //==========================================================================================================================================
272 bool oC_Thread_IsOwnedByStack( oC_Thread_t Thread , const void * Address , bool * outAddressInRedZone )
273 {
274  bool owned = false;
275 
276  if(oC_Thread_IsCorrect(Thread) && (outAddressInRedZone == NULL || isram(outAddressInRedZone)))
277  {
278  void * stackEnd = Thread->StackStart;
279  void * stackStart = Thread->StackStart;
280 
281  stackEnd += Thread->StackSize;
282 
283  if(outAddressInRedZone != NULL)
284  {
285  void * redZoneStart = Thread->RedZone;
286  void * redZoneEnd = Thread->RedZoneEnd;
287  *outAddressInRedZone = Address >= redZoneStart && Address <= redZoneEnd;
288  }
289 
290  owned = Address >= stackStart && Address < stackEnd;
291  }
292 
293  return owned;
294 }
295 
296 //==========================================================================================================================================
297 //==========================================================================================================================================
298 oC_Thread_t oC_Thread_CloneWithNewStack( oC_Thread_t Thread , oC_MemorySize_t NewStackSize )
299 {
300  oC_Thread_t newThread = NULL;
301 
302  if(oC_Thread_IsCorrect(Thread) && NewStackSize > 0)
303  {
304  newThread = oC_Thread_New(Thread->Priority,NewStackSize,Thread->Process,Thread->Name,Thread->Function,Thread->Parameter);
305  }
306 
307  return newThread;
308 }
309 
310 //==========================================================================================================================================
311 //==========================================================================================================================================
312 bool oC_Thread_Delete( oC_Thread_t * Thread )
313 {
314  bool deleted = false;
315 
316  if(isram(Thread) && oC_Thread_IsCorrect(*Thread))
317  {
318  if(oC_ThreadMan_GetCurrentThread() != (*Thread))
319  {
320  uint32_t blockingFlag = 0;
321  bool threadRemoved = false;
322 
323  oC_Thread_SetBlocked(*Thread,&blockingFlag,oC_Thread_Unblock_WhenEqual,0xff,oC_Thread_UnblockMask_All,oC_hour(1));
324 
325  oC_IntMan_EnterCriticalSection();
326 
327  if(oC_Thread_IsActive(*Thread))
328  {
329  threadRemoved = oC_SaveIfErrorOccur("Thread - Removing from list: ", oC_ThreadMan_RemoveThread(*Thread));
330  deleted = threadRemoved;
331  (*Thread)->ObjectControl = 0;
332  }
333  else
334  {
335  void * realStack = (*Thread)->RealStackStart;
336 
337  bool stackReleased = false;
338  bool objectReleased= false;
339 
340  oC_ARRAY_FOREACH_IN_ARRAY((*Thread)->ActionsToRevert,action)
341  {
342  if(action->Function != NULL)
343  {
344  if(oC_SaveIfFalse("cannot revert action", isaddresscorrect(action->Function), oC_ErrorCode_WrongAddress))
345  {
346  oC_SaveIfFalse("cannot revert action", action->Function(*Thread,action->Object,action->Parameter), oC_ErrorCode_InternalDataAreDamaged );
347  }
348  }
349  }
350 
351  threadRemoved = true;
352  (*Thread)->ObjectControl = 0;
353 
354  stackReleased = kfree(realStack, AllocationFlags_CanWaitForever);
355  objectReleased = kfree(*Thread, AllocationFlags_CanWaitForever);
356 
357  if(
358  threadRemoved
359  && oC_SaveIfFalse("Thread - Stack - ", stackReleased , oC_ErrorCode_ReleaseError )
360  && oC_SaveIfFalse("Thread - Object - ", objectReleased , oC_ErrorCode_ReleaseError )
361  )
362  {
363  *Thread = NULL;
364  deleted = true;
365  }
366 
367  }
368  oC_IntMan_ExitCriticalSection();
369 
370  }
371  else
372  {
373  oC_IntMan_EnterCriticalSection();
374  /* This is current thread, we cannot delete it now */
375  oC_ErrorCode_t errorCode = oC_ThreadMan_RemoveThread(*Thread);
376 
377  if(oC_ErrorOccur(errorCode))
378  {
379  oC_SaveError((*Thread)->Name , errorCode);
380  }
381  else
382  {
383  deleted = true;
384  }
385 
386  oC_IntMan_ExitCriticalSection();
387 
388  if(oC_IntMan_AreInterruptsTurnedOn())
389  {
390  while(deleted);
391  }
392  }
393  }
394 
395 
396  return deleted;
397 }
398 
399 //==========================================================================================================================================
400 //==========================================================================================================================================
401 bool oC_Thread_IsCorrect( oC_Thread_t Thread )
402 {
403  return oC_MemMan_IsDynamicAllocatedAddress(Thread) && oC_CheckObjectControl(Thread,oC_ObjectId_Thread,Thread->ObjectControl);
404 }
405 
406 //==========================================================================================================================================
407 //==========================================================================================================================================
408 bool oC_Thread_IsActive( oC_Thread_t Thread )
409 {
410  return oC_Thread_IsCorrect(Thread) && oC_ThreadMan_ContainsThread(Thread);
411 }
412 
413 //==========================================================================================================================================
414 //==========================================================================================================================================
415 bool oC_Thread_SetBlocked( oC_Thread_t Thread , uint32_t * BlockingFlag , oC_Thread_Unblock_t Unblock , uint32_t StateToUnblock , oC_Thread_UnblockMask_t UnblockMask , oC_Time_t Timeout )
416 {
417  bool blocked = false;
418 
419  if(
420  oC_Thread_IsCorrect(Thread) &&
421  oC_MemMan_IsRamAddress(BlockingFlag) &&
422  Timeout >= 0
423  )
424  {
425  oC_IntMan_EnterCriticalSection();
426  Thread->BlockedFlag = BlockingFlag;
427  Thread->StateToUnblock = StateToUnblock;
428  Thread->TimeoutTimestamp = oC_KTime_GetTimestamp() + Timeout;
429  Thread->Unblock = Unblock;
430  Thread->UnblockMask = UnblockMask;
431  oC_IntMan_ExitCriticalSection();
432 
433  oC_ThreadMan_SwitchThread();
434 
435  blocked = *BlockingFlag != StateToUnblock;
436  }
437 
438  return blocked;
439 }
440 
441 //==========================================================================================================================================
442 //==========================================================================================================================================
443 bool oC_Thread_SetUnblocked( oC_Thread_t Thread )
444 {
445  bool unblocked = false;
446 
447  if(oC_Thread_IsCorrect(Thread))
448  {
449  oC_IntMan_EnterCriticalSection();
450  Thread->BlockedFlag = NULL;
451  Thread->TimeoutTimestamp = 0;
452  unblocked = true;
453  oC_IntMan_ExitCriticalSection();
454 
455  oC_ThreadMan_SwitchThread();
456  }
457 
458  return unblocked;
459 }
460 
461 //==========================================================================================================================================
462 //==========================================================================================================================================
463 bool oC_Thread_IsBlocked( oC_Thread_t Thread )
464 {
465  bool blocked = true;
466 
467  if(oC_Thread_IsCorrect(Thread))
468  {
469  oC_IntMan_EnterCriticalSection();
470  oC_Timestamp_t currentTimestamp = oC_KTime_GetTimestamp();
471  oC_Timestamp_t timeout = Thread->TimeoutTimestamp;
472  uint32_t blockedFlag = *Thread->BlockedFlag;
473  uint32_t stateToUnblock = Thread->StateToUnblock;
474  uint32_t unblockMask = Thread->UnblockMask;
475  uint32_t* blockedFlagRef = Thread->BlockedFlag;
476  oC_IntMan_ExitCriticalSection();
477 
478  if(
479  ((blockedFlagRef == NULL) && (currentTimestamp < Thread->TimeoutTimestamp)) ||
480  ((blockedFlagRef != NULL) && (CheckFunctions[Thread->Unblock](blockedFlag,stateToUnblock,unblockMask)) && (currentTimestamp < timeout))
481  )
482  {
483  blocked = true;
484  }
485  else
486  {
487  blocked = false;
488  }
489  }
490 
491  return blocked;
492 }
493 
494 
495 //==========================================================================================================================================
496 //==========================================================================================================================================
497 bool oC_Thread_IsBlockedBy( oC_Thread_t Thread , uint32_t * BlockingFlag )
498 {
499  return oC_Thread_IsCorrect(Thread) && isram(BlockingFlag) && Thread->BlockedFlag == BlockingFlag;
500 }
501 
502 //==========================================================================================================================================
503 //==========================================================================================================================================
504 bool oC_Thread_Run( oC_Thread_t Thread )
505 {
506  bool runned = false;
507 
508  if(oC_Thread_IsCorrect(Thread))
509  {
510  oC_ErrorCode_t errorCode = oC_ThreadMan_AddThread(Thread);
511 
512  if(oC_ErrorOccur(errorCode))
513  {
514  oC_SaveError(Thread->Name,errorCode);
515  }
516  else
517  {
518  runned = true;
519  }
520  }
521 
522  return runned;
523 }
524 
525 //==========================================================================================================================================
526 //==========================================================================================================================================
527 bool oC_Thread_Cancel( oC_Thread_t * Thread )
528 {
529  bool canceled = false;
530 
531  if(oC_Thread_IsCorrect(*Thread))
532  {
533  oC_Thread_t thread = *Thread;
534 
535  if(thread->FinishedFunction != NULL)
536  {
537  if(oC_SaveIfFalse("Finished Function", isaddresscorrect(thread->FinishedFunction), oC_ErrorCode_WrongAddress))
538  {
539  thread->FinishedFunction(thread, thread->FinishedParameter);
540  thread->FinishedFunction = NULL;
541  }
542  }
543 
544  oC_ErrorCode_t errorCode = oC_ThreadMan_RemoveThread(*Thread);
545 
546  if(oC_ErrorOccur(errorCode))
547  {
548  oC_SaveError((*Thread)->Name , errorCode);
549  }
550  else
551  {
552  canceled = true;
553  *Thread = NULL;
554  }
555  }
556 
557  return canceled;
558 }
559 
560 //==========================================================================================================================================
561 //==========================================================================================================================================
562 void * oC_Thread_GetContext( oC_Thread_t Thread )
563 {
564  void * context = NULL;
565 
566  if(oC_Thread_IsCorrect(Thread))
567  {
568  context = Thread->Context;
569  }
570 
571  return context;
572 }
573 
574 //==========================================================================================================================================
575 //==========================================================================================================================================
576 oC_Thread_Priority_t oC_Thread_GetPriority( oC_Thread_t Thread )
577 {
578  oC_Thread_Priority_t priority = 0;
579 
580  if(oC_Thread_IsCorrect(Thread))
581  {
582  priority = Thread->Priority;
583  }
584 
585  return priority;
586 }
587 
588 //==========================================================================================================================================
589 //==========================================================================================================================================
590 void * oC_Thread_GetParameter( oC_Thread_t Thread )
591 {
592  void * parameter = NULL;
593 
594  if(oC_Thread_IsCorrect(Thread))
595  {
596  parameter = Thread->Parameter;
597  }
598 
599  return parameter;
600 }
601 
602 //==========================================================================================================================================
603 //==========================================================================================================================================
604 const char * oC_Thread_GetName( oC_Thread_t Thread )
605 {
606  const char * name = "incorrect thread";
607 
608  if(oC_Thread_IsCorrect(Thread))
609  {
610  name = Thread->Name;
611  }
612 
613  return name;
614 }
615 
616 //==========================================================================================================================================
617 //==========================================================================================================================================
618 bool oC_Thread_Sleep( oC_Thread_t Thread , oC_Time_t Time )
619 {
620  bool asleep = false;
621 
622  if(oC_Thread_IsCorrect(Thread))
623  {
624  oC_IntMan_EnterCriticalSection();
625 
626  Thread->BlockedFlag = NULL;
627  Thread->TimeoutTimestamp = oC_KTime_GetTimestamp() + Time;
628  asleep = true;
629  oC_IntMan_ExitCriticalSection();
630 
631  while(oC_Thread_IsBlocked(Thread));
632  }
633 
634  return asleep;
635 }
636 
637 //==========================================================================================================================================
638 //==========================================================================================================================================
639 oC_Time_t oC_Thread_GetExecutionTime ( oC_Thread_t Thread )
640 {
641  oC_Time_t executionTime = 0;
642 
643  if(oC_Thread_IsCorrect(Thread))
644  {
645  executionTime = Thread->ExecutionTime;
646  }
647 
648  return executionTime;
649 }
650 
651 //==========================================================================================================================================
652 //==========================================================================================================================================
653 bool oC_Thread_AddToExecutionTime( oC_Thread_t Thread , oC_Time_t Time )
654 {
655  bool added = false;
656 
657  if(oC_Thread_IsCorrect(Thread))
658  {
659  Thread->ExecutionTime += Time;
660  }
661 
662  return added;
663 }
664 
665 //==========================================================================================================================================
666 //==========================================================================================================================================
667 uint64_t oC_Thread_GetLastExecutionTick(oC_Thread_t Thread )
668 {
669  uint64_t tick = 0;
670 
671  if(oC_Thread_IsCorrect(Thread))
672  {
673  tick = Thread->LastExecutionTick;
674  }
675 
676  return tick;
677 }
678 
679 //==========================================================================================================================================
680 //==========================================================================================================================================
681 bool oC_Thread_SetLastExecutionTick(oC_Thread_t Thread , uint64_t Tick )
682 {
683  bool set = false;
684 
685  if(oC_Thread_IsCorrect(Thread))
686  {
687  Thread->LastExecutionTick = Tick;
688  }
689 
690  return set;
691 }
692 
693 //==========================================================================================================================================
694 //==========================================================================================================================================
695 oC_UInt_t oC_Thread_GetStackSize( oC_Thread_t Thread )
696 {
697  oC_UInt_t size = 0;
698 
699  if(oC_Thread_IsCorrect(Thread))
700  {
701  size = oC_SYS_LLD_GetContextStackSize(Thread->Context);
702 
703  if(size != Thread->StackSize)
704  {
705  size = Thread->StackSize;
706  }
707  }
708 
709  return size;
710 }
711 
712 //==========================================================================================================================================
713 //==========================================================================================================================================
714 oC_Int_t oC_Thread_GetFreeStackSize( oC_Thread_t Thread , bool Current )
715 {
716  oC_Int_t size = 0;
717 
718  if(oC_Thread_IsCorrect(Thread))
719  {
720  if(Current)
721  {
723  }
724  else
725  {
726  oC_UInt_t contextSize = oC_SYS_LLD_GetContextStackSize(Thread->Context);
727  uint16_t* redZoneEnd = (void*)(((oC_UInt_t)Thread->RedZoneEnd));
728 
729  //==========================================================================================================================
730  /*
731  * Checking if red zone is was used
732  */
733  //==========================================================================================================================
734  for(uint16_t * stack = (uint16_t*)Thread->RedZone ; stack < redZoneEnd ; stack++ )
735  {
736  if(*stack != NotUsedByteValue)
737  {
738  size-=sizeof(uint16_t);
739  }
740  }
741 
742  if(size == 0)
743  {
744  uint16_t * stackEnd = (Thread->StackStart + contextSize);
745 
746  //======================================================================================================================
747  /*
748  * If 'Red-Zone' was not used, then check if there is any stack free
749  */
750  //======================================================================================================================
751  for(uint16_t * stack = Thread->StackStart ; stack < stackEnd ; stack++ )
752  {
753  if(*stack == NotUsedByteValue)
754  {
755  size+=sizeof(uint16_t);
756  }
757  }
758  }
759  }
760  }
761 
762  return size;
763 }
764 
765 //==========================================================================================================================================
766 //==========================================================================================================================================
767 bool oC_Thread_SaveToRevert( oC_Thread_t Thread , oC_Thread_RevertFunction_t Function, void * Object , uint32_t Parameter )
768 {
769  bool success = false;
770 
771  if(
772  oC_SaveIfFalse("Thread object", oC_Thread_IsCorrect(Thread), oC_ErrorCode_ObjectNotCorrect )
773  && oC_SaveIfFalse("Function" , isaddresscorrect(Function) , oC_ErrorCode_WrongAddress )
774  )
775  {
776  oC_IntMan_EnterCriticalSection();
777  oC_ARRAY_FOREACH_IN_ARRAY(Thread->ActionsToRevert,action)
778  {
779  if(action->Function == NULL)
780  {
781  action->Function = Function;
782  action->Object = Object;
783  action->Parameter= Parameter;
784 
785  success = true;
786  break;
787  }
788  }
789  oC_IntMan_ExitCriticalSection();
790  oC_SaveIfFalse("Cannot add function", success, oC_ErrorCode_NoFreeSlots);
791  }
792 
793  return success;
794 }
795 
796 //==========================================================================================================================================
797 //==========================================================================================================================================
798 bool oC_Thread_RemoveFromRevert( oC_Thread_t Thread , oC_Thread_RevertFunction_t Function, void * Object )
799 {
800  bool success = false;
801 
802  if(
803  oC_SaveIfFalse("Thread object", oC_Thread_IsCorrect(Thread), oC_ErrorCode_ObjectNotCorrect )
804  && oC_SaveIfFalse("Function" , isaddresscorrect(Function) , oC_ErrorCode_WrongAddress )
805  )
806  {
807  oC_IntMan_EnterCriticalSection();
808  oC_ARRAY_FOREACH_IN_ARRAY(Thread->ActionsToRevert,action)
809  {
810  if(action->Function == Function && action->Object == Object)
811  {
812  action->Function = NULL;
813  action->Parameter = 0;
814  action->Object = NULL;
815  success = true;
816  break;
817  }
818  }
819  oC_IntMan_ExitCriticalSection();
820  oC_SaveIfFalse("Cannot remove function", success, oC_ErrorCode_ObjectNotFoundOnList);
821  }
822 
823  return success;
824 }
825 
826 //==========================================================================================================================================
827 //==========================================================================================================================================
828 bool oC_Thread_SetFinishedFunction( oC_Thread_t Thread , oC_Thread_FinishedFunction_t Function, void * Parameter )
829 {
830  bool success = false;
831 
832  if(
833  oC_SaveIfFalse("Thread object", oC_Thread_IsCorrect(Thread), oC_ErrorCode_ObjectNotCorrect )
834  && oC_SaveIfFalse("Function" , isaddresscorrect(Function) , oC_ErrorCode_WrongAddress )
835  )
836  {
837  Thread->FinishedFunction = Function;
838  Thread->FinishedParameter = Parameter;
839  success = true;
840  }
841 
842  return success;
843 }
844 
845 #undef _________________________________________INTERFACE_FUNCTIONS_SECTION________________________________________________________________
846 
853 #define _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
854 
855 //==========================================================================================================================================
856 //==========================================================================================================================================
857 static void ThreadExitHandler( void )
858 {
859  oC_Thread_t thread = oC_ThreadMan_GetCurrentThread();
860  oC_List(oC_Thread_t) threads = oC_ThreadMan_GetList();
861  bool contains = oC_List_Contains(threads,thread);
862 
863  if(thread->FinishedFunction != NULL)
864  {
865  if(oC_SaveIfFalse("Finished Function", isaddresscorrect(thread->FinishedFunction), oC_ErrorCode_WrongAddress))
866  {
867  thread->FinishedFunction(thread, thread->FinishedParameter);
868  thread->FinishedFunction = NULL;
869  }
870  }
871 
872  if(oC_Thread_IsCorrect(thread) && contains)
873  {
874  oC_Thread_Delete(&thread);
875  }
876  while(1);
877 }
878 
879 //==========================================================================================================================================
880 //==========================================================================================================================================
881 static bool CheckUnblockedWhenEqual( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask )
882 {
883  return (Value & UnblockMask) != (Expected & UnblockMask);
884 }
885 
886 //==========================================================================================================================================
887 //==========================================================================================================================================
888 static bool CheckUnblockedWhenNotEqual( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask )
889 {
890  return (Value & UnblockMask) == (Expected & UnblockMask);
891 }
892 
893 //==========================================================================================================================================
894 //==========================================================================================================================================
895 static bool CheckUnblockedWhenSmaller( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask )
896 {
897  return (Value & UnblockMask) >= (Expected & UnblockMask);
898 }
899 
900 //==========================================================================================================================================
901 //==========================================================================================================================================
902 static bool CheckUnblockedWhenGreater( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask )
903 {
904  return (Value & UnblockMask) <= (Expected & UnblockMask);
905 }
906 
907 //==========================================================================================================================================
908 //==========================================================================================================================================
909 static bool CheckUnblockedWhenSmallerOrEqual( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask )
910 {
911  return (Value & UnblockMask) > (Expected & UnblockMask);
912 }
913 
914 //==========================================================================================================================================
915 //==========================================================================================================================================
916 static bool CheckUnblockedWhenGreaterOrEqual( uint32_t Value , uint32_t Expected , oC_Thread_UnblockMask_t UnblockMask )
917 {
918  return (Value & UnblockMask ) < (Expected & UnblockMask);
919 }
920 
921 #undef _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
922 
FILE__DESCRIPTION
oC_Int_t oC_SYS_LLD_GetMinimumContextSize(oC_Int_t StackSize)
returns minimum size to allocate for context
Definition: oc_sys_lld.c:452
void * oC_MemMan_AlignAddressTo(const void *Address, oC_UInt_t Alignment)
returns address aligned to the given alignment.
Definition: oc_memman.c:1174
The file with interface for thread managing.
bool oC_MemMan_IsRamAddress(const void *Address)
checks if address is in ram section
Definition: oc_memman.c:1542
identifier for allocations
Definition: oc_stdlib.h:159
oC_ErrorCode_t oC_SYS_LLD_InitializeContext(oC_SYS_LLD_Context_t **Context, oC_Int_t StackSize, oC_SYS_LLD_ContextHandler_t ContextHandler, void *Parameters, oC_SYS_LLD_ContextExitHandler_t ExitHandler)
initializes stack of process
Definition: oc_sys_lld.c:419
oC_UInt_t oC_MemMan_AlignSizeTo(oC_UInt_t Size, oC_UInt_t Alignment)
returns size aligned to the given alignment
Definition: oc_memman.c:1239
The file with interface for process manager.
uint32_t * BlockedFlag
!< Size of the stack with red zone
Definition: oc_thread.c:72
oC_Int_t StackSize
!< Tick of last execution
Definition: oc_thread.c:79
oC_Int_t RealStackSize
!< Pointer to the normal stack (not red zone)
Definition: oc_thread.c:71
oC_Process_t Process
!< Control value for checking if object is correct
Definition: oc_thread.c:63
oC_ErrorCode_t oC_SYS_LLD_TurnOnDriver(void)
initializes the driver to work
Definition: oc_sys_lld.c:103
The file with LLD interface for the MEM driver.
void * StackStart
!< Machine context (stack)
Definition: oc_thread.c:70
oC_UInt_t * RedZoneEnd
!< Pointer to the red zone
Definition: oc_thread.c:67
FinishedFunction_t FinishedFunction
!< Parameter to main function
Definition: oc_thread.c:82
void oC_SYS_LLD_Context_t
type for storing context of the machine
Definition: oc_sys_lld.h:143
oC_UInt_t * RedZone
!< Name of the thread
Definition: oc_thread.c:66
The file with helper macros for managing objects.
bool oC_MemMan_IsDynamicAllocatedAddress(const void *Address)
checks if address is in dynamic allocated section
Definition: oc_memman.c:1552
oC_Time_t ExecutionTime
!< Timeout for the blocked state
Definition: oc_thread.c:77
oC_Thread_Unblock_t Unblock
!< Mask with bits important for unblocking
Definition: oc_thread.c:75
oC_Int_t oC_SYS_LLD_GetContextStackSize(oC_SYS_LLD_Context_t *Context)
returns size of the stack for context
Definition: oc_sys_lld.c:350
uint32_t oC_ObjectControl_t
stores object control value
Definition: oc_object.h:141
The file with interface for interrupt manager.
static oC_ObjectControl_t oC_CountObjectControl(void *ObjectPointer, oC_ObjectId_t ObjectId)
counts object control for object
Definition: oc_object.h:168
static bool oC_CheckObjectControl(void *ObjectPointer, oC_ObjectId_t ObjectId, oC_ObjectControl_t ObjectControl)
checks if object control is correct
Definition: oc_object.h:203
uint32_t LastExecutionTick
!< Time of execution of this thread
Definition: oc_thread.c:78
uint32_t StateToUnblock
!< Reference to the flag of the blocked context
Definition: oc_thread.c:73
oC_Thread_Function_t Function
!< Size of the stack
Definition: oc_thread.c:80
oC_Thread_Priority_t Priority
!< Process owner
Definition: oc_thread.c:64
void * RealStackStart
!< Pointer to end of the RedZone (start of the real stack)
Definition: oc_thread.c:68
void * FinishedParameter
!< Function to call after thread finish
Definition: oc_thread.c:83
The file with memory manager interface.
void * Parameter
!< Main function to execute
Definition: oc_thread.c:81
oC_SYS_LLD_Context_t * Context
!< Pointer to the real stack (real allocated memory)
Definition: oc_thread.c:69
oC_Timestamp_t TimeoutTimestamp
!< Type of operation to unblock thread
Definition: oc_thread.c:76
The file with LLD interface for the SYS driver.
bool oC_Thread_IsOwnedByStack(oC_Thread_t Thread, const void *Address, bool *outAddressInRedZone)
checks if the given address is owned by the thread stack
Definition: oc_thread.c:272
RevertAction_t ActionsToRevert[CFG_UINT8_MAX_ACTIONS_TO_REVERT]
!< Parameter to give to the thread finish
Definition: oc_thread.c:84
uint32_t UnblockMask
!< State to unblock thread
Definition: oc_thread.c:74
The file with interface for Thread Manager.
const char * Name
!< Priority of this thread
Definition: oc_thread.c:65
bool oC_SYS_LLD_IsStackPushDecrementPointer(void)
flag if stack push is decrement pointer
Definition: oc_sys_lld.c:507
#define oC_MEM_LLD_STACK_ALIGNMENT
number of bytes in alignment of the stack
Definition: oc_mem_lld.h:105
bool oC_SYS_LLD_IsMachineSupportMultithreadMode(void)
checks if the machine supports multi-thread mode
Definition: oc_sys_lld.c:195
#define NULL
pointer to a zero
Definition: oc_null.h:37
oC_Int_t oC_SYS_LLD_GetContextFreeStackSize(oC_SYS_LLD_Context_t *Context)
returns size of free stack in the context
Definition: oc_sys_lld.c:368