📄 os_mutex.lst
字号:
337 pevent->OSEventCnt = 0;
338 OSEventFreeList = pevent; /* Get next free event control block */
339 OS_EXIT_CRITICAL();
340 if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
341 OS_Sched(); /* Find highest priority task ready to run */
342 }
343 *perr = OS_ERR_NONE;
344 pevent_return = (OS_EVENT *)0; /* Mutex has been deleted */
345 break;
346
347 default:
348 OS_EXIT_CRITICAL();
349 *perr = OS_ERR_INVALID_OPT;
350 pevent_return = pevent;
351 break;
352 }
353 return (pevent_return);
354 }
355 #endif
356
357 /*$PAGE*/
358 /*
359 *********************************************************************************************************
360 * PEND ON MUTUAL EXCLUSION SEMAPHORE
361 *
362 * Description: This function waits for a mutual exclusion semaphore.
363 *
364 * Arguments : pevent is a pointer to the event control block associated with the desired
365 * mutex.
366 *
367 * timeout is an optional timeout period (in clock ticks). If non-zero, your task will
368 * wait for the resource up to the amount of time specified by this argument.
369 * If you specify 0, however, your task will wait forever at the specified
370 * mutex or, until the resource becomes available.
371 *
372 * perr is a pointer to where an error message will be deposited. Possible error
373 * messages are:
374 * OS_ERR_NONE The call was successful and your task owns the mutex
375 * OS_ERR_TIMEOUT The mutex was not available within the specified 'timeout'.
376 * OS_ERR_PEND_ABORT The wait on the mutex was aborted.
377 * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex
378 * OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer
379 * OS_ERR_PEND_ISR If you called this function from an ISR and the result
380 * would lead to a suspension.
381 * OS_ERR_PIP_LOWER If the priority of the task that owns the Mutex is
382 * HIGHER (i.e. a lower number) than the PIP. This error
383 * indicates that you did not set the PIP higher (lower
384 * number) than ALL the tasks that compete for the Mutex.
385 * Unfortunately, this is something that could not be
386 * detected when the Mutex is created because we don't know
387 * what tasks will be using the Mutex.
388 * OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
389 *
390 * Returns : none
391 *
392 * Note(s) : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex.
393 *
394 * 2) You MUST NOT change the priority of the task that owns the mutex
395 *********************************************************************************************************
396 */
397
398 void OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr)
399 {
400 INT8U pip; /* Priority Inheritance Priority (PIP) */
401 INT8U mprio; /* Mutex owner priority */
402 BOOLEAN rdy; /* Flag indicating task was ready */
403 OS_TCB *ptcb;
404 OS_EVENT *pevent2;
405 INT8U y;
406 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
407 OS_CPU_SR cpu_sr = 0;
408 #endif
409
410
411
412 #if OS_ARG_CHK_EN > 0
413 if (perr == (INT8U *)0) { /* Validate 'perr' */
414 return;
415 }
416 if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
417 *perr = OS_ERR_PEVENT_NULL;
418 return;
419 }
420 #endif
421 if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
422 *perr = OS_ERR_EVENT_TYPE;
423 return;
424 }
425 if (OSIntNesting > 0) { /* See if called from ISR ... */
426 *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
427 return;
428 }
429 if (OSLockNesting > 0) { /* See if called with scheduler locked ... */
430 *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
431 return;
432 }
433 /*$PAGE*/
434 OS_ENTER_CRITICAL();
435 pip = (INT8U)(pevent->OSEventCnt >> 8); /* Get PIP from mutex */
436 /* Is Mutex available? */
437 if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
438 pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Yes, Acquire the resource */
439 pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; /* Save priority of owning task */
440 pevent->OSEventPtr = (void *)OSTCBCur; /* Point to owning task's OS_TCB */
441 if (OSTCBCur->OSTCBPrio <= pip) { /* PIP 'must' have a SMALLER prio ... */
442 OS_EXIT_CRITICAL(); /* ... than current task! */
443 *perr = OS_ERR_PIP_LOWER;
444 } else {
445 OS_EXIT_CRITICAL();
446 *perr = OS_ERR_NONE;
447 }
448 return;
449 }
450 mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* No, Get priority of mutex owner */
451 ptcb = (OS_TCB *)(pevent->OSEventPtr); /* Point to TCB of mutex owner */
452 if (ptcb->OSTCBPrio > pip) { /* Need to promote prio of owner?*/
453 if (mprio > OSTCBCur->OSTCBPrio) {
454 y = ptcb->OSTCBY;
455 if ((OSRdyTbl[y] & ptcb->OSTCBBitX) != 0) { /* See if mutex owner is ready */
456 OSRdyTbl[y] &= ~ptcb->OSTCBBitX; /* Yes, Remove owner from Rdy ...*/
457 if (OSRdyTbl[y] == 0) { /* ... list at current prio */
458 OSRdyGrp &= ~ptcb->OSTCBBitY;
459 }
460 rdy = OS_TRUE;
461 } else {
462 pevent2 = ptcb->OSTCBEventPtr;
463 if (pevent2 != (OS_EVENT *)0) { /* Remove from event wait list */
464 if ((pevent2->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {
465 pevent2->OSEventGrp &= ~ptcb->OSTCBBitY;
466 }
467 }
468 rdy = OS_FALSE; /* No */
469 }
470 ptcb->OSTCBPrio = pip; /* Change owner task prio to PIP */
471 #if OS_LOWEST_PRIO <= 63
472 ptcb->OSTCBY = (INT8U)( ptcb->OSTCBPrio >> 3);
473 ptcb->OSTCBX = (INT8U)( ptcb->OSTCBPrio & 0x07);
474 ptcb->OSTCBBitY = (INT8U)(1 << ptcb->OSTCBY);
475 ptcb->OSTCBBitX = (INT8U)(1 << ptcb->OSTCBX);
476 #else
477 ptcb->OSTCBY = (INT8U)((ptcb->OSTCBPrio >> 4) & 0xFF);
478 ptcb->OSTCBX = (INT8U)( ptcb->OSTCBPrio & 0x0F);
479 ptcb->OSTCBBitY = (INT16U)(1 << ptcb->OSTCBY);
480 ptcb->OSTCBBitX = (INT16U)(1 << ptcb->OSTCBX);
481 #endif
482 if (rdy == OS_TRUE) { /* If task was ready at owner's priority ...*/
483 OSRdyGrp |= ptcb->OSTCBBitY; /* ... make it ready at new priority. */
484 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
485 } else {
486 pevent2 = ptcb->OSTCBEventPtr;
487 if (pevent2 != (OS_EVENT *)0) { /* Add to event wait list */
488 pevent2->OSEventGrp |= ptcb->OSTCBBitY;
489 pevent2->OSEventTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
490 }
491 }
492 OSTCBPrioTbl[pip] = ptcb;
493 }
494 }
495 OSTCBCur->OSTCBStat |= OS_STAT_MUTEX; /* Mutex not available, pend current task */
496 OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
497 OSTCBCur->OSTCBDly = timeout; /* Store timeout in current task's TCB */
498 OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
499 OS_EXIT_CRITICAL();
500 OS_Sched(); /* Find next highest priority task ready */
501 OS_ENTER_CRITICAL();
502 switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
503 case OS_STAT_PEND_OK:
504 *perr = OS_ERR_NONE;
505 break;
506
507 case OS_STAT_PEND_ABORT:
508 *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted getting mutex */
509 break;
510
511 case OS_STAT_PEND_TO:
512 default:
513 OS_EventTaskRemove(OSTCBCur, pevent);
514 *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get mutex within TO */
515 break;
516 }
517 OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
518 OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
519 OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
520 #if (OS_EVENT_MULTI_EN > 0)
521 OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
522 #endif
523 OS_EXIT_CRITICAL();
524 }
525 /*$PAGE*/
526 /*
527 *********************************************************************************************************
528 * POST TO A MUTUAL EXCLUSION SEMAPHORE
529 *
530 * Description: This function signals a mutual exclusion semaphore
531 *
532 * Arguments : pevent is a pointer to the event control block associated with the desired
533 * mutex.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -