📄 os_mutex.lst
字号:
140 * attempts to obtain the semaphore then the priority of the task owning the
141 * semaphore is raised to this priority. It is assumed that you will specify
142 * a priority that is LOWER in value than ANY of the tasks competing for the
143 * mutex.
144 *
145 * perr is a pointer to an error code which will be returned to your application:
146 * OS_ERR_NONE if the call was successful.
147 * OS_ERR_CREATE_ISR if you attempted to create a MUTEX from an ISR
148 * OS_ERR_PRIO_EXIST if a task at the priority inheritance priority
149 * already exist.
150 * OS_ERR_PEVENT_NULL No more event control blocks available.
151 * OS_ERR_PRIO_INVALID if the priority you specify is higher that the
152 * maximum allowed (i.e. > OS_LOWEST_PRIO)
153 *
154 * Returns : != (void *)0 is a pointer to the event control clock (OS_EVENT) associated with the
155 * created mutex.
156 * == (void *)0 if an error is detected.
157 *
158 * Note(s) : 1) The LEAST significant 8 bits of '.OSEventCnt' are used to hold the priority number
159 * of the task owning the mutex or 0xFF if no task owns the mutex.
160 *
161 * 2) The MOST significant 8 bits of '.OSEventCnt' are used to hold the priority number
162 * to use to reduce priority inversion.
163 *********************************************************************************************************
164 */
165
166 OS_EVENT *OSMutexCreate (INT8U prio, INT8U *perr)
167 {
168 OS_EVENT *pevent;
169 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
170 OS_CPU_SR cpu_sr = 0;
171 #endif
172
173
174
175 #if OS_ARG_CHK_EN > 0
176 if (perr == (INT8U *)0) { /* Validate 'perr' */
177 return ((OS_EVENT *)0);
178 }
179 if (prio >= OS_LOWEST_PRIO) { /* Validate PIP */
180 *perr = OS_ERR_PRIO_INVALID;
181 return ((OS_EVENT *)0);
182 }
183 #endif
184 if (OSIntNesting > 0) { /* See if called from ISR ... */
185 *perr = OS_ERR_CREATE_ISR; /* ... can't CREATE mutex from an ISR */
186 return ((OS_EVENT *)0);
187 }
188 OS_ENTER_CRITICAL();
189 if (OSTCBPrioTbl[prio] != (OS_TCB *)0) { /* Mutex priority must not already exist */
190 OS_EXIT_CRITICAL(); /* Task already exist at priority ... */
191 *perr = OS_ERR_PRIO_EXIST; /* ... inheritance priority */
192 return ((OS_EVENT *)0);
193 }
194 OSTCBPrioTbl[prio] = OS_TCB_RESERVED; /* Reserve the table entry */
195 pevent = OSEventFreeList; /* Get next free event control block */
196 if (pevent == (OS_EVENT *)0) { /* See if an ECB was available */
197 OSTCBPrioTbl[prio] = (OS_TCB *)0; /* No, Release the table entry */
198 OS_EXIT_CRITICAL();
199 *perr = OS_ERR_PEVENT_NULL; /* No more event control blocks */
200 return (pevent);
201 }
202 OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; /* Adjust the free list */
203 OS_EXIT_CRITICAL();
204 pevent->OSEventType = OS_EVENT_TYPE_MUTEX;
205 pevent->OSEventCnt = (INT16U)((INT16U)prio << 8) | OS_MUTEX_AVAILABLE; /* Resource is avail. */
206 pevent->OSEventPtr = (void *)0; /* No task owning the mutex */
207 #if OS_EVENT_NAME_SIZE > 1
208 pevent->OSEventName[0] = '?';
209 pevent->OSEventName[1] = OS_ASCII_NUL;
210 #endif
211 OS_EventWaitListInit(pevent);
212 *perr = OS_ERR_NONE;
213 return (pevent);
214 }
215
216 /*$PAGE*/
217 /*
218 *********************************************************************************************************
219 * DELETE A MUTEX
220 *
221 * Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it.
222 *
223 * Arguments : pevent is a pointer to the event control block associated with the desired mutex.
224 *
225 * opt determines delete options as follows:
226 * opt == OS_DEL_NO_PEND Delete mutex ONLY if no task pending
227 * opt == OS_DEL_ALWAYS Deletes the mutex even if tasks are waiting.
228 * In this case, all the tasks pending will be readied.
229 *
230 * perr is a pointer to an error code that can contain one of the following values:
231 * OS_ERR_NONE The call was successful and the mutex was deleted
232 * OS_ERR_DEL_ISR If you attempted to delete the MUTEX from an ISR
233 * OS_ERR_INVALID_OPT An invalid option was specified
234 * OS_ERR_TASK_WAITING One or more tasks were waiting on the mutex
235 * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex
236 * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
237 *
238 * Returns : pevent upon error
239 * (OS_EVENT *)0 if the mutex was successfully deleted.
240 *
241 * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
242 * the mutex MUST check the return code of OSMutexPend().
243 *
244 * 2) This call can potentially disable interrupts for a long time. The interrupt disable
245 * time is directly proportional to the number of tasks waiting on the mutex.
246 *
247 * 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the
248 * resource(s) will no longer be guarded by the mutex.
249 *
250 * 4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that the owner of the Mutex (if there
251 * is one) is ready-to-run and is thus NOT pending on another kernel object or
252 * has delayed itself. In other words, if a task owns the mutex being deleted,
253 * that task will be made ready-to-run at its original priority.
254 *********************************************************************************************************
255 */
256
257 #if OS_MUTEX_DEL_EN
258 OS_EVENT *OSMutexDel (OS_EVENT *pevent, INT8U opt, INT8U *perr)
259 {
260 BOOLEAN tasks_waiting;
261 OS_EVENT *pevent_return;
262 INT8U pip; /* Priority inheritance priority */
263 INT8U prio;
264 OS_TCB *ptcb;
265 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
266 OS_CPU_SR cpu_sr = 0;
267 #endif
268
269
270
271 #if OS_ARG_CHK_EN > 0
272 if (perr == (INT8U *)0) { /* Validate 'perr' */
273 return (pevent);
274 }
275 if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
276 *perr = OS_ERR_PEVENT_NULL;
277 return (pevent);
278 }
279 #endif
280 if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
281 *perr = OS_ERR_EVENT_TYPE;
282 return (pevent);
283 }
284 if (OSIntNesting > 0) { /* See if called from ISR ... */
285 *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
286 return (pevent);
287 }
288 OS_ENTER_CRITICAL();
289 if (pevent->OSEventGrp != 0) { /* See if any tasks waiting on mutex */
290 tasks_waiting = OS_TRUE; /* Yes */
291 } else {
292 tasks_waiting = OS_FALSE; /* No */
293 }
294 switch (opt) {
295 case OS_DEL_NO_PEND: /* DELETE MUTEX ONLY IF NO TASK WAITING --- */
296 if (tasks_waiting == OS_FALSE) {
297 #if OS_EVENT_NAME_SIZE > 1
298 pevent->OSEventName[0] = '?'; /* Unknown name */
299 pevent->OSEventName[1] = OS_ASCII_NUL;
300 #endif
301 pip = (INT8U)(pevent->OSEventCnt >> 8);
302 OSTCBPrioTbl[pip] = (OS_TCB *)0; /* Free up the PIP */
303 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
304 pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
305 pevent->OSEventCnt = 0;
306 OSEventFreeList = pevent;
307 OS_EXIT_CRITICAL();
308 *perr = OS_ERR_NONE;
309 pevent_return = (OS_EVENT *)0; /* Mutex has been deleted */
310 } else {
311 OS_EXIT_CRITICAL();
312 *perr = OS_ERR_TASK_WAITING;
313 pevent_return = pevent;
314 }
315 break;
316
317 case OS_DEL_ALWAYS: /* ALWAYS DELETE THE MUTEX ---------------- */
318 pip = (INT8U)(pevent->OSEventCnt >> 8); /* Get PIP of mutex */
319 prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's original prio */
320 ptcb = (OS_TCB *)pevent->OSEventPtr;
321 if (ptcb != (OS_TCB *)0) { /* See if any task owns the mutex */
322 if (ptcb->OSTCBPrio == pip) { /* See if original prio was changed */
323 OSMutex_RdyAtPrio(ptcb, prio); /* Yes, Restore the task's original prio */
324 }
325 }
326 while (pevent->OSEventGrp != 0) { /* Ready ALL tasks waiting for mutex */
327 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK);
328 }
329 #if OS_EVENT_NAME_SIZE > 1
330 pevent->OSEventName[0] = '?'; /* Unknown name */
331 pevent->OSEventName[1] = OS_ASCII_NUL;
332 #endif
333 pip = (INT8U)(pevent->OSEventCnt >> 8);
334 OSTCBPrioTbl[pip] = (OS_TCB *)0; /* Free up the PIP */
335 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
336 pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -