Split core message queue and watchdog handler objects into separate files.

This commit is contained in:
Joel Sherrill
1999-11-02 21:45:15 +00:00
parent 93b4e6ef7e
commit 82cb78d84c
29 changed files with 1736 additions and 1984 deletions

View File

@@ -22,6 +22,14 @@ INSTALL_CHANGE = @INSTALL_CHANGE@
MP_C_PIECES_yes_V = mpci objectmp threadmp
MP_C_PIECES = $(MP_C_PIECES_$(HAS_MP)_V)
CORE_MESSAGE_QUEUE_C_PIECES= coremsg coremsgbroadcast coremsgclose \
coremsgflush coremsgflushsupp coremsgseize coremsgsubmit
CORE_MUTEX_C_PIECES= coremutex coremutexflush coremutexseize \
coremutexsurrender
CORE_SEMAPHORE_C_PIECES= coresem coresemflush coresemseize coresemsurrender
HEAP_C_PIECES = heap heapallocate heapextend heapfree \
heapsizeofuserarea heapwalk
@@ -48,11 +56,15 @@ THREADQ_C_PIECES= threadq threadqdequeue threadqdequeuefifo \
TOD_C_PIECES= coretod coretodset coretodtickle coretodtoseconds \
coretodvalidate
WATCHDOG_C_PIECES= watchdog watchdogadjust watchdoginsert watchdogremove \
watchdogtickle
# C and C++ source names, if any, go here -- minus the .c or .cc
C_PIECES = apiext chain coremsg coremutex coresem $(HEAP_C_PIECES) interr isr \
C_PIECES = apiext chain $(CORE_MESSAGE_QUEUE_C_PIECES) $(CORE_MUTEX_C_PIECES) \
$(CORE_SEMAPHORE_C_PIECES) $(HEAP_C_PIECES) interr isr \
$(OBJECT_C_PIECES) $(THREAD_C_PIECES) $(THREADQ_C_PIECES) \
$(TOD_C_PIECES) userext \
watchdog wkspace $(MP_C_PIECES)
$(WATCHDOG_C_PIECES) wkspace $(MP_C_PIECES)
C_FILES = $(C_PIECES:%=%.c)
C_O_FILES = $(C_PIECES:%=${ARCH}/%.o)

View File

@@ -107,364 +107,3 @@ boolean _CORE_message_queue_Initialize(
return TRUE;
}
/*PAGE
*
* _CORE_message_queue_Close
*
* This function closes a message by returning all allocated space and
* flushing the message_queue's task wait queue.
*
* Input parameters:
* the_message_queue - the message_queue to be flushed
* remote_extract_callout - function to invoke remotely
* status - status to pass to thread
*
* Output parameters: NONE
*/
void _CORE_message_queue_Close(
CORE_message_queue_Control *the_message_queue,
Thread_queue_Flush_callout remote_extract_callout,
unsigned32 status
)
{
if ( the_message_queue->number_of_pending_messages != 0 )
(void) _CORE_message_queue_Flush_support( the_message_queue );
else
_Thread_queue_Flush(
&the_message_queue->Wait_queue,
remote_extract_callout,
status
);
(void) _Workspace_Free( the_message_queue->message_buffers );
}
/*PAGE
*
* _CORE_message_queue_Flush
*
* This function flushes the message_queue's task wait queue. The number
* of messages flushed from the queue is returned.
*
* Input parameters:
* the_message_queue - the message_queue to be flushed
*
* Output parameters:
* returns - the number of messages flushed from the queue
*/
unsigned32 _CORE_message_queue_Flush(
CORE_message_queue_Control *the_message_queue
)
{
if ( the_message_queue->number_of_pending_messages != 0 )
return _CORE_message_queue_Flush_support( the_message_queue );
else
return 0;
}
/*PAGE
*
* _CORE_message_queue_Broadcast
*
* This function sends a message for every thread waiting on the queue and
* returns the number of threads made ready by the message.
*
* Input parameters:
* the_message_queue - message is submitted to this message queue
* buffer - pointer to message buffer
* size - size in bytes of message to send
* id - id of message queue
* api_message_queue_mp_support - api specific mp support callout
* count - area to store number of threads made ready
*
* Output parameters:
* count - number of threads made ready
* CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
* error code - if unsuccessful
*/
CORE_message_queue_Status _CORE_message_queue_Broadcast(
CORE_message_queue_Control *the_message_queue,
void *buffer,
unsigned32 size,
Objects_Id id,
CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
unsigned32 *count
)
{
Thread_Control *the_thread;
unsigned32 number_broadcasted;
Thread_Wait_information *waitp;
unsigned32 constrained_size;
number_broadcasted = 0;
while ((the_thread = _Thread_queue_Dequeue(&the_message_queue->Wait_queue))) {
waitp = &the_thread->Wait;
number_broadcasted += 1;
constrained_size = size;
if ( size > the_message_queue->maximum_message_size )
constrained_size = the_message_queue->maximum_message_size;
_CORE_message_queue_Copy_buffer(
buffer,
waitp->return_argument,
constrained_size
);
*(unsigned32 *)the_thread->Wait.return_argument_1 = size;
#if defined(RTEMS_MULTIPROCESSING)
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
(*api_message_queue_mp_support) ( the_thread, id );
#endif
}
*count = number_broadcasted;
return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
}
/*PAGE
*
* _CORE_message_queue_Seize
*
* This kernel routine dequeues a message, copies the message buffer to
* a given destination buffer, and frees the message buffer to the
* inactive message pool. The thread will be blocked if wait is TRUE,
* otherwise an error will be given to the thread if no messages are available.
*
* Input parameters:
* the_message_queue - pointer to message queue
* id - id of object we are waitig on
* buffer - pointer to message buffer to be filled
* size - pointer to the size of buffer to be filled
* wait - TRUE if wait is allowed, FALSE otherwise
* timeout - time to wait for a message
*
* Output parameters: NONE
*
* NOTE: Dependent on BUFFER_LENGTH
*
* INTERRUPT LATENCY:
* available
* wait
*/
void _CORE_message_queue_Seize(
CORE_message_queue_Control *the_message_queue,
Objects_Id id,
void *buffer,
unsigned32 *size,
boolean wait,
Watchdog_Interval timeout
)
{
ISR_Level level;
CORE_message_queue_Buffer_control *the_message;
Thread_Control *executing;
executing = _Thread_Executing;
executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
_ISR_Disable( level );
if ( the_message_queue->number_of_pending_messages != 0 ) {
the_message_queue->number_of_pending_messages -= 1;
the_message = _CORE_message_queue_Get_pending_message( the_message_queue );
_ISR_Enable( level );
*size = the_message->Contents.size;
_CORE_message_queue_Copy_buffer(the_message->Contents.buffer,buffer,*size );
_CORE_message_queue_Free_message_buffer(the_message_queue, the_message );
return;
}
if ( !wait ) {
_ISR_Enable( level );
executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT;
return;
}
_Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
executing->Wait.queue = &the_message_queue->Wait_queue;
executing->Wait.id = id;
executing->Wait.return_argument = (void *)buffer;
executing->Wait.return_argument_1 = (void *)size;
_ISR_Enable( level );
_Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
}
/*PAGE
*
* _CORE_message_queue_Flush_support
*
* This message handler routine removes all messages from a message queue
* and returns them to the inactive message pool. The number of messages
* flushed from the queue is returned
*
* Input parameters:
* the_message_queue - pointer to message queue
*
* Output parameters:
* returns - number of messages placed on inactive chain
*
* INTERRUPT LATENCY:
* only case
*/
unsigned32 _CORE_message_queue_Flush_support(
CORE_message_queue_Control *the_message_queue
)
{
ISR_Level level;
Chain_Node *inactive_first;
Chain_Node *message_queue_first;
Chain_Node *message_queue_last;
unsigned32 count;
_ISR_Disable( level );
inactive_first = the_message_queue->Inactive_messages.first;
message_queue_first = the_message_queue->Pending_messages.first;
message_queue_last = the_message_queue->Pending_messages.last;
the_message_queue->Inactive_messages.first = message_queue_first;
message_queue_last->next = inactive_first;
inactive_first->previous = message_queue_last;
message_queue_first->previous =
_Chain_Head( &the_message_queue->Inactive_messages );
_Chain_Initialize_empty( &the_message_queue->Pending_messages );
count = the_message_queue->number_of_pending_messages;
the_message_queue->number_of_pending_messages = 0;
_ISR_Enable( level );
return count;
}
/*PAGE
*
* _CORE_message_queue_Submit
*
* This routine implements the send and urgent message functions. It
* processes a message that is to be submitted to the designated
* message queue. The message will either be processed as a
* send message which it will be inserted at the rear of the queue
* or it will be processed as an urgent message which will be inserted
* at the front of the queue.
*
* Input parameters:
* the_message_queue - message is submitted to this message queue
* buffer - pointer to message buffer
* size - size in bytes of message to send
* id - id of message queue
* api_message_queue_mp_support - api specific mp support callout
* submit_type - send or urgent message
*
* Output parameters:
* CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
* error code - if unsuccessful
*/
CORE_message_queue_Status _CORE_message_queue_Submit(
CORE_message_queue_Control *the_message_queue,
void *buffer,
unsigned32 size,
Objects_Id id,
CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
CORE_message_queue_Submit_types submit_type
)
{
CORE_message_queue_Buffer_control *the_message;
Thread_Control *the_thread;
if ( size > the_message_queue->maximum_message_size )
return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
/*
* Is there a thread currently waiting on this message queue?
*/
the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
if ( the_thread )
{
_CORE_message_queue_Copy_buffer(
buffer,
the_thread->Wait.return_argument,
size
);
*(unsigned32 *)the_thread->Wait.return_argument_1 = size;
#if defined(RTEMS_MULTIPROCESSING)
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
(*api_message_queue_mp_support) ( the_thread, id );
#endif
return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
}
/*
* No one waiting on this one currently.
* Allocate a message buffer and store it away
*/
if ( the_message_queue->number_of_pending_messages ==
the_message_queue->maximum_pending_messages ) {
return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
}
the_message = _CORE_message_queue_Allocate_message_buffer(the_message_queue);
if ( the_message == 0)
return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
_CORE_message_queue_Copy_buffer( buffer, the_message->Contents.buffer, size );
the_message->Contents.size = size;
the_message->priority = submit_type;
the_message_queue->number_of_pending_messages += 1;
switch ( submit_type ) {
case CORE_MESSAGE_QUEUE_SEND_REQUEST:
_CORE_message_queue_Append( the_message_queue, the_message );
break;
case CORE_MESSAGE_QUEUE_URGENT_REQUEST:
_CORE_message_queue_Prepend( the_message_queue, the_message );
break;
default:
/* XXX interrupt critical section needs to be addressed */
{
CORE_message_queue_Buffer_control *this_message;
Chain_Node *the_node;
the_message->priority = submit_type;
for ( the_node = the_message_queue->Pending_messages.first ;
!_Chain_Is_tail( &the_message_queue->Pending_messages, the_node ) ;
the_node = the_node->next ) {
this_message = (CORE_message_queue_Buffer_control *) the_node;
if ( this_message->priority >= the_message->priority )
continue;
_Chain_Insert( the_node, &the_message->Node );
break;
}
}
break;
}
/*
* According to POSIX, does this happen before or after the message
* is actually enqueued. It is logical to think afterwards, because
* the message is actually in the queue at this point.
*/
if ( the_message_queue->number_of_pending_messages == 1 &&
the_message_queue->notify_handler )
(*the_message_queue->notify_handler)( the_message_queue->notify_argument );
return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
}

View File

@@ -0,0 +1,94 @@
/*
* CORE Message Queue Handler
*
* DESCRIPTION:
*
* This package is the implementation of the CORE Message Queue Handler.
* This core object provides task synchronization and communication functions
* via messages passed to queue objects.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/chain.h>
#include <rtems/score/isr.h>
#include <rtems/score/object.h>
#include <rtems/score/coremsg.h>
#include <rtems/score/states.h>
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
#if defined(RTEMS_MULTIPROCESSING)
#include <rtems/score/mpci.h>
#endif
/*PAGE
*
* _CORE_message_queue_Broadcast
*
* This function sends a message for every thread waiting on the queue and
* returns the number of threads made ready by the message.
*
* Input parameters:
* the_message_queue - message is submitted to this message queue
* buffer - pointer to message buffer
* size - size in bytes of message to send
* id - id of message queue
* api_message_queue_mp_support - api specific mp support callout
* count - area to store number of threads made ready
*
* Output parameters:
* count - number of threads made ready
* CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
* error code - if unsuccessful
*/
CORE_message_queue_Status _CORE_message_queue_Broadcast(
CORE_message_queue_Control *the_message_queue,
void *buffer,
unsigned32 size,
Objects_Id id,
CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
unsigned32 *count
)
{
Thread_Control *the_thread;
unsigned32 number_broadcasted;
Thread_Wait_information *waitp;
unsigned32 constrained_size;
number_broadcasted = 0;
while ((the_thread = _Thread_queue_Dequeue(&the_message_queue->Wait_queue))) {
waitp = &the_thread->Wait;
number_broadcasted += 1;
constrained_size = size;
if ( size > the_message_queue->maximum_message_size )
constrained_size = the_message_queue->maximum_message_size;
_CORE_message_queue_Copy_buffer(
buffer,
waitp->return_argument,
constrained_size
);
*(unsigned32 *)the_thread->Wait.return_argument_1 = size;
#if defined(RTEMS_MULTIPROCESSING)
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
(*api_message_queue_mp_support) ( the_thread, id );
#endif
}
*count = number_broadcasted;
return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
}

View File

@@ -0,0 +1,67 @@
/*
* CORE Message Queue Handler
*
* DESCRIPTION:
*
* This package is the implementation of the CORE Message Queue Handler.
* This core object provides task synchronization and communication functions
* via messages passed to queue objects.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/chain.h>
#include <rtems/score/isr.h>
#include <rtems/score/object.h>
#include <rtems/score/coremsg.h>
#include <rtems/score/states.h>
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
#if defined(RTEMS_MULTIPROCESSING)
#include <rtems/score/mpci.h>
#endif
/*PAGE
*
* _CORE_message_queue_Close
*
* This function closes a message by returning all allocated space and
* flushing the message_queue's task wait queue.
*
* Input parameters:
* the_message_queue - the message_queue to be flushed
* remote_extract_callout - function to invoke remotely
* status - status to pass to thread
*
* Output parameters: NONE
*/
void _CORE_message_queue_Close(
CORE_message_queue_Control *the_message_queue,
Thread_queue_Flush_callout remote_extract_callout,
unsigned32 status
)
{
if ( the_message_queue->number_of_pending_messages != 0 )
(void) _CORE_message_queue_Flush_support( the_message_queue );
else
_Thread_queue_Flush(
&the_message_queue->Wait_queue,
remote_extract_callout,
status
);
(void) _Workspace_Free( the_message_queue->message_buffers );
}

View File

@@ -0,0 +1,56 @@
/*
* CORE Message Queue Handler
*
* DESCRIPTION:
*
* This package is the implementation of the CORE Message Queue Handler.
* This core object provides task synchronization and communication functions
* via messages passed to queue objects.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/chain.h>
#include <rtems/score/isr.h>
#include <rtems/score/object.h>
#include <rtems/score/coremsg.h>
#include <rtems/score/states.h>
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
#if defined(RTEMS_MULTIPROCESSING)
#include <rtems/score/mpci.h>
#endif
/*PAGE
*
* _CORE_message_queue_Flush
*
* This function flushes the message_queue's task wait queue. The number
* of messages flushed from the queue is returned.
*
* Input parameters:
* the_message_queue - the message_queue to be flushed
*
* Output parameters:
* returns - the number of messages flushed from the queue
*/
unsigned32 _CORE_message_queue_Flush(
CORE_message_queue_Control *the_message_queue
)
{
if ( the_message_queue->number_of_pending_messages != 0 )
return _CORE_message_queue_Flush_support( the_message_queue );
else
return 0;
}

View File

@@ -0,0 +1,79 @@
/*
* CORE Message Queue Handler
*
* DESCRIPTION:
*
* This package is the implementation of the CORE Message Queue Handler.
* This core object provides task synchronization and communication functions
* via messages passed to queue objects.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/chain.h>
#include <rtems/score/isr.h>
#include <rtems/score/object.h>
#include <rtems/score/coremsg.h>
#include <rtems/score/states.h>
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
#if defined(RTEMS_MULTIPROCESSING)
#include <rtems/score/mpci.h>
#endif
/*PAGE
*
* _CORE_message_queue_Flush_support
*
* This message handler routine removes all messages from a message queue
* and returns them to the inactive message pool. The number of messages
* flushed from the queue is returned
*
* Input parameters:
* the_message_queue - pointer to message queue
*
* Output parameters:
* returns - number of messages placed on inactive chain
*
* INTERRUPT LATENCY:
* only case
*/
unsigned32 _CORE_message_queue_Flush_support(
CORE_message_queue_Control *the_message_queue
)
{
ISR_Level level;
Chain_Node *inactive_first;
Chain_Node *message_queue_first;
Chain_Node *message_queue_last;
unsigned32 count;
_ISR_Disable( level );
inactive_first = the_message_queue->Inactive_messages.first;
message_queue_first = the_message_queue->Pending_messages.first;
message_queue_last = the_message_queue->Pending_messages.last;
the_message_queue->Inactive_messages.first = message_queue_first;
message_queue_last->next = inactive_first;
inactive_first->previous = message_queue_last;
message_queue_first->previous =
_Chain_Head( &the_message_queue->Inactive_messages );
_Chain_Initialize_empty( &the_message_queue->Pending_messages );
count = the_message_queue->number_of_pending_messages;
the_message_queue->number_of_pending_messages = 0;
_ISR_Enable( level );
return count;
}

View File

@@ -0,0 +1,101 @@
/*
* CORE Message Queue Handler
*
* DESCRIPTION:
*
* This package is the implementation of the CORE Message Queue Handler.
* This core object provides task synchronization and communication functions
* via messages passed to queue objects.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/chain.h>
#include <rtems/score/isr.h>
#include <rtems/score/object.h>
#include <rtems/score/coremsg.h>
#include <rtems/score/states.h>
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
#if defined(RTEMS_MULTIPROCESSING)
#include <rtems/score/mpci.h>
#endif
/*PAGE
*
* _CORE_message_queue_Seize
*
* This kernel routine dequeues a message, copies the message buffer to
* a given destination buffer, and frees the message buffer to the
* inactive message pool. The thread will be blocked if wait is TRUE,
* otherwise an error will be given to the thread if no messages are available.
*
* Input parameters:
* the_message_queue - pointer to message queue
* id - id of object we are waitig on
* buffer - pointer to message buffer to be filled
* size - pointer to the size of buffer to be filled
* wait - TRUE if wait is allowed, FALSE otherwise
* timeout - time to wait for a message
*
* Output parameters: NONE
*
* NOTE: Dependent on BUFFER_LENGTH
*
* INTERRUPT LATENCY:
* available
* wait
*/
void _CORE_message_queue_Seize(
CORE_message_queue_Control *the_message_queue,
Objects_Id id,
void *buffer,
unsigned32 *size,
boolean wait,
Watchdog_Interval timeout
)
{
ISR_Level level;
CORE_message_queue_Buffer_control *the_message;
Thread_Control *executing;
executing = _Thread_Executing;
executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
_ISR_Disable( level );
if ( the_message_queue->number_of_pending_messages != 0 ) {
the_message_queue->number_of_pending_messages -= 1;
the_message = _CORE_message_queue_Get_pending_message( the_message_queue );
_ISR_Enable( level );
*size = the_message->Contents.size;
_CORE_message_queue_Copy_buffer(the_message->Contents.buffer,buffer,*size );
_CORE_message_queue_Free_message_buffer(the_message_queue, the_message );
return;
}
if ( !wait ) {
_ISR_Enable( level );
executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT;
return;
}
_Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
executing->Wait.queue = &the_message_queue->Wait_queue;
executing->Wait.id = id;
executing->Wait.return_argument = (void *)buffer;
executing->Wait.return_argument_1 = (void *)size;
_ISR_Enable( level );
_Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
}

View File

@@ -0,0 +1,155 @@
/*
* CORE Message Queue Handler
*
* DESCRIPTION:
*
* This package is the implementation of the CORE Message Queue Handler.
* This core object provides task synchronization and communication functions
* via messages passed to queue objects.
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/chain.h>
#include <rtems/score/isr.h>
#include <rtems/score/object.h>
#include <rtems/score/coremsg.h>
#include <rtems/score/states.h>
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
#if defined(RTEMS_MULTIPROCESSING)
#include <rtems/score/mpci.h>
#endif
/*PAGE
*
* _CORE_message_queue_Submit
*
* This routine implements the send and urgent message functions. It
* processes a message that is to be submitted to the designated
* message queue. The message will either be processed as a
* send message which it will be inserted at the rear of the queue
* or it will be processed as an urgent message which will be inserted
* at the front of the queue.
*
* Input parameters:
* the_message_queue - message is submitted to this message queue
* buffer - pointer to message buffer
* size - size in bytes of message to send
* id - id of message queue
* api_message_queue_mp_support - api specific mp support callout
* submit_type - send or urgent message
*
* Output parameters:
* CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
* error code - if unsuccessful
*/
CORE_message_queue_Status _CORE_message_queue_Submit(
CORE_message_queue_Control *the_message_queue,
void *buffer,
unsigned32 size,
Objects_Id id,
CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
CORE_message_queue_Submit_types submit_type
)
{
CORE_message_queue_Buffer_control *the_message;
Thread_Control *the_thread;
if ( size > the_message_queue->maximum_message_size )
return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
/*
* Is there a thread currently waiting on this message queue?
*/
the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
if ( the_thread )
{
_CORE_message_queue_Copy_buffer(
buffer,
the_thread->Wait.return_argument,
size
);
*(unsigned32 *)the_thread->Wait.return_argument_1 = size;
#if defined(RTEMS_MULTIPROCESSING)
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
(*api_message_queue_mp_support) ( the_thread, id );
#endif
return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
}
/*
* No one waiting on this one currently.
* Allocate a message buffer and store it away
*/
if ( the_message_queue->number_of_pending_messages ==
the_message_queue->maximum_pending_messages ) {
return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
}
the_message = _CORE_message_queue_Allocate_message_buffer(the_message_queue);
if ( the_message == 0)
return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
_CORE_message_queue_Copy_buffer( buffer, the_message->Contents.buffer, size );
the_message->Contents.size = size;
the_message->priority = submit_type;
the_message_queue->number_of_pending_messages += 1;
switch ( submit_type ) {
case CORE_MESSAGE_QUEUE_SEND_REQUEST:
_CORE_message_queue_Append( the_message_queue, the_message );
break;
case CORE_MESSAGE_QUEUE_URGENT_REQUEST:
_CORE_message_queue_Prepend( the_message_queue, the_message );
break;
default:
/* XXX interrupt critical section needs to be addressed */
{
CORE_message_queue_Buffer_control *this_message;
Chain_Node *the_node;
the_message->priority = submit_type;
for ( the_node = the_message_queue->Pending_messages.first ;
!_Chain_Is_tail( &the_message_queue->Pending_messages, the_node ) ;
the_node = the_node->next ) {
this_message = (CORE_message_queue_Buffer_control *) the_node;
if ( this_message->priority >= the_message->priority )
continue;
_Chain_Insert( the_node, &the_message->Node );
break;
}
}
break;
}
/*
* According to POSIX, does this happen before or after the message
* is actually enqueued. It is logical to think afterwards, because
* the message is actually in the queue at this point.
*/
if ( the_message_queue->number_of_pending_messages == 1 &&
the_message_queue->notify_handler )
(*the_message_queue->notify_handler)( the_message_queue->notify_argument );
return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
}

View File

@@ -80,272 +80,3 @@ void _CORE_mutex_Initialize(
);
}
/*PAGE
*
* _CORE_mutex_Seize
*
* This routine attempts to allocate a mutex to the calling thread.
*
* Input parameters:
* the_mutex - pointer to mutex control block
* id - id of object to wait on
* wait - TRUE if wait is allowed, FALSE otherwise
* timeout - number of ticks to wait (0 means forever)
*
* Output parameters: NONE
*
* INTERRUPT LATENCY:
* available
* wait
*/
void _CORE_mutex_Seize(
CORE_mutex_Control *the_mutex,
Objects_Id id,
boolean wait,
Watchdog_Interval timeout
)
{
Thread_Control *executing;
ISR_Level level;
executing = _Thread_Executing;
switch ( the_mutex->Attributes.discipline ) {
case CORE_MUTEX_DISCIPLINES_FIFO:
case CORE_MUTEX_DISCIPLINES_PRIORITY:
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
break;
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
if ( executing->current_priority <
the_mutex->Attributes.priority_ceiling) {
executing->Wait.return_code = CORE_MUTEX_STATUS_CEILING_VIOLATED;
return;
}
}
executing->Wait.return_code = CORE_MUTEX_STATUS_SUCCESSFUL;
_ISR_Disable( level );
if ( ! _CORE_mutex_Is_locked( the_mutex ) ) {
the_mutex->lock = CORE_MUTEX_LOCKED;
the_mutex->holder = executing;
the_mutex->holder_id = executing->Object.id;
the_mutex->nest_count = 1;
executing->resource_count++;
_ISR_Enable( level );
switch ( the_mutex->Attributes.discipline ) {
case CORE_MUTEX_DISCIPLINES_FIFO:
case CORE_MUTEX_DISCIPLINES_PRIORITY:
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
/* already the highest priority */
break;
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
if ( the_mutex->Attributes.priority_ceiling <
executing->current_priority ) {
_Thread_Change_priority(
the_mutex->holder,
the_mutex->Attributes.priority_ceiling,
FALSE
);
}
}
return;
}
if ( _Objects_Are_ids_equal(
_Thread_Executing->Object.id, the_mutex->holder_id ) ) {
if ( _CORE_mutex_Is_nesting_allowed( &the_mutex->Attributes ) )
the_mutex->nest_count++;
else
executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
_ISR_Enable( level );
return;
}
if ( !wait ) {
_ISR_Enable( level );
executing->Wait.return_code = CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT;
return;
}
_Thread_queue_Enter_critical_section( &the_mutex->Wait_queue );
executing->Wait.queue = &the_mutex->Wait_queue;
executing->Wait.id = id;
_ISR_Enable( level );
switch ( the_mutex->Attributes.discipline ) {
case CORE_MUTEX_DISCIPLINES_FIFO:
case CORE_MUTEX_DISCIPLINES_PRIORITY:
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
break;
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
if ( the_mutex->holder->current_priority > executing->current_priority ) {
_Thread_Change_priority(
the_mutex->holder,
executing->current_priority,
FALSE
);
}
break;
}
_Thread_queue_Enqueue( &the_mutex->Wait_queue, timeout );
if ( _Thread_Executing->Wait.return_code == CORE_MUTEX_STATUS_SUCCESSFUL ) {
switch ( the_mutex->Attributes.discipline ) {
case CORE_MUTEX_DISCIPLINES_FIFO:
case CORE_MUTEX_DISCIPLINES_PRIORITY:
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
break;
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
if ( the_mutex->Attributes.priority_ceiling <
executing->current_priority ) {
_Thread_Change_priority(
executing,
the_mutex->Attributes.priority_ceiling,
FALSE
);
};
break;
}
}
}
/*
* _CORE_mutex_Surrender
*
* DESCRIPTION:
*
* This routine frees a unit to the mutex. If a task was blocked waiting for
* a unit from this mutex, then that task will be readied and the unit
* given to that task. Otherwise, the unit will be returned to the mutex.
*
* Input parameters:
* the_mutex - the mutex to be flushed
* id - id of parent mutex
* api_mutex_mp_support - api dependent MP support actions
*
* Output parameters:
* CORE_MUTEX_STATUS_SUCCESSFUL - if successful
* core error code - if unsuccessful
*/
CORE_mutex_Status _CORE_mutex_Surrender(
CORE_mutex_Control *the_mutex,
Objects_Id id,
CORE_mutex_API_mp_support_callout api_mutex_mp_support
)
{
Thread_Control *the_thread;
Thread_Control *executing;
executing = _Thread_Executing;
/*
* The following code allows a thread (or ISR) other than the thread
* which acquired the mutex to release that mutex. This is only
* allowed when the mutex in quetion is FIFO or simple Priority
* discipline. But Priority Ceiling or Priority Inheritance mutexes
* must be released by the thread which acquired them.
*/
if ( !_Objects_Are_ids_equal(
_Thread_Executing->Object.id, the_mutex->holder_id ) ) {
switch ( the_mutex->Attributes.discipline ) {
case CORE_MUTEX_DISCIPLINES_FIFO:
case CORE_MUTEX_DISCIPLINES_PRIORITY:
break;
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
return( CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE );
break;
}
}
the_mutex->nest_count--;
if ( the_mutex->nest_count != 0 )
return( CORE_MUTEX_STATUS_SUCCESSFUL );
_Thread_Executing->resource_count--;
the_mutex->holder = NULL;
the_mutex->holder_id = 0;
/*
* Whether or not someone is waiting for the mutex, an
* inherited priority must be lowered if this is the last
* mutex (i.e. resource) this task has.
*/
switch ( the_mutex->Attributes.discipline ) {
case CORE_MUTEX_DISCIPLINES_FIFO:
case CORE_MUTEX_DISCIPLINES_PRIORITY:
break;
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
if ( executing->resource_count == 0 &&
executing->real_priority != executing->current_priority ) {
_Thread_Change_priority( executing, executing->real_priority, TRUE );
}
break;
}
if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) {
#if defined(RTEMS_MULTIPROCESSING)
if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {
the_mutex->holder = NULL;
the_mutex->holder_id = the_thread->Object.id;
the_mutex->nest_count = 1;
( *api_mutex_mp_support)( the_thread, id );
} else
#endif
{
the_mutex->holder = the_thread;
the_mutex->holder_id = the_thread->Object.id;
the_thread->resource_count++;
the_mutex->nest_count = 1;
/*
* No special action for priority inheritance or priority ceiling
* because the_thread is guaranteed to be the highest priority
* thread waiting for the mutex.
*/
}
} else
the_mutex->lock = CORE_MUTEX_UNLOCKED;
return( CORE_MUTEX_STATUS_SUCCESSFUL );
}
/*PAGE
*
* _CORE_mutex_Flush
*
* This function a flushes the mutex's task wait queue.
*
* Input parameters:
* the_mutex - the mutex to be flushed
* remote_extract_callout - function to invoke remotely
* status - status to pass to thread
*
* Output parameters: NONE
*/
void _CORE_mutex_Flush(
CORE_mutex_Control *the_mutex,
Thread_queue_Flush_callout remote_extract_callout,
unsigned32 status
)
{
_Thread_queue_Flush(
&the_mutex->Wait_queue,
remote_extract_callout,
status
);
}

View File

@@ -67,130 +67,3 @@ void _CORE_semaphore_Initialize(
CORE_SEMAPHORE_TIMEOUT
);
}
/*PAGE
*
* _CORE_semaphore_Surrender
*
* Input parameters:
* the_semaphore - the semaphore to be flushed
* id - id of parent semaphore
* api_semaphore_mp_support - api dependent MP support actions
*
* Output parameters:
* CORE_SEMAPHORE_STATUS_SUCCESSFUL - if successful
* core error code - if unsuccessful
*
* Output parameters:
*/
CORE_semaphore_Status _CORE_semaphore_Surrender(
CORE_semaphore_Control *the_semaphore,
Objects_Id id,
CORE_semaphore_API_mp_support_callout api_semaphore_mp_support
)
{
Thread_Control *the_thread;
ISR_Level level;
CORE_semaphore_Status status;
status = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
if ( (the_thread = _Thread_queue_Dequeue(&the_semaphore->Wait_queue)) ) {
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
(*api_semaphore_mp_support) ( the_thread, id );
} else {
_ISR_Disable( level );
if ( the_semaphore->count <= the_semaphore->Attributes.maximum_count )
the_semaphore->count += 1;
else
status = CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED;
_ISR_Enable( level );
}
return status;
}
/*PAGE
*
* _CORE_semaphore_Seize
*
* This routine attempts to allocate a core semaphore to the calling thread.
*
* Input parameters:
* the_semaphore - pointer to semaphore control block
* id - id of object to wait on
* wait - TRUE if wait is allowed, FALSE otherwise
* timeout - number of ticks to wait (0 means forever)
*
* Output parameters: NONE
*
* INTERRUPT LATENCY:
* available
* wait
*/
void _CORE_semaphore_Seize(
CORE_semaphore_Control *the_semaphore,
Objects_Id id,
boolean wait,
Watchdog_Interval timeout
)
{
Thread_Control *executing;
ISR_Level level;
executing = _Thread_Executing;
executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
_ISR_Disable( level );
if ( the_semaphore->count != 0 ) {
the_semaphore->count -= 1;
_ISR_Enable( level );
return;
}
if ( !wait ) {
_ISR_Enable( level );
executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
return;
}
_Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
executing->Wait.queue = &the_semaphore->Wait_queue;
executing->Wait.id = id;
_ISR_Enable( level );
_Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
}
/*PAGE
*
* _CORE_semaphore_Flush
*
* This function a flushes the semaphore's task wait queue.
*
* Input parameters:
* the_semaphore - the semaphore to be flushed
* remote_extract_callout - function to invoke remotely
* status - status to pass to thread
*
* Output parameters: NONE
*/
void _CORE_semaphore_Flush(
CORE_semaphore_Control *the_semaphore,
Thread_queue_Flush_callout remote_extract_callout,
unsigned32 status
)
{
_Thread_queue_Flush(
&the_semaphore->Wait_queue,
remote_extract_callout,
status
);
}

View File

@@ -37,237 +37,3 @@ void _Watchdog_Handler_initialization( void )
_Chain_Initialize_empty( &_Watchdog_Ticks_chain );
_Chain_Initialize_empty( &_Watchdog_Seconds_chain );
}
/*PAGE
*
* _Watchdog_Remove
*
* The routine removes a watchdog from a delta chain and updates
* the delta counters of the remaining watchdogs.
*/
Watchdog_States _Watchdog_Remove(
Watchdog_Control *the_watchdog
)
{
ISR_Level level;
Watchdog_States previous_state;
Watchdog_Control *next_watchdog;
_ISR_Disable( level );
previous_state = the_watchdog->state;
switch ( previous_state ) {
case WATCHDOG_INACTIVE:
break;
case WATCHDOG_BEING_INSERTED:
/*
* It is not actually on the chain so just change the state and
* the Insert operation we interrupted will be aborted.
*/
the_watchdog->state = WATCHDOG_INACTIVE;
break;
case WATCHDOG_ACTIVE:
case WATCHDOG_REMOVE_IT:
the_watchdog->state = WATCHDOG_INACTIVE;
next_watchdog = _Watchdog_Next( the_watchdog );
if ( _Watchdog_Next(next_watchdog) )
next_watchdog->delta_interval += the_watchdog->delta_interval;
if ( _Watchdog_Sync_count )
_Watchdog_Sync_level = _ISR_Nest_level;
_Chain_Extract_unprotected( &the_watchdog->Node );
break;
}
the_watchdog->stop_time = _Watchdog_Ticks_since_boot;
_ISR_Enable( level );
return( previous_state );
}
/*PAGE
*
* _Watchdog_Adjust
*
* This routine adjusts the delta chain backward or forward in response
* to a time change.
*
* Input parameters:
* header - pointer to the delta chain to be adjusted
* direction - forward or backward adjustment to delta chain
* units - units to adjust
*
* Output parameters:
*/
void _Watchdog_Adjust(
Chain_Control *header,
Watchdog_Adjust_directions direction,
Watchdog_Interval units
)
{
if ( !_Chain_Is_empty( header ) ) {
switch ( direction ) {
case WATCHDOG_BACKWARD:
_Watchdog_First( header )->delta_interval += units;
break;
case WATCHDOG_FORWARD:
while ( units ) {
if ( units < _Watchdog_First( header )->delta_interval ) {
_Watchdog_First( header )->delta_interval -= units;
break;
} else {
units -= _Watchdog_First( header )->delta_interval;
_Watchdog_First( header )->delta_interval = 1;
_Watchdog_Tickle( header );
if ( _Chain_Is_empty( header ) )
break;
}
}
break;
}
}
}
/*PAGE
*
* _Watchdog_Insert
*
* This routine inserts a watchdog timer on to the appropriate delta
* chain while updating the delta interval counters.
*/
void _Watchdog_Insert(
Chain_Control *header,
Watchdog_Control *the_watchdog
)
{
ISR_Level level;
Watchdog_Control *after;
unsigned32 insert_isr_nest_level;
Watchdog_Interval delta_interval;
insert_isr_nest_level = _ISR_Nest_level;
the_watchdog->state = WATCHDOG_BEING_INSERTED;
_Watchdog_Sync_count++;
restart:
delta_interval = the_watchdog->initial;
_ISR_Disable( level );
for ( after = _Watchdog_First( header ) ;
;
after = _Watchdog_Next( after ) ) {
if ( delta_interval == 0 || !_Watchdog_Next( after ) )
break;
if ( delta_interval < after->delta_interval ) {
after->delta_interval -= delta_interval;
break;
}
delta_interval -= after->delta_interval;
/*
* If you experience problems comment out the _ISR_Flash line.
* 3.2.0 was the first release with this critical section redesigned.
* Under certain circumstances, the PREVIOUS critical section algorithm
* used around this flash point allowed interrupts to execute
* which violated the design assumptions. The critical section
* mechanism used here WAS redesigned to address this.
*/
_ISR_Flash( level );
if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
goto exit_insert;
}
if ( _Watchdog_Sync_level > insert_isr_nest_level ) {
_Watchdog_Sync_level = insert_isr_nest_level;
_ISR_Enable( level );
goto restart;
}
}
_Watchdog_Activate( the_watchdog );
the_watchdog->delta_interval = delta_interval;
_Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node );
the_watchdog->start_time = _Watchdog_Ticks_since_boot;
exit_insert:
_Watchdog_Sync_level = insert_isr_nest_level;
_Watchdog_Sync_count--;
_ISR_Enable( level );
}
/*PAGE
*
* _Watchdog_Tickle
*
* This routine decrements the delta counter in response to a tick. The
* delta chain is updated accordingly.
*
* Input parameters:
* header - pointer to the delta chain to be tickled
*
* Output parameters: NONE
*/
void _Watchdog_Tickle(
Chain_Control *header
)
{
Watchdog_Control *the_watchdog;
if ( _Chain_Is_empty( header ) )
return;
the_watchdog = _Watchdog_First( header );
the_watchdog->delta_interval--;
if ( the_watchdog->delta_interval != 0 )
return;
do {
switch( _Watchdog_Remove( the_watchdog ) ) {
case WATCHDOG_ACTIVE:
(*the_watchdog->routine)(
the_watchdog->id,
the_watchdog->user_data
);
break;
case WATCHDOG_INACTIVE:
/*
* This state indicates that the watchdog is not on any chain.
* Thus, it is NOT on a chain being tickled. This case should
* never occur.
*/
break;
case WATCHDOG_BEING_INSERTED:
/*
* This state indicates that the watchdog is in the process of
* BEING inserted on the chain. Thus, it can NOT be on a chain
* being tickled. This case should never occur.
*/
break;
case WATCHDOG_REMOVE_IT:
break;
}
the_watchdog = _Watchdog_First( header );
} while ( !_Chain_Is_empty( header ) &&
(the_watchdog->delta_interval == 0) );
}

View File

@@ -0,0 +1,63 @@
/*
* Watchdog Handler
*
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/isr.h>
#include <rtems/score/watchdog.h>
/*PAGE
*
* _Watchdog_Adjust
*
* This routine adjusts the delta chain backward or forward in response
* to a time change.
*
* Input parameters:
* header - pointer to the delta chain to be adjusted
* direction - forward or backward adjustment to delta chain
* units - units to adjust
*
* Output parameters:
*/
void _Watchdog_Adjust(
Chain_Control *header,
Watchdog_Adjust_directions direction,
Watchdog_Interval units
)
{
if ( !_Chain_Is_empty( header ) ) {
switch ( direction ) {
case WATCHDOG_BACKWARD:
_Watchdog_First( header )->delta_interval += units;
break;
case WATCHDOG_FORWARD:
while ( units ) {
if ( units < _Watchdog_First( header )->delta_interval ) {
_Watchdog_First( header )->delta_interval -= units;
break;
} else {
units -= _Watchdog_First( header )->delta_interval;
_Watchdog_First( header )->delta_interval = 1;
_Watchdog_Tickle( header );
if ( _Chain_Is_empty( header ) )
break;
}
}
break;
}
}
}

View File

@@ -0,0 +1,97 @@
/*
* Watchdog Handler
*
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/isr.h>
#include <rtems/score/watchdog.h>
/*PAGE
*
* _Watchdog_Insert
*
* This routine inserts a watchdog timer on to the appropriate delta
* chain while updating the delta interval counters.
*/
void _Watchdog_Insert(
Chain_Control *header,
Watchdog_Control *the_watchdog
)
{
ISR_Level level;
Watchdog_Control *after;
unsigned32 insert_isr_nest_level;
Watchdog_Interval delta_interval;
insert_isr_nest_level = _ISR_Nest_level;
the_watchdog->state = WATCHDOG_BEING_INSERTED;
_Watchdog_Sync_count++;
restart:
delta_interval = the_watchdog->initial;
_ISR_Disable( level );
for ( after = _Watchdog_First( header ) ;
;
after = _Watchdog_Next( after ) ) {
if ( delta_interval == 0 || !_Watchdog_Next( after ) )
break;
if ( delta_interval < after->delta_interval ) {
after->delta_interval -= delta_interval;
break;
}
delta_interval -= after->delta_interval;
/*
* If you experience problems comment out the _ISR_Flash line.
* 3.2.0 was the first release with this critical section redesigned.
* Under certain circumstances, the PREVIOUS critical section algorithm
* used around this flash point allowed interrupts to execute
* which violated the design assumptions. The critical section
* mechanism used here WAS redesigned to address this.
*/
_ISR_Flash( level );
if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
goto exit_insert;
}
if ( _Watchdog_Sync_level > insert_isr_nest_level ) {
_Watchdog_Sync_level = insert_isr_nest_level;
_ISR_Enable( level );
goto restart;
}
}
_Watchdog_Activate( the_watchdog );
the_watchdog->delta_interval = delta_interval;
_Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node );
the_watchdog->start_time = _Watchdog_Ticks_since_boot;
exit_insert:
_Watchdog_Sync_level = insert_isr_nest_level;
_Watchdog_Sync_count--;
_ISR_Enable( level );
}

View File

@@ -0,0 +1,71 @@
/*
* Watchdog Handler
*
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/isr.h>
#include <rtems/score/watchdog.h>
/*PAGE
*
* _Watchdog_Remove
*
* The routine removes a watchdog from a delta chain and updates
* the delta counters of the remaining watchdogs.
*/
Watchdog_States _Watchdog_Remove(
Watchdog_Control *the_watchdog
)
{
ISR_Level level;
Watchdog_States previous_state;
Watchdog_Control *next_watchdog;
_ISR_Disable( level );
previous_state = the_watchdog->state;
switch ( previous_state ) {
case WATCHDOG_INACTIVE:
break;
case WATCHDOG_BEING_INSERTED:
/*
* It is not actually on the chain so just change the state and
* the Insert operation we interrupted will be aborted.
*/
the_watchdog->state = WATCHDOG_INACTIVE;
break;
case WATCHDOG_ACTIVE:
case WATCHDOG_REMOVE_IT:
the_watchdog->state = WATCHDOG_INACTIVE;
next_watchdog = _Watchdog_Next( the_watchdog );
if ( _Watchdog_Next(next_watchdog) )
next_watchdog->delta_interval += the_watchdog->delta_interval;
if ( _Watchdog_Sync_count )
_Watchdog_Sync_level = _ISR_Nest_level;
_Chain_Extract_unprotected( &the_watchdog->Node );
break;
}
the_watchdog->stop_time = _Watchdog_Ticks_since_boot;
_ISR_Enable( level );
return( previous_state );
}

View File

@@ -0,0 +1,78 @@
/*
* Watchdog Handler
*
*
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/isr.h>
#include <rtems/score/watchdog.h>
/*PAGE
*
* _Watchdog_Tickle
*
* This routine decrements the delta counter in response to a tick. The
* delta chain is updated accordingly.
*
* Input parameters:
* header - pointer to the delta chain to be tickled
*
* Output parameters: NONE
*/
void _Watchdog_Tickle(
Chain_Control *header
)
{
Watchdog_Control *the_watchdog;
if ( _Chain_Is_empty( header ) )
return;
the_watchdog = _Watchdog_First( header );
the_watchdog->delta_interval--;
if ( the_watchdog->delta_interval != 0 )
return;
do {
switch( _Watchdog_Remove( the_watchdog ) ) {
case WATCHDOG_ACTIVE:
(*the_watchdog->routine)(
the_watchdog->id,
the_watchdog->user_data
);
break;
case WATCHDOG_INACTIVE:
/*
* This state indicates that the watchdog is not on any chain.
* Thus, it is NOT on a chain being tickled. This case should
* never occur.
*/
break;
case WATCHDOG_BEING_INSERTED:
/*
* This state indicates that the watchdog is in the process of
* BEING inserted on the chain. Thus, it can NOT be on a chain
* being tickled. This case should never occur.
*/
break;
case WATCHDOG_REMOVE_IT:
break;
}
the_watchdog = _Watchdog_First( header );
} while ( !_Chain_Is_empty( header ) &&
(the_watchdog->delta_interval == 0) );
}