626 lines
26 KiB
C
626 lines
26 KiB
C
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||
|
/* */
|
||
|
/* This software is licensed under the Microsoft Software License */
|
||
|
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||
|
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||
|
/* and in the root directory of this software. */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/**************************************************************************/
|
||
|
/** */
|
||
|
/** ThreadX Component */
|
||
|
/** */
|
||
|
/** Event Flags */
|
||
|
/** */
|
||
|
/**************************************************************************/
|
||
|
/**************************************************************************/
|
||
|
|
||
|
#define TX_SOURCE_CODE
|
||
|
|
||
|
|
||
|
/* Include necessary system files. */
|
||
|
|
||
|
#include "tx_api.h"
|
||
|
#include "tx_trace.h"
|
||
|
#include "tx_thread.h"
|
||
|
#include "tx_event_flags.h"
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* FUNCTION RELEASE */
|
||
|
/* */
|
||
|
/* _tx_event_flags_set PORTABLE C */
|
||
|
/* 6.1.11 */
|
||
|
/* AUTHOR */
|
||
|
/* */
|
||
|
/* William E. Lamie, Microsoft Corporation */
|
||
|
/* */
|
||
|
/* DESCRIPTION */
|
||
|
/* */
|
||
|
/* This function sets the specified flags in the event group based on */
|
||
|
/* the set option specified. All threads suspended on the group whose */
|
||
|
/* get request can now be satisfied are resumed. */
|
||
|
/* */
|
||
|
/* INPUT */
|
||
|
/* */
|
||
|
/* group_ptr Pointer to group control block */
|
||
|
/* flags_to_set Event flags to set */
|
||
|
/* set_option Specified either AND or OR */
|
||
|
/* operation on the event flags */
|
||
|
/* */
|
||
|
/* OUTPUT */
|
||
|
/* */
|
||
|
/* TX_SUCCESS Always returns success */
|
||
|
/* */
|
||
|
/* CALLS */
|
||
|
/* */
|
||
|
/* _tx_thread_system_preempt_check Check for preemption */
|
||
|
/* _tx_thread_system_resume Resume thread service */
|
||
|
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||
|
/* */
|
||
|
/* CALLED BY */
|
||
|
/* */
|
||
|
/* Application Code */
|
||
|
/* */
|
||
|
/* RELEASE HISTORY */
|
||
|
/* */
|
||
|
/* DATE NAME DESCRIPTION */
|
||
|
/* */
|
||
|
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
||
|
/* resulting in version 6.1 */
|
||
|
/* 04-25-2022 William E. Lamie Modified comment(s), and */
|
||
|
/* added corrected preemption */
|
||
|
/* check logic, resulting in */
|
||
|
/* version 6.1.11 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
UINT _tx_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option)
|
||
|
{
|
||
|
|
||
|
TX_INTERRUPT_SAVE_AREA
|
||
|
|
||
|
TX_THREAD *thread_ptr;
|
||
|
TX_THREAD *next_thread_ptr;
|
||
|
TX_THREAD *next_thread;
|
||
|
TX_THREAD *previous_thread;
|
||
|
TX_THREAD *satisfied_list;
|
||
|
TX_THREAD *last_satisfied;
|
||
|
TX_THREAD *suspended_list;
|
||
|
UINT suspended_count;
|
||
|
ULONG current_event_flags;
|
||
|
ULONG requested_flags;
|
||
|
ULONG flags_satisfied;
|
||
|
ULONG *suspend_info_ptr;
|
||
|
UINT and_request;
|
||
|
UINT get_option;
|
||
|
UINT clear_request;
|
||
|
UINT preempt_check;
|
||
|
#ifndef TX_NOT_INTERRUPTABLE
|
||
|
UINT interrupted_set_request;
|
||
|
#endif
|
||
|
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||
|
VOID (*events_set_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *notify_group_ptr);
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/* Disable interrupts to remove the semaphore from the created list. */
|
||
|
TX_DISABLE
|
||
|
|
||
|
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||
|
|
||
|
/* Increment the total event flags set counter. */
|
||
|
_tx_event_flags_performance_set_count++;
|
||
|
|
||
|
/* Increment the number of event flags sets on this semaphore. */
|
||
|
group_ptr -> tx_event_flags_group_performance_set_count++;
|
||
|
#endif
|
||
|
|
||
|
/* If trace is enabled, insert this event into the trace buffer. */
|
||
|
TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_SET, group_ptr, flags_to_set, set_option, group_ptr -> tx_event_flags_group_suspended_count, TX_TRACE_EVENT_FLAGS_EVENTS)
|
||
|
|
||
|
/* Log this kernel call. */
|
||
|
TX_EL_EVENT_FLAGS_SET_INSERT
|
||
|
|
||
|
/* Determine how to set this group's event flags. */
|
||
|
if ((set_option & TX_EVENT_FLAGS_AND_MASK) == TX_AND)
|
||
|
{
|
||
|
|
||
|
#ifndef TX_NOT_INTERRUPTABLE
|
||
|
|
||
|
/* Set interrupted set request flag to false. */
|
||
|
interrupted_set_request = TX_FALSE;
|
||
|
|
||
|
/* Determine if the suspension list is being processed by an interrupted
|
||
|
set request. */
|
||
|
if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
|
||
|
{
|
||
|
|
||
|
if (group_ptr -> tx_event_flags_group_suspension_list == TX_NULL)
|
||
|
{
|
||
|
|
||
|
/* Set the interrupted set request flag. */
|
||
|
interrupted_set_request = TX_TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Was a set request interrupted? */
|
||
|
if (interrupted_set_request == TX_TRUE)
|
||
|
{
|
||
|
|
||
|
/* A previous set operation was interrupted, we need to defer the
|
||
|
event clearing until the set operation is complete. */
|
||
|
|
||
|
/* Remember the events to clear. */
|
||
|
group_ptr -> tx_event_flags_group_delayed_clear =
|
||
|
group_ptr -> tx_event_flags_group_delayed_clear | ~flags_to_set;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#endif
|
||
|
|
||
|
/* Previous set operation was not interrupted, simply clear the
|
||
|
specified flags by "ANDing" the flags into the current events
|
||
|
of the group. */
|
||
|
group_ptr -> tx_event_flags_group_current =
|
||
|
group_ptr -> tx_event_flags_group_current & flags_to_set;
|
||
|
|
||
|
#ifndef TX_NOT_INTERRUPTABLE
|
||
|
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Restore interrupts. */
|
||
|
TX_RESTORE
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||
|
|
||
|
/* Pickup the notify callback routine for this event flag group. */
|
||
|
events_set_notify = group_ptr -> tx_event_flags_group_set_notify;
|
||
|
#endif
|
||
|
|
||
|
/* "OR" the flags into the current events of the group. */
|
||
|
group_ptr -> tx_event_flags_group_current =
|
||
|
group_ptr -> tx_event_flags_group_current | flags_to_set;
|
||
|
|
||
|
#ifndef TX_NOT_INTERRUPTABLE
|
||
|
|
||
|
/* Determine if there are any delayed flags to clear. */
|
||
|
if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0))
|
||
|
{
|
||
|
|
||
|
/* Yes, we need to neutralize the delayed clearing as well. */
|
||
|
group_ptr -> tx_event_flags_group_delayed_clear =
|
||
|
group_ptr -> tx_event_flags_group_delayed_clear & ~flags_to_set;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Clear the preempt check flag. */
|
||
|
preempt_check = TX_FALSE;
|
||
|
|
||
|
/* Pickup the thread suspended count. */
|
||
|
suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
|
||
|
|
||
|
/* Determine if there are any threads suspended on the event flag group. */
|
||
|
if (group_ptr -> tx_event_flags_group_suspension_list != TX_NULL)
|
||
|
{
|
||
|
|
||
|
/* Determine if there is just a single thread waiting on the event
|
||
|
flag group. */
|
||
|
if (suspended_count == ((UINT) 1))
|
||
|
{
|
||
|
|
||
|
/* Single thread waiting for event flags. Bypass the multiple thread
|
||
|
logic. */
|
||
|
|
||
|
/* Setup thread pointer. */
|
||
|
thread_ptr = group_ptr -> tx_event_flags_group_suspension_list;
|
||
|
|
||
|
/* Pickup the current event flags. */
|
||
|
current_event_flags = group_ptr -> tx_event_flags_group_current;
|
||
|
|
||
|
/* Pickup the suspend information. */
|
||
|
requested_flags = thread_ptr -> tx_thread_suspend_info;
|
||
|
|
||
|
/* Pickup the suspend option. */
|
||
|
get_option = thread_ptr -> tx_thread_suspend_option;
|
||
|
|
||
|
/* Isolate the AND selection. */
|
||
|
and_request = (get_option & TX_AND);
|
||
|
|
||
|
/* Check for AND condition. All flags must be present to satisfy request. */
|
||
|
if (and_request == TX_AND)
|
||
|
{
|
||
|
|
||
|
/* AND request is present. */
|
||
|
|
||
|
/* Calculate the flags present. */
|
||
|
flags_satisfied = (current_event_flags & requested_flags);
|
||
|
|
||
|
/* Determine if they satisfy the AND request. */
|
||
|
if (flags_satisfied != requested_flags)
|
||
|
{
|
||
|
|
||
|
/* No, not all the requested flags are present. Clear the flags present variable. */
|
||
|
flags_satisfied = ((ULONG) 0);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
/* OR request is present. Simply or the requested flags and the current flags. */
|
||
|
flags_satisfied = (current_event_flags & requested_flags);
|
||
|
}
|
||
|
|
||
|
/* Determine if the request is satisfied. */
|
||
|
if (flags_satisfied != ((ULONG) 0))
|
||
|
{
|
||
|
|
||
|
/* Yes, resume the thread and apply any event flag
|
||
|
clearing. */
|
||
|
|
||
|
/* Return the actual event flags that satisfied the request. */
|
||
|
suspend_info_ptr = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
|
||
|
*suspend_info_ptr = current_event_flags;
|
||
|
|
||
|
/* Pickup the clear bit. */
|
||
|
clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
|
||
|
|
||
|
/* Determine whether or not clearing needs to take place. */
|
||
|
if (clear_request == TX_TRUE)
|
||
|
{
|
||
|
|
||
|
/* Yes, clear the flags that satisfied this request. */
|
||
|
group_ptr -> tx_event_flags_group_current = group_ptr -> tx_event_flags_group_current & (~requested_flags);
|
||
|
}
|
||
|
|
||
|
/* Clear the suspension information in the event flag group. */
|
||
|
group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
|
||
|
group_ptr -> tx_event_flags_group_suspended_count = TX_NO_SUSPENSIONS;
|
||
|
|
||
|
/* Clear cleanup routine to avoid timeout. */
|
||
|
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||
|
|
||
|
/* Put return status into the thread control block. */
|
||
|
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||
|
|
||
|
#ifdef TX_NOT_INTERRUPTABLE
|
||
|
|
||
|
/* Resume the thread! */
|
||
|
_tx_thread_system_ni_resume(thread_ptr);
|
||
|
#else
|
||
|
|
||
|
/* Temporarily disable preemption. */
|
||
|
_tx_thread_preempt_disable++;
|
||
|
|
||
|
/* Restore interrupts. */
|
||
|
TX_RESTORE
|
||
|
|
||
|
/* Resume thread. */
|
||
|
_tx_thread_system_resume(thread_ptr);
|
||
|
|
||
|
/* Disable interrupts to remove the semaphore from the created list. */
|
||
|
TX_DISABLE
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
/* Otherwise, the event flag requests of multiple threads must be
|
||
|
examined. */
|
||
|
|
||
|
/* Setup thread pointer, keep a local copy of the head pointer. */
|
||
|
suspended_list = group_ptr -> tx_event_flags_group_suspension_list;
|
||
|
thread_ptr = suspended_list;
|
||
|
|
||
|
/* Clear the suspended list head pointer to thwart manipulation of
|
||
|
the list in ISR's while we are processing here. */
|
||
|
group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
|
||
|
|
||
|
/* Setup the satisfied thread pointers. */
|
||
|
satisfied_list = TX_NULL;
|
||
|
last_satisfied = TX_NULL;
|
||
|
|
||
|
/* Pickup the current event flags. */
|
||
|
current_event_flags = group_ptr -> tx_event_flags_group_current;
|
||
|
|
||
|
/* Disable preemption while we process the suspended list. */
|
||
|
_tx_thread_preempt_disable++;
|
||
|
|
||
|
/* Since we have temporarily disabled preemption globally, set the preempt
|
||
|
check flag to check for any preemption condition - including from
|
||
|
unrelated ISR processing. */
|
||
|
preempt_check = TX_TRUE;
|
||
|
|
||
|
/* Loop to examine all of the suspended threads. */
|
||
|
do
|
||
|
{
|
||
|
|
||
|
#ifndef TX_NOT_INTERRUPTABLE
|
||
|
|
||
|
/* Restore interrupts temporarily. */
|
||
|
TX_RESTORE
|
||
|
|
||
|
/* Disable interrupts again. */
|
||
|
TX_DISABLE
|
||
|
#endif
|
||
|
|
||
|
/* Determine if we need to reset the search. */
|
||
|
if (group_ptr -> tx_event_flags_group_reset_search != TX_FALSE)
|
||
|
{
|
||
|
|
||
|
/* Clear the reset search flag. */
|
||
|
group_ptr -> tx_event_flags_group_reset_search = TX_FALSE;
|
||
|
|
||
|
/* Move the thread pointer to the beginning of the search list. */
|
||
|
thread_ptr = suspended_list;
|
||
|
|
||
|
/* Reset the suspended count. */
|
||
|
suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
|
||
|
|
||
|
/* Update the current events with any new ones that might
|
||
|
have been set in a nested set events call from an ISR. */
|
||
|
current_event_flags = current_event_flags | group_ptr -> tx_event_flags_group_current;
|
||
|
}
|
||
|
|
||
|
/* Save next thread pointer. */
|
||
|
next_thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||
|
|
||
|
/* Pickup the suspend information. */
|
||
|
requested_flags = thread_ptr -> tx_thread_suspend_info;
|
||
|
|
||
|
/* Pickup this thread's suspension get option. */
|
||
|
get_option = thread_ptr -> tx_thread_suspend_option;
|
||
|
|
||
|
/* Isolate the AND selection. */
|
||
|
and_request = (get_option & TX_AND);
|
||
|
|
||
|
/* Check for AND condition. All flags must be present to satisfy request. */
|
||
|
if (and_request == TX_AND)
|
||
|
{
|
||
|
|
||
|
/* AND request is present. */
|
||
|
|
||
|
/* Calculate the flags present. */
|
||
|
flags_satisfied = (current_event_flags & requested_flags);
|
||
|
|
||
|
/* Determine if they satisfy the AND request. */
|
||
|
if (flags_satisfied != requested_flags)
|
||
|
{
|
||
|
|
||
|
/* No, not all the requested flags are present. Clear the flags present variable. */
|
||
|
flags_satisfied = ((ULONG) 0);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
/* OR request is present. Simply or the requested flags and the current flags. */
|
||
|
flags_satisfied = (current_event_flags & requested_flags);
|
||
|
}
|
||
|
|
||
|
/* Check to see if the thread had a timeout or wait abort during the event search processing.
|
||
|
If so, just set the flags satisfied to ensure the processing here removes the thread from
|
||
|
the suspension list. */
|
||
|
if (thread_ptr -> tx_thread_state != TX_EVENT_FLAG)
|
||
|
{
|
||
|
|
||
|
/* Simply set the satisfied flags to 1 in order to remove the thread from the suspension list. */
|
||
|
flags_satisfied = ((ULONG) 1);
|
||
|
}
|
||
|
|
||
|
/* Determine if the request is satisfied. */
|
||
|
if (flags_satisfied != ((ULONG) 0))
|
||
|
{
|
||
|
|
||
|
/* Yes, this request can be handled now. */
|
||
|
|
||
|
/* Determine if the thread is still suspended on the event flag group. If not, a wait
|
||
|
abort must have been done from an ISR. */
|
||
|
if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG)
|
||
|
{
|
||
|
|
||
|
/* Return the actual event flags that satisfied the request. */
|
||
|
suspend_info_ptr = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
|
||
|
*suspend_info_ptr = current_event_flags;
|
||
|
|
||
|
/* Pickup the clear bit. */
|
||
|
clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
|
||
|
|
||
|
/* Determine whether or not clearing needs to take place. */
|
||
|
if (clear_request == TX_TRUE)
|
||
|
{
|
||
|
|
||
|
/* Yes, clear the flags that satisfied this request. */
|
||
|
group_ptr -> tx_event_flags_group_current = group_ptr -> tx_event_flags_group_current & ~requested_flags;
|
||
|
}
|
||
|
|
||
|
/* Prepare for resumption of the first thread. */
|
||
|
|
||
|
/* Clear cleanup routine to avoid timeout. */
|
||
|
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||
|
|
||
|
/* Put return status into the thread control block. */
|
||
|
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/* We need to remove the thread from the suspension list and place it in the
|
||
|
expired list. */
|
||
|
|
||
|
/* See if this is the only suspended thread on the list. */
|
||
|
if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
|
||
|
{
|
||
|
|
||
|
/* Yes, the only suspended thread. */
|
||
|
|
||
|
/* Update the head pointer. */
|
||
|
suspended_list = TX_NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
/* At least one more thread is on the same expiration list. */
|
||
|
|
||
|
/* Update the links of the adjacent threads. */
|
||
|
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||
|
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||
|
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||
|
previous_thread -> tx_thread_suspended_next = next_thread;
|
||
|
|
||
|
/* Update the list head pointer, if removing the head of the
|
||
|
list. */
|
||
|
if (suspended_list == thread_ptr)
|
||
|
{
|
||
|
|
||
|
/* Yes, head pointer needs to be updated. */
|
||
|
suspended_list = thread_ptr -> tx_thread_suspended_next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Decrement the suspension count. */
|
||
|
group_ptr -> tx_event_flags_group_suspended_count--;
|
||
|
|
||
|
/* Place this thread on the expired list. */
|
||
|
if (satisfied_list == TX_NULL)
|
||
|
{
|
||
|
|
||
|
/* First thread on the satisfied list. */
|
||
|
satisfied_list = thread_ptr;
|
||
|
last_satisfied = thread_ptr;
|
||
|
|
||
|
/* Setup initial next pointer. */
|
||
|
thread_ptr -> tx_thread_suspended_next = TX_NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
/* Not the first thread on the satisfied list. */
|
||
|
|
||
|
/* Link it up at the end. */
|
||
|
last_satisfied -> tx_thread_suspended_next = thread_ptr;
|
||
|
thread_ptr -> tx_thread_suspended_next = TX_NULL;
|
||
|
last_satisfied = thread_ptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Copy next thread pointer to working thread ptr. */
|
||
|
thread_ptr = next_thread_ptr;
|
||
|
|
||
|
/* Decrement the suspension count. */
|
||
|
suspended_count--;
|
||
|
|
||
|
} while (suspended_count != TX_NO_SUSPENSIONS);
|
||
|
|
||
|
/* Setup the group's suspension list head again. */
|
||
|
group_ptr -> tx_event_flags_group_suspension_list = suspended_list;
|
||
|
|
||
|
#ifndef TX_NOT_INTERRUPTABLE
|
||
|
|
||
|
/* Determine if there is any delayed event clearing to perform. */
|
||
|
if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0))
|
||
|
{
|
||
|
|
||
|
/* Perform the delayed event clearing. */
|
||
|
group_ptr -> tx_event_flags_group_current =
|
||
|
group_ptr -> tx_event_flags_group_current & ~(group_ptr -> tx_event_flags_group_delayed_clear);
|
||
|
|
||
|
/* Clear the delayed event flag clear value. */
|
||
|
group_ptr -> tx_event_flags_group_delayed_clear = ((ULONG) 0);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Restore interrupts. */
|
||
|
TX_RESTORE
|
||
|
|
||
|
/* Walk through the satisfied list, setup initial thread pointer. */
|
||
|
thread_ptr = satisfied_list;
|
||
|
while(thread_ptr != TX_NULL)
|
||
|
{
|
||
|
|
||
|
/* Get next pointer first. */
|
||
|
next_thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||
|
|
||
|
/* Disable interrupts. */
|
||
|
TX_DISABLE
|
||
|
|
||
|
#ifdef TX_NOT_INTERRUPTABLE
|
||
|
|
||
|
/* Resume the thread! */
|
||
|
_tx_thread_system_ni_resume(thread_ptr);
|
||
|
|
||
|
/* Restore interrupts. */
|
||
|
TX_RESTORE
|
||
|
#else
|
||
|
|
||
|
/* Disable preemption again. */
|
||
|
_tx_thread_preempt_disable++;
|
||
|
|
||
|
/* Restore interrupt posture. */
|
||
|
TX_RESTORE
|
||
|
|
||
|
/* Resume the thread. */
|
||
|
_tx_thread_system_resume(thread_ptr);
|
||
|
#endif
|
||
|
|
||
|
/* Move next thread to current. */
|
||
|
thread_ptr = next_thread_ptr;
|
||
|
}
|
||
|
|
||
|
/* Disable interrupts. */
|
||
|
TX_DISABLE
|
||
|
|
||
|
/* Release thread preemption disable. */
|
||
|
_tx_thread_preempt_disable--;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
/* Determine if we need to set the reset search field. */
|
||
|
if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
|
||
|
{
|
||
|
|
||
|
/* We interrupted a search of an event flag group suspension
|
||
|
list. Make sure we reset the search. */
|
||
|
group_ptr -> tx_event_flags_group_reset_search = TX_TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Restore interrupts. */
|
||
|
TX_RESTORE
|
||
|
|
||
|
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||
|
|
||
|
/* Determine if a notify callback is required. */
|
||
|
if (events_set_notify != TX_NULL)
|
||
|
{
|
||
|
|
||
|
/* Call application event flags set notification. */
|
||
|
(events_set_notify)(group_ptr);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Determine if a check for preemption is necessary. */
|
||
|
if (preempt_check == TX_TRUE)
|
||
|
{
|
||
|
|
||
|
/* Yes, one or more threads were resumed, check for preemption. */
|
||
|
_tx_thread_system_preempt_check();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Return completion status. */
|
||
|
return(TX_SUCCESS);
|
||
|
}
|
||
|
|