Choco OS  V.0.16.9.0
Join to the chocolate world
oc_mutex.c
Go to the documentation of this file.
1 
27 #include <oc_mutex.h>
28 #include <oc_thread.h>
29 #include <oc_object.h>
30 #include <oc_stdlib.h>
31 #include <oc_thread.h>
32 #include <oc_intman.h>
33 #include <oc_threadman.h>
34 #include <oc_null.h>
35 
41 #define _________________________________________LOCAL_TYPES_SECTION_______________________________________________________________________
42 
43 struct Mutex_t
44 {
45  oC_ObjectControl_t ObjectControl;
46  int16_t RecursiveCount;
47  oC_Mutex_Type_t Type;
48  uint32_t LockedFlag;
49  oC_Thread_t BlockedThread;
50 };
51 
52 #undef _________________________________________LOCAL_TYPES_SECTION_______________________________________________________________________
53 
54 
60 #define _________________________________________LOCAL_VARIABLES_SECTION____________________________________________________________________
61 
62 
63 #undef _________________________________________LOCAL_VARIABLES_SECTION____________________________________________________________________
64 
65 
71 #define _________________________________________LOCAL_PROTOTYPES_SECTION___________________________________________________________________
72 
73 static bool RevertFunction( oC_Thread_t Thread, void * Mutex, uint32_t Parameter );
74 
75 #undef _________________________________________LOCAL_PROTOTYPES_SECTION___________________________________________________________________
76 
82 #define _________________________________________INTERFACE_FUNCTIONS_SECTION________________________________________________________________
83 
86 //==========================================================================================================================================
87 //==========================================================================================================================================
88 oC_Mutex_t oC_Mutex_New( oC_Mutex_Type_t Type , Allocator_t Allocator , AllocationFlags_t AllocationFlags )
89 {
90  oC_Mutex_t mutex = kmalloc(sizeof(struct Mutex_t), Allocator , AllocationFlags_NoWait);
91 
92  if(mutex)
93  {
94  mutex->LockedFlag = false;
95  mutex->BlockedThread = NULL;
96  mutex->Type = Type;
97  mutex->ObjectControl = oC_CountObjectControl(mutex,oC_ObjectId_Mutex);
98  }
99 
100  return mutex;
101 }
102 
103 //==========================================================================================================================================
104 //==========================================================================================================================================
105 bool oC_Mutex_Delete( oC_Mutex_t * Mutex , AllocationFlags_t AllocationFlags )
106 {
107  bool deleted = false;
108 
109  if(oC_Mutex_IsCorrect(*Mutex))
110  {
111  oC_IntMan_EnterCriticalSection();
112  (*Mutex)->ObjectControl = 0;
113  oC_ThreadMan_UnblockAllBlockedBy(&((*Mutex)->LockedFlag),false);
114  if(!kfree(*Mutex,AllocationFlags))
115  {
116  oC_SaveError("Mutex" , oC_ErrorCode_ReleaseError);
117  }
118  else
119  {
120  *Mutex = NULL;
121  deleted = true;
122  }
123  oC_IntMan_ExitCriticalSection();
124  }
125  else
126  {
127  oC_SaveError("Mutex" , oC_ErrorCode_ObjectNotCorrect);
128  }
129 
130  return deleted;
131 }
132 
133 //==========================================================================================================================================
134 //==========================================================================================================================================
135 bool oC_Mutex_Give( oC_Mutex_t Mutex )
136 {
137  bool given = false;
138 
139  if(oC_Mutex_IsCorrect(Mutex))
140  {
141  if(oC_ThreadMan_GetCurrentThread() == Mutex->BlockedThread)
142  {
143  oC_IntMan_EnterCriticalSection();
144  Mutex->RecursiveCount++;
145  if(
146  (Mutex->Type == oC_Mutex_Type_Normal) ||
147  (Mutex->RecursiveCount >= 0)
148  )
149  {
150  oC_Thread_RemoveFromRevert(getcurthread(),RevertFunction, Mutex);
151  Mutex->LockedFlag = false;
152  }
153  given = true;
154  oC_IntMan_ExitCriticalSection();
155  }
156  else
157  {
158  oC_SaveError("Mutex" , oC_ErrorCode_WrongThread);
159  }
160  }
161  else
162  {
163  oC_SaveError("Mutex" , oC_ErrorCode_ObjectNotCorrect);
164  }
165 
166  return given;
167 }
168 
169 //==========================================================================================================================================
170 //==========================================================================================================================================
171 bool oC_Mutex_Take( oC_Mutex_t Mutex , oC_Time_t Timeout )
172 {
173  bool taken = false;
174 
175  if(oC_Mutex_IsCorrect(Mutex))
176  {
177  oC_Thread_t currentThread = oC_ThreadMan_GetCurrentThread();
178 
179  if(Mutex->LockedFlag)
180  {
181  if(currentThread != Mutex->BlockedThread)
182  {
183  if( oC_Thread_SetBlocked(currentThread , &Mutex->LockedFlag , oC_Thread_Unblock_WhenEqual , false , oC_Thread_UnblockMask_All , Timeout ) )
184  {
185  while(oC_Thread_IsBlocked(currentThread));
186 
187  oC_Thread_SetUnblocked(currentThread);
188 
189  oC_IntMan_EnterCriticalSection();
190  if(oC_Mutex_IsCorrect(Mutex) && (Mutex->LockedFlag == 0))
191  {
192  Mutex->LockedFlag = true;
193  Mutex->BlockedThread = currentThread;
194  Mutex->RecursiveCount--;
195  taken = true;
196 
197  oC_Thread_SaveToRevert(currentThread,RevertFunction,Mutex,0);
198  }
199  oC_IntMan_ExitCriticalSection();
200  }
201  }
202  else
203  {
204  oC_IntMan_EnterCriticalSection();
205  Mutex->RecursiveCount--;
206  taken = true;
207  oC_IntMan_ExitCriticalSection();
208  }
209  }
210  else
211  {
212  oC_IntMan_EnterCriticalSection();
213  Mutex->LockedFlag = true;
214  Mutex->BlockedThread = currentThread;
215  Mutex->RecursiveCount--;
216  taken = true;
217 
218  oC_Thread_SaveToRevert(currentThread,RevertFunction,Mutex,0);
219  oC_IntMan_ExitCriticalSection();
220  }
221  }
222  else
223  {
224  oC_SaveError("Mutex" , oC_ErrorCode_ObjectNotCorrect);
225  }
226 
227  return taken;
228 }
229 
230 //==========================================================================================================================================
231 //==========================================================================================================================================
232 bool oC_Mutex_IsCorrect( oC_Mutex_t Mutex )
233 {
234  return oC_MemMan_IsRamAddress(Mutex) && oC_CheckObjectControl(Mutex , oC_ObjectId_Mutex , Mutex->ObjectControl);
235 }
236 
237 #undef _________________________________________INTERFACE_FUNCTIONS_SECTION________________________________________________________________
238 
245 #define _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
246 
247 //==========================================================================================================================================
251 //==========================================================================================================================================
252 static bool RevertFunction( oC_Thread_t Thread, void * Mutex, uint32_t Parameter )
253 {
254  bool reverted = false;
255  oC_Mutex_t mutex = Mutex;
256 
257  oC_IntMan_EnterCriticalSection();
258  if(oC_SaveIfFalse("Mutex", oC_Mutex_IsCorrect(mutex), oC_ErrorCode_ObjectNotCorrect))
259  {
260  mutex->BlockedThread = NULL;
261  mutex->LockedFlag = false;
262  mutex->RecursiveCount = 0;
263  reverted = true;
264  }
265  oC_IntMan_ExitCriticalSection();
266 
267  return reverted;
268 }
269 
270 #undef _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
271 
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
The file with helper macros for managing objects.
uint32_t oC_ObjectControl_t
stores object control value
Definition: oc_object.h:141
The file with interface for interrupt manager.
static bool RevertFunction(oC_Thread_t Thread, void *Mutex, uint32_t Parameter)
called to revert changes made by the thread
Definition: oc_mutex.c:252
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
The file with interface for mutex managing.
Definition of the null pointer.
static const oC_Allocator_t Allocator
Definition: oc_eth.c:152
The file with interface for Thread Manager.
#define NULL
pointer to a zero
Definition: oc_null.h:37