📄 smc.c
字号:
suspend_ptr -> sm_semaphore = semaphore;
suspend_ptr -> sm_suspend_link.cs_next = NU_NULL;
suspend_ptr -> sm_suspend_link.cs_previous = NU_NULL;
task = (TC_TCB *) TCT_Current_Thread();
suspend_ptr -> sm_suspended_task = task;
/* Determine if priority or FIFO suspension is associated with the
semaphore. */
if (semaphore -> sm_fifo_suspend)
{
/* FIFO suspension is required. Link the suspend block into
the list of suspended tasks on this semaphore. */
CSC_Place_On_List((CS_NODE **)
&(semaphore -> sm_suspension_list),
&(suspend_ptr -> sm_suspend_link));
}
else
{
/* Get the priority of the current thread so the suspend block
can be placed in the appropriate place. */
suspend_ptr -> sm_suspend_link.cs_priority =
TCC_Task_Priority(task);
CSC_Priority_Place_On_List((CS_NODE **)
&(semaphore -> sm_suspension_list),
&(suspend_ptr -> sm_suspend_link));
}
/* Finally, suspend the calling task. Note that the suspension call
automatically clears the protection on the semaphore. */
TCC_Suspend_Task((NU_TASK *) task, NU_SEMAPHORE_SUSPEND,
SMC_Cleanup, suspend_ptr, suspend);
/* Pickup the return status. */
status = suspend_ptr -> sm_return_status;
}
else
/* No suspension requested. Simply return an error status. */
status = NU_UNAVAILABLE;
}
/* Release protection against access to the semaphore. */
TCT_Unprotect();
/* Return the completion status. */
return(status);
}
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* SMC_Release_Semaphore */
/* */
/* DESCRIPTION */
/* */
/* This function releases a previously obtained semaphore. If one */
/* or more tasks are waiting, the first task is given the released */
/* instance of the semaphore. Otherwise, the semaphore instance */
/* counter is simply incremented. */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Accelerated Technology, Inc. */
/* */
/* CALLED BY */
/* */
/* Application */
/* SMCE_Release_Semaphore Error checking shell */
/* */
/* CALLS */
/* */
/* CSC_Remove_From_List Remove from suspend list */
/* [HIC_Make_History_Entry] Make entry in history log */
/* TCC_Resume_Task Resume a suspended task */
/* [TCT_Check_Stack] Stack checking function */
/* TCT_Control_To_System Transfer control to system */
/* TCT_System_Protect Protect semaphore */
/* TCT_Unprotect Release protection */
/* */
/* INPUTS */
/* */
/* semaphore_ptr Semaphore control block ptr */
/* */
/* OUTPUTS */
/* */
/* NU_SUCCESS */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* W. Lamie 03-01-1993 Created initial version 1.0 */
/* D. Lamie 04-19-1993 Verified version 1.0 */
/* W. Lamie 03-01-1994 Changed function interfaces to */
/* match those in prototype, */
/* added register options, changed*/
/* protection logic to reduce */
/* overhead, resulting in */
/* version 1.1 */
/* R. Pfaff - */
/* D. Lamie 03-18-1994 Verified version 1.1 */
/* */
/*************************************************************************/
STATUS SMC_Release_Semaphore(NU_SEMAPHORE *semaphore_ptr)
{
R1 SM_SCB *semaphore; /* Semaphore control blk ptr */
R2 SM_SUSPEND *suspend_ptr; /* Pointer to suspend block */
STATUS preempt; /* Preemption flag */
STATUS status; /* Completion status */
/* Move input semaphore pointer into internal pointer. */
semaphore = (SM_SCB *) semaphore_ptr;
#ifdef NU_ENABLE_STACK_CHECK
/* Call stack checking function to check for an overflow condition. */
TCT_Check_Stack();
#endif
#ifdef NU_ENABLE_HISTORY
/* Make an entry that corresponds to this function in the system history
log. */
HIC_Make_History_Entry(NU_RELEASE_SEMAPHORE_ID, (UNSIGNED) semaphore,
(UNSIGNED) 0, (UNSIGNED) 0);
#endif
/* Initialize the status as successful. */
status = NU_SUCCESS;
/* Protect against simultaneous access to the semaphore. */
TCT_System_Protect();
/* Determine if another task is waiting on the semaphore. */
if (semaphore -> sm_tasks_waiting)
{
/* Yes, another task is waiting for an instance of the semaphore. */
/* Decrement the number of tasks waiting counter. */
semaphore -> sm_tasks_waiting--;
/* Remove the first suspended block from the list. */
suspend_ptr = semaphore -> sm_suspension_list;
CSC_Remove_From_List((CS_NODE **) &(semaphore -> sm_suspension_list),
&(suspend_ptr -> sm_suspend_link));
/* Setup the appropriate return value. */
suspend_ptr -> sm_return_status = NU_SUCCESS;
/* Resume the suspended task. */
preempt =
TCC_Resume_Task((NU_TASK *) suspend_ptr -> sm_suspended_task,
NU_SEMAPHORE_SUSPEND);
/* Determine if a preempt condition is present. */
if (preempt)
/* Transfer control to the system if the resumed task function
detects a preemption condition. */
TCT_Control_To_System();
}
else
/* Increment the semaphore instance counter. */
semaphore -> sm_semaphore_count++;
/* Release protection against access to the semaphore. */
TCT_Unprotect();
/* Return the completion status. */
return(status);
}
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* SMC_Cleanup */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for removing a suspension block */
/* from a semaphore. It is not called unless a timeout or a task */
/* terminate is in progress. Note that protection is already in */
/* effect - the same protection at suspension time. */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Accelerated Technology, Inc. */
/* */
/* CALLED BY */
/* */
/* TCC_Timeout Task timeout */
/* TCC_Terminate Task terminate */
/* */
/* CALLS */
/* */
/* CSC_Remove_From_List Remove suspend block from */
/* the suspension list */
/* */
/* INPUTS */
/* */
/* information Pointer to suspend block */
/* */
/* OUTPUTS */
/* */
/* None */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* W. Lamie 03-01-1993 Created initial version 1.0 */
/* D. Lamie 04-19-1993 Verified version 1.0 */
/* */
/*************************************************************************/
VOID SMC_Cleanup(VOID *information)
{
SM_SUSPEND *suspend_ptr; /* Suspension block pointer */
/* Use the information pointer as a suspend pointer. */
suspend_ptr = (SM_SUSPEND *) information;
/* By default, indicate that the service timed-out. It really does not
matter if this function is called from a terminate request since
the task does not resume. */
suspend_ptr -> sm_return_status = NU_TIMEOUT;
/* Decrement the number of tasks waiting counter. */
(suspend_ptr -> sm_semaphore) -> sm_tasks_waiting--;
/* Unlink the suspend block from the suspension list. */
CSC_Remove_From_List((CS_NODE **)
&((suspend_ptr -> sm_semaphore) -> sm_suspension_list),
&(suspend_ptr -> sm_suspend_link));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -