diff options
Diffstat (limited to 'cpukit/score')
-rw-r--r-- | cpukit/score/cpu/hppa1.1/cpu.c | 9 | ||||
-rw-r--r-- | cpukit/score/cpu/i386/cpu.c | 4 | ||||
-rw-r--r-- | cpukit/score/cpu/unix/cpu.c | 85 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/coremsg.h | 408 | ||||
-rw-r--r-- | cpukit/score/inline/rtems/score/coremsg.inl | 186 | ||||
-rw-r--r-- | cpukit/score/macros/rtems/score/coremsg.inl | 121 | ||||
-rw-r--r-- | cpukit/score/src/coremsg.c | 436 |
7 files changed, 1215 insertions, 34 deletions
diff --git a/cpukit/score/cpu/hppa1.1/cpu.c b/cpukit/score/cpu/hppa1.1/cpu.c index 6dee0c1225..ba70357a33 100644 --- a/cpukit/score/cpu/hppa1.1/cpu.c +++ b/cpukit/score/cpu/hppa1.1/cpu.c @@ -193,7 +193,7 @@ void _CPU_ISR_install_vector( void hppa_external_interrupt_initialize(void) { - hppa_rtems_isr_entry ignore; + hppa_rtems_isr_entry ignore = 0; /* mark them all unused */ @@ -201,8 +201,11 @@ hppa_external_interrupt_initialize(void) DISMISS(~0); /* install the external interrupt handler */ - rtems_interrupt_catch((rtems_isr_entry) hppa_external_interrupt, - HPPA_INTERRUPT_EXTERNAL_INTERRUPT, &ignore) ; + _CPU_ISR_install_vector( + HPPA_INTERRUPT_EXTERNAL_INTERRUPT, + (proc_ptr)hppa_external_interrupt, + (proc_ptr *)ignore + ); } /* diff --git a/cpukit/score/cpu/i386/cpu.c b/cpukit/score/cpu/i386/cpu.c index 446515d6f9..73108e66d1 100644 --- a/cpukit/score/cpu/i386/cpu.c +++ b/cpukit/score/cpu/i386/cpu.c @@ -34,7 +34,7 @@ void _CPU_Initialize( ) { register unsigned16 fp_status asm ("ax"); - register unsigned8 *fp_context; + register void *fp_context; _CPU_Table = *cpu_table; @@ -56,7 +56,7 @@ void _CPU_Initialize( if ( fp_status == 0 ) { - fp_context = _CPU_Null_fp_context; + fp_context = &_CPU_Null_fp_context; asm volatile( "fsave (%0)" : "=r" (fp_context) : "0" (fp_context) diff --git a/cpukit/score/cpu/unix/cpu.c b/cpukit/score/cpu/unix/cpu.c index 339bb2a3ce..a1994da5ae 100644 --- a/cpukit/score/cpu/unix/cpu.c +++ b/cpukit/score/cpu/unix/cpu.c @@ -1,5 +1,5 @@ /* - * HP PA-RISC CPU Dependent Source + * UNIX Simulator Dependent Source * * * To anyone who acknowledges that this file is provided "AS IS" @@ -18,6 +18,7 @@ #include <rtems/system.h> #include <rtems/core/isr.h> +#include <rtems/core/interr.h> #include <stdio.h> #include <stdlib.h> @@ -169,21 +170,16 @@ void _CPU_Context_From_CPU_Init() */ _CPU_ISR_Set_level( 0 ); - setjmp( _CPU_Context_Default_with_ISRs_enabled.regs ); - sigprocmask( - SIG_SETMASK, /* ignored when second arg is NULL */ - 0, - &_CPU_Context_Default_with_ISRs_enabled.isr_level + _CPU_Context_switch( + &_CPU_Context_Default_with_ISRs_enabled, + &_CPU_Context_Default_with_ISRs_enabled ); _CPU_ISR_Set_level( 1 ); - setjmp( _CPU_Context_Default_with_ISRs_disabled.regs ); - sigprocmask( - SIG_SETMASK, /* ignored when second arg is NULL */ - 0, - &_CPU_Context_Default_with_ISRs_disabled.isr_level + _CPU_Context_switch( + &_CPU_Context_Default_with_ISRs_disabled, + &_CPU_Context_Default_with_ISRs_disabled ); - } /*PAGE @@ -191,21 +187,21 @@ void _CPU_Context_From_CPU_Init() * _CPU_ISR_Get_level */ +sigset_t GET_old_mask; + unsigned32 _CPU_ISR_Get_level( void ) { - sigset_t sigset; +/* sigset_t old_mask; */ + unsigned32 old_level; - sigprocmask( 0, 0, &sigset ); - - /* - * This is an educated guess based on ONLY ONE of the signals we - * disable/enable to mask ISRs. - */ + sigprocmask(0, 0, &GET_old_mask); + + if (memcmp((void *)&posix_empty_mask, (void *)&GET_old_mask, sizeof(sigset_t))) + old_level = 1; + else + old_level = 0; - if ( sigismember( &sigset, SIGUSR1 ) ) - return 1; - else - return 0; + return old_level; } /* _CPU_Initialize @@ -383,7 +379,7 @@ void _CPU_Context_Initialize( else source = _CPU_Context_Default_with_ISRs_disabled.regs; - memcpy(_the_context, source, sizeof(jmp_buf)); + memcpy(_the_context, source, sizeof(Context_Control) ); /* sizeof(jmp_buf)); */ addr = (unsigned32 *)_the_context; @@ -470,15 +466,30 @@ void _CPU_Context_switch( Context_Control *next ) { + int status; + /* * Switch levels in one operation */ - sigprocmask( SIG_SETMASK, &next->isr_level, ¤t->isr_level ); + status = sigprocmask( SIG_SETMASK, &next->isr_level, ¤t->isr_level ); + if ( status ) + _Internal_error_Occurred( + INTERNAL_ERROR_CORE, + TRUE, + status + ); if (setjmp(current->regs) == 0) { /* Save the current context */ longjmp(next->regs, 0); /* Switch to the new context */ + if ( status ) + _Internal_error_Occurred( + INTERNAL_ERROR_CORE, + TRUE, + status + ); } + } /*PAGE @@ -510,11 +521,18 @@ void _CPU_Restore_float_context( unsigned32 _CPU_ISR_Disable_support(void) { + int status; sigset_t old_mask; - sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, &old_mask); + status = sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, &old_mask); + if ( status ) + _Internal_error_Occurred( + INTERNAL_ERROR_CORE, + TRUE, + status + ); - if (memcmp((void *)&posix_empty_mask, (void *)&old_mask, sizeof(sigset_t)) != 0) + if (memcmp((void *)&posix_empty_mask, (void *)&old_mask, sizeof(sigset_t))) return 1; return 0; @@ -529,10 +547,19 @@ void _CPU_ISR_Enable( unsigned32 level ) { + int status; + if (level == 0) - sigprocmask(SIG_UNBLOCK, &_CPU_Signal_mask, 0); + status = sigprocmask(SIG_UNBLOCK, &_CPU_Signal_mask, 0); else - sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, 0); + status = sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, 0); + + if ( status ) + _Internal_error_Occurred( + INTERNAL_ERROR_CORE, + TRUE, + status + ); } /*PAGE diff --git a/cpukit/score/include/rtems/score/coremsg.h b/cpukit/score/include/rtems/score/coremsg.h new file mode 100644 index 0000000000..109d792c78 --- /dev/null +++ b/cpukit/score/include/rtems/score/coremsg.h @@ -0,0 +1,408 @@ +/* coremsg.h + * + * This include file contains all the constants and structures associated + * with the Message queue Handler. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __RTEMS_CORE_MESSAGE_QUEUE_h +#define __RTEMS_CORE_MESSAGE_QUEUE_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/core/thread.h> +#include <rtems/core/threadq.h> +#include <rtems/core/priority.h> +#include <rtems/core/watchdog.h> + +/* + * The following type defines the callout which the API provides + * to support global/multiprocessor operations on message_queues. + */ + +typedef void ( *CORE_message_queue_API_mp_support_callout )( + Thread_Control *, + Objects_Id + ); + +/* + * The following defines the data types needed to manipulate + * the contents of message buffers. + * Since msgs are variable length we just make a ptr to 1. + */ + +typedef struct { + unsigned32 size; + +#ifndef __cplusplus + /* NOTE: [0] is gcc specific, + * but specifically disallowed by ANSI STD C++ + * g++ warns about it, so we #ifdef it out to + * get rid of warnings when compiled by g++. + */ + unsigned32 buffer[0]; +#endif + +} CORE_message_queue_Buffer; + +/* + * The following records define the organization of a message + * buffer. + */ + +typedef struct { + Chain_Node Node; + CORE_message_queue_Buffer Contents; +} CORE_message_queue_Buffer_control; + +/* + * Blocking disciplines for a message_queue. + */ + +typedef enum { + CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO, + CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY +} CORE_message_queue_Disciplines; + +/* + * The following enumerated type details the modes in which a message + * may be submitted to a message queue. The message may be posted + * in a send or urgent fashion. + */ + +typedef enum { + CORE_MESSAGE_QUEUE_SEND_REQUEST = 0, + CORE_MESSAGE_QUEUE_URGENT_REQUEST = 1 +} CORE_message_queue_Submit_types; + +/* + * Core Message queue handler return statuses. + */ + +typedef enum { + CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL, + CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE, + CORE_MESSAGE_QUEUE_STATUS_TOO_MANY, + CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED, + CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT, + CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED, + CORE_MESSAGE_QUEUE_STATUS_TIMEOUT +} CORE_message_queue_Status; + +/* + * The following defines the control block used to manage the + * attributes of each message queue. + */ + +typedef struct { + CORE_message_queue_Disciplines discipline; +} CORE_message_queue_Attributes; + +/* + * The following defines the control block used to manage each + * counting message_queue. + */ + +typedef struct { + Thread_queue_Control Wait_queue; + CORE_message_queue_Attributes Attributes; + unsigned32 maximum_pending_messages; + unsigned32 number_of_pending_messages; + unsigned32 maximum_message_size; + Chain_Control Pending_messages; + CORE_message_queue_Buffer *message_buffers; + Chain_Control Inactive_messages; +} CORE_message_queue_Control; + +/* + * _CORE_message_queue_Initialize + * + * DESCRIPTION: + * + * This routine initializes the message_queue based on the parameters passed. + */ + +boolean _CORE_message_queue_Initialize( + CORE_message_queue_Control *the_message_queue, + Objects_Classes the_class, + CORE_message_queue_Attributes *the_message_queue_attributes, + unsigned32 maximum_pending_messages, + unsigned32 maximum_message_size, + Thread_queue_Extract_callout proxy_extract_callout +); + +/* + * _CORE_message_queue_Close + * + * DESCRIPTION: + * + * This function closes a message by returning all allocated space and + * flushing the message_queue's task wait queue. + */ + +void _CORE_message_queue_Close( + CORE_message_queue_Control *the_message_queue, + Thread_queue_Flush_callout remote_extract_callout, + unsigned32 status +); + +/* + * + * _CORE_message_queue_Flush + * + * DESCRIPTION: + * + * This function flushes the message_queue's task wait queue. The number + * messages flushed from the queue is returned. + * + */ + +unsigned32 _CORE_message_queue_Flush( + CORE_message_queue_Control *the_message_queue +); + +/* + * _CORE_message_queue_Flush_support + * + * DESCRIPTION: + * + * This routine flushes all outstanding messages and returns + * them to the inactive message chain. + */ + +unsigned32 _CORE_message_queue_Flush_support( + CORE_message_queue_Control *the_message_queue +); + +/* + * _CORE_message_queue_send + * + * DESCRIPTION: + * + * This routine sends a message to the end of the specified message queue. + * + */ + +STATIC INLINE CORE_message_queue_Status _CORE_message_queue_Send( + 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_Urgent + * + * DESCRIPTION: + * + * This routine sends a message to the front of the specified message queue. + * + */ + +STATIC INLINE CORE_message_queue_Status _CORE_message_queue_Urgent( + 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_Broadcast + * + * DESCRIPTION: + * + * This function sends a message for every thread waiting on the queue and + * returns the number of threads made ready by the message. + * + */ + +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 +); + +/* + * + * _CORE_message_queue_Submit + * + * DESCRIPTION: + * + * 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. + * + */ + +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_Seize + * + * DESCRIPTION: + * + * 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. + * + */ + +void _CORE_message_queue_Seize( + CORE_message_queue_Control *the_message_queue, + Objects_Id id, + void *buffer, + unsigned32 *size, + boolean wait, + Watchdog_Interval timeout +); + +/* + * _CORE_message_queue_Allocate_message_buffer + * + * DESCRIPTION: + * + * This function allocates a message buffer from the inactive + * message buffer chain. + */ + +STATIC INLINE CORE_message_queue_Buffer_control * + _CORE_message_queue_Allocate_message_buffer ( + CORE_message_queue_Control *the_message_queue +); + +/* + * _CORE_message_queue_Free_message_buffer + * + * DESCRIPTION: + * + * This routine frees a message buffer to the inactive + * message buffer chain. + */ + +STATIC INLINE void _CORE_message_queue_Free_message_buffer ( + CORE_message_queue_Control *the_message_queue, + CORE_message_queue_Buffer_control *the_message +); + +/* + * _CORE_message_queue_Copy_buffer + * + * DESCRIPTION: + * + * This routine copies the contents of the source message buffer + * to the destination message buffer. + */ + +STATIC INLINE void _CORE_message_queue_Copy_buffer ( + void *source, + void *destination, + unsigned32 size +); + +/* + * _CORE_message_queue_Get_pending_message + * + * DESCRIPTION: + * + * This function removes the first message from the_message_queue + * and returns a pointer to it. + */ + +STATIC INLINE + CORE_message_queue_Buffer_control *_CORE_message_queue_Get_pending_message ( + CORE_message_queue_Control *the_message_queue +); + +/* + * _CORE_message_queue_Is_priority + * + * DESCRIPTION: + * + * This function returns TRUE if the priority attribute is + * enabled in the attribute_set and FALSE otherwise. + */ + +STATIC INLINE boolean _CORE_message_queue_Is_priority( + CORE_message_queue_Attributes *the_attribute +); + +/* + * _CORE_message_queue_Append + * + * DESCRIPTION: + * + * This routine places the_message at the rear of the outstanding + * messages on the_message_queue. + */ + +STATIC INLINE void _CORE_message_queue_Append ( + CORE_message_queue_Control *the_message_queue, + CORE_message_queue_Buffer_control *the_message +); + +/* + * _CORE_message_queue_Prepend + * + * DESCRIPTION: + * + * This routine places the_message at the rear of the outstanding + * messages on the_message_queue. + */ + +STATIC INLINE void _CORE_message_queue_Prepend ( + CORE_message_queue_Control *the_message_queue, + CORE_message_queue_Buffer_control *the_message +); + +/* + * _CORE_message_queue_Is_null + * + * DESCRIPTION: + * + * This function places the_message at the rear of the outstanding + * messages on the_message_queue. + */ + +STATIC INLINE boolean _CORE_message_queue_Is_null ( + CORE_message_queue_Control *the_message_queue +); + +#include <rtems/core/coremsg.inl> + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ + diff --git a/cpukit/score/inline/rtems/score/coremsg.inl b/cpukit/score/inline/rtems/score/coremsg.inl new file mode 100644 index 0000000000..d1b5429947 --- /dev/null +++ b/cpukit/score/inline/rtems/score/coremsg.inl @@ -0,0 +1,186 @@ +/* coremsg.inl + * + * This include file contains the static inline implementation of all + * inlined routines in the Core Message Handler. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __CORE_MESSAGE_QUEUE_inl +#define __CORE_MESSAGE_QUEUE_inl + +/*PAGE + * + * _CORE_message_queue_Send + * + */ + +STATIC INLINE CORE_message_queue_Status _CORE_message_queue_Send( + 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 +) +{ + return _CORE_message_queue_Submit( + the_message_queue, + buffer, + size, + id, + api_message_queue_mp_support, + CORE_MESSAGE_QUEUE_SEND_REQUEST + ); +} + +/*PAGE + * + * _CORE_message_queue_Urgent + * + */ + +STATIC INLINE CORE_message_queue_Status _CORE_message_queue_Urgent( + 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 +) +{ + return _CORE_message_queue_Submit( + the_message_queue, + buffer, + size, + id, + api_message_queue_mp_support, + CORE_MESSAGE_QUEUE_URGENT_REQUEST + ); +} + +/*PAGE + * + * _CORE_message_queue_Copy_buffer + * + */ + +STATIC INLINE void _CORE_message_queue_Copy_buffer ( + void *source, + void *destination, + unsigned32 size +) +{ + memcpy(destination, source, size); +} + +/*PAGE + * + * _CORE_message_queue_Allocate_message_buffer + * + */ + +STATIC INLINE CORE_message_queue_Buffer_control * +_CORE_message_queue_Allocate_message_buffer ( + CORE_message_queue_Control *the_message_queue +) +{ + return (CORE_message_queue_Buffer_control *) + _Chain_Get( &the_message_queue->Inactive_messages ); +} + +/*PAGE + * + * _CORE_message_queue_Free_message_buffer + * + */ + +STATIC INLINE void _CORE_message_queue_Free_message_buffer ( + CORE_message_queue_Control *the_message_queue, + CORE_message_queue_Buffer_control *the_message +) +{ + _Chain_Append( &the_message_queue->Inactive_messages, &the_message->Node ); +} + +/*PAGE + * + * _CORE_message_queue_Get_pending_message + * + */ + +STATIC INLINE + CORE_message_queue_Buffer_control *_CORE_message_queue_Get_pending_message ( + CORE_message_queue_Control *the_message_queue +) +{ + return (CORE_message_queue_Buffer_control *) + _Chain_Get_unprotected( &the_message_queue->Pending_messages ); +} + +/*PAGE + * + * _CORE_message_queue_Is_priority + * + */ + +STATIC INLINE boolean _CORE_message_queue_Is_priority( + CORE_message_queue_Attributes *the_attribute +) +{ + return (the_attribute->discipline == CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY); +} + +/*PAGE + * + * _CORE_message_queue_Append + * + */ + +STATIC INLINE void _CORE_message_queue_Append ( + CORE_message_queue_Control *the_message_queue, + CORE_message_queue_Buffer_control *the_message +) +{ + _Chain_Append( &the_message_queue->Pending_messages, &the_message->Node ); +} + +/*PAGE + * + * _CORE_message_queue_Prepend + * + */ + +STATIC INLINE void _CORE_message_queue_Prepend ( + CORE_message_queue_Control *the_message_queue, + CORE_message_queue_Buffer_control *the_message +) +{ + _Chain_Prepend( + &the_message_queue->Pending_messages, + &the_message->Node + ); +} + +/*PAGE + * + * _CORE_message_queue_Is_null + * + */ + +STATIC INLINE boolean _CORE_message_queue_Is_null ( + CORE_message_queue_Control *the_message_queue +) +{ + return ( the_message_queue == NULL ); +} + + +#endif +/* end of include file */ diff --git a/cpukit/score/macros/rtems/score/coremsg.inl b/cpukit/score/macros/rtems/score/coremsg.inl new file mode 100644 index 0000000000..877d737afd --- /dev/null +++ b/cpukit/score/macros/rtems/score/coremsg.inl @@ -0,0 +1,121 @@ +/* coremsg.inl + * + * This include file contains the macro implementation of all + * inlined routines in the Core Message Handler. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __CORE_MESSAGE_QUEUE_inl +#define __CORE_MESSAGE_QUEUE_inl + +/*PAGE + * + * _CORE_message_queue_Send + * + */ + +#define _CORE_message_queue_Send( _the_message_queue, _buffer, _size, \ +_id, _api_message_queue_mp_support ) \ + _CORE_message_queue_Submit( (_the_message_queue), (_buffer), (_size), \ + (_id), (_api_message_queue_mp_support), CORE_MESSAGE_QUEUE_SEND_REQUEST ) + +/*PAGE + * + * _CORE_message_queue_Urgent + * + */ + +#define _CORE_message_queue_Urgent( _the_message_queue, _buffer, _size, \ +_id, _api_message_queue_mp_support ) \ + _CORE_message_queue_Submit( (_the_message_queue), (_buffer), (_size), \ + (_id), (_api_message_queue_mp_support), CORE_MESSAGE_QUEUE_URGENT_REQUEST ) + +/*PAGE + * + * _CORE_message_queue_Copy_buffer + */ + +#define _CORE_message_queue_Copy_buffer( _source, _destination, _size ) \ + memcpy( _destination, _source, _size) + +/*PAGE + * + * _CORE_message_queue_Allocate_message_buffer + * + */ + +#define _CORE_message_queue_Allocate_message_buffer( _the_message_queue ) \ + (CORE_message_queue_Buffer_control *) \ + _Chain_Get( &(_the_message_queue)->Inactive_messages ) + +/*PAGE + * + * _CORE_message_queue_Free_message_buffer + * + */ + +#define _CORE_message_queue_Free_message_buffer( _the_message_queue, _the_message ) \ + _Chain_Append( \ + &(_the_message_queue)->Inactive_messages, \ + &(_the_message)->Node \ + ) + +/*PAGE + * + * _CORE_message_queue_Is_priority + * + */ + +#define _CORE_message_queue_Is_priority( _the_attribute ) \ + ((_the_attribute)->discipline == CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY) + +/*PAGE + * + * _CORE_message_queue_Get_pending_message + * + */ + +#define _CORE_message_queue_Get_pending_message( _the_message_queue ) \ + (CORE_message_queue_Buffer_control *) \ + _Chain_Get_unprotected( &(_the_message_queue)->Pending_messages ) + +/*PAGE + * + * _CORE_message_queue_Append + * + */ + +#define _CORE_message_queue_Append( _the_message_queue, _the_message ) \ + _Chain_Append( &(_the_message_queue)->Pending_messages, \ + &(_the_message)->Node ) + +/*PAGE + * + * _CORE_message_queue_Prepend + * + */ + +#define _CORE_message_queue_Prepend( _the_message_queue, _the_message ) \ + _Chain_Prepend( &(_the_message_queue)->Pending_messages, \ + &(_the_message)->Node ) + +/*PAGE + * + * _CORE_message_queue_Is_null + * + */ + +#define _CORE_message_queue_Is_null( _the_message_queue ) \ + ( (_the_message_queue) == NULL ) + +#endif +/* end of include file */ diff --git a/cpukit/score/src/coremsg.c b/cpukit/score/src/coremsg.c new file mode 100644 index 0000000000..2ce0587b5f --- /dev/null +++ b/cpukit/score/src/coremsg.c @@ -0,0 +1,436 @@ +/* + * 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, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/core/chain.h> +#include <rtems/core/isr.h> +#include <rtems/rtems/message.h> +#include <rtems/core/object.h> +#include <rtems/rtems/options.h> +#include <rtems/core/states.h> +#include <rtems/rtems/support.h> +#include <rtems/core/thread.h> +#include <rtems/core/wkspace.h> +#include <rtems/core/mpci.h> +#include <rtems/sysstate.h> + +/*PAGE + * + * _CORE_message_queue_Initialize + * + * This routine initializes a newly created message queue based on the + * specified data. + * + * Input parameters: + * the_message_queue - the message queue to initialize + * the_class - the API specific object class + * the_message_queue_attributes - the message queue's attributes + * maximum_pending_messages - maximum message and reserved buffer count + * maximum_message_size - maximum size of each message + * proxy_extract_callout - remote extract support + * + * Output parameters: + * TRUE - if the message queue is initialized + * FALSE - if the message queue is NOT initialized + */ + +boolean _CORE_message_queue_Initialize( + CORE_message_queue_Control *the_message_queue, + Objects_Classes the_class, + CORE_message_queue_Attributes *the_message_queue_attributes, + unsigned32 maximum_pending_messages, + unsigned32 maximum_message_size, + Thread_queue_Extract_callout proxy_extract_callout +) +{ + unsigned32 message_buffering_required; + unsigned32 allocated_message_size; + + the_message_queue->maximum_pending_messages = maximum_pending_messages; + the_message_queue->number_of_pending_messages = 0; + the_message_queue->maximum_message_size = maximum_message_size; + + /* + * round size up to multiple of a ptr for chain init + */ + + allocated_message_size = maximum_message_size; + if (allocated_message_size & (sizeof(unsigned32) - 1)) { + allocated_message_size += sizeof(unsigned32); + allocated_message_size &= ~(sizeof(unsigned32) - 1); + } + + message_buffering_required = maximum_pending_messages * + (allocated_message_size + sizeof(CORE_message_queue_Buffer_control)); + + the_message_queue->message_buffers = (CORE_message_queue_Buffer *) + _Workspace_Allocate( message_buffering_required ); + + if (the_message_queue->message_buffers == 0) + return FALSE; + + _Chain_Initialize ( + &the_message_queue->Inactive_messages, + the_message_queue->message_buffers, + maximum_pending_messages, + allocated_message_size + sizeof( CORE_message_queue_Buffer_control ) + ); + + _Chain_Initialize_empty( &the_message_queue->Pending_messages ); + + _Thread_queue_Initialize( + &the_message_queue->Wait_queue, + the_class, + _CORE_message_queue_Is_priority( the_message_queue_attributes ) ? + THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO, + STATES_WAITING_FOR_MESSAGE, + proxy_extract_callout, + CORE_MESSAGE_QUEUE_STATUS_TIMEOUT + ); + + 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 + ); + + *(rtems_unsigned32 *)the_thread->Wait.return_argument_1 = size; + + if ( !_Objects_Is_local_id( the_thread->Object.id ) ) + (*api_message_queue_mp_support) ( the_thread, id ); + + } + *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; + } + + the_message_queue->Wait_queue.sync = TRUE; + 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 + ); + *(rtems_unsigned32 *)the_thread->Wait.return_argument_1 = size; + + if ( !_Objects_Is_local_id( the_thread->Object.id ) ) + (*api_message_queue_mp_support) ( the_thread, id ); + + 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_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; + } + + return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL; +} |