diff options
Diffstat (limited to 'cpukit/rtems/src')
156 files changed, 14485 insertions, 0 deletions
diff --git a/cpukit/rtems/src/attr.c b/cpukit/rtems/src/attr.c new file mode 100644 index 0000000000..2312d36bb5 --- /dev/null +++ b/cpukit/rtems/src/attr.c @@ -0,0 +1,31 @@ +/* + * Body for Attribute Routines + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/stack.h> +#include <rtems/rtems/modes.h> + +uint32_t rtems_interrupt_mask = RTEMS_INTERRUPT_MASK; + +rtems_attribute rtems_interrupt_level_attribute( + uint32_t level +) +{ + return RTEMS_INTERRUPT_LEVEL(level); +} diff --git a/cpukit/rtems/src/barrier.c b/cpukit/rtems/src/barrier.c new file mode 100644 index 0000000000..b35b5e3415 --- /dev/null +++ b/cpukit/rtems/src/barrier.c @@ -0,0 +1,65 @@ +/* + * Barrier Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Barrier Manager. + * + * Directives provided are: + * + * + create a barrier + * + get an ID of a barrier + * + delete a barrier + * + acquire a barrier + * + release a barrier + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/barrier.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif + +/** + * @brief _Barrier_Manager_initialization + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _Barrier_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_Barrier_Information, /* object information table */ + OBJECTS_CLASSIC_API, /* object API */ + OBJECTS_RTEMS_BARRIERS, /* object class */ + Configuration_RTEMS_API.maximum_barriers, + /* maximum objects of this class */ + sizeof( Barrier_Control ), /* size of this object's control block */ + false, /* true if the name is a string */ + RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/rtems/src/barriercreate.c b/cpukit/rtems/src/barriercreate.c new file mode 100644 index 0000000000..89c4b55ec9 --- /dev/null +++ b/cpukit/rtems/src/barriercreate.c @@ -0,0 +1,92 @@ +/* + * Barrier Manager -- Create a Barrier Instance + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/attr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/barrier.h> + +/* + * rtems_barrier_create + * + * This directive creates a barrier. A barrier id is returned. + * + * Input parameters: + * name - user defined barrier name + * attribute_set - barrier attributes + * maximum_waiters - number of threads before automatic release + * priority_ceiling - barrier's ceiling priority + * id - pointer to barrier id + * + * Output parameters: + * id - barrier id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_barrier_create( + rtems_name name, + rtems_attribute attribute_set, + uint32_t maximum_waiters, + rtems_id *id +) +{ + Barrier_Control *the_barrier; + CORE_barrier_Attributes the_attributes; + + if ( !rtems_is_name_valid( name ) ) + return RTEMS_INVALID_NAME; + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + + /* Initialize core barrier attributes */ + if ( _Attributes_Is_barrier_automatic( attribute_set ) ) { + the_attributes.discipline = CORE_BARRIER_AUTOMATIC_RELEASE; + if ( maximum_waiters == 0 ) + return RTEMS_INVALID_NUMBER; + } else + the_attributes.discipline = CORE_BARRIER_MANUAL_RELEASE; + the_attributes.maximum_count = maximum_waiters; + + _Thread_Disable_dispatch(); /* prevents deletion */ + + the_barrier = _Barrier_Allocate(); + + if ( !the_barrier ) { + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } + + the_barrier->attribute_set = attribute_set; + + _CORE_barrier_Initialize( &the_barrier->Barrier, &the_attributes ); + + _Objects_Open( + &_Barrier_Information, + &the_barrier->Object, + (Objects_Name) name + ); + + *id = the_barrier->Object.id; + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/barrierdata.c b/cpukit/rtems/src/barrierdata.c new file mode 100644 index 0000000000..6e4af5a4c8 --- /dev/null +++ b/cpukit/rtems/src/barrierdata.c @@ -0,0 +1,23 @@ +/* + * Barrier Manager -- Instantiate Data + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate barrier data */ +#define RTEMS_BARRIER_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/barrier.h> + diff --git a/cpukit/rtems/src/barrierdelete.c b/cpukit/rtems/src/barrierdelete.c new file mode 100644 index 0000000000..6843a1bc00 --- /dev/null +++ b/cpukit/rtems/src/barrierdelete.c @@ -0,0 +1,73 @@ +/* + * Barrier Manager -- Delete a Barrier + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/barrier.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> + +/* + * rtems_barrier_delete + * + * This directive allows a thread to delete a barrier specified by + * the barrier id. The barrier is freed back to the inactive + * barrier chain. + * + * Input parameters: + * id - barrier id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_barrier_delete( + rtems_id id +) +{ + Barrier_Control *the_barrier; + Objects_Locations location; + + the_barrier = _Barrier_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _CORE_barrier_Flush( + &the_barrier->Barrier, + NULL, + CORE_BARRIER_WAS_DELETED + ); + + _Objects_Close( &_Barrier_Information, &the_barrier->Object ); + + _Barrier_Free( the_barrier ); + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/barrierident.c b/cpukit/rtems/src/barrierident.c new file mode 100644 index 0000000000..6b90dacf70 --- /dev/null +++ b/cpukit/rtems/src/barrierident.c @@ -0,0 +1,56 @@ +/* + * Barrier Manager Name to ID + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/barrier.h> + +/* + * rtems_barrier_ident + * + * This directive returns the system ID associated with + * the barrier name. + * + * Input parameters: + * name - user defined barrier name + * id - pointer to barrier id + * + * Output parameters: + * *id - barrier id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_barrier_ident( + rtems_name name, + rtems_id *id +) +{ + Objects_Name_or_id_lookup_errors status; + + status = _Objects_Name_to_id_u32( + &_Barrier_Information, + name, + OBJECTS_SEARCH_LOCAL_NODE, + id + ); + + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/barrierrelease.c b/cpukit/rtems/src/barrierrelease.c new file mode 100644 index 0000000000..8bb53b8664 --- /dev/null +++ b/cpukit/rtems/src/barrierrelease.c @@ -0,0 +1,67 @@ +/* + * Barrier Manager -- Release Tasks Waitng at a Barrier + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/barrier.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> + +/* + * rtems_barrier_release + * + * This directive releases all threads waiting at a barrier. + * + * Input parameters: + * id - barrier id + * released - pointer to number of threads unblocked + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + * *released - number of threads unblocked + */ + +rtems_status_code rtems_barrier_release( + rtems_id id, + uint32_t *released +) +{ + Barrier_Control *the_barrier; + Objects_Locations location; + + if ( !released ) + return RTEMS_INVALID_ADDRESS; + + the_barrier = _Barrier_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + *released = _CORE_barrier_Release( &the_barrier->Barrier, id, NULL ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/barriertranslatereturncode.c b/cpukit/rtems/src/barriertranslatereturncode.c new file mode 100644 index 0000000000..97d7feb911 --- /dev/null +++ b/cpukit/rtems/src/barriertranslatereturncode.c @@ -0,0 +1,53 @@ +/* + * Barrier Manager -- Translate SuperCore Status + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/barrier.h> + +/* + * _Barrier_Translate_core_barrier_return_code + * + * Input parameters: + * the_barrier_status - barrier status code to translate + * + * Output parameters: + * rtems status code - translated RTEMS status code + * + */ + +rtems_status_code _Barrier_Translate_core_barrier_return_code_[] = { + RTEMS_SUCCESSFUL, /* CORE_BARRIER_STATUS_SUCCESSFUL */ + RTEMS_SUCCESSFUL, /* CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED */ + RTEMS_OBJECT_WAS_DELETED, /* CORE_BARRIER_WAS_DELETED */ + RTEMS_TIMEOUT /* CORE_BARRIER_TIMEOUT */ +}; + +rtems_status_code _Barrier_Translate_core_barrier_return_code ( + CORE_barrier_Status the_barrier_status +) +{ + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( the_barrier_status > CORE_BARRIER_STATUS_LAST ) + return RTEMS_INTERNAL_ERROR; + #endif + return _Barrier_Translate_core_barrier_return_code_[the_barrier_status]; +} diff --git a/cpukit/rtems/src/barrierwait.c b/cpukit/rtems/src/barrierwait.c new file mode 100644 index 0000000000..04b2389051 --- /dev/null +++ b/cpukit/rtems/src/barrierwait.c @@ -0,0 +1,70 @@ +/* + * Barrier Manager -- Wait at a Barrier + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/barrier.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> + +/* + * rtems_barrier_wait + * + * This directive allows a thread to wait at a barrier. + * + * Input parameters: + * id - barrier id + * timeout - number of ticks to wait (0 means wait forever) + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_barrier_wait( + rtems_id id, + rtems_interval timeout +) +{ + Barrier_Control *the_barrier; + Objects_Locations location; + + the_barrier = _Barrier_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _CORE_barrier_Wait( + &the_barrier->Barrier, + id, + true, + timeout, + NULL + ); + _Thread_Enable_dispatch(); + return _Barrier_Translate_core_barrier_return_code( + _Thread_Executing->Wait.return_code ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/clockget.c b/cpukit/rtems/src/clockget.c new file mode 100644 index 0000000000..03d8ec453f --- /dev/null +++ b/cpukit/rtems/src/clockget.c @@ -0,0 +1,76 @@ +/* + * Clock Manager + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/* + * rtems_clock_get + * + * This directive returns the current date and time. If the time has + * not been set by a tm_set then an error is returned. + * + * Input parameters: + * option - which value to return + * time_buffer - pointer to output buffer (a time and date structure + * or an interval) + * + * Output parameters: + * time_buffer - output filled in + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_clock_get( + rtems_clock_get_options option, + void *time_buffer +) +{ + if ( !time_buffer ) + return RTEMS_INVALID_ADDRESS; + + if ( option == RTEMS_CLOCK_GET_TOD ) + return rtems_clock_get_tod( (rtems_time_of_day *)time_buffer ); + + if ( option == RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH ) + return rtems_clock_get_seconds_since_epoch((rtems_interval *)time_buffer); + + if ( option == RTEMS_CLOCK_GET_TICKS_SINCE_BOOT ) { + rtems_interval *interval = (rtems_interval *)time_buffer; + + *interval = rtems_clock_get_ticks_since_boot(); + return RTEMS_SUCCESSFUL; + } + + if ( option == RTEMS_CLOCK_GET_TICKS_PER_SECOND ) { + rtems_interval *interval = (rtems_interval *)time_buffer; + + *interval = rtems_clock_get_ticks_per_second(); + return RTEMS_SUCCESSFUL; + } + + if ( option == RTEMS_CLOCK_GET_TIME_VALUE ) + return rtems_clock_get_tod_timeval( (struct timeval *)time_buffer ); + + return RTEMS_INVALID_NUMBER; + +} diff --git a/cpukit/rtems/src/clockgetsecondssinceepoch.c b/cpukit/rtems/src/clockgetsecondssinceepoch.c new file mode 100644 index 0000000000..c8fcdc3183 --- /dev/null +++ b/cpukit/rtems/src/clockgetsecondssinceepoch.c @@ -0,0 +1,38 @@ +/* + * Clock Manager - Get Seconds Since Epoch + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +rtems_status_code rtems_clock_get_seconds_since_epoch( + rtems_interval *the_interval +) +{ + if ( !the_interval ) + return RTEMS_INVALID_ADDRESS; + + if ( !_TOD_Is_set ) + return RTEMS_NOT_DEFINED; + + *the_interval = _TOD_Seconds_since_epoch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/clockgettickspersecond.c b/cpukit/rtems/src/clockgettickspersecond.c new file mode 100644 index 0000000000..23e2dd7c39 --- /dev/null +++ b/cpukit/rtems/src/clockgettickspersecond.c @@ -0,0 +1,31 @@ +/* + * Clock Manager - Get Ticks Per Second + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +rtems_interval rtems_clock_get_ticks_per_second(void) +{ + return TOD_MICROSECONDS_PER_SECOND / + rtems_configuration_get_microseconds_per_tick(); +} diff --git a/cpukit/rtems/src/clockgettickssinceboot.c b/cpukit/rtems/src/clockgettickssinceboot.c new file mode 100644 index 0000000000..a97e40106e --- /dev/null +++ b/cpukit/rtems/src/clockgettickssinceboot.c @@ -0,0 +1,29 @@ +/* + * Clock Manager - Get Ticks Since Boot + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +rtems_interval rtems_clock_get_ticks_since_boot(void) +{ + return _Watchdog_Ticks_since_boot; +} diff --git a/cpukit/rtems/src/clockgettod.c b/cpukit/rtems/src/clockgettod.c new file mode 100644 index 0000000000..4c4e77c2ae --- /dev/null +++ b/cpukit/rtems/src/clockgettod.c @@ -0,0 +1,58 @@ +/* + * Clock Manager - rtems_clock_get_tod + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +rtems_status_code rtems_clock_get_tod( + rtems_time_of_day *time_buffer +) +{ + rtems_time_of_day *tmbuf = time_buffer; + struct tm time; + struct timeval now; + + if ( !time_buffer ) + return RTEMS_INVALID_ADDRESS; + + if ( !_TOD_Is_set ) + return RTEMS_NOT_DEFINED; + + /* Obtain the current time */ + _TOD_Get_timeval( &now ); + + /* Split it into a closer format */ + gmtime_r( &now.tv_sec, &time ); + + /* Now adjust it to the RTEMS format */ + tmbuf->year = time.tm_year + 1900; + tmbuf->month = time.tm_mon + 1; + tmbuf->day = time.tm_mday; + tmbuf->hour = time.tm_hour; + tmbuf->minute = time.tm_min; + tmbuf->second = time.tm_sec; + tmbuf->ticks = now.tv_usec / + rtems_configuration_get_microseconds_per_tick(); + + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/clockgettodtimeval.c b/cpukit/rtems/src/clockgettodtimeval.c new file mode 100644 index 0000000000..71e53ffd24 --- /dev/null +++ b/cpukit/rtems/src/clockgettodtimeval.c @@ -0,0 +1,39 @@ +/* + * Clock Manager - Get TOD in Time Value Format + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +rtems_status_code rtems_clock_get_tod_timeval( + struct timeval *time +) +{ + if ( !time ) + return RTEMS_INVALID_ADDRESS; + + if ( !_TOD_Is_set ) + return RTEMS_NOT_DEFINED; + + _TOD_Get_timeval( time ); + + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/clockgetuptime.c b/cpukit/rtems/src/clockgetuptime.c new file mode 100644 index 0000000000..b6ea0e5448 --- /dev/null +++ b/cpukit/rtems/src/clockgetuptime.c @@ -0,0 +1,51 @@ +/* + * Clock Manager - get uptime + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/timestamp.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_clock_get_uptime + * + * This directive obtains the system uptime. A timestamp is the seconds + * and nanoseconds since boot. + * + * Input parameters: + * timestamp - pointer to the timestamp + * + * Output parameters: + * *uptime - filled in + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ +rtems_status_code rtems_clock_get_uptime( + struct timespec *uptime +) +{ + if ( !uptime ) + return RTEMS_INVALID_ADDRESS; + + _TOD_Get_uptime_as_timespec( uptime ); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/clockset.c b/cpukit/rtems/src/clockset.c new file mode 100644 index 0000000000..bb27697829 --- /dev/null +++ b/cpukit/rtems/src/clockset.c @@ -0,0 +1,61 @@ +/* + * Clock Manager + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_clock_set + * + * This directive sets the date and time for this node. + * + * Input parameters: + * time_buffer - pointer to the time and date structure + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_clock_set( + rtems_time_of_day *time_buffer +) +{ + struct timespec newtime; + + if ( !time_buffer ) + return RTEMS_INVALID_ADDRESS; + + if ( _TOD_Validate( time_buffer ) ) { + newtime.tv_sec = _TOD_To_seconds( time_buffer ); + newtime.tv_nsec = time_buffer->ticks * + rtems_configuration_get_nanoseconds_per_tick(); + + _Thread_Disable_dispatch(); + _TOD_Set( &newtime ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + return RTEMS_INVALID_CLOCK; +} diff --git a/cpukit/rtems/src/clocksetnsecshandler.c b/cpukit/rtems/src/clocksetnsecshandler.c new file mode 100644 index 0000000000..8e4d0b113e --- /dev/null +++ b/cpukit/rtems/src/clocksetnsecshandler.c @@ -0,0 +1,49 @@ +/* + * Clock Manager + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_clock_set_nanoseconds_extension + * + * This directive sets the BSP provided nanoseconds since last tick + * extension. + * + * Input parameters: + * routine - pointer to the extension routine + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ +rtems_status_code rtems_clock_set_nanoseconds_extension( + rtems_nanoseconds_extension_routine routine +) +{ + if ( !routine ) + return RTEMS_INVALID_ADDRESS; + + _Watchdog_Nanoseconds_since_tick_handler = routine; + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/clocktick.c b/cpukit/rtems/src/clocktick.c new file mode 100644 index 0000000000..f02f48fb45 --- /dev/null +++ b/cpukit/rtems/src/clocktick.c @@ -0,0 +1,55 @@ +/* + * Clock Manager + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_clock_tick + * + * This directive notifies the executve that a tick has occurred. + * When the tick occurs the time manager updates and maintains + * the calendar time, timeslicing, and any timeout delays. + * + * Input parameters: NONE + * + * Output parameters: + * RTEMS_SUCCESSFUL - always succeeds + * + * NOTE: This routine only works for leap-years through 2099. + */ + +rtems_status_code rtems_clock_tick( void ) +{ + _TOD_Tickle_ticks(); + + _Watchdog_Tickle_ticks(); + + _Thread_Tickle_timeslice(); + + if ( _Thread_Is_context_switch_necessary() && + _Thread_Is_dispatching_enabled() ) + _Thread_Dispatch(); + + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/clocktodtoseconds.c b/cpukit/rtems/src/clocktodtoseconds.c new file mode 100644 index 0000000000..c5093e180d --- /dev/null +++ b/cpukit/rtems/src/clocktodtoseconds.c @@ -0,0 +1,85 @@ +/* + * Time of Day (TOD) Handler - Classic TOD to Seconds + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/clock.h> + +/* + * The following array contains the number of days in all months + * up to the month indicated by the index of the second dimension. + * The first dimension should be 1 for leap years, and 0 otherwise. + */ +const uint16_t _TOD_Days_to_date[2][13] = { + { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, + { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } +}; + +/* + * The following array contains the number of days in the years + * since the last leap year. The index should be 0 for leap + * years, and the number of years since the beginning of a leap + * year otherwise. + */ +const uint16_t _TOD_Days_since_last_leap_year[4] = { 0, 366, 731, 1096 }; + + + +/*PAGE + * + * _TOD_To_seconds + * + * This routine returns the seconds from the epoch until the + * current date and time. + * + * Input parameters: + * the_tod - pointer to the time and date structure + * + * Output parameters: + * returns - seconds since epoch until the_tod + */ + +uint32_t _TOD_To_seconds( + const rtems_time_of_day *the_tod +) +{ + uint32_t time; + uint32_t year_mod_4; + + time = the_tod->day - 1; + year_mod_4 = the_tod->year & 3; + + if ( year_mod_4 == 0 ) + time += _TOD_Days_to_date[ 1 ][ the_tod->month ]; + else + time += _TOD_Days_to_date[ 0 ][ the_tod->month ]; + + time += ( (the_tod->year - TOD_BASE_YEAR) / 4 ) * + ( (TOD_DAYS_PER_YEAR * 4) + 1); + + time += _TOD_Days_since_last_leap_year[ year_mod_4 ]; + + time *= TOD_SECONDS_PER_DAY; + + time += ((the_tod->hour * TOD_MINUTES_PER_HOUR) + the_tod->minute) + * TOD_SECONDS_PER_MINUTE; + + time += the_tod->second; + + time += TOD_SECONDS_1970_THROUGH_1988; + + return( time ); +} diff --git a/cpukit/rtems/src/clocktodvalidate.c b/cpukit/rtems/src/clocktodvalidate.c new file mode 100644 index 0000000000..1dac1dc6b1 --- /dev/null +++ b/cpukit/rtems/src/clocktodvalidate.c @@ -0,0 +1,79 @@ +/* + * Time of Day (TOD) Handler -- Validate Classic TOD + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/clock.h> + +/* + * The following array contains the number of days in all months. + * The first dimension should be 1 for leap years, and 0 otherwise. + * The second dimension should range from 1 to 12 for January to + * February, respectively. + */ +const uint32_t _TOD_Days_per_month[ 2 ][ 13 ] = { + { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +/*PAGE + * + * _TOD_Validate + * + * This kernel routine checks the validity of a date and time structure. + * + * Input parameters: + * the_tod - pointer to a time and date structure + * + * Output parameters: + * true - if the date, time, and tick are valid + * false - if the the_tod is invalid + * + * NOTE: This routine only works for leap-years through 2099. + */ + +bool _TOD_Validate( + const rtems_time_of_day *the_tod +) +{ + uint32_t days_in_month; + uint32_t ticks_per_second; + + ticks_per_second = TOD_MICROSECONDS_PER_SECOND / + rtems_configuration_get_microseconds_per_tick(); + if ((!the_tod) || + (the_tod->ticks >= ticks_per_second) || + (the_tod->second >= TOD_SECONDS_PER_MINUTE) || + (the_tod->minute >= TOD_MINUTES_PER_HOUR) || + (the_tod->hour >= TOD_HOURS_PER_DAY) || + (the_tod->month == 0) || + (the_tod->month > TOD_MONTHS_PER_YEAR) || + (the_tod->year < TOD_BASE_YEAR) || + (the_tod->day == 0) ) + return false; + + if ( (the_tod->year % 4) == 0 ) + days_in_month = _TOD_Days_per_month[ 1 ][ the_tod->month ]; + else + days_in_month = _TOD_Days_per_month[ 0 ][ the_tod->month ]; + + if ( the_tod->day > days_in_month ) + return false; + + return true; +} diff --git a/cpukit/rtems/src/dpmem.c b/cpukit/rtems/src/dpmem.c new file mode 100644 index 0000000000..9cc58914b8 --- /dev/null +++ b/cpukit/rtems/src/dpmem.c @@ -0,0 +1,57 @@ +/* + * Dual Port Memory Manager + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/rtems/dpmem.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * _Dual_ported_memory_Manager_initialization + * + * This routine initializes all dual-ported memory manager related + * data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _Dual_ported_memory_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_Dual_ported_memory_Information, /* object information table */ + OBJECTS_CLASSIC_API, /* object API */ + OBJECTS_RTEMS_PORTS, /* object class */ + Configuration_RTEMS_API.maximum_ports, + /* maximum objects of this class */ + sizeof( Dual_ported_memory_Control ), + /* size of this object's control block */ + false, /* true if names of this object are strings */ + RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/rtems/src/dpmemcreate.c b/cpukit/rtems/src/dpmemcreate.c new file mode 100644 index 0000000000..69df430dd8 --- /dev/null +++ b/cpukit/rtems/src/dpmemcreate.c @@ -0,0 +1,88 @@ +/* + * Dual Port Memory Manager + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/rtems/dpmem.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/dpmem.h> + +/*PAGE + * + * rtems_port_create + * + * This directive creates a port into a dual-ported memory area. + * + * Input parameters: + * name - user defined port name + * internal_start - internal start address of port + * external_start - external start address of port + * length - physical length in bytes + * id - address of port id to set + * + * Output parameters: + * id - port id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_port_create( + rtems_name name, + void *internal_start, + void *external_start, + uint32_t length, + rtems_id *id +) +{ + register Dual_ported_memory_Control *the_port; + + if ( !rtems_is_name_valid( name ) ) + return RTEMS_INVALID_NAME; + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + + if ( !_Addresses_Is_aligned( internal_start ) || + !_Addresses_Is_aligned( external_start ) ) + return RTEMS_INVALID_ADDRESS; + + _Thread_Disable_dispatch(); /* to prevent deletion */ + + the_port = _Dual_ported_memory_Allocate(); + + if ( !the_port ) { + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } + + the_port->internal_base = internal_start; + the_port->external_base = external_start; + the_port->length = length - 1; + + _Objects_Open( + &_Dual_ported_memory_Information, + &the_port->Object, + (Objects_Name) name + ); + + *id = the_port->Object.id; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/dpmemdata.c b/cpukit/rtems/src/dpmemdata.c new file mode 100644 index 0000000000..cc2285c1f6 --- /dev/null +++ b/cpukit/rtems/src/dpmemdata.c @@ -0,0 +1,22 @@ +/* + * Dual Port Memory Manager -- Instantiate Data + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate semaphore data */ +#define RTEMS_DPMEM_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/dpmem.h> diff --git a/cpukit/rtems/src/dpmemdelete.c b/cpukit/rtems/src/dpmemdelete.c new file mode 100644 index 0000000000..003c27fecb --- /dev/null +++ b/cpukit/rtems/src/dpmemdelete.c @@ -0,0 +1,66 @@ +/* + * Dual Port Memory Manager + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/rtems/dpmem.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/dpmem.h> + +/*PAGE + * + * rtems_port_delete + * + * This directive allows a thread to delete a dual-ported memory area + * specified by the dual-ported memory identifier. + * + * Input parameters: + * id - dual-ported memory area id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_port_delete( + rtems_id id +) +{ + register Dual_ported_memory_Control *the_port; + Objects_Locations location; + + the_port = _Dual_ported_memory_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Objects_Close( &_Dual_ported_memory_Information, &the_port->Object ); + _Dual_ported_memory_Free( the_port ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/dpmemexternal2internal.c b/cpukit/rtems/src/dpmemexternal2internal.c new file mode 100644 index 0000000000..45c8344588 --- /dev/null +++ b/cpukit/rtems/src/dpmemexternal2internal.c @@ -0,0 +1,79 @@ +/* + * Dual Port Memory Manager + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/rtems/dpmem.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/dpmem.h> + +/*PAGE + * + * rtems_port_external_to_internal + * + * This directive converts an external dual-ported memory address to an + * internal dual-ported memory address. If the given external address + * is an invalid dual-ported address, then the internal address is set + * to the given external address. + * + * Input parameters: + * id - id of dp memory object + * external - external address + * internal - pointer of internal address to set + * + * Output parameters: + * internal - internal address + * RTEMS_SUCCESSFUL - always succeeds + */ + +rtems_status_code rtems_port_external_to_internal( + rtems_id id, + void *external, + void **internal +) +{ + register Dual_ported_memory_Control *the_port; + Objects_Locations location; + uint32_t ending; + + if ( !internal ) + return RTEMS_INVALID_ADDRESS; + + the_port = _Dual_ported_memory_Get( id, &location ); + switch ( location ) { + case OBJECTS_LOCAL: + ending = _Addresses_Subtract( external, the_port->external_base ); + if ( ending > the_port->length ) + *internal = external; + else + *internal = _Addresses_Add_offset( the_port->internal_base, + ending ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/dpmemident.c b/cpukit/rtems/src/dpmemident.c new file mode 100644 index 0000000000..f41aef293b --- /dev/null +++ b/cpukit/rtems/src/dpmemident.c @@ -0,0 +1,59 @@ +/* + * Dual Port Memory Manager + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/rtems/dpmem.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/dpmem.h> + +/*PAGE + * + * rtems_port_ident + * + * This directive returns the system ID associated with + * the port name. + * + * Input parameters: + * name - user defined port name + * id - pointer to port id + * + * Output parameters: + * *id - port id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_port_ident( + rtems_name name, + rtems_id *id +) +{ + Objects_Name_or_id_lookup_errors status; + + status = _Objects_Name_to_id_u32( + &_Dual_ported_memory_Information, + name, + OBJECTS_SEARCH_ALL_NODES, + id + ); + + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/dpmeminternal2external.c b/cpukit/rtems/src/dpmeminternal2external.c new file mode 100644 index 0000000000..5bf4d4fe93 --- /dev/null +++ b/cpukit/rtems/src/dpmeminternal2external.c @@ -0,0 +1,80 @@ +/* + * Dual Port Memory Manager + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/rtems/dpmem.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/dpmem.h> + +/*PAGE + * + * rtems_port_internal_to_external + * + * This directive converts an internal dual-ported memory address to an + * external dual-ported memory address. If the given internal address + * is an invalid dual-ported address, then the external address is set + * to the given internal address. + * + * Input parameters: + * id - id of dual-ported memory object + * internal - internal address to set + * external - pointer to external address + * + * Output parameters: + * external - external address + * RTEMS_SUCCESSFUL - always succeeds + */ + +rtems_status_code rtems_port_internal_to_external( + rtems_id id, + void *internal, + void **external +) +{ + register Dual_ported_memory_Control *the_port; + Objects_Locations location; + uint32_t ending; + + if ( !external ) + return RTEMS_INVALID_ADDRESS; + + the_port = _Dual_ported_memory_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + ending = _Addresses_Subtract( internal, the_port->internal_base ); + if ( ending > the_port->length ) + *external = internal; + else + *external = _Addresses_Add_offset( the_port->external_base, + ending ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/event.c b/cpukit/rtems/src/event.c new file mode 100644 index 0000000000..85d35829c2 --- /dev/null +++ b/cpukit/rtems/src/event.c @@ -0,0 +1,48 @@ +/* + * Event Manager + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/event.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/tasks.h> + +/*PAGE + * + * _Event_Manager_initialization + * + * DESCRIPTION: + * + * This routine performs the initialization necessary for this manager. + */ + +void _Event_Manager_initialization( void ) +{ + _Event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; + + /* + * Register the MP Process Packet routine. + */ + +#if defined(RTEMS_MULTIPROCESSING) + _MPCI_Register_packet_processor( MP_PACKET_EVENT, _Event_MP_Process_packet ); +#endif +} diff --git a/cpukit/rtems/src/eventdata.c b/cpukit/rtems/src/eventdata.c new file mode 100644 index 0000000000..bc7eb466c1 --- /dev/null +++ b/cpukit/rtems/src/eventdata.c @@ -0,0 +1,22 @@ +/* + * Event Manager -- Instantiate Data + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate RTEMS event data */ +#define RTEMS_EVENT_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/event.h> diff --git a/cpukit/rtems/src/eventmp.c b/cpukit/rtems/src/eventmp.c new file mode 100644 index 0000000000..552d283994 --- /dev/null +++ b/cpukit/rtems/src/eventmp.c @@ -0,0 +1,193 @@ +/* + * Multiprocessing Support for the Event Manager + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/event.h> +#include <rtems/score/mpci.h> +#include <rtems/score/mppkt.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _Event_MP_Send_process_packet + * + * This subprogram is not needed since there are no process + * packets to be sent by this manager. + * + */ + +/*PAGE + * + * _Event_MP_Send_request_packet + * + */ + +rtems_status_code _Event_MP_Send_request_packet ( + Event_MP_Remote_operations operation, + Objects_Id event_id, + rtems_event_set event_in +) +{ + Event_MP_Packet *the_packet; + + switch ( operation ) { + + case EVENT_MP_SEND_REQUEST: + + the_packet = _Event_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_EVENT; + the_packet->Prefix.length = sizeof ( Event_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( Event_MP_Packet ); + the_packet->operation = operation; + the_packet->Prefix.id = event_id; + the_packet->event_in = event_in; + + return (rtems_status_code) + _MPCI_Send_request_packet( + _Objects_Get_node( event_id ), + &the_packet->Prefix, + STATES_READY + ); + + break; + + case EVENT_MP_SEND_RESPONSE: + break; + + } + /* + * The following line is included to satisfy compilers which + * produce warnings when a function does not end with a return. + */ + return RTEMS_SUCCESSFUL; +} + +/*PAGE + * + * _Event_MP_Send_response_packet + * + */ + +void _Event_MP_Send_response_packet ( + Event_MP_Remote_operations operation, + Thread_Control *the_thread +) +{ + Event_MP_Packet *the_packet; + + switch ( operation ) { + + case EVENT_MP_SEND_RESPONSE: + + the_packet = ( Event_MP_Packet *) the_thread->receive_packet; + +/* + * The packet being returned already contains the class, length, and + * to_convert fields, therefore they are not set in this routine. + */ + the_packet->operation = operation; + the_packet->Prefix.id = the_packet->Prefix.source_tid; + + _MPCI_Send_response_packet( + _Objects_Get_node( the_packet->Prefix.source_tid ), + &the_packet->Prefix + ); + break; + + case EVENT_MP_SEND_REQUEST: + break; + + } +} + +/*PAGE + * + * + * _Event_MP_Process_packet + * + */ + +void _Event_MP_Process_packet ( + rtems_packet_prefix *the_packet_prefix +) +{ + Event_MP_Packet *the_packet; + Thread_Control *the_thread; + + the_packet = (Event_MP_Packet *) the_packet_prefix; + + switch ( the_packet->operation ) { + + case EVENT_MP_SEND_REQUEST: + + the_packet->Prefix.return_code = rtems_event_send( + the_packet->Prefix.id, + the_packet->event_in + ); + + _Event_MP_Send_response_packet( + EVENT_MP_SEND_RESPONSE, + _Thread_Executing + ); + break; + + case EVENT_MP_SEND_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + _MPCI_Return_packet( the_packet_prefix ); + + break; + + } +} + +/*PAGE + * + * _Event_MP_Send_object_was_deleted + * + * This subprogram is not needed since there are no objects + * deleted by this manager. + * + */ + +/*PAGE + * + * _Event_MP_Send_extract_proxy + * + * This subprogram is not needed since there are no objects + * deleted by this manager. + * + */ + +/*PAGE + * + * _Event_MP_Get_packet + * + */ + +Event_MP_Packet *_Event_MP_Get_packet ( void ) +{ + return ( (Event_MP_Packet *) _MPCI_Get_packet() ); +} + +/* end of file */ diff --git a/cpukit/rtems/src/eventreceive.c b/cpukit/rtems/src/eventreceive.c new file mode 100644 index 0000000000..54bb7ef54c --- /dev/null +++ b/cpukit/rtems/src/eventreceive.c @@ -0,0 +1,69 @@ +/* + * Event Manager + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/event.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/tasks.h> + +/*PAGE + * + * rtems_event_receive + * + * This directive allows a thread to receive a set of events. + * + * Input parameters: + * event_in - input event condition + * option_set - options + * ticks - number of ticks to wait (0 means wait forever) + * event_out - pointer to output event set + * + * Output parameters: + * event out - event set + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_event_receive( + rtems_event_set event_in, + rtems_option option_set, + rtems_interval ticks, + rtems_event_set *event_out +) +{ + RTEMS_API_Control *api; + + if ( !event_out ) + return RTEMS_INVALID_ADDRESS; + + api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ]; + + if ( _Event_sets_Is_empty( event_in ) ) { + *event_out = api->pending_events; + return RTEMS_SUCCESSFUL; + } + + _Thread_Disable_dispatch(); + _Event_Seize( event_in, option_set, ticks, event_out ); + _Thread_Enable_dispatch(); + return( _Thread_Executing->Wait.return_code ); +} diff --git a/cpukit/rtems/src/eventseize.c b/cpukit/rtems/src/eventseize.c new file mode 100644 index 0000000000..0b6bf2d623 --- /dev/null +++ b/cpukit/rtems/src/eventseize.c @@ -0,0 +1,133 @@ +/* + * Event Manager + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/event.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/tasks.h> + +/*PAGE + * + * _Event_Seize + * + * This routine attempts to satisfy the requested event condition + * for the running thread. + * + * Input parameters: + * event_in - the event condition to satisfy + * option_set - acquire event options + * ticks - interval to wait + * event_out - pointer to event set output area + * + * Output parameters: NONE + * *event_out - event set output area filled in + * + * INTERRUPT LATENCY: + * available + * wait + * check sync + */ + +void _Event_Seize( + rtems_event_set event_in, + rtems_option option_set, + rtems_interval ticks, + rtems_event_set *event_out +) +{ + Thread_Control *executing; + rtems_event_set seized_events; + rtems_event_set pending_events; + ISR_Level level; + RTEMS_API_Control *api; + Thread_blocking_operation_States sync_state; + + executing = _Thread_Executing; + executing->Wait.return_code = RTEMS_SUCCESSFUL; + + api = executing->API_Extensions[ THREAD_API_RTEMS ]; + + _ISR_Disable( level ); + pending_events = api->pending_events; + seized_events = _Event_sets_Get( pending_events, event_in ); + + if ( !_Event_sets_Is_empty( seized_events ) && + (seized_events == event_in || _Options_Is_any( option_set )) ) { + api->pending_events = + _Event_sets_Clear( pending_events, seized_events ); + _ISR_Enable( level ); + *event_out = seized_events; + return; + } + + if ( _Options_Is_no_wait( option_set ) ) { + _ISR_Enable( level ); + executing->Wait.return_code = RTEMS_UNSATISFIED; + *event_out = seized_events; + return; + } + + /* + * Note what we are waiting for BEFORE we enter the critical section. + * The interrupt critical section management code needs this to be + * set properly when we are marked as in the event critical section. + * + * NOTE: Since interrupts are disabled, this isn't that much of an + * issue but better safe than sorry. + */ + executing->Wait.option = (uint32_t) option_set; + executing->Wait.count = (uint32_t) event_in; + executing->Wait.return_argument = event_out; + + _Event_Sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; + + _ISR_Enable( level ); + + if ( ticks ) { + _Watchdog_Initialize( + &executing->Timer, + _Event_Timeout, + executing->Object.id, + NULL + ); + _Watchdog_Insert_ticks( &executing->Timer, ticks ); + } + + _Thread_Set_state( executing, STATES_WAITING_FOR_EVENT ); + + _ISR_Disable( level ); + + sync_state = _Event_Sync_state; + _Event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; + if ( sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) { + _ISR_Enable( level ); + return; + } + + /* + * An interrupt completed the thread's blocking request. + * The blocking thread was satisfied by an ISR or timed out. + * + * WARNING! Returning with interrupts disabled! + */ + _Thread_blocking_operation_Cancel( sync_state, executing, level ); +} diff --git a/cpukit/rtems/src/eventsend.c b/cpukit/rtems/src/eventsend.c new file mode 100644 index 0000000000..412d52a7f1 --- /dev/null +++ b/cpukit/rtems/src/eventsend.c @@ -0,0 +1,78 @@ +/* + * Event Manager + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/event.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/tasks.h> + +/*PAGE + * + * rtems_event_send + * + * This directive allows a thread send an event set to another thread. + * + * Input parameters: + * id - thread id + * event - event set + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_event_send( + rtems_id id, + rtems_event_set event_in +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + RTEMS_API_Control *api; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + _Event_sets_Post( event_in, &api->pending_events ); + _Event_Surrender( the_thread ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return( + _Event_MP_Send_request_packet( + EVENT_MP_SEND_REQUEST, + id, + event_in + ) + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/eventsurrender.c b/cpukit/rtems/src/eventsurrender.c new file mode 100644 index 0000000000..179727f523 --- /dev/null +++ b/cpukit/rtems/src/eventsurrender.c @@ -0,0 +1,116 @@ +/* + * Event Manager + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/event.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/tasks.h> + +/*PAGE + * + * _Event_Surrender + * + * This routines remove a thread from the specified threadq. + * + * Input parameters: + * the_thread - pointer to thread to be dequeued + * + * Output parameters: NONE + * + * INTERRUPT LATENCY: + * before flash + * after flash + * check sync + */ + +void _Event_Surrender( + Thread_Control *the_thread +) +{ + ISR_Level level; + rtems_event_set pending_events; + rtems_event_set event_condition; + rtems_event_set seized_events; + rtems_option option_set; + RTEMS_API_Control *api; + + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + + option_set = (rtems_option) the_thread->Wait.option; + + _ISR_Disable( level ); + pending_events = api->pending_events; + event_condition = (rtems_event_set) the_thread->Wait.count; + + seized_events = _Event_sets_Get( pending_events, event_condition ); + + /* + * No events were seized in this operation + */ + if ( _Event_sets_Is_empty( seized_events ) ) { + _ISR_Enable( level ); + return; + } + + /* + * If we are in an ISR and sending to the current thread, then + * we have a critical section issue to deal with. + */ + if ( _ISR_Is_in_progress() && + _Thread_Is_executing( the_thread ) && + ((_Event_Sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT) || + (_Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED)) ) { + if ( seized_events == event_condition || _Options_Is_any(option_set) ) { + api->pending_events = _Event_sets_Clear( pending_events,seized_events ); + the_thread->Wait.count = 0; + *(rtems_event_set *)the_thread->Wait.return_argument = seized_events; + _Event_Sync_state = THREAD_BLOCKING_OPERATION_SATISFIED; + } + _ISR_Enable( level ); + return; + } + + /* + * Otherwise, this is a normal send to another thread + */ + if ( _States_Is_waiting_for_event( the_thread->current_state ) ) { + if ( seized_events == event_condition || _Options_Is_any( option_set ) ) { + api->pending_events = _Event_sets_Clear( pending_events, seized_events ); + the_thread->Wait.count = 0; + *(rtems_event_set *)the_thread->Wait.return_argument = seized_events; + + _ISR_Flash( level ); + + if ( !_Watchdog_Is_active( &the_thread->Timer ) ) { + _ISR_Enable( level ); + _Thread_Unblock( the_thread ); + } else { + _Watchdog_Deactivate( &the_thread->Timer ); + _ISR_Enable( level ); + (void) _Watchdog_Remove( &the_thread->Timer ); + _Thread_Unblock( the_thread ); + } + return; + } + } + _ISR_Enable( level ); +} diff --git a/cpukit/rtems/src/eventtimeout.c b/cpukit/rtems/src/eventtimeout.c new file mode 100644 index 0000000000..c1eef71f9e --- /dev/null +++ b/cpukit/rtems/src/eventtimeout.c @@ -0,0 +1,93 @@ +/* + * Event Manager + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/event.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/tasks.h> + +/*PAGE + * + * _Event_Timeout + * + * This routine processes a thread which timeouts while waiting to + * receive an event_set. It is called by the watchdog handler. + * + * Input parameters: + * id - thread id + * + * Output parameters: NONE + */ + +void _Event_Timeout( + Objects_Id id, + void *ignored +) +{ + Thread_Control *the_thread; + Objects_Locations location; + ISR_Level level; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + /* + * If the event manager is not synchronized, then it is either + * "nothing happened", "timeout", or "satisfied". If the_thread + * is the executing thread, then it is in the process of blocking + * and it is the thread which is responsible for the synchronization + * process. + * + * If it is not satisfied, then it is "nothing happened" and + * this is the "timeout" transition. After a request is satisfied, + * a timeout is not allowed to occur. + */ + _ISR_Disable( level ); + #if defined(RTEMS_DEBUG) + if ( !the_thread->Wait.count ) { /* verify thread is waiting */ + _Thread_Unnest_dispatch(); + _ISR_Enable( level ); + return; + } + #endif + + the_thread->Wait.count = 0; + if ( _Thread_Is_executing( the_thread ) ) { + if ( _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) + _Event_Sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT; + } + + the_thread->Wait.return_code = RTEMS_TIMEOUT; + _ISR_Enable( level ); + _Thread_Unblock( the_thread ); + _Thread_Unnest_dispatch(); + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* impossible */ +#endif + case OBJECTS_ERROR: + break; + } +} diff --git a/cpukit/rtems/src/intrbody.c b/cpukit/rtems/src/intrbody.c new file mode 100644 index 0000000000..aac994229d --- /dev/null +++ b/cpukit/rtems/src/intrbody.c @@ -0,0 +1,74 @@ +/* + * Bodies for Inlined Interrupt Manager Routines + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/score/isr.h> +#include <rtems/rtems/intr.h> + +/* + * Real body for rtems_interrupt_disable + */ + +#undef rtems_interrupt_disable + +rtems_interrupt_level rtems_interrupt_disable( void ) +{ + rtems_interrupt_level previous_level; + + _ISR_Disable( previous_level ); + + return previous_level; +} + +/* + * Real body for rtems_interrupt_enable + */ + +#undef rtems_interrupt_enable + +void rtems_interrupt_enable( + rtems_interrupt_level previous_level +) +{ + _ISR_Enable( previous_level ); +} + +/* + * Real body for rtems_interrupt_flash + */ + +#undef rtems_interrupt_flash + +void rtems_interrupt_flash( + rtems_interrupt_level previous_level +) +{ + _ISR_Flash( previous_level ); +} + +/* + * Real body for rtems_interrupt_is_in_progress + */ + +#undef rtems_interrupt_is_in_progress + +bool rtems_interrupt_is_in_progress( void ) +{ + return _ISR_Is_in_progress(); +} diff --git a/cpukit/rtems/src/intrcatch.c b/cpukit/rtems/src/intrcatch.c new file mode 100644 index 0000000000..dc3f1d4684 --- /dev/null +++ b/cpukit/rtems/src/intrcatch.c @@ -0,0 +1,61 @@ +/* + * Interrupt Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/score/isr.h> +#include <rtems/rtems/intr.h> + +#if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE) + +/* rtems_interrupt_catch + * + * This directive allows a thread to specify what action to take when + * catching signals. + * + * Input parameters: + * new_isr_handler - address of interrupt service routine (isr) + * vector - interrupt vector number + * old_isr_handler - address at which to store previous ISR address + * + * Output parameters: + * RTEMS_SUCCESSFUL - always succeeds + * *old_isr_handler - previous ISR address + */ + +rtems_status_code rtems_interrupt_catch( + rtems_isr_entry new_isr_handler, + rtems_vector_number vector, + rtems_isr_entry *old_isr_handler +) +{ + if ( !_ISR_Is_vector_number_valid( vector ) ) + return RTEMS_INVALID_NUMBER; + + if ( !_ISR_Is_valid_user_handler( (void *) new_isr_handler ) ) + return RTEMS_INVALID_ADDRESS; + + if ( !_ISR_Is_valid_user_handler( (void *) old_isr_handler ) ) + return RTEMS_INVALID_ADDRESS; + + _ISR_Install_vector( + vector, (proc_ptr)new_isr_handler, (proc_ptr *)old_isr_handler ); + + return RTEMS_SUCCESSFUL; +} +#endif diff --git a/cpukit/rtems/src/mp.c b/cpukit/rtems/src/mp.c new file mode 100644 index 0000000000..5749dddb4a --- /dev/null +++ b/cpukit/rtems/src/mp.c @@ -0,0 +1,45 @@ +/* + * Multiprocessing Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/mp.h> +#include <rtems/score/mpci.h> + +/*PAGE + * + * _Multiprocessing_Manager_initialization + * + */ + +void _Multiprocessing_Manager_initialization ( void ) +{ +} + +/*PAGE + * + * rtems_multiprocessing_announce + * + */ + +void rtems_multiprocessing_announce ( void ) +{ + _MPCI_Announce(); +} + +/* end of file */ diff --git a/cpukit/rtems/src/msg.c b/cpukit/rtems/src/msg.c new file mode 100644 index 0000000000..25e65aaaa5 --- /dev/null +++ b/cpukit/rtems/src/msg.c @@ -0,0 +1,81 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _Message_queue_Manager_initialization + * + * This routine initializes all message queue manager related + * data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _Message_queue_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_Message_queue_Information, /* object information table */ + OBJECTS_CLASSIC_API, /* object API */ + OBJECTS_RTEMS_MESSAGE_QUEUES, /* object class */ + Configuration_RTEMS_API.maximum_message_queues, + /* maximum objects of this class */ + sizeof( Message_queue_Control ), + /* size of this object's control block */ + false, /* true if names of this object are strings */ + RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + true, /* true if this is a global object class */ + _Message_queue_MP_Send_extract_proxy + /* Proxy extraction support callout */ +#endif + ); + + /* + * Register the MP Process Packet routine. + */ + +#if defined(RTEMS_MULTIPROCESSING) + _MPCI_Register_packet_processor( + MP_PACKET_MESSAGE_QUEUE, + _Message_queue_MP_Process_packet + ); +#endif + +} diff --git a/cpukit/rtems/src/msgdata.c b/cpukit/rtems/src/msgdata.c new file mode 100644 index 0000000000..70baa35723 --- /dev/null +++ b/cpukit/rtems/src/msgdata.c @@ -0,0 +1,23 @@ +/* + * Barrier Manager -- Instantiate Data + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate message queue data */ +#define RTEMS_MESSAGE_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/message.h> + diff --git a/cpukit/rtems/src/msgmp.c b/cpukit/rtems/src/msgmp.c new file mode 100644 index 0000000000..9f033a8bbb --- /dev/null +++ b/cpukit/rtems/src/msgmp.c @@ -0,0 +1,510 @@ +/* + * Multiprocessing Support for the Message Queue Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/message.h> +#include <rtems/score/mpci.h> +#include <rtems/rtems/msgmp.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _Message_queue_MP_Send_process_packet + * + */ + +void _Message_queue_MP_Send_process_packet ( + Message_queue_MP_Remote_operations operation, + Objects_Id message_queue_id, + rtems_name name, + Objects_Id proxy_id +) +{ + Message_queue_MP_Packet *the_packet; + uint32_t node; + + switch ( operation ) { + + case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE: + case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE: + case MESSAGE_QUEUE_MP_EXTRACT_PROXY: + + the_packet = _Message_queue_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_MESSAGE_QUEUE; + the_packet->Prefix.length = sizeof ( Message_queue_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( Message_queue_MP_Packet ); + the_packet->operation = operation; + the_packet->Prefix.id = message_queue_id; + the_packet->name = name; + the_packet->proxy_id = proxy_id; + + if ( operation == MESSAGE_QUEUE_MP_EXTRACT_PROXY ) + node = _Objects_Get_node( message_queue_id ); + else + node = MPCI_ALL_NODES; + + _MPCI_Send_process_packet( node, &the_packet->Prefix ); + break; + + case MESSAGE_QUEUE_MP_RECEIVE_REQUEST: + case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE: + case MESSAGE_QUEUE_MP_SEND_REQUEST: + case MESSAGE_QUEUE_MP_SEND_RESPONSE: + case MESSAGE_QUEUE_MP_URGENT_REQUEST: + case MESSAGE_QUEUE_MP_URGENT_RESPONSE: + case MESSAGE_QUEUE_MP_BROADCAST_REQUEST: + case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE: + case MESSAGE_QUEUE_MP_FLUSH_REQUEST: + case MESSAGE_QUEUE_MP_FLUSH_RESPONSE: + case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST: + case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE: + break; + + } +} + +/*PAGE + * + * _Message_queue_MP_Send_request_packet + * + */ + +rtems_status_code _Message_queue_MP_Send_request_packet ( + Message_queue_MP_Remote_operations operation, + Objects_Id message_queue_id, + const void *buffer, + size_t *size_p, + rtems_option option_set, + rtems_interval timeout +) +{ + Message_queue_MP_Packet *the_packet; + + switch ( operation ) { + + case MESSAGE_QUEUE_MP_SEND_REQUEST: + case MESSAGE_QUEUE_MP_URGENT_REQUEST: + case MESSAGE_QUEUE_MP_BROADCAST_REQUEST: + case MESSAGE_QUEUE_MP_FLUSH_REQUEST: + case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST: + + the_packet = _Message_queue_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_MESSAGE_QUEUE; + the_packet->Prefix.length = sizeof(Message_queue_MP_Packet); + if ( size_p ) + the_packet->Prefix.length += *size_p; + the_packet->Prefix.to_convert = sizeof(Message_queue_MP_Packet); + + /* + * make sure message is not too big for our MPCI driver + * We have to check it here instead of waiting for MPCI because + * we are about to slam in the payload + */ + + if (the_packet->Prefix.length > _MPCI_table->maximum_packet_size) { + _Thread_Enable_dispatch(); + return RTEMS_INVALID_SIZE; + } + + if (! _Options_Is_no_wait(option_set)) + the_packet->Prefix.timeout = timeout; + + the_packet->operation = operation; + the_packet->Prefix.id = message_queue_id; + the_packet->option_set = option_set; + + /* + * Copy the data into place if needed + */ + + if (buffer) { + the_packet->Buffer.size = *size_p; + _CORE_message_queue_Copy_buffer( + buffer, + the_packet->Buffer.buffer, + *size_p + ); + } + + return (rtems_status_code) _MPCI_Send_request_packet( + _Objects_Get_node(message_queue_id), + &the_packet->Prefix, + STATES_WAITING_FOR_MESSAGE + ); + break; + + case MESSAGE_QUEUE_MP_RECEIVE_REQUEST: + + the_packet = _Message_queue_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_MESSAGE_QUEUE; + the_packet->Prefix.length = sizeof(Message_queue_MP_Packet); + the_packet->Prefix.to_convert = sizeof(Message_queue_MP_Packet); + + if (! _Options_Is_no_wait(option_set)) + the_packet->Prefix.timeout = timeout; + + the_packet->operation = MESSAGE_QUEUE_MP_RECEIVE_REQUEST; + the_packet->Prefix.id = message_queue_id; + the_packet->option_set = option_set; + the_packet->size = 0; /* just in case of an error */ + + _Thread_Executing->Wait.return_argument_second.immutable_object = buffer; + _Thread_Executing->Wait.return_argument = size_p; + + return (rtems_status_code) _MPCI_Send_request_packet( + _Objects_Get_node(message_queue_id), + &the_packet->Prefix, + STATES_WAITING_FOR_MESSAGE + ); + break; + + case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE: + case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE: + case MESSAGE_QUEUE_MP_EXTRACT_PROXY: + case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE: + case MESSAGE_QUEUE_MP_SEND_RESPONSE: + case MESSAGE_QUEUE_MP_URGENT_RESPONSE: + case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE: + case MESSAGE_QUEUE_MP_FLUSH_RESPONSE: + case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE: + break; + } + + return RTEMS_SUCCESSFUL; +} + +/*PAGE + * + * _Message_queue_MP_Send_response_packet + * + */ + +void _Message_queue_MP_Send_response_packet ( + Message_queue_MP_Remote_operations operation, + Objects_Id message_queue_id, + Thread_Control *the_thread +) +{ + Message_queue_MP_Packet *the_packet; + + switch ( operation ) { + + case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE: + case MESSAGE_QUEUE_MP_SEND_RESPONSE: + case MESSAGE_QUEUE_MP_URGENT_RESPONSE: + case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE: + case MESSAGE_QUEUE_MP_FLUSH_RESPONSE: + case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE: + + the_packet = ( Message_queue_MP_Packet *) the_thread->receive_packet; + +/* + * The packet being returned already contains the class, length, and + * to_convert fields, therefore they are not set in this routine. + * + * Exception: MESSAGE_QUEUE_MP_RECEIVE_RESPONSE needs payload length + * added to 'length' + */ + the_packet->operation = operation; + the_packet->Prefix.id = the_packet->Prefix.source_tid; + + if (operation == MESSAGE_QUEUE_MP_RECEIVE_RESPONSE) + the_packet->Prefix.length += the_packet->size; + + _MPCI_Send_response_packet( + _Objects_Get_node( the_packet->Prefix.source_tid ), + &the_packet->Prefix + ); + break; + + case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE: + case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE: + case MESSAGE_QUEUE_MP_EXTRACT_PROXY: + case MESSAGE_QUEUE_MP_RECEIVE_REQUEST: + case MESSAGE_QUEUE_MP_SEND_REQUEST: + case MESSAGE_QUEUE_MP_URGENT_REQUEST: + case MESSAGE_QUEUE_MP_BROADCAST_REQUEST: + case MESSAGE_QUEUE_MP_FLUSH_REQUEST: + case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST: + break; + + } +} + +/*PAGE + * + * + * _Message_queue_MP_Process_packet + * + */ + +void _Message_queue_MP_Process_packet ( + rtems_packet_prefix *the_packet_prefix +) +{ + Message_queue_MP_Packet *the_packet; + Thread_Control *the_thread; + bool ignored; + + the_packet = (Message_queue_MP_Packet *) the_packet_prefix; + + switch ( the_packet->operation ) { + + case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE: + + ignored = _Objects_MP_Allocate_and_open( + &_Message_queue_Information, + the_packet->name, + the_packet->Prefix.id, + true + ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE: + + _Objects_MP_Close( &_Message_queue_Information, the_packet->Prefix.id ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case MESSAGE_QUEUE_MP_EXTRACT_PROXY: + + the_thread = _Thread_MP_Find_proxy( the_packet->proxy_id ); + + if (! _Thread_Is_null( the_thread ) ) + _Thread_queue_Extract( the_thread->Wait.queue, the_thread ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case MESSAGE_QUEUE_MP_RECEIVE_REQUEST: + + the_packet->Prefix.return_code = rtems_message_queue_receive( + the_packet->Prefix.id, + the_packet->Buffer.buffer, + &the_packet->size, + the_packet->option_set, + the_packet->Prefix.timeout + ); + + if ( the_packet->Prefix.return_code != RTEMS_PROXY_BLOCKING ) + _Message_queue_MP_Send_response_packet( + MESSAGE_QUEUE_MP_RECEIVE_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + if (the_packet->Prefix.return_code == RTEMS_SUCCESSFUL) { + *(size_t *) the_thread->Wait.return_argument = + the_packet->size; + + _CORE_message_queue_Copy_buffer( + the_packet->Buffer.buffer, + the_thread->Wait.return_argument_second.mutable_object, + the_packet->size + ); + } + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case MESSAGE_QUEUE_MP_SEND_REQUEST: + + the_packet->Prefix.return_code = rtems_message_queue_send( + the_packet->Prefix.id, + the_packet->Buffer.buffer, + the_packet->Buffer.size + ); + + _Message_queue_MP_Send_response_packet( + MESSAGE_QUEUE_MP_SEND_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case MESSAGE_QUEUE_MP_SEND_RESPONSE: + case MESSAGE_QUEUE_MP_URGENT_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case MESSAGE_QUEUE_MP_URGENT_REQUEST: + + the_packet->Prefix.return_code = rtems_message_queue_urgent( + the_packet->Prefix.id, + the_packet->Buffer.buffer, + the_packet->Buffer.size + ); + + _Message_queue_MP_Send_response_packet( + MESSAGE_QUEUE_MP_URGENT_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case MESSAGE_QUEUE_MP_BROADCAST_REQUEST: + + the_packet->Prefix.return_code = rtems_message_queue_broadcast( + the_packet->Prefix.id, + the_packet->Buffer.buffer, + the_packet->Buffer.size, + &the_packet->count + ); + + _Message_queue_MP_Send_response_packet( + MESSAGE_QUEUE_MP_BROADCAST_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE: + case MESSAGE_QUEUE_MP_FLUSH_RESPONSE: + case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + *(uint32_t *) the_thread->Wait.return_argument = the_packet->count; + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case MESSAGE_QUEUE_MP_FLUSH_REQUEST: + + the_packet->Prefix.return_code = rtems_message_queue_flush( + the_packet->Prefix.id, + &the_packet->count + ); + + _Message_queue_MP_Send_response_packet( + MESSAGE_QUEUE_MP_FLUSH_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST: + + the_packet->Prefix.return_code = rtems_message_queue_get_number_pending( + the_packet->Prefix.id, + &the_packet->count + ); + + _Message_queue_MP_Send_response_packet( + MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + } +} + +/*PAGE + * + * _Message_queue_MP_Send_object_was_deleted + * + */ + +void _Message_queue_MP_Send_object_was_deleted ( + Thread_Control *the_proxy +) +{ + the_proxy->receive_packet->return_code = RTEMS_OBJECT_WAS_DELETED; + + _Message_queue_MP_Send_response_packet( + MESSAGE_QUEUE_MP_RECEIVE_RESPONSE, + the_proxy->Wait.id, + the_proxy + ); +} + +/*PAGE + * + * _Message_queue_MP_Send_extract_proxy + * + */ + +void _Message_queue_MP_Send_extract_proxy ( + void *argument +) +{ + Thread_Control *the_thread = (Thread_Control *)argument; + + _Message_queue_MP_Send_process_packet( + MESSAGE_QUEUE_MP_EXTRACT_PROXY, + the_thread->Wait.id, + (rtems_name) 0, + the_thread->Object.id + ); +} + +/*PAGE + * + * _Message_queue_MP_Get_packet + * + */ + +Message_queue_MP_Packet *_Message_queue_MP_Get_packet ( void ) +{ + return ( (Message_queue_MP_Packet *) _MPCI_Get_packet() ); +} + + +/*PAGE + * + * _Message_queue_Core_message_queue_mp_support + * + * Input parameters: + * the_thread - the remote thread the message was submitted to + * id - id of the message queue + * + * Output parameters: NONE + */ + +void _Message_queue_Core_message_queue_mp_support ( + Thread_Control *the_thread, + Objects_Id id +) +{ + the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL; + + _Message_queue_MP_Send_response_packet( + MESSAGE_QUEUE_MP_RECEIVE_RESPONSE, + id, + the_thread + ); +} + +/* end of file */ diff --git a/cpukit/rtems/src/msgqallocate.c b/cpukit/rtems/src/msgqallocate.c new file mode 100644 index 0000000000..e5603dd9d8 --- /dev/null +++ b/cpukit/rtems/src/msgqallocate.c @@ -0,0 +1,56 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _Message_queue_Allocate + * + * Allocate a message queue and the space for its messages + * + * Input parameters: + * the_message_queue - the message queue to allocate message buffers + * count - maximum message and reserved buffer count + * max_message_size - maximum size of each message + * + * Output parameters: + * the_message_queue - set if successful, NULL otherwise + */ + +Message_queue_Control *_Message_queue_Allocate(void) +{ + return (Message_queue_Control *) + _Objects_Allocate(&_Message_queue_Information); +} diff --git a/cpukit/rtems/src/msgqbroadcast.c b/cpukit/rtems/src/msgqbroadcast.c new file mode 100644 index 0000000000..96389b8d23 --- /dev/null +++ b/cpukit/rtems/src/msgqbroadcast.c @@ -0,0 +1,113 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * rtems_message_queue_broadcast + * + * This directive sends a message for every thread waiting on the queue + * designated by id. + * + * Input parameters: + * id - pointer to message queue + * buffer - pointer to message buffer + * size - size of message to broadcast + * count - pointer to area to store number of threads made ready + * + * Output parameters: + * count - number of threads made ready + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_message_queue_broadcast( + rtems_id id, + const void *buffer, + size_t size, + uint32_t *count +) +{ + register Message_queue_Control *the_message_queue; + Objects_Locations location; + CORE_message_queue_Status core_status; + + if ( !buffer ) + return RTEMS_INVALID_ADDRESS; + + if ( !count ) + return RTEMS_INVALID_ADDRESS; + + the_message_queue = _Message_queue_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + core_status = _CORE_message_queue_Broadcast( + &the_message_queue->message_queue, + buffer, + size, + id, + #if defined(RTEMS_MULTIPROCESSING) + _Message_queue_Core_message_queue_mp_support, + #else + NULL, + #endif + count + ); + + _Thread_Enable_dispatch(); + return + _Message_queue_Translate_core_message_queue_return_code( core_status ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Executing->Wait.return_argument = count; + + return + _Message_queue_MP_Send_request_packet( + MESSAGE_QUEUE_MP_BROADCAST_REQUEST, + id, + buffer, + &size, + 0, /* option_set not used */ + MPCI_DEFAULT_TIMEOUT + ); +#endif + + case OBJECTS_ERROR: + break; + } + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/msgqcreate.c b/cpukit/rtems/src/msgqcreate.c new file mode 100644 index 0000000000..77af8eac95 --- /dev/null +++ b/cpukit/rtems/src/msgqcreate.c @@ -0,0 +1,165 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * rtems_message_queue_create + * + * This directive creates a message queue by allocating and initializing + * a message queue data structure. + * + * Input parameters: + * name - user defined queue name + * count - maximum message and reserved buffer count + * max_message_size - maximum size of each message + * attribute_set - process method + * id - pointer to queue + * + * Output parameters: + * id - queue id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_message_queue_create( + rtems_name name, + uint32_t count, + size_t max_message_size, + rtems_attribute attribute_set, + rtems_id *id +) +{ + register Message_queue_Control *the_message_queue; + CORE_message_queue_Attributes the_msgq_attributes; +#if defined(RTEMS_MULTIPROCESSING) + bool is_global; +#endif + + if ( !rtems_is_name_valid( name ) ) + return RTEMS_INVALID_NAME; + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + +#if defined(RTEMS_MULTIPROCESSING) + if ( (is_global = _Attributes_Is_global( attribute_set ) ) && + !_System_state_Is_multiprocessing ) + return RTEMS_MP_NOT_CONFIGURED; +#endif + + if ( count == 0 ) + return RTEMS_INVALID_NUMBER; + + if ( max_message_size == 0 ) + return RTEMS_INVALID_SIZE; + +#if defined(RTEMS_MULTIPROCESSING) +#if 1 + /* + * I am not 100% sure this should be an error. + * It seems reasonable to create a que with a large max size, + * and then just send smaller msgs from remote (or all) nodes. + */ + + if ( is_global && (_MPCI_table->maximum_packet_size < max_message_size) ) + return RTEMS_INVALID_SIZE; +#endif +#endif + + _Thread_Disable_dispatch(); /* protects object pointer */ + + the_message_queue = _Message_queue_Allocate(); + + if ( !the_message_queue ) { + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } + +#if defined(RTEMS_MULTIPROCESSING) + if ( is_global && + !( _Objects_MP_Allocate_and_open( &_Message_queue_Information, + name, the_message_queue->Object.id, false ) ) ) { + _Message_queue_Free( the_message_queue ); + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } +#endif + + the_message_queue->attribute_set = attribute_set; + + if (_Attributes_Is_priority( attribute_set ) ) + the_msgq_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY; + else + the_msgq_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO; + + if ( ! _CORE_message_queue_Initialize( + &the_message_queue->message_queue, + &the_msgq_attributes, + count, + max_message_size + ) ) { +#if defined(RTEMS_MULTIPROCESSING) + if ( is_global ) + _Objects_MP_Close( + &_Message_queue_Information, the_message_queue->Object.id); +#endif + + _Message_queue_Free( the_message_queue ); + _Thread_Enable_dispatch(); + return RTEMS_UNSATISFIED; + } + + _Objects_Open( + &_Message_queue_Information, + &the_message_queue->Object, + (Objects_Name) name + ); + + *id = the_message_queue->Object.id; + +#if defined(RTEMS_MULTIPROCESSING) + if ( is_global ) + _Message_queue_MP_Send_process_packet( + MESSAGE_QUEUE_MP_ANNOUNCE_CREATE, + the_message_queue->Object.id, + name, + 0 + ); +#endif + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/msgqdelete.c b/cpukit/rtems/src/msgqdelete.c new file mode 100644 index 0000000000..8834886e38 --- /dev/null +++ b/cpukit/rtems/src/msgqdelete.c @@ -0,0 +1,107 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * rtems_message_queue_delete + * + * This directive allows a thread to delete the message queue specified + * by the given queue identifier. + * + * Input parameters: + * id - queue id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_message_queue_delete( + rtems_id id +) +{ + register Message_queue_Control *the_message_queue; + Objects_Locations location; + + the_message_queue = _Message_queue_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Objects_Close( &_Message_queue_Information, + &the_message_queue->Object ); + + _CORE_message_queue_Close( + &the_message_queue->message_queue, + #if defined(RTEMS_MULTIPROCESSING) + _Message_queue_MP_Send_object_was_deleted, + #else + NULL, + #endif + CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED + ); + + _Message_queue_Free( the_message_queue ); + +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( the_message_queue->attribute_set ) ) { + _Objects_MP_Close( + &_Message_queue_Information, + the_message_queue->Object.id + ); + + _Message_queue_MP_Send_process_packet( + MESSAGE_QUEUE_MP_ANNOUNCE_DELETE, + the_message_queue->Object.id, + 0, /* Not used */ + 0 + ); + } +#endif + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/msgqflush.c b/cpukit/rtems/src/msgqflush.c new file mode 100644 index 0000000000..deee3b80ae --- /dev/null +++ b/cpukit/rtems/src/msgqflush.c @@ -0,0 +1,94 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * rtems_message_queue_flush + * + * This directive removes all pending messages from a queue and returns + * the number of messages removed. If no messages were present then + * a count of zero is returned. + * + * Input parameters: + * id - queue id + * count - return area for count + * + * Output parameters: + * count - number of messages removed ( 0 = empty queue ) + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_message_queue_flush( + rtems_id id, + uint32_t *count +) +{ + register Message_queue_Control *the_message_queue; + Objects_Locations location; + + if ( !count ) + return RTEMS_INVALID_ADDRESS; + + the_message_queue = _Message_queue_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + *count = _CORE_message_queue_Flush( &the_message_queue->message_queue ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Executing->Wait.return_argument = count; + + return + _Message_queue_MP_Send_request_packet( + MESSAGE_QUEUE_MP_FLUSH_REQUEST, + id, + 0, /* buffer not used */ + 0, /* size */ + 0, /* option_set not used */ + MPCI_DEFAULT_TIMEOUT + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/msgqgetnumberpending.c b/cpukit/rtems/src/msgqgetnumberpending.c new file mode 100644 index 0000000000..cedb2b23d3 --- /dev/null +++ b/cpukit/rtems/src/msgqgetnumberpending.c @@ -0,0 +1,91 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * rtems_message_queue_get_number_pending + * + * This directive returns the number of messages pending. + * + * Input parameters: + * id - queue id + * count - return area for count + * + * Output parameters: + * count - number of messages removed ( 0 = empty queue ) + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_message_queue_get_number_pending( + rtems_id id, + uint32_t *count +) +{ + register Message_queue_Control *the_message_queue; + Objects_Locations location; + + if ( !count ) + return RTEMS_INVALID_ADDRESS; + + the_message_queue = _Message_queue_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + *count = the_message_queue->message_queue.number_of_pending_messages; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Executing->Wait.return_argument = count; + + return _Message_queue_MP_Send_request_packet( + MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST, + id, + 0, /* buffer not used */ + 0, /* size */ + 0, /* option_set not used */ + MPCI_DEFAULT_TIMEOUT + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/msgqident.c b/cpukit/rtems/src/msgqident.c new file mode 100644 index 0000000000..9030d5df3f --- /dev/null +++ b/cpukit/rtems/src/msgqident.c @@ -0,0 +1,71 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * rtems_message_queue_ident + * + * This directive returns the system ID associated with + * the message queue name. + * + * Input parameters: + * name - user defined message queue name + * node - node(s) to be searched + * id - pointer to message queue id + * + * Output parameters: + * *id - message queue id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_message_queue_ident( + rtems_name name, + uint32_t node, + rtems_id *id +) +{ + Objects_Name_or_id_lookup_errors status; + + status = _Objects_Name_to_id_u32( + &_Message_queue_Information, + name, + node, + id + ); + + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/msgqreceive.c b/cpukit/rtems/src/msgqreceive.c new file mode 100644 index 0000000000..f7f0db1605 --- /dev/null +++ b/cpukit/rtems/src/msgqreceive.c @@ -0,0 +1,113 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * rtems_message_queue_receive + * + * This directive dequeues a message from the designated message queue + * and copies it into the requesting thread's buffer. + * + * Input parameters: + * id - queue id + * buffer - pointer to message buffer + * size - size of message receive + * option_set - options on receive + * timeout - number of ticks to wait + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_message_queue_receive( + rtems_id id, + void *buffer, + size_t *size, + rtems_option option_set, + rtems_interval timeout +) +{ + register Message_queue_Control *the_message_queue; + Objects_Locations location; + bool wait; + + if ( !buffer ) + return RTEMS_INVALID_ADDRESS; + + if ( !size ) + return RTEMS_INVALID_ADDRESS; + + the_message_queue = _Message_queue_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( _Options_Is_no_wait( option_set ) ) + wait = false; + else + wait = true; + + _CORE_message_queue_Seize( + &the_message_queue->message_queue, + the_message_queue->Object.id, + buffer, + size, + wait, + timeout + ); + _Thread_Enable_dispatch(); + return _Message_queue_Translate_core_message_queue_return_code( + _Thread_Executing->Wait.return_code + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _Message_queue_MP_Send_request_packet( + MESSAGE_QUEUE_MP_RECEIVE_REQUEST, + id, + buffer, + size, + option_set, + timeout + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/msgqsend.c b/cpukit/rtems/src/msgqsend.c new file mode 100644 index 0000000000..9c2c251cfd --- /dev/null +++ b/cpukit/rtems/src/msgqsend.c @@ -0,0 +1,112 @@ +/* + * Message Queue Manager - rtems_message_queue_send + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/* + * + * rtems_message_queue_send + * + * This routine implements the directive rtems_message_queue_send. It sends a + * message to the specified message queue. + * + * Input parameters: + * id - pointer to message queue + * buffer - pointer to message buffer + * size - size of message to send + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +#if defined(RTEMS_MULTIPROCESSING) +#define MESSAGE_QUEUE_MP_HANDLER _Message_queue_Core_message_queue_mp_support +#else +#define MESSAGE_QUEUE_MP_HANDLER NULL +#endif + +rtems_status_code rtems_message_queue_send( + rtems_id id, + const void *buffer, + size_t size +) +{ + register Message_queue_Control *the_message_queue; + Objects_Locations location; + CORE_message_queue_Status status; + + if ( !buffer ) + return RTEMS_INVALID_ADDRESS; + + the_message_queue = _Message_queue_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + status = _CORE_message_queue_Send( + &the_message_queue->message_queue, + buffer, + size, + id, + MESSAGE_QUEUE_MP_HANDLER, + false, /* sender does not block */ + 0 /* no timeout */ + ); + + _Thread_Enable_dispatch(); + + /* + * Since this API does not allow for blocking sends, we can directly + * return the returned status. + */ + + return _Message_queue_Translate_core_message_queue_return_code(status); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _Message_queue_MP_Send_request_packet( + MESSAGE_QUEUE_MP_SEND_REQUEST, + id, + buffer, + &size, + 0, /* option_set */ + MPCI_DEFAULT_TIMEOUT + ); + break; +#endif + + case OBJECTS_ERROR: + break; + } + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/msgqtranslatereturncode.c b/cpukit/rtems/src/msgqtranslatereturncode.c new file mode 100644 index 0000000000..8a554cb7cc --- /dev/null +++ b/cpukit/rtems/src/msgqtranslatereturncode.c @@ -0,0 +1,81 @@ +/* + * Message Queue Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _Message_queue_Translate_core_message_queue_return_code + * + * Input parameters: + * the_message_queue_status - message_queue status code to translate + * + * Output parameters: + * rtems status code - translated RTEMS status code + * + */ + +rtems_status_code _Message_queue_Translate_core_return_code_[] = { + RTEMS_SUCCESSFUL, /* CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL */ + RTEMS_INVALID_SIZE, /* CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE */ + RTEMS_TOO_MANY, /* CORE_MESSAGE_QUEUE_STATUS_TOO_MANY */ + RTEMS_UNSATISFIED, /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED */ + RTEMS_UNSATISFIED, /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT */ + RTEMS_OBJECT_WAS_DELETED, /* CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED */ + RTEMS_TIMEOUT /* CORE_MESSAGE_QUEUE_STATUS_TIMEOUT */ +}; + +rtems_status_code _Message_queue_Translate_core_message_queue_return_code ( + uint32_t status +) +{ + /* + * Check for proxy blocking first since it is out of range + * from the external status codes. + */ + #if defined(RTEMS_MULTIPROCESSING) + if ( _Thread_Is_proxy_blocking(status) ) + return RTEMS_PROXY_BLOCKING; + #endif + + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( status > CORE_MESSAGE_QUEUE_STATUS_TIMEOUT ) + return RTEMS_INTERNAL_ERROR; + #endif + + return _Message_queue_Translate_core_return_code_[status]; +} diff --git a/cpukit/rtems/src/msgqurgent.c b/cpukit/rtems/src/msgqurgent.c new file mode 100644 index 0000000000..ddb66a8488 --- /dev/null +++ b/cpukit/rtems/src/msgqurgent.c @@ -0,0 +1,111 @@ +/* + * Message Queue Manager - rtems_message_queue_urgent + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/coremsg.h> +#include <rtems/score/object.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 +#include <rtems/rtems/status.h> +#include <rtems/rtems/attr.h> +#include <rtems/rtems/message.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * rtems_message_queue_urgent + * + * This routine implements the directives rtems_message_queue_urgent. It + * prepends a message to the specified message queue. + * + * Input parameters: + * id - pointer to message queue + * buffer - pointer to message buffer + * size - size of message to send urgently + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +#if defined(RTEMS_MULTIPROCESSING) +#define MESSAGE_QUEUE_MP_HANDLER _Message_queue_Core_message_queue_mp_support +#else +#define MESSAGE_QUEUE_MP_HANDLER NULL +#endif + +rtems_status_code rtems_message_queue_urgent( + rtems_id id, + const void *buffer, + size_t size +) +{ + register Message_queue_Control *the_message_queue; + Objects_Locations location; + CORE_message_queue_Status status; + + if ( !buffer ) + return RTEMS_INVALID_ADDRESS; + + the_message_queue = _Message_queue_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + status = _CORE_message_queue_Urgent( + &the_message_queue->message_queue, + buffer, + size, + id, + MESSAGE_QUEUE_MP_HANDLER, + false, /* sender does not block */ + 0 /* no timeout */ + ); + _Thread_Enable_dispatch(); + + /* + * Since this API does not allow for blocking sends, we can directly + * return the returned status. + */ + + return _Message_queue_Translate_core_message_queue_return_code(status); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _Message_queue_MP_Send_request_packet( + MESSAGE_QUEUE_MP_URGENT_REQUEST, + id, + buffer, + &size, + 0, /* option_set */ + MPCI_DEFAULT_TIMEOUT + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/part.c b/cpukit/rtems/src/part.c new file mode 100644 index 0000000000..a5c12e5fb9 --- /dev/null +++ b/cpukit/rtems/src/part.c @@ -0,0 +1,69 @@ +/* + * Partition Manager + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/score/object.h> +#include <rtems/rtems/part.h> +#include <rtems/score/thread.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * _Partition_Manager_initialization + * + * This routine initializes all partition manager related + * data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _Partition_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_Partition_Information, /* object information table */ + OBJECTS_CLASSIC_API, /* object API */ + OBJECTS_RTEMS_PARTITIONS, /* object class */ + Configuration_RTEMS_API.maximum_partitions, + /* maximum objects of this class */ + sizeof( Partition_Control ), /* size of this object's control block */ + false, /* true if the name is a string */ + RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */ +#if defined(RTEMS_MULTIPROCESSING) + , + true, /* true if this is a global object class */ + _Partition_MP_Send_extract_proxy /* Proxy extraction support callout */ +#endif + ); + + /* + * Register the MP Process Packet routine. + */ + +#if defined(RTEMS_MULTIPROCESSING) + _MPCI_Register_packet_processor( + MP_PACKET_PARTITION, + _Partition_MP_Process_packet + ); +#endif + +} diff --git a/cpukit/rtems/src/partcreate.c b/cpukit/rtems/src/partcreate.c new file mode 100644 index 0000000000..6b3d819ea5 --- /dev/null +++ b/cpukit/rtems/src/partcreate.c @@ -0,0 +1,129 @@ +/* + * Partition Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/score/object.h> +#include <rtems/rtems/part.h> +#include <rtems/score/thread.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_partition_create + * + * This directive creates a partiton of fixed sized buffers from the + * given contiguous memory area. + * + * Input parameters: + * name - user defined partition name + * starting_address - physical start address of partition + * length - physical length in bytes + * buffer_size - size of buffers in bytes + * attribute_set - partition attributes + * id - pointer to partition id + * + * Output parameters: + * id - partition id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_partition_create( + rtems_name name, + void *starting_address, + uint32_t length, + uint32_t buffer_size, + rtems_attribute attribute_set, + rtems_id *id +) +{ + register Partition_Control *the_partition; + + if ( !rtems_is_name_valid( name ) ) + return RTEMS_INVALID_NAME; + + if ( !starting_address ) + return RTEMS_INVALID_ADDRESS; + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + + if ( length == 0 || buffer_size == 0 || length < buffer_size || + !_Partition_Is_buffer_size_aligned( buffer_size ) ) + return RTEMS_INVALID_SIZE; + + if ( !_Addresses_Is_aligned( starting_address ) ) + return RTEMS_INVALID_ADDRESS; + +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( attribute_set ) && + !_System_state_Is_multiprocessing ) + return RTEMS_MP_NOT_CONFIGURED; +#endif + + _Thread_Disable_dispatch(); /* prevents deletion */ + + the_partition = _Partition_Allocate(); + + if ( !the_partition ) { + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } + +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( attribute_set ) && + !( _Objects_MP_Allocate_and_open( &_Partition_Information, name, + the_partition->Object.id, false ) ) ) { + _Partition_Free( the_partition ); + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } +#endif + + the_partition->starting_address = starting_address; + the_partition->length = length; + the_partition->buffer_size = buffer_size; + the_partition->attribute_set = attribute_set; + the_partition->number_of_used_blocks = 0; + + _Chain_Initialize( &the_partition->Memory, starting_address, + length / buffer_size, buffer_size ); + + _Objects_Open( + &_Partition_Information, + &the_partition->Object, + (Objects_Name) name + ); + + *id = the_partition->Object.id; +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( attribute_set ) ) + _Partition_MP_Send_process_packet( + PARTITION_MP_ANNOUNCE_CREATE, + the_partition->Object.id, + name, + 0 /* Not used */ + ); +#endif + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/partdata.c b/cpukit/rtems/src/partdata.c new file mode 100644 index 0000000000..8f6c5b4531 --- /dev/null +++ b/cpukit/rtems/src/partdata.c @@ -0,0 +1,22 @@ +/* + * Partition Manager -- Instantiate Data + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate RTEMS partition data */ +#define RTEMS_PART_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/part.h> diff --git a/cpukit/rtems/src/partdelete.c b/cpukit/rtems/src/partdelete.c new file mode 100644 index 0000000000..871e198f3f --- /dev/null +++ b/cpukit/rtems/src/partdelete.c @@ -0,0 +1,92 @@ +/* + * Partition Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/score/object.h> +#include <rtems/rtems/part.h> +#include <rtems/score/thread.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_partition_delete + * + * This directive allows a thread to delete a partition specified by + * the partition identifier, provided that none of its buffers are + * still allocated. + * + * Input parameters: + * id - partition id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_partition_delete( + rtems_id id +) +{ + register Partition_Control *the_partition; + Objects_Locations location; + + the_partition = _Partition_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( the_partition->number_of_used_blocks == 0 ) { + _Objects_Close( &_Partition_Information, &the_partition->Object ); + _Partition_Free( the_partition ); +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( the_partition->attribute_set ) ) { + + _Objects_MP_Close( + &_Partition_Information, + the_partition->Object.id + ); + + _Partition_MP_Send_process_packet( + PARTITION_MP_ANNOUNCE_DELETE, + the_partition->Object.id, + 0, /* Not used */ + 0 /* Not used */ + ); + } +#endif + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); + return RTEMS_RESOURCE_IN_USE; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/partgetbuffer.c b/cpukit/rtems/src/partgetbuffer.c new file mode 100644 index 0000000000..56d58a1103 --- /dev/null +++ b/cpukit/rtems/src/partgetbuffer.c @@ -0,0 +1,87 @@ +/* + * Partition Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/score/object.h> +#include <rtems/rtems/part.h> +#include <rtems/score/thread.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_partition_get_buffer + * + * This directive will obtain a buffer from a buffer partition. + * + * Input parameters: + * id - partition id + * buffer - pointer to buffer address + * + * Output parameters: + * buffer - pointer to buffer address filled in + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_partition_get_buffer( + rtems_id id, + void **buffer +) +{ + register Partition_Control *the_partition; + Objects_Locations location; + void *the_buffer; + + if ( !buffer ) + return RTEMS_INVALID_ADDRESS; + + the_partition = _Partition_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + the_buffer = _Partition_Allocate_buffer( the_partition ); + if ( the_buffer ) { + the_partition->number_of_used_blocks += 1; + _Thread_Enable_dispatch(); + *buffer = the_buffer; + return RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); + return RTEMS_UNSATISFIED; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Executing->Wait.return_argument = buffer; + return( + _Partition_MP_Send_request_packet( + PARTITION_MP_GET_BUFFER_REQUEST, + id, + 0 /* Not used */ + ) + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/partident.c b/cpukit/rtems/src/partident.c new file mode 100644 index 0000000000..8f9004ea8e --- /dev/null +++ b/cpukit/rtems/src/partident.c @@ -0,0 +1,57 @@ +/* + * Partition Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/score/object.h> +#include <rtems/rtems/part.h> +#include <rtems/score/thread.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_partition_ident + * + * This directive returns the system ID associated with + * the partition name. + * + * Input parameters: + * name - user defined partition name + * node - node(s) to be searched + * id - pointer to partition id + * + * Output parameters: + * *id - partition id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_partition_ident( + rtems_name name, + uint32_t node, + rtems_id *id +) +{ + Objects_Name_or_id_lookup_errors status; + + status = _Objects_Name_to_id_u32( &_Partition_Information, name, node, id ); + + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/partmp.c b/cpukit/rtems/src/partmp.c new file mode 100644 index 0000000000..da6e2ca8d6 --- /dev/null +++ b/cpukit/rtems/src/partmp.c @@ -0,0 +1,307 @@ +/* + * Multiprocessing Support for the Partition Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/score/mpci.h> +#include <rtems/score/mppkt.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/part.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _Partition_MP_Send_process_packet + * + */ + +void _Partition_MP_Send_process_packet ( + Partition_MP_Remote_operations operation, + Objects_Id partition_id, + rtems_name name, + Objects_Id proxy_id +) +{ + Partition_MP_Packet *the_packet; + uint32_t node; + + switch ( operation ) { + + case PARTITION_MP_ANNOUNCE_CREATE: + case PARTITION_MP_ANNOUNCE_DELETE: + case PARTITION_MP_EXTRACT_PROXY: + + the_packet = _Partition_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_PARTITION; + the_packet->Prefix.length = sizeof ( Partition_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( Partition_MP_Packet ); + the_packet->operation = operation; + the_packet->Prefix.id = partition_id; + the_packet->name = name; + the_packet->proxy_id = proxy_id; + + if ( operation == PARTITION_MP_EXTRACT_PROXY ) + node = _Objects_Get_node( partition_id ); + else + node = MPCI_ALL_NODES; + + _MPCI_Send_process_packet( node, &the_packet->Prefix ); + break; + + case PARTITION_MP_GET_BUFFER_REQUEST: + case PARTITION_MP_GET_BUFFER_RESPONSE: + case PARTITION_MP_RETURN_BUFFER_REQUEST: + case PARTITION_MP_RETURN_BUFFER_RESPONSE: + break; + } +} + +/*PAGE + * + * _Partition_MP_Send_request_packet + * + */ + +rtems_status_code _Partition_MP_Send_request_packet ( + Partition_MP_Remote_operations operation, + Objects_Id partition_id, + void *buffer +) +{ + Partition_MP_Packet *the_packet; + + switch ( operation ) { + + case PARTITION_MP_GET_BUFFER_REQUEST: + case PARTITION_MP_RETURN_BUFFER_REQUEST: + + the_packet = _Partition_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_PARTITION; + the_packet->Prefix.length = sizeof ( Partition_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( Partition_MP_Packet ); + the_packet->operation = operation; + the_packet->Prefix.id = partition_id; + the_packet->buffer = buffer; + + return + _MPCI_Send_request_packet( + _Objects_Get_node( partition_id ), + &the_packet->Prefix, + STATES_READY /* Not used */ + ); + + break; + + case PARTITION_MP_ANNOUNCE_CREATE: + case PARTITION_MP_ANNOUNCE_DELETE: + case PARTITION_MP_EXTRACT_PROXY: + case PARTITION_MP_GET_BUFFER_RESPONSE: + case PARTITION_MP_RETURN_BUFFER_RESPONSE: + break; + + } + /* + * The following line is included to satisfy compilers which + * produce warnings when a function does not end with a return. + */ + return RTEMS_SUCCESSFUL; +} + +/*PAGE + * + * _Partition_MP_Send_response_packet + * + */ + +void _Partition_MP_Send_response_packet ( + Partition_MP_Remote_operations operation, + Objects_Id partition_id, + Thread_Control *the_thread +) +{ + Partition_MP_Packet *the_packet; + + switch ( operation ) { + + case PARTITION_MP_GET_BUFFER_RESPONSE: + case PARTITION_MP_RETURN_BUFFER_RESPONSE: + + the_packet = ( Partition_MP_Packet *) the_thread->receive_packet; + +/* + * The packet being returned already contains the class, length, and + * to_convert fields, therefore they are not set in this routine. + */ + the_packet->operation = operation; + the_packet->Prefix.id = the_packet->Prefix.source_tid; + + _MPCI_Send_response_packet( + _Objects_Get_node( the_packet->Prefix.source_tid ), + &the_packet->Prefix + ); + break; + + case PARTITION_MP_ANNOUNCE_CREATE: + case PARTITION_MP_ANNOUNCE_DELETE: + case PARTITION_MP_EXTRACT_PROXY: + case PARTITION_MP_GET_BUFFER_REQUEST: + case PARTITION_MP_RETURN_BUFFER_REQUEST: + break; + + } +} + +/*PAGE + * + * + * _Partition_MP_Process_packet + * + */ + +void _Partition_MP_Process_packet ( + rtems_packet_prefix *the_packet_prefix +) +{ + Partition_MP_Packet *the_packet; + Thread_Control *the_thread; + bool ignored; + + the_packet = (Partition_MP_Packet *) the_packet_prefix; + + switch ( the_packet->operation ) { + + case PARTITION_MP_ANNOUNCE_CREATE: + + ignored = _Objects_MP_Allocate_and_open( + &_Partition_Information, + the_packet->name, + the_packet->Prefix.id, + true + ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case PARTITION_MP_ANNOUNCE_DELETE: + + _Objects_MP_Close( &_Partition_Information, the_packet->Prefix.id ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case PARTITION_MP_EXTRACT_PROXY: + + the_thread = _Thread_MP_Find_proxy( the_packet->proxy_id ); + + if ( ! _Thread_Is_null( the_thread ) ) + _Thread_queue_Extract( the_thread->Wait.queue, the_thread ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case PARTITION_MP_GET_BUFFER_REQUEST: + + the_packet->Prefix.return_code = rtems_partition_get_buffer( + the_packet->Prefix.id, + &the_packet->buffer + ); + + _Partition_MP_Send_response_packet( + PARTITION_MP_GET_BUFFER_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case PARTITION_MP_GET_BUFFER_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + *(void **)the_thread->Wait.return_argument = the_packet->buffer; + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case PARTITION_MP_RETURN_BUFFER_REQUEST: + + the_packet->Prefix.return_code = rtems_partition_return_buffer( + the_packet->Prefix.id, + the_packet->buffer + ); + + _Partition_MP_Send_response_packet( + PARTITION_MP_RETURN_BUFFER_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case PARTITION_MP_RETURN_BUFFER_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + } +} + +/*PAGE + * + * _Partition_MP_Send_object_was_deleted + * + * This routine is not needed by the Partition since a partition + * cannot be deleted when buffers are in use. + * + */ + +/*PAGE + * + * _Partition_MP_Send_extract_proxy + * + */ + +void _Partition_MP_Send_extract_proxy ( + void *argument +) +{ + Thread_Control *the_thread = (Thread_Control *)argument; + + _Partition_MP_Send_process_packet( + PARTITION_MP_EXTRACT_PROXY, + the_thread->Wait.id, + (rtems_name) 0, + the_thread->Object.id + ); + +} + +/*PAGE + * + * _Partition_MP_Get_packet + * + */ + +Partition_MP_Packet *_Partition_MP_Get_packet ( void ) +{ + return ( (Partition_MP_Packet *) _MPCI_Get_packet() ); +} + +/* end of file */ diff --git a/cpukit/rtems/src/partreturnbuffer.c b/cpukit/rtems/src/partreturnbuffer.c new file mode 100644 index 0000000000..8b83ab3cec --- /dev/null +++ b/cpukit/rtems/src/partreturnbuffer.c @@ -0,0 +1,79 @@ +/* + * Partition Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/address.h> +#include <rtems/score/object.h> +#include <rtems/rtems/part.h> +#include <rtems/score/thread.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_partition_return_buffer + * + * This directive will return the given buffer to the specified + * buffer partition. + * + * Input parameters: + * id - partition id + * buffer - pointer to buffer address + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_partition_return_buffer( + rtems_id id, + void *buffer +) +{ + register Partition_Control *the_partition; + Objects_Locations location; + + the_partition = _Partition_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( _Partition_Is_buffer_valid( buffer, the_partition ) ) { + _Partition_Free_buffer( the_partition, buffer ); + the_partition->number_of_used_blocks -= 1; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); + return RTEMS_INVALID_ADDRESS; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _Partition_MP_Send_request_packet( + PARTITION_MP_RETURN_BUFFER_REQUEST, + id, + buffer + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/ratemon.c b/cpukit/rtems/src/ratemon.c new file mode 100644 index 0000000000..9f17a777b8 --- /dev/null +++ b/cpukit/rtems/src/ratemon.c @@ -0,0 +1,60 @@ +/* + * Rate Monotonic Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * _Rate_monotonic_Manager_initialization + * + * This routine initializes all Rate Monotonic Manager related + * data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * NOTE: The Rate Monotonic Manager is built on top of the Watchdog + * Handler. + */ + +void _Rate_monotonic_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_Rate_monotonic_Information, /* object information table */ + OBJECTS_CLASSIC_API, /* object API */ + OBJECTS_RTEMS_PERIODS, /* object class */ + Configuration_RTEMS_API.maximum_periods, + /* maximum objects of this class */ + sizeof( Rate_monotonic_Control ),/* size of this object's control block */ + false, /* true if the name is a string */ + RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/rtems/src/ratemoncancel.c b/cpukit/rtems/src/ratemoncancel.c new file mode 100644 index 0000000000..7950fe58d1 --- /dev/null +++ b/cpukit/rtems/src/ratemoncancel.c @@ -0,0 +1,68 @@ +/* + * Rate Monotonic Manager -- Cancel a Period + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * rtems_rate_monotonic_cancel + * + * This directive allows a thread to cancel a rate monotonic timer. + * + * Input parameters: + * id - rate monotonic id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful and caller is not the owning thread + * error code - if unsuccessful + */ + +rtems_status_code rtems_rate_monotonic_cancel( + rtems_id id +) +{ + Rate_monotonic_Control *the_period; + Objects_Locations location; + + the_period = _Rate_monotonic_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( !_Thread_Is_executing( the_period->owner ) ) { + _Thread_Enable_dispatch(); + return RTEMS_NOT_OWNER_OF_RESOURCE; + } + (void) _Watchdog_Remove( &the_period->Timer ); + the_period->state = RATE_MONOTONIC_INACTIVE; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/ratemoncreate.c b/cpukit/rtems/src/ratemoncreate.c new file mode 100644 index 0000000000..9fb16aa56c --- /dev/null +++ b/cpukit/rtems/src/ratemoncreate.c @@ -0,0 +1,81 @@ +/* + * Rate Monotonic Manager -- Create a Period + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * rtems_rate_monotonic_create + * + * This directive creates a rate monotonic timer and performs + * some initialization. + * + * Input parameters: + * name - name of period + * id - pointer to rate monotonic id + * + * Output parameters: + * id - rate monotonic id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_rate_monotonic_create( + rtems_name name, + rtems_id *id +) +{ + Rate_monotonic_Control *the_period; + + if ( !rtems_is_name_valid( name ) ) + return RTEMS_INVALID_NAME; + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + + _Thread_Disable_dispatch(); /* to prevent deletion */ + + the_period = _Rate_monotonic_Allocate(); + + if ( !the_period ) { + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } + + the_period->owner = _Thread_Executing; + the_period->state = RATE_MONOTONIC_INACTIVE; + + _Watchdog_Initialize( &the_period->Timer, NULL, 0, NULL ); + + _Rate_monotonic_Reset_statistics( the_period ); + + _Objects_Open( + &_Rate_monotonic_Information, + &the_period->Object, + (Objects_Name) name + ); + + *id = the_period->Object.id; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/ratemondata.c b/cpukit/rtems/src/ratemondata.c new file mode 100644 index 0000000000..efd461fa02 --- /dev/null +++ b/cpukit/rtems/src/ratemondata.c @@ -0,0 +1,22 @@ +/* + * Rate Monotonic Manager -- Instantiate Data + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate RTEMS period data */ +#define RTEMS_RATEMON_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/ratemon.h> diff --git a/cpukit/rtems/src/ratemondelete.c b/cpukit/rtems/src/ratemondelete.c new file mode 100644 index 0000000000..8149233079 --- /dev/null +++ b/cpukit/rtems/src/ratemondelete.c @@ -0,0 +1,66 @@ +/* + * Rate Monotonic Manager -- Delete a Period + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * rtems_rate_monotonic_delete + * + * This directive allows a thread to delete a rate monotonic timer. + * + * Input parameters: + * id - rate monotonic id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_rate_monotonic_delete( + rtems_id id +) +{ + Rate_monotonic_Control *the_period; + Objects_Locations location; + + the_period = _Rate_monotonic_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Objects_Close( &_Rate_monotonic_Information, &the_period->Object ); + (void) _Watchdog_Remove( &the_period->Timer ); + the_period->state = RATE_MONOTONIC_INACTIVE; + _Rate_monotonic_Free( the_period ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/ratemongetstatistics.c b/cpukit/rtems/src/ratemongetstatistics.c new file mode 100644 index 0000000000..0ecd5515f1 --- /dev/null +++ b/cpukit/rtems/src/ratemongetstatistics.c @@ -0,0 +1,91 @@ +/* + * Rate Monotonic Manager -- Get Statistics + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * rtems_rate_monotonic_get_statistics + * + * This directive allows a thread to obtain statistics information on a + * period. + * + * Input parameters: + * id - rate monotonic id + * statistics - pointer to statistics control block + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + * + */ + +rtems_status_code rtems_rate_monotonic_get_statistics( + rtems_id id, + rtems_rate_monotonic_period_statistics *statistics +) +{ + Objects_Locations location; + Rate_monotonic_Control *the_period; + rtems_rate_monotonic_period_statistics *dst; + Rate_monotonic_Statistics *src; + + if ( !statistics ) + return RTEMS_INVALID_ADDRESS; + + the_period = _Rate_monotonic_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + dst = statistics; + src = &the_period->Statistics; + dst->count = src->count; + dst->missed_count = src->missed_count; + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + _Timestamp_To_timespec( &src->min_cpu_time, &dst->min_cpu_time ); + _Timestamp_To_timespec( &src->max_cpu_time, &dst->max_cpu_time ); + _Timestamp_To_timespec( &src->total_cpu_time, &dst->total_cpu_time ); + _Timestamp_To_timespec( &src->min_wall_time, &dst->min_wall_time ); + _Timestamp_To_timespec( &src->max_wall_time, &dst->max_wall_time ); + _Timestamp_To_timespec( &src->total_wall_time, &dst->total_wall_time ); + #else + dst->min_cpu_time = src->min_cpu_time; + dst->max_cpu_time = src->max_cpu_time; + dst->total_cpu_time = src->total_cpu_time; + dst->min_wall_time = src->min_wall_time; + dst->max_wall_time = src->max_wall_time; + dst->total_wall_time = src->total_wall_time; + #endif + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/ratemongetstatus.c b/cpukit/rtems/src/ratemongetstatus.c new file mode 100644 index 0000000000..c18b5b57ba --- /dev/null +++ b/cpukit/rtems/src/ratemongetstatus.c @@ -0,0 +1,118 @@ +/* + * Rate Monotonic Manager -- Get Status + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + #include <rtems/score/timespec.h> +#endif + +/*PAGE + * + * rtems_rate_monotonic_get_status + * + * This directive allows a thread to obtain status information on a + * period. + * + * Input parameters: + * id - rate monotonic id + * status - pointer to status control block + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + * + */ + +rtems_status_code rtems_rate_monotonic_get_status( + rtems_id id, + rtems_rate_monotonic_period_status *status +) +{ + Thread_CPU_usage_t executed; + Objects_Locations location; + Rate_monotonic_Period_time_t since_last_period; + Rate_monotonic_Control *the_period; + bool valid_status; + + if ( !status ) + return RTEMS_INVALID_ADDRESS; + + the_period = _Rate_monotonic_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + status->owner = the_period->owner->Object.id; + status->state = the_period->state; + + /* + * If the period is inactive, there is no information. + */ + if ( status->state == RATE_MONOTONIC_INACTIVE ) { + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + _Timespec_Set_to_zero( &status->since_last_period ); + _Timespec_Set_to_zero( &status->executed_since_last_period ); + #else + status->since_last_period = 0; + status->executed_since_last_period = 0; + #endif + + } else { + + /* + * Grab the current status. + */ + valid_status = + _Rate_monotonic_Get_status( + the_period, &since_last_period, &executed + ); + if (!valid_status) { + _Thread_Enable_dispatch(); + return RTEMS_NOT_DEFINED; + } + + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + _Timestamp_To_timespec( + &since_last_period, &status->since_last_period + ); + _Timestamp_To_timespec( + &executed, &status->executed_since_last_period + ); + #else + status->since_last_period = since_last_period; + status->executed_since_last_period = executed; + #endif + } + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/ratemonident.c b/cpukit/rtems/src/ratemonident.c new file mode 100644 index 0000000000..68df076cbb --- /dev/null +++ b/cpukit/rtems/src/ratemonident.c @@ -0,0 +1,58 @@ +/* + * Rate Monotonic Manager -- Name to Id Lookup + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * rtems_rate_monotonic_ident + * + * This directive returns the system ID associated with + * the rate monotonic period name. + * + * Input parameters: + * name - user defined period name + * id - pointer to period id + * + * Output parameters: + * *id - region id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_rate_monotonic_ident( + rtems_name name, + rtems_id *id +) +{ + Objects_Name_or_id_lookup_errors status; + + status = _Objects_Name_to_id_u32( + &_Rate_monotonic_Information, + name, + OBJECTS_SEARCH_LOCAL_NODE, + id + ); + + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/ratemonperiod.c b/cpukit/rtems/src/ratemonperiod.c new file mode 100644 index 0000000000..e244fd5778 --- /dev/null +++ b/cpukit/rtems/src/ratemonperiod.c @@ -0,0 +1,374 @@ +/* + * Rate Monotonic Manager - Period Blocking and Status + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +bool _Rate_monotonic_Get_status( + Rate_monotonic_Control *the_period, + Rate_monotonic_Period_time_t *wall_since_last_period, + Thread_CPU_usage_t *cpu_since_last_period +) +{ + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + Timestamp_Control uptime; + #endif + Thread_Control *owning_thread = the_period->owner; + Thread_CPU_usage_t used; + + /* + * Determine elapsed wall time since period initiated. + */ + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + _TOD_Get_uptime( &uptime ); + _Timestamp_Subtract( + &the_period->time_period_initiated, &uptime, wall_since_last_period + ); + #else + *wall_since_last_period = + _Watchdog_Ticks_since_boot - the_period->time_period_initiated; + #endif + + /* + * Determine cpu usage since period initiated. + */ + used = owning_thread->cpu_time_used; + + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + if (owning_thread == _Thread_Executing) { + + Thread_CPU_usage_t ran; + + /* How much time time since last context switch */ + _Timestamp_Subtract( + &_Thread_Time_of_last_context_switch, &uptime, &ran + ); + + /* cpu usage += ran */ + _Timestamp_Add_to( &used, &ran ); + + /* + * The cpu usage info was reset while executing. Can't + * determine a status. + */ + if (_Timestamp_Less_than(&used, &the_period->cpu_usage_period_initiated)) + return false; + + /* used = current cpu usage - cpu usage at start of period */ + _Timestamp_Subtract( + &the_period->cpu_usage_period_initiated, + &used, + cpu_since_last_period + ); + } + #else + /* + * The cpu usage info was reset while executing. Can't + * determine a status. + */ + if (used < the_period->cpu_usage_period_initiated) + return false; + + *cpu_since_last_period = used - the_period->cpu_usage_period_initiated; + #endif + return true; +} + +void _Rate_monotonic_Initiate_statistics( + Rate_monotonic_Control *the_period +) +{ + Thread_Control *owning_thread = the_period->owner; + + /* + * If using nanosecond statistics, we need to obtain the uptime. + */ + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + Timestamp_Control uptime; + + _TOD_Get_uptime( &uptime ); + #endif + + /* + * Set the starting point and the CPU time used for the statistics. + */ + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + the_period->time_period_initiated = uptime; + #else + the_period->time_period_initiated = _Watchdog_Ticks_since_boot; + #endif + + the_period->cpu_usage_period_initiated = owning_thread->cpu_time_used; + + /* + * If using nanosecond statistics and the period's thread is currently + * executing, then we need to take into account how much time the + * executing thread has run since the last context switch. When this + * routine is invoked from rtems_rate_monotonic_period, the owner will + * be the executing thread. When this routine is invoked from + * _Rate_monotonic_Timeout, it will not. + */ + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + if (owning_thread == _Thread_Executing) { + + rtems_thread_cpu_usage_t ran; + + /* + * Adjust the CPU time used to account for the time since last + * context switch. + */ + _Timespec_Subtract( + &_Thread_Time_of_last_context_switch, &uptime, &ran + ); + + _Timespec_Add_to( &the_period->cpu_usage_period_initiated, &ran ); + } + #endif +} + +void _Rate_monotonic_Update_statistics( + Rate_monotonic_Control *the_period +) +{ + Thread_CPU_usage_t executed; + Rate_monotonic_Period_time_t since_last_period; + Rate_monotonic_Statistics *stats; + bool valid_status; + + /* + * Assume we are only called in states where it is appropriate + * to update the statistics. This should only be RATE_MONOTONIC_ACTIVE + * and RATE_MONOTONIC_EXPIRED. + */ + + /* + * Update the counts. + */ + stats = &the_period->Statistics; + stats->count++; + + if ( the_period->state == RATE_MONOTONIC_EXPIRED ) + stats->missed_count++; + + /* + * Grab status for time statistics. + */ + valid_status = + _Rate_monotonic_Get_status( the_period, &since_last_period, &executed ); + if (!valid_status) + return; + + /* + * Update CPU time + */ + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + _Timestamp_Add_to( &stats->total_cpu_time, &executed ); + + if ( _Timestamp_Less_than( &executed, &stats->min_cpu_time ) ) + stats->min_cpu_time = executed; + + if ( _Timestamp_Greater_than( &executed, &stats->max_cpu_time ) ) + stats->max_cpu_time = executed; + #else + stats->total_cpu_time += executed; + + if ( executed < stats->min_cpu_time ) + stats->min_cpu_time = executed; + + if ( executed > stats->max_cpu_time ) + stats->max_cpu_time = executed; + #endif + + /* + * Update Wall time + */ + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + _Timestamp_Add_to( &stats->total_wall_time, &since_last_period ); + + if ( _Timestamp_Less_than( &since_last_period, &stats->min_wall_time ) ) + stats->min_wall_time = since_last_period; + + if ( _Timestamp_Greater_than( &since_last_period, &stats->max_wall_time ) ) + stats->max_wall_time = since_last_period; + #else + + /* Sanity check wall time */ + if ( since_last_period < executed ) + since_last_period = executed; + + stats->total_wall_time += since_last_period; + + if ( since_last_period < stats->min_wall_time ) + stats->min_wall_time = since_last_period; + + if ( since_last_period > stats->max_wall_time ) + stats->max_wall_time = since_last_period; + #endif +} + + +/*PAGE + * + * rtems_rate_monotonic_period + * + * This directive allows a thread to manipulate a rate monotonic timer. + * + * Input parameters: + * id - rate monotonic id + * length - length of period (in ticks) + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_rate_monotonic_period( + rtems_id id, + rtems_interval length +) +{ + Rate_monotonic_Control *the_period; + Objects_Locations location; + rtems_status_code return_value; + rtems_rate_monotonic_period_states local_state; + ISR_Level level; + + the_period = _Rate_monotonic_Get( id, &location ); + + switch ( location ) { + case OBJECTS_LOCAL: + if ( !_Thread_Is_executing( the_period->owner ) ) { + _Thread_Enable_dispatch(); + return RTEMS_NOT_OWNER_OF_RESOURCE; + } + + if ( length == RTEMS_PERIOD_STATUS ) { + switch ( the_period->state ) { + case RATE_MONOTONIC_INACTIVE: + return_value = RTEMS_NOT_DEFINED; + break; + case RATE_MONOTONIC_EXPIRED: + case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING: + return_value = RTEMS_TIMEOUT; + break; + case RATE_MONOTONIC_ACTIVE: + default: /* unreached -- only to remove warnings */ + return_value = RTEMS_SUCCESSFUL; + break; + } + _Thread_Enable_dispatch(); + return( return_value ); + } + + _ISR_Disable( level ); + if ( the_period->state == RATE_MONOTONIC_INACTIVE ) { + _ISR_Enable( level ); + + /* + * Baseline statistics information for the beginning of a period. + */ + _Rate_monotonic_Initiate_statistics( the_period ); + + the_period->state = RATE_MONOTONIC_ACTIVE; + _Watchdog_Initialize( + &the_period->Timer, + _Rate_monotonic_Timeout, + id, + NULL + ); + + the_period->next_length = length; + + _Watchdog_Insert_ticks( &the_period->Timer, length ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + + if ( the_period->state == RATE_MONOTONIC_ACTIVE ) { + /* + * Update statistics from the concluding period. + */ + _Rate_monotonic_Update_statistics( the_period ); + + /* + * This tells the _Rate_monotonic_Timeout that this task is + * in the process of blocking on the period and that we + * may be changing the length of the next period. + */ + the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING; + the_period->next_length = length; + + _ISR_Enable( level ); + + _Thread_Executing->Wait.id = the_period->Object.id; + _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD ); + + /* + * Did the watchdog timer expire while we were actually blocking + * on it? + */ + _ISR_Disable( level ); + local_state = the_period->state; + the_period->state = RATE_MONOTONIC_ACTIVE; + _ISR_Enable( level ); + + /* + * If it did, then we want to unblock ourself and continue as + * if nothing happen. The period was reset in the timeout routine. + */ + if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) + _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD ); + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + + if ( the_period->state == RATE_MONOTONIC_EXPIRED ) { + /* + * Update statistics from the concluding period + */ + _Rate_monotonic_Update_statistics( the_period ); + + _ISR_Enable( level ); + + the_period->state = RATE_MONOTONIC_ACTIVE; + the_period->next_length = length; + + _Watchdog_Insert_ticks( &the_period->Timer, length ); + _Thread_Enable_dispatch(); + return RTEMS_TIMEOUT; + } + + /* + * These should never happen so just return invalid Id. + * - RATE_MONOTONIC_OWNER_IS_BLOCKING: + * - RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING: + */ +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/ratemonreportstatistics.c b/cpukit/rtems/src/ratemonreportstatistics.c new file mode 100644 index 0000000000..fe65151d04 --- /dev/null +++ b/cpukit/rtems/src/ratemonreportstatistics.c @@ -0,0 +1,209 @@ +/* + * Rate Monotonic Manager -- Report Statistics for All Periods + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems.h> +#include <stdlib.h> +#include <ctype.h> +#include <inttypes.h> + +#include <rtems/bspIo.h> +#include <rtems/score/timespec.h> + +#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + /* We print to 1/10's of milliseconds */ + #define NANOSECONDS_DIVIDER 1000 + #define PERCENT_FMT "%04" PRId32 + #define NANOSECONDS_FMT "%06" PRId32 +#endif + +/* + * This directive allows a thread to print the statistics information + * on ALL period instances which have non-zero counts using printk. + * + * The implementation of this directive straddles the fence between + * inside and outside of RTEMS. It is presented as part of the Manager + * but actually uses other services of the Manager. + */ +void rtems_rate_monotonic_report_statistics_with_plugin( + void *context, + rtems_printk_plugin_t print +) +{ + rtems_status_code status; + rtems_id id; + rtems_rate_monotonic_period_statistics the_stats; + rtems_rate_monotonic_period_status the_status; + char name[5]; + + if ( !print ) + return; + + (*print)( context, "Period information by period\n" ); + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + (*print)( context, "--- CPU times are in seconds ---\n" ); + (*print)( context, "--- Wall times are in seconds ---\n" ); + #endif +/* +Layout by columns -- in memory of Hollerith :) + +1234567890123456789012345678901234567890123456789012345678901234567890123456789\ + ID OWNER COUNT MISSED X +ididididid NNNN ccccc mmmmmm X + + Uncomment the following if you are tinkering with the formatting. + Be sure to test the various cases. + (*print)( context,"\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789\ +\n"); +*/ + (*print)( context, " ID OWNER COUNT MISSED " + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + " " + #endif + "CPU TIME " + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + " " + #endif + " WALL TIME\n" + ); + (*print)( context, " " + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + " " + #endif + "MIN/MAX/AVG " + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + " " + #endif + " MIN/MAX/AVG\n" + ); + + /* + * Cycle through all possible ids and try to report on each one. If it + * is a period that is inactive, we just get an error back. No big deal. + */ + for ( id=_Rate_monotonic_Information.minimum_id ; + id <= _Rate_monotonic_Information.maximum_id ; + id++ ) { + status = rtems_rate_monotonic_get_statistics( id, &the_stats ); + if ( status != RTEMS_SUCCESSFUL ) + continue; + + /* If the above passed, so should this but check it anyway */ + #if defined(RTEMS_DEBUG) + status = rtems_rate_monotonic_get_status( id, &the_status ); + if ( status != RTEMS_SUCCESSFUL ) + continue; + #else + (void) rtems_rate_monotonic_get_status( id, &the_status ); + #endif + + rtems_object_get_name( the_status.owner, sizeof(name), name ); + + /* + * Print part of report line that is not dependent on granularity + */ + (*print)( context, + "0x%08" PRIx32 " %4s %5" PRId32 " %6" PRId32 " ", + id, name, + the_stats.count, the_stats.missed_count + ); + + /* + * If the count is zero, don't print statistics + */ + if (the_stats.count == 0) { + (*print)( context, "\n" ); + continue; + } + + /* + * print CPU Usage part of statistics + */ + { + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + struct timespec cpu_average; + struct timespec *min_cpu = &the_stats.min_cpu_time; + struct timespec *max_cpu = &the_stats.max_cpu_time; + struct timespec *total_cpu = &the_stats.total_cpu_time; + + _Timespec_Divide_by_integer( total_cpu, the_stats.count, &cpu_average ); + (*print)( context, + "%" PRId32 "." NANOSECONDS_FMT "/" /* min cpu time */ + "%" PRId32 "." NANOSECONDS_FMT "/" /* max cpu time */ + "%" PRId32 "." NANOSECONDS_FMT " ", /* avg cpu time */ + _Timespec_Get_seconds( min_cpu ), + _Timespec_Get_nanoseconds( min_cpu ) / NANOSECONDS_DIVIDER, + _Timespec_Get_seconds( max_cpu ), + _Timespec_Get_nanoseconds( max_cpu ) / NANOSECONDS_DIVIDER, + _Timespec_Get_seconds( &cpu_average ), + _Timespec_Get_nanoseconds( &cpu_average ) / NANOSECONDS_DIVIDER + ); + #else + uint32_t ival_cpu, fval_cpu; + + ival_cpu = the_stats.total_cpu_time * 100 / the_stats.count; + fval_cpu = ival_cpu % 100; + ival_cpu /= 100; + + (*print)( context, + "%3" PRId32 "/%4" PRId32 "/%3" PRId32 ".%02" PRId32 " ", + the_stats.min_cpu_time, the_stats.max_cpu_time, ival_cpu, fval_cpu + ); + #endif + } + + /* + * print wall time part of statistics + */ + { + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + struct timespec wall_average; + struct timespec *min_wall = &the_stats.min_wall_time; + struct timespec *max_wall = &the_stats.max_wall_time; + struct timespec *total_wall = &the_stats.total_wall_time; + + _Timespec_Divide_by_integer(total_wall, the_stats.count, &wall_average); + (*print)( context, + "%" PRId32 "." NANOSECONDS_FMT "/" /* min wall time */ + "%" PRId32 "." NANOSECONDS_FMT "/" /* max wall time */ + "%" PRId32 "." NANOSECONDS_FMT "\n", /* avg wall time */ + _Timespec_Get_seconds( min_wall ), + _Timespec_Get_nanoseconds( min_wall ) / NANOSECONDS_DIVIDER, + _Timespec_Get_seconds( max_wall ), + _Timespec_Get_nanoseconds( max_wall ) / NANOSECONDS_DIVIDER, + _Timespec_Get_seconds( &wall_average ), + _Timespec_Get_nanoseconds( &wall_average ) / NANOSECONDS_DIVIDER + ); + #else + uint32_t ival_wall, fval_wall; + + ival_wall = the_stats.total_wall_time * 100 / the_stats.count; + fval_wall = ival_wall % 100; + ival_wall /= 100; + (*print)( context, + "%3" PRId32 "/%4" PRId32 "/%3" PRId32 ".%02" PRId32 "\n", + the_stats.min_wall_time, the_stats.max_wall_time, ival_wall, fval_wall + ); + #endif + } + } +} + +void rtems_rate_monotonic_report_statistics( void ) +{ + rtems_rate_monotonic_report_statistics_with_plugin( NULL, printk_plugin ); +} diff --git a/cpukit/rtems/src/ratemonresetall.c b/cpukit/rtems/src/ratemonresetall.c new file mode 100644 index 0000000000..39a2ec91e7 --- /dev/null +++ b/cpukit/rtems/src/ratemonresetall.c @@ -0,0 +1,55 @@ +/* + * Rate Monotonic Manager -- Reset Statistics for All Periods + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +/* + * rtems_rate_monotonic_reset_all_statistics + */ +void rtems_rate_monotonic_reset_all_statistics( void ) +{ + Objects_Id id; + + /* + * Prevent allocation or deallocation of any of the periods while + * we are cycling. Also this is an optimization which ensures that + * we only disable/enable once. The call to + * rtems_rate_monotonic_reset_statistics will be in a nested dispatch + * disabled critical section. + */ + _Thread_Disable_dispatch(); + + /* + * Cycle through all possible ids and try to reset each one. If it + * is a period that is inactive, we just get an error back. No big deal. + */ + for ( id=_Rate_monotonic_Information.minimum_id ; + id <= _Rate_monotonic_Information.maximum_id ; + id++ ) { + (void) rtems_rate_monotonic_reset_statistics( id ); + } + + /* + * Done so exit thread dispatching disabled critical section. + */ + _Thread_Enable_dispatch(); +} diff --git a/cpukit/rtems/src/ratemonresetstatistics.c b/cpukit/rtems/src/ratemonresetstatistics.c new file mode 100644 index 0000000000..065c31aec2 --- /dev/null +++ b/cpukit/rtems/src/ratemonresetstatistics.c @@ -0,0 +1,65 @@ +/* + * Rate Monotonic Manager -- Reset Statistics + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * rtems_rate_monotonic_reset_statistics + * + * This directive allows a thread to reset the statistics information + * on a specific period instance. + * + * Input parameters: + * id - rate monotonic id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + * + */ + +rtems_status_code rtems_rate_monotonic_reset_statistics( + rtems_id id +) +{ + Objects_Locations location; + Rate_monotonic_Control *the_period; + + the_period = _Rate_monotonic_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Rate_monotonic_Reset_statistics( the_period ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/ratemontimeout.c b/cpukit/rtems/src/ratemontimeout.c new file mode 100644 index 0000000000..de1674636c --- /dev/null +++ b/cpukit/rtems/src/ratemontimeout.c @@ -0,0 +1,83 @@ +/* + * Rate Monotonic Manager -- Period End Timeout Handler + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/ratemon.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * _Rate_monotonic_Timeout + * + * This routine processes a period ending. If the owning thread + * is waiting for the period, that thread is unblocked and the + * period reinitiated. Otherwise, the period is expired. + * This routine is called by the watchdog handler. + * + * Input parameters: + * id - period id + * + * Output parameters: NONE + */ + +void _Rate_monotonic_Timeout( + Objects_Id id, + void *ignored +) +{ + Rate_monotonic_Control *the_period; + Objects_Locations location; + Thread_Control *the_thread; + + /* + * When we get here, the Timer is already off the chain so we do not + * have to worry about that -- hence no _Watchdog_Remove(). + */ + the_period = _Rate_monotonic_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + the_thread = the_period->owner; + if ( _States_Is_waiting_for_period( the_thread->current_state ) && + the_thread->Wait.id == the_period->Object.id ) { + _Thread_Unblock( the_thread ); + + _Rate_monotonic_Initiate_statistics( the_period ); + + _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length ); + } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) { + the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING; + + _Rate_monotonic_Initiate_statistics( the_period ); + + _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length ); + } else + the_period->state = RATE_MONOTONIC_EXPIRED; + _Thread_Unnest_dispatch(); + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* impossible */ +#endif + case OBJECTS_ERROR: + break; + } +} diff --git a/cpukit/rtems/src/region.c b/cpukit/rtems/src/region.c new file mode 100644 index 0000000000..1b06ee60b5 --- /dev/null +++ b/cpukit/rtems/src/region.c @@ -0,0 +1,70 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * _Region_Manager_initialization + * + * This routine initializes all region manager related data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _Region_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_Region_Information, /* object information table */ + OBJECTS_CLASSIC_API, /* object API */ + OBJECTS_RTEMS_REGIONS, /* object class */ + Configuration_RTEMS_API.maximum_regions, + /* maximum objects of this class */ + sizeof( Region_Control ), /* size of this object's control block */ + false, /* true if the name is a string */ + RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); + + /* + * Register the MP Process Packet routine. + */ + +#if defined(RTEMS_MULTIPROCESSING) + _MPCI_Register_packet_processor( + MP_PACKET_REGION, + 0 /* XXX _Region_MP_Process_packet */ + ); +#endif + +} diff --git a/cpukit/rtems/src/regioncreate.c b/cpukit/rtems/src/regioncreate.c new file mode 100644 index 0000000000..90aca79ea7 --- /dev/null +++ b/cpukit/rtems/src/regioncreate.c @@ -0,0 +1,118 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_region_create + * + * This directive creates a region of physical contiguous memory area + * from which variable sized segments can be allocated. + * + * Input parameters: + * name - user defined region name + * starting_address - physical start address of region + * length - physical length in bytes + * page_size - page size in bytes + * attribute_set - region attributes + * id - address of region id to set + * + * Output parameters: + * id - region id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_create( + rtems_name name, + void *starting_address, + uintptr_t length, + uintptr_t page_size, + rtems_attribute attribute_set, + rtems_id *id +) +{ + rtems_status_code return_status; + Region_Control *the_region; + + if ( !rtems_is_name_valid( name ) ) + return RTEMS_INVALID_NAME; + + if ( !starting_address ) + return RTEMS_INVALID_ADDRESS; + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + + _RTEMS_Lock_allocator(); /* to prevent deletion */ + + the_region = _Region_Allocate(); + + if ( !the_region ) + return_status = RTEMS_TOO_MANY; + + else { + + the_region->maximum_segment_size = _Heap_Initialize( + &the_region->Memory, starting_address, length, page_size + ); + + if ( !the_region->maximum_segment_size ) { + _Region_Free( the_region ); + return_status = RTEMS_INVALID_SIZE; + } + + else { + + the_region->starting_address = starting_address; + the_region->length = length; + the_region->page_size = page_size; + the_region->attribute_set = attribute_set; + the_region->number_of_used_blocks = 0; + + _Thread_queue_Initialize( + &the_region->Wait_queue, + _Attributes_Is_priority( attribute_set ) ? + THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO, + STATES_WAITING_FOR_SEGMENT, + RTEMS_TIMEOUT + ); + + _Objects_Open( + &_Region_Information, + &the_region->Object, + (Objects_Name) name + ); + + *id = the_region->Object.id; + return_status = RTEMS_SUCCESSFUL; + } + } + + _RTEMS_Unlock_allocator(); + return return_status; +} diff --git a/cpukit/rtems/src/regiondata.c b/cpukit/rtems/src/regiondata.c new file mode 100644 index 0000000000..9ecce9e7bb --- /dev/null +++ b/cpukit/rtems/src/regiondata.c @@ -0,0 +1,22 @@ +/* + * Region Manager -- Instantiate Data + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate RTEMS Region data */ +#define RTEMS_REGION_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/region.h> diff --git a/cpukit/rtems/src/regiondelete.c b/cpukit/rtems/src/regiondelete.c new file mode 100644 index 0000000000..8217e68f71 --- /dev/null +++ b/cpukit/rtems/src/regiondelete.c @@ -0,0 +1,82 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_region_delete + * + * This directive allows a thread to delete a region specified by + * the region identifier, provided that none of its segments are + * still allocated. + * + * Input parameters: + * id - region id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_delete( + rtems_id id +) +{ + Objects_Locations location; + rtems_status_code return_status; + Region_Control *the_region; + + _RTEMS_Lock_allocator(); + + the_region = _Region_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Region_Debug_Walk( the_region, 5 ); + if ( the_region->number_of_used_blocks != 0 ) + return_status = RTEMS_RESOURCE_IN_USE; + else { + _Objects_Close( &_Region_Information, &the_region->Object ); + _Region_Free( the_region ); + return_status = RTEMS_SUCCESSFUL; + } + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ + break; +#endif + + case OBJECTS_ERROR: + default: + return_status = RTEMS_INVALID_ID; + break; + } + + _RTEMS_Unlock_allocator(); + return return_status; +} diff --git a/cpukit/rtems/src/regionextend.c b/cpukit/rtems/src/regionextend.c new file mode 100644 index 0000000000..f4b6c93c2d --- /dev/null +++ b/cpukit/rtems/src/regionextend.c @@ -0,0 +1,96 @@ +/* + * Region Manager - Extend (add memory to) a Region + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_region_extend + * + * This directive attempts to grow a region of physical contiguous memory area + * from which variable sized segments can be allocated. + * + * Input parameters: + * id - id of region to grow + * start - starting address of memory area for extension + * length - physical length in bytes to grow the region + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_extend( + rtems_id id, + void *starting_address, + uintptr_t length +) +{ + uintptr_t amount_extended; + bool extend_ok; + Objects_Locations location; + rtems_status_code return_status; + Region_Control *the_region; + + if ( !starting_address ) + return RTEMS_INVALID_ADDRESS; + + _RTEMS_Lock_allocator(); /* to prevent deletion */ + + the_region = _Region_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + extend_ok = _Heap_Extend( + &the_region->Memory, + starting_address, + length, + &amount_extended + ); + + if ( extend_ok ) { + the_region->length += amount_extended; + the_region->maximum_segment_size += amount_extended; + return_status = RTEMS_SUCCESSFUL; + } else { + return_status = RTEMS_INVALID_ADDRESS; + } + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ + break; +#endif + + case OBJECTS_ERROR: + default: + return_status = RTEMS_INVALID_ID; + break; + } + + _RTEMS_Unlock_allocator(); + return return_status; +} diff --git a/cpukit/rtems/src/regiongetfreeinfo.c b/cpukit/rtems/src/regiongetfreeinfo.c new file mode 100644 index 0000000000..fcfa3bc8b2 --- /dev/null +++ b/cpukit/rtems/src/regiongetfreeinfo.c @@ -0,0 +1,88 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/apimutex.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * rtems_region_get_free_information + * + * This directive will return information about the free blocks + * in the region specified. Information about the used blocks + * will be returned as zero. + * + * Input parameters: + * id - region id + * the_info - pointer to region information block + * + * Output parameters: + * *the_info - region information block filled in + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_get_free_information( + rtems_id id, + Heap_Information_block *the_info +) +{ + Objects_Locations location; + rtems_status_code return_status; + register Region_Control *the_region; + + if ( !the_info ) + return RTEMS_INVALID_ADDRESS; + + _RTEMS_Lock_allocator(); + + the_region = _Region_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + the_info->Used.number = 0; + the_info->Used.total = 0; + the_info->Used.largest = 0; + + _Heap_Get_free_information( &the_region->Memory, &the_info->Free ); + + return_status = RTEMS_SUCCESSFUL; + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ + break; +#endif + + case OBJECTS_ERROR: + default: + return_status = RTEMS_INVALID_ID; + break; + } + + _RTEMS_Unlock_allocator(); + return return_status; +} diff --git a/cpukit/rtems/src/regiongetinfo.c b/cpukit/rtems/src/regiongetinfo.c new file mode 100644 index 0000000000..306f3da947 --- /dev/null +++ b/cpukit/rtems/src/regiongetinfo.c @@ -0,0 +1,80 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/apimutex.h> +#include <rtems/score/thread.h> + +/*PAGE + * + * rtems_region_get_information + * + * This directive will return information about the region specified. + * + * Input parameters: + * id - region id + * the_info - pointer to region information block + * + * Output parameters: + * *the_info - region information block filled in + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_get_information( + rtems_id id, + Heap_Information_block *the_info +) +{ + Objects_Locations location; + rtems_status_code return_status; + register Region_Control *the_region; + + if ( !the_info ) + return RTEMS_INVALID_ADDRESS; + + _RTEMS_Lock_allocator(); + + the_region = _Region_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Heap_Get_information( &the_region->Memory, the_info ); + return_status = RTEMS_SUCCESSFUL; + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ + break; +#endif + + case OBJECTS_ERROR: + default: + return_status = RTEMS_INVALID_ID; + break; + } + + _RTEMS_Unlock_allocator(); + return return_status; +} diff --git a/cpukit/rtems/src/regiongetsegment.c b/cpukit/rtems/src/regiongetsegment.c new file mode 100644 index 0000000000..c8c8cfa0fb --- /dev/null +++ b/cpukit/rtems/src/regiongetsegment.c @@ -0,0 +1,131 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_region_get_segment + * + * This directive will obtain a segment from the given region. + * + * Input parameters: + * id - region id + * size - segment size in bytes + * option_set - wait option + * timeout - number of ticks to wait (0 means wait forever) + * segment - pointer to segment address + * + * Output parameters: + * segment - pointer to segment address filled in + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_get_segment( + rtems_id id, + uintptr_t size, + rtems_option option_set, + rtems_interval timeout, + void **segment +) +{ + Thread_Control *executing; + Objects_Locations location; + rtems_status_code return_status; + Region_Control *the_region; + void *the_segment; + + if ( !segment ) + return RTEMS_INVALID_ADDRESS; + + *segment = NULL; + + if ( size == 0 ) + return RTEMS_INVALID_SIZE; + + _RTEMS_Lock_allocator(); + + executing = _Thread_Executing; + the_region = _Region_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( size > the_region->maximum_segment_size ) + return_status = RTEMS_INVALID_SIZE; + + else { + _Region_Debug_Walk( the_region, 1 ); + + the_segment = _Region_Allocate_segment( the_region, size ); + + _Region_Debug_Walk( the_region, 2 ); + + if ( the_segment ) { + the_region->number_of_used_blocks += 1; + *segment = the_segment; + return_status = RTEMS_SUCCESSFUL; + } else if ( _Options_Is_no_wait( option_set ) ) { + return_status = RTEMS_UNSATISFIED; + } else { + /* + * Switch from using the memory allocation mutex to using a + * dispatching disabled critical section. We have to do this + * because this thread is going to block. + */ + _Thread_Disable_dispatch(); + _RTEMS_Unlock_allocator(); + + executing->Wait.queue = &the_region->Wait_queue; + executing->Wait.id = id; + executing->Wait.count = size; + executing->Wait.return_argument = segment; + + _Thread_queue_Enter_critical_section( &the_region->Wait_queue ); + + _Thread_queue_Enqueue( &the_region->Wait_queue, timeout ); + + _Thread_Enable_dispatch(); + + return (rtems_status_code) executing->Wait.return_code; + } + } + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ + break; +#endif + + case OBJECTS_ERROR: + default: + return_status = RTEMS_INVALID_ID; + break; + } + + _RTEMS_Unlock_allocator(); + return return_status; +} diff --git a/cpukit/rtems/src/regiongetsegmentsize.c b/cpukit/rtems/src/regiongetsegmentsize.c new file mode 100644 index 0000000000..601145128a --- /dev/null +++ b/cpukit/rtems/src/regiongetsegmentsize.c @@ -0,0 +1,83 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_region_get_segment_size + * + * This directive will return the size of the segment indicated + * + * Input parameters: + * id - region id + * segment - segment address + * size - pointer to segment size in bytes + * + * Output parameters: + * size - segment size in bytes filled in + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_get_segment_size( + rtems_id id, + void *segment, + uintptr_t *size +) +{ + Objects_Locations location; + rtems_status_code return_status = RTEMS_SUCCESSFUL; + register Region_Control *the_region; + + if ( !segment ) + return RTEMS_INVALID_ADDRESS; + + if ( !size ) + return RTEMS_INVALID_ADDRESS; + + _RTEMS_Lock_allocator(); + + the_region = _Region_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( !_Heap_Size_of_alloc_area( &the_region->Memory, segment, size ) ) + return_status = RTEMS_INVALID_ADDRESS; + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ + break; +#endif + + case OBJECTS_ERROR: + return_status = RTEMS_INVALID_ID; + break; + } + + _RTEMS_Unlock_allocator(); + return return_status; +} diff --git a/cpukit/rtems/src/regionident.c b/cpukit/rtems/src/regionident.c new file mode 100644 index 0000000000..55df94d48c --- /dev/null +++ b/cpukit/rtems/src/regionident.c @@ -0,0 +1,61 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_region_ident + * + * This directive returns the system ID associated with + * the region name. + * + * Input parameters: + * name - user defined region name + * id - pointer to region id + * + * Output parameters: + * *id - region id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_ident( + rtems_name name, + rtems_id *id +) +{ + Objects_Name_or_id_lookup_errors status; + + status = _Objects_Name_to_id_u32( + &_Region_Information, + name, + OBJECTS_SEARCH_LOCAL_NODE, + id + ); + + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/regionmp.c b/cpukit/rtems/src/regionmp.c new file mode 100644 index 0000000000..a978c2d288 --- /dev/null +++ b/cpukit/rtems/src/regionmp.c @@ -0,0 +1,315 @@ +/* + * Multiprocessing Support for the Region Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/score/mpci.h> +#include <rtems/score/mppkt.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _Region_MP_Send_process_packet + * + */ + +void _Region_MP_Send_process_packet ( + Region_MP_Remote_operations operation, + Objects_Id region_id, + rtems_name name, + Objects_Id proxy_id +) +{ + Region_MP_Packet *the_packet; + uint32_t node; + + switch ( operation ) { + + case REGION_MP_ANNOUNCE_CREATE: + case REGION_MP_ANNOUNCE_DELETE: + case REGION_MP_EXTRACT_PROXY: + + the_packet = _Region_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_REGION; + the_packet->Prefix.length = sizeof ( Region_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( Region_MP_Packet ); + the_packet->operation = operation; + the_packet->Prefix.id = region_id; + the_packet->name = name; + the_packet->proxy_id = proxy_id; + + if ( operation == REGION_MP_EXTRACT_PROXY ) + node = _Objects_Get_node( region_id ); + else + node = MPCI_ALL_NODES; + + _MPCI_Send_process_packet( node, &the_packet->Prefix ); + break; + + case REGION_MP_GET_SEGMENT_REQUEST: + case REGION_MP_GET_SEGMENT_RESPONSE: + case REGION_MP_RETURN_SEGMENT_REQUEST: + case REGION_MP_RETURN_SEGMENT_RESPONSE: + break; + } +} + +/*PAGE + * + * _Region_MP_Send_request_packet + * + */ + +rtems_status_code _Region_MP_Send_request_packet ( + Region_MP_Remote_operations operation, + Objects_Id region_id, + void *segment, + intptr_t size, + rtems_option option_set, + rtems_interval timeout +) +{ + Region_MP_Packet *the_packet; + + switch ( operation ) { + + case REGION_MP_GET_SEGMENT_REQUEST: + case REGION_MP_RETURN_SEGMENT_REQUEST: + + the_packet = _Region_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_REGION; + the_packet->Prefix.length = sizeof ( Region_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( Region_MP_Packet ); + if ( ! _Options_Is_no_wait(option_set)) + the_packet->Prefix.timeout = timeout; + + the_packet->operation = operation; + the_packet->Prefix.id = region_id; + the_packet->segment = segment; + the_packet->size = size; + the_packet->option_set = option_set; + + return (rtems_status_code) _MPCI_Send_request_packet( + _Objects_Get_node( region_id ), + &the_packet->Prefix, + STATES_READY /* Not used */ + ); + break; + + case REGION_MP_ANNOUNCE_CREATE: + case REGION_MP_ANNOUNCE_DELETE: + case REGION_MP_EXTRACT_PROXY: + case REGION_MP_GET_SEGMENT_RESPONSE: + case REGION_MP_RETURN_SEGMENT_RESPONSE: + break; + + } + /* + * The following line is included to satisfy compilers which + * produce warnings when a function does not end with a return. + */ + return RTEMS_INTERNAL_ERROR; +} + +/*PAGE + * + * _Region_MP_Send_response_packet + * + */ + +void _Region_MP_Send_response_packet ( + Region_MP_Remote_operations operation, + Objects_Id region_id, + Thread_Control *the_thread +) +{ + Region_MP_Packet *the_packet; + + switch ( operation ) { + + case REGION_MP_GET_SEGMENT_RESPONSE: + case REGION_MP_RETURN_SEGMENT_RESPONSE: + + the_packet = ( Region_MP_Packet *) the_thread->receive_packet; + +/* + * The packet being returned already contains the class, length, and + * to_convert fields, therefore they are not set in this routine. + */ + the_packet->operation = operation; + the_packet->Prefix.id = the_packet->Prefix.source_tid; + + _MPCI_Send_response_packet( + _Objects_Get_node( the_packet->Prefix.source_tid ), + &the_packet->Prefix + ); + break; + + case REGION_MP_ANNOUNCE_CREATE: + case REGION_MP_ANNOUNCE_DELETE: + case REGION_MP_EXTRACT_PROXY: + case REGION_MP_GET_SEGMENT_REQUEST: + case REGION_MP_RETURN_SEGMENT_REQUEST: + break; + + } +} + +/*PAGE + * + * + * _Region_MP_Process_packet + * + */ + +void _Region_MP_Process_packet ( + rtems_packet_prefix *the_packet_prefix +) +{ + Region_MP_Packet *the_packet; + Thread_Control *the_thread; + bool ignored; + + the_packet = (Region_MP_Packet *) the_packet_prefix; + + switch ( the_packet->operation ) { + + case REGION_MP_ANNOUNCE_CREATE: + + ignored = _Objects_MP_Allocate_and_open( + &_Region_Information, + the_packet->name, + the_packet->Prefix.id, + true + ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case REGION_MP_ANNOUNCE_DELETE: + + _Objects_MP_Close( &_Region_Information, the_packet->Prefix.id ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case REGION_MP_EXTRACT_PROXY: + + the_thread = _Thread_MP_Find_proxy( the_packet->proxy_id ); + + if ( ! _Thread_Is_null( the_thread ) ) + _Thread_queue_Extract( the_thread->Wait.queue, the_thread ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case REGION_MP_GET_SEGMENT_REQUEST: + + the_packet->Prefix.return_code = rtems_region_get_segment( + the_packet->Prefix.id, + the_packet->size, + the_packet->option_set, + the_packet->Prefix.timeout, + &the_packet->segment + ); + + _Region_MP_Send_response_packet( + REGION_MP_GET_SEGMENT_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case REGION_MP_GET_SEGMENT_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + *(void **)the_thread->Wait.return_argument = the_packet->segment; + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case REGION_MP_RETURN_SEGMENT_REQUEST: + + the_packet->Prefix.return_code = rtems_region_return_segment( + the_packet->Prefix.id, + the_packet->segment + ); + + _Region_MP_Send_response_packet( + REGION_MP_RETURN_SEGMENT_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case REGION_MP_RETURN_SEGMENT_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + } +} + +/*PAGE + * + * _Region_MP_Send_object_was_deleted + * + * This routine is not needed by the Region since a region + * cannot be deleted when segments are in use. + * + */ + +/*PAGE + * + * _Region_MP_Send_extract_proxy + * + */ + +void _Region_MP_Send_extract_proxy ( + void *argument +) +{ + Thread_Control *the_thread = (Thread_Control *)argument; + + _Region_MP_Send_process_packet( + REGION_MP_EXTRACT_PROXY, + the_thread->Wait.id, + (rtems_name) 0, + the_thread->Object.id + ); +} + +/*PAGE + * + * _Region_MP_Get_packet + * + */ + +Region_MP_Packet *_Region_MP_Get_packet ( void ) +{ + return ( (Region_MP_Packet *) _MPCI_Get_packet() ); +} + +/* end of file */ diff --git a/cpukit/rtems/src/regionprocessqueue.c b/cpukit/rtems/src/regionprocessqueue.c new file mode 100644 index 0000000000..011e646a6c --- /dev/null +++ b/cpukit/rtems/src/regionprocessqueue.c @@ -0,0 +1,87 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * _Region_Process_queue + * + * If enough memory is available to satisfy the rtems_region_get_segment of + * the first blocked task, then that task and as many subsequent tasks as + * possible will be unblocked with their requests satisfied. + * + * Input parameters: + * the_region - the region + * + * Output parameters: + * none + */ + +void _Region_Process_queue( + Region_Control *the_region +) +{ + Thread_Control *the_thread; + void *the_segment; + /* + * Switch from using the memory allocation mutex to using a + * dispatching disabled critical section. We have to do this + * because this thread may unblock one or more threads that were + * waiting on memory. + * + * NOTE: Be sure to disable dispatching before unlocking the mutex + * since we do not want to open a window where a context + * switch could occur. + */ + _Thread_Disable_dispatch(); + _RTEMS_Unlock_allocator(); + + /* + * NOTE: The following loop is O(n) where n is the number of + * threads whose memory request is satisfied. + */ + for ( ; ; ) { + the_thread = _Thread_queue_First( &the_region->Wait_queue ); + + if ( the_thread == NULL ) + break; + + the_segment = (void **) _Region_Allocate_segment( + the_region, + the_thread->Wait.count + ); + + if ( the_segment == NULL ) + break; + + *(void **)the_thread->Wait.return_argument = the_segment; + the_region->number_of_used_blocks += 1; + _Thread_queue_Extract( &the_region->Wait_queue, the_thread ); + the_thread->Wait.return_code = RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); +} diff --git a/cpukit/rtems/src/regionresizesegment.c b/cpukit/rtems/src/regionresizesegment.c new file mode 100644 index 0000000000..737e31436e --- /dev/null +++ b/cpukit/rtems/src/regionresizesegment.c @@ -0,0 +1,109 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_region_resize_segment + * + * This directive will try to resize segment to the new size 'size' + * "in place". + * + * Input parameters: + * id - region id + * segment - pointer to segment address + * size - new required size + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_resize_segment( + rtems_id id, + void *segment, + uintptr_t size, + uintptr_t *old_size +) +{ + uintptr_t avail_size; + Objects_Locations location; + uintptr_t osize; + rtems_status_code return_status; + Heap_Resize_status status; + register Region_Control *the_region; + + if ( !old_size ) + return RTEMS_INVALID_ADDRESS; + + _RTEMS_Lock_allocator(); + + the_region = _Region_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + _Region_Debug_Walk( the_region, 7 ); + + status = _Heap_Resize_block( + &the_region->Memory, + segment, + (uint32_t) size, + &osize, + &avail_size + ); + *old_size = (uint32_t) osize; + + _Region_Debug_Walk( the_region, 8 ); + + if ( status == HEAP_RESIZE_SUCCESSFUL ) + _Region_Process_queue( the_region ); /* unlocks allocator */ + else + _RTEMS_Unlock_allocator(); + + + if (status == HEAP_RESIZE_SUCCESSFUL) + return RTEMS_SUCCESSFUL; + if (status == HEAP_RESIZE_UNSATISFIED) + return RTEMS_UNSATISFIED; + return RTEMS_INVALID_ADDRESS; + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ + break; +#endif + + case OBJECTS_ERROR: + default: + return_status = RTEMS_INVALID_ID; + break; + } + + _RTEMS_Unlock_allocator(); + return return_status; +} diff --git a/cpukit/rtems/src/regionreturnsegment.c b/cpukit/rtems/src/regionreturnsegment.c new file mode 100644 index 0000000000..b98ff1d486 --- /dev/null +++ b/cpukit/rtems/src/regionreturnsegment.c @@ -0,0 +1,111 @@ +/* + * Region Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_REGION_SHRED_ON_FREE +#include <string.h> + +#ifndef RTEMS_REGION_FREE_SHRED_PATTERN +#define RTEMS_REGION_FREE_SHRED_PATTERN 0x00 +#endif +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/region.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_region_return_segment + * + * This directive will return a segment to its region. + * + * Input parameters: + * id - region id + * segment - pointer to segment address + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_region_return_segment( + rtems_id id, + void *segment +) +{ + Objects_Locations location; + rtems_status_code return_status; +#ifdef RTEMS_REGION_FREE_SHRED_PATTERN + uint32_t size; +#endif + int status; + register Region_Control *the_region; + + _RTEMS_Lock_allocator(); + + the_region = _Region_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + _Region_Debug_Walk( the_region, 3 ); + +#ifdef RTEMS_REGION_FREE_SHRED_PATTERN + if ( !_Heap_Size_of_alloc_area( &the_region->Memory, segment, &size ) ) + return_status = RTEMS_INVALID_ADDRESS; + else { + memset( segment, (RTEMS_REGION_FREE_SHRED_PATTERN & 0xFF), size ); +#endif + status = _Region_Free_segment( the_region, segment ); + + _Region_Debug_Walk( the_region, 4 ); + + if ( !status ) + return_status = RTEMS_INVALID_ADDRESS; + else { + the_region->number_of_used_blocks -= 1; + + _Region_Process_queue(the_region); /* unlocks allocator */ + + return RTEMS_SUCCESSFUL; + } +#ifdef RTEMS_REGION_FREE_SHRED_PATTERN + } +#endif + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* this error cannot be returned */ + break; +#endif + + case OBJECTS_ERROR: + default: + return_status = RTEMS_INVALID_ID; + break; + } + + _RTEMS_Unlock_allocator(); + return return_status; +} diff --git a/cpukit/rtems/src/rtclock.c b/cpukit/rtems/src/rtclock.c new file mode 100644 index 0000000000..652f443677 --- /dev/null +++ b/cpukit/rtems/src/rtclock.c @@ -0,0 +1,26 @@ +/* + * Clock Manager + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/* No initialization routine */ diff --git a/cpukit/rtems/src/rtemsbuildid.c b/cpukit/rtems/src/rtemsbuildid.c new file mode 100644 index 0000000000..916d1dfab5 --- /dev/null +++ b/cpukit/rtems/src/rtemsbuildid.c @@ -0,0 +1,31 @@ +/* + * RTEMS Object Helper -- Build an Object Id + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +#undef rtems_build_id +rtems_id rtems_build_id( + uint32_t api, + uint32_t class, + uint32_t node, + uint32_t index +) +{ + return _Objects_Build_id( api, class, node, index ); +} diff --git a/cpukit/rtems/src/rtemsbuildname.c b/cpukit/rtems/src/rtemsbuildname.c new file mode 100644 index 0000000000..1fbd727297 --- /dev/null +++ b/cpukit/rtems/src/rtemsbuildname.c @@ -0,0 +1,31 @@ +/* + * RTEMS Object Helper -- Build an Object Name + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +#undef rtems_build_name +rtems_name rtems_build_name( + char C1, + char C2, + char C3, + char C4 +) +{ + return _Objects_Build_name( C1, C2, C3, C4 ); +} diff --git a/cpukit/rtems/src/rtemsobjectapimaximumclass.c b/cpukit/rtems/src/rtemsobjectapimaximumclass.c new file mode 100644 index 0000000000..16133084d2 --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectapimaximumclass.c @@ -0,0 +1,27 @@ +/* + * RTEMS Object Helper -- Get Greatest Valid Class for an API + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +int rtems_object_api_maximum_class( + int api +) +{ + return _Objects_API_maximum_class(api); +} diff --git a/cpukit/rtems/src/rtemsobjectapiminimumclass.c b/cpukit/rtems/src/rtemsobjectapiminimumclass.c new file mode 100644 index 0000000000..a3995eb32a --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectapiminimumclass.c @@ -0,0 +1,29 @@ +/* + * RTEMS Object Helper -- Get Least Valid Class for an API + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +uint32_t rtems_object_api_minimum_class( + uint32_t api +) +{ + if ( _Objects_Is_api_valid( api ) ) + return 1; + return -1; +} diff --git a/cpukit/rtems/src/rtemsobjectgetapiclassname.c b/cpukit/rtems/src/rtemsobjectgetapiclassname.c new file mode 100644 index 0000000000..2ea697bc37 --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectgetapiclassname.c @@ -0,0 +1,81 @@ +/* + * RTEMS Object Helper -- Obtain Name of API + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/object.h> + +#include <rtems/assoc.h> + +rtems_assoc_t rtems_object_api_internal_assoc[] = { + { "Thread", OBJECTS_INTERNAL_THREADS, 0}, + { "Mutex", OBJECTS_INTERNAL_MUTEXES, 0}, +}; + +rtems_assoc_t rtems_object_api_classic_assoc[] = { + { "Task", OBJECTS_RTEMS_TASKS, 0}, + { "Timer", OBJECTS_RTEMS_TIMERS, 0}, + { "Semaphore", OBJECTS_RTEMS_SEMAPHORES, 0}, + { "Message Queue", OBJECTS_RTEMS_MESSAGE_QUEUES, 0}, + { "Partition", OBJECTS_RTEMS_PARTITIONS, 0}, + { "Region", OBJECTS_RTEMS_REGIONS, 0}, + { "Port", OBJECTS_RTEMS_PORTS, 0}, + { "Period", OBJECTS_RTEMS_PERIODS, 0}, + { "Extension", OBJECTS_RTEMS_EXTENSIONS, 0}, + { "Barrier", OBJECTS_RTEMS_BARRIERS, 0}, +}; + +#ifdef RTEMS_POSIX_API +rtems_assoc_t rtems_object_api_posix_assoc[] = { + { "Thread", OBJECTS_POSIX_THREADS, 0}, + { "Key", OBJECTS_POSIX_KEYS, 0}, + { "Interrupt", OBJECTS_POSIX_INTERRUPTS, 0}, + { "Queued fd", OBJECTS_POSIX_MESSAGE_QUEUE_FDS, 0}, + { "Message Queue", OBJECTS_POSIX_MESSAGE_QUEUES, 0}, + { "Mutex", OBJECTS_POSIX_MUTEXES, 0}, + { "Semaphore", OBJECTS_POSIX_SEMAPHORES, 0}, + { "Condition Variable", OBJECTS_POSIX_CONDITION_VARIABLES, 0}, + { "Timer", OBJECTS_POSIX_TIMERS, 0}, + { "Barrier", OBJECTS_POSIX_BARRIERS, 0}, + { "Spinlock", OBJECTS_POSIX_SPINLOCKS, 0}, + { "RWLock", OBJECTS_POSIX_RWLOCKS, 0}, +}; +#endif + +const char *rtems_object_get_api_class_name( + int the_api, + int the_class +) +{ + const rtems_assoc_t *api_assoc; + const rtems_assoc_t *class_assoc; + + if ( the_api == OBJECTS_INTERNAL_API ) + api_assoc = rtems_object_api_internal_assoc; + else if ( the_api == OBJECTS_CLASSIC_API ) + api_assoc = rtems_object_api_classic_assoc; +#ifdef RTEMS_POSIX_API + else if ( the_api == OBJECTS_POSIX_API ) + api_assoc = rtems_object_api_posix_assoc; +#endif + else + return "BAD API"; + class_assoc = rtems_assoc_ptr_by_local( api_assoc, the_class ); + if ( class_assoc ) + return class_assoc->name; + return "BAD CLASS"; +} diff --git a/cpukit/rtems/src/rtemsobjectgetapiname.c b/cpukit/rtems/src/rtemsobjectgetapiname.c new file mode 100644 index 0000000000..90a6afa198 --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectgetapiname.c @@ -0,0 +1,42 @@ +/* + * RTEMS Object Helper -- Obtain Name of API + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/object.h> + +#include <rtems/assoc.h> + +rtems_assoc_t rtems_objects_api_assoc[] = { + { "Internal", OBJECTS_INTERNAL_API, 0}, + { "Classic", OBJECTS_CLASSIC_API, 0}, + { "POSIX", OBJECTS_POSIX_API, 0}, + { 0, 0, 0 } +}; + +const char *rtems_object_get_api_name( + int api +) +{ + const rtems_assoc_t *api_assoc; + + api_assoc = rtems_assoc_ptr_by_local( rtems_objects_api_assoc, api ); + if ( api_assoc ) + return api_assoc->name; + return "BAD CLASS"; +} + diff --git a/cpukit/rtems/src/rtemsobjectgetclassicname.c b/cpukit/rtems/src/rtemsobjectgetclassicname.c new file mode 100644 index 0000000000..7a78d59e7e --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectgetclassicname.c @@ -0,0 +1,55 @@ +/* + * RTEMS ID To Name Lookup + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/types.h> + +/*PAGE + * + * rtems_object_get_classic_name + * + * This directive returns the name associated with the specified + * object ID. + * + * Input parameters: + * id - message queue id + * + * Output parameters: + * *name - user defined object name + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_object_get_classic_name( + rtems_id id, + rtems_name *name +) +{ + Objects_Name_or_id_lookup_errors status; + Objects_Name name_u; + + if ( !name ) + return RTEMS_INVALID_ADDRESS; + + status = _Objects_Id_to_name( id, &name_u ); + + *name = name_u.name_u32; + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/rtemsobjectgetclassinfo.c b/cpukit/rtems/src/rtemsobjectgetclassinfo.c new file mode 100644 index 0000000000..4f20a6f61f --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectgetclassinfo.c @@ -0,0 +1,59 @@ +/* + * RTEMS Object Helper -- Get Information on Class + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/score/object.h> +#include <rtems/rtems/object.h> + +rtems_status_code rtems_object_get_class_information( + int the_api, + int the_class, + rtems_object_api_class_information *info +) +{ + Objects_Information *obj_info; + int unallocated; + int i; + + /* + * Validate parameters and look up information structure. + */ + if ( !info ) + return RTEMS_INVALID_ADDRESS; + + obj_info = _Objects_Get_information( the_api, the_class ); + if ( !obj_info ) + return RTEMS_INVALID_NUMBER; + + /* + * Return information about this object class to the user. + */ + info->minimum_id = obj_info->minimum_id; + info->maximum_id = obj_info->maximum_id; + info->auto_extend = obj_info->auto_extend; + info->maximum = obj_info->maximum; + + for ( unallocated=0, i=1 ; i <= info->maximum ; i++ ) + if ( !obj_info->local_table[i] ) + unallocated++; + + info->unallocated = unallocated; + + return RTEMS_SUCCESSFUL; +} + diff --git a/cpukit/rtems/src/rtemsobjectgetname.c b/cpukit/rtems/src/rtemsobjectgetname.c new file mode 100644 index 0000000000..c414d2e478 --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectgetname.c @@ -0,0 +1,33 @@ +/* + * RTEMS Object Helper -- Obtain Name of Object as String + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> + +/* + * This method obtain the name of an object and returns its name + * in the form of a C string. It attempts to be careful about + * overflowing the user's string and about returning unprintable characters. + */ +char *rtems_object_get_name( + Objects_Id id, + size_t length, + char *name +) +{ + return _Objects_Get_name_as_string( id, length, name ); +} diff --git a/cpukit/rtems/src/rtemsobjectidapimaximum.c b/cpukit/rtems/src/rtemsobjectidapimaximum.c new file mode 100644 index 0000000000..fbf6c19d02 --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectidapimaximum.c @@ -0,0 +1,26 @@ +/* + * RTEMS Object Helper -- Get Greatest Valid API Number + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +#undef rtems_object_id_api_maximum +int rtems_object_id_api_maximum(void) +{ + return OBJECTS_APIS_LAST; +} diff --git a/cpukit/rtems/src/rtemsobjectidapiminimum.c b/cpukit/rtems/src/rtemsobjectidapiminimum.c new file mode 100644 index 0000000000..057fa09d70 --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectidapiminimum.c @@ -0,0 +1,26 @@ +/* + * RTEMS Object Helper -- Get Least Valid API Number + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +#undef rtems_object_id_api_minimum +int rtems_object_id_api_minimum(void) +{ + return OBJECTS_INTERNAL_API; +} diff --git a/cpukit/rtems/src/rtemsobjectidgetapi.c b/cpukit/rtems/src/rtemsobjectidgetapi.c new file mode 100644 index 0000000000..859e4b5bc6 --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectidgetapi.c @@ -0,0 +1,28 @@ +/* + * RTEMS Object Helper -- Extract API From Id + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +#undef rtems_object_id_get_api +int rtems_object_id_get_api( + rtems_id id +) +{ + return _Objects_Get_API( id ); +} diff --git a/cpukit/rtems/src/rtemsobjectidgetclass.c b/cpukit/rtems/src/rtemsobjectidgetclass.c new file mode 100644 index 0000000000..fe85050c4a --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectidgetclass.c @@ -0,0 +1,28 @@ +/* + * RTEMS Object Helper -- Extract Class From Id + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +#undef rtems_object_id_get_class +int rtems_object_id_get_class( + rtems_id id +) +{ + return _Objects_Get_class( id ); +} diff --git a/cpukit/rtems/src/rtemsobjectidgetindex.c b/cpukit/rtems/src/rtemsobjectidgetindex.c new file mode 100644 index 0000000000..67f795be8d --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectidgetindex.c @@ -0,0 +1,28 @@ +/* + * RTEMS Object Helper -- Extract Index From Id + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +#undef rtems_object_id_get_index +int rtems_object_id_get_index( + rtems_id id +) +{ + return _Objects_Get_index( id ); +} diff --git a/cpukit/rtems/src/rtemsobjectidgetnode.c b/cpukit/rtems/src/rtemsobjectidgetnode.c new file mode 100644 index 0000000000..5dfae4b1f9 --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectidgetnode.c @@ -0,0 +1,28 @@ +/* + * RTEMS Object Helper -- Extract Node From Id + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/rtems/types.h> + +#undef rtems_object_id_get_node +int rtems_object_id_get_node( + rtems_id id +) +{ + return _Objects_Get_node( id ); +} diff --git a/cpukit/rtems/src/rtemsobjectsetname.c b/cpukit/rtems/src/rtemsobjectsetname.c new file mode 100644 index 0000000000..91fac13e7c --- /dev/null +++ b/cpukit/rtems/src/rtemsobjectsetname.c @@ -0,0 +1,64 @@ +/* + * RTEMS Object Helper -- Set Name of Object as String + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/types.h> + +/* + * This method will set the object name based upon the user string. + * If the object class uses 32-bit names, then only the first 4 bytes + * of the string will be used. + */ +rtems_status_code rtems_object_set_name( + rtems_id id, + const char *name +) +{ + Objects_Information *information; + Objects_Locations location; + Objects_Control *the_object; + Objects_Id tmpId; + + if ( !name ) + return RTEMS_INVALID_ADDRESS; + + tmpId = (id == OBJECTS_ID_OF_SELF) ? _Thread_Executing->Object.id : id; + + information = _Objects_Get_information_id( tmpId ); + if ( !information ) + return RTEMS_INVALID_ID; + + the_object = _Objects_Get( information, tmpId, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Objects_Set_name( information, the_object, name ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/rtemstimer.c b/cpukit/rtems/src/rtemstimer.c new file mode 100644 index 0000000000..3cff1f3bf7 --- /dev/null +++ b/cpukit/rtems/src/rtemstimer.c @@ -0,0 +1,64 @@ +/* + * Timer Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * _Timer_Manager_initialization + * + * This routine initializes all timer manager related data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _Timer_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_Timer_Information, /* object information table */ + OBJECTS_CLASSIC_API, /* object API */ + OBJECTS_RTEMS_TIMERS, /* object class */ + Configuration_RTEMS_API.maximum_timers , + /* maximum objects of this class */ + sizeof( Timer_Control ), /* size of this object's control block */ + false, /* true if the name is a string */ + RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); + + /* + * Initialize the pointer to the default timer server control block to NULL + * indicating that task-based timer support is not initialized. + */ + + _Timer_server = NULL; +} diff --git a/cpukit/rtems/src/rtemstimerdata.c b/cpukit/rtems/src/rtemstimerdata.c new file mode 100644 index 0000000000..b817c2f788 --- /dev/null +++ b/cpukit/rtems/src/rtemstimerdata.c @@ -0,0 +1,22 @@ +/* + * Timer Manager -- Instantiate Data + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate RTEMS timer data */ +#define RTEMS_TIMER_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/timer.h> diff --git a/cpukit/rtems/src/sem.c b/cpukit/rtems/src/sem.c new file mode 100644 index 0000000000..ecf070e44d --- /dev/null +++ b/cpukit/rtems/src/sem.c @@ -0,0 +1,93 @@ +/* + * Semaphore Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Semaphore Manager. + * This manager utilizes standard Dijkstra counting semaphores to provide + * synchronization and mutual exclusion capabilities. + * + * Directives provided are: + * + * + create a semaphore + * + get an ID of a semaphore + * + delete a semaphore + * + acquire a semaphore + * + release a semaphore + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/attr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/sem.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/coresem.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/score/sysstate.h> + +#include <rtems/score/interr.h> + +/*PAGE + * + * _Semaphore_Manager_initialization + * + * This routine initializes all semaphore manager related data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _Semaphore_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_Semaphore_Information, /* object information table */ + OBJECTS_CLASSIC_API, /* object API */ + OBJECTS_RTEMS_SEMAPHORES, /* object class */ + Configuration_RTEMS_API.maximum_semaphores, + /* maximum objects of this class */ + sizeof( Semaphore_Control ), /* size of this object's control block */ + false, /* true if the name is a string */ + RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */ +#if defined(RTEMS_MULTIPROCESSING) + , + true, /* true if this is a global object class */ + _Semaphore_MP_Send_extract_proxy /* Proxy extraction support callout */ +#endif + ); + + /* + * Register the MP Process Packet routine. + */ + +#if defined(RTEMS_MULTIPROCESSING) + _MPCI_Register_packet_processor( + MP_PACKET_SEMAPHORE, + _Semaphore_MP_Process_packet + ); +#endif + +} diff --git a/cpukit/rtems/src/semcreate.c b/cpukit/rtems/src/semcreate.c new file mode 100644 index 0000000000..49cffc8e10 --- /dev/null +++ b/cpukit/rtems/src/semcreate.c @@ -0,0 +1,231 @@ +/* + * Semaphore Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Semaphore Manager. + * This manager utilizes standard Dijkstra counting semaphores to provide + * synchronization and mutual exclusion capabilities. + * + * Directives provided are: + * + * + create a semaphore + * + get an ID of a semaphore + * + delete a semaphore + * + acquire a semaphore + * + release a semaphore + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/attr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/sem.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/coresem.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/score/sysstate.h> + +#include <rtems/score/interr.h> + +/*PAGE + * + * rtems_semaphore_create + * + * This directive creates a semaphore and sets the initial value based + * on the given count. A semaphore id is returned. + * + * Input parameters: + * name - user defined semaphore name + * count - initial count of semaphore + * attribute_set - semaphore attributes + * priority_ceiling - semaphore's ceiling priority + * id - pointer to semaphore id + * + * Output parameters: + * id - semaphore id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_semaphore_create( + rtems_name name, + uint32_t count, + rtems_attribute attribute_set, + rtems_task_priority priority_ceiling, + rtems_id *id +) +{ + register Semaphore_Control *the_semaphore; + CORE_mutex_Attributes the_mutex_attr; + CORE_semaphore_Attributes the_semaphore_attr; + CORE_mutex_Status mutex_status; + + if ( !rtems_is_name_valid( name ) ) + return RTEMS_INVALID_NAME; + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( attribute_set ) ) { + + if ( !_System_state_Is_multiprocessing ) + return RTEMS_MP_NOT_CONFIGURED; + + if ( _Attributes_Is_inherit_priority( attribute_set ) || + _Attributes_Is_priority_ceiling( attribute_set ) ) + return RTEMS_NOT_DEFINED; + + } else +#endif + + if ( _Attributes_Is_inherit_priority( attribute_set ) || + _Attributes_Is_priority_ceiling( attribute_set ) ) { + + if ( ! (_Attributes_Is_binary_semaphore( attribute_set ) && + _Attributes_Is_priority( attribute_set ) ) ) + return RTEMS_NOT_DEFINED; + + } + + if ( _Attributes_Is_inherit_priority( attribute_set ) && + _Attributes_Is_priority_ceiling( attribute_set ) ) + return RTEMS_NOT_DEFINED; + + if ( !_Attributes_Is_counting_semaphore( attribute_set ) && ( count > 1 ) ) + return RTEMS_INVALID_NUMBER; + + _Thread_Disable_dispatch(); /* prevents deletion */ + + the_semaphore = _Semaphore_Allocate(); + + if ( !the_semaphore ) { + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } + +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( attribute_set ) && + ! ( _Objects_MP_Allocate_and_open( &_Semaphore_Information, name, + the_semaphore->Object.id, false ) ) ) { + _Semaphore_Free( the_semaphore ); + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } +#endif + + the_semaphore->attribute_set = attribute_set; + + /* + * Initialize it as a counting semaphore. + */ + if ( _Attributes_Is_counting_semaphore( attribute_set ) ) { + /* + * This effectively disables limit checking. + */ + the_semaphore_attr.maximum_count = 0xFFFFFFFF; + + if ( _Attributes_Is_priority( attribute_set ) ) + the_semaphore_attr.discipline = CORE_SEMAPHORE_DISCIPLINES_PRIORITY; + else + the_semaphore_attr.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO; + + /* + * The following are just to make Purify happy. + */ + the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES; + the_mutex_attr.priority_ceiling = PRIORITY_MINIMUM; + + _CORE_semaphore_Initialize( + &the_semaphore->Core_control.semaphore, + &the_semaphore_attr, + count + ); + } else { + /* + * It is either simple binary semaphore or a more powerful mutex + * style binary semaphore. This is the mutex style. + */ + if ( _Attributes_Is_priority( attribute_set ) ) + the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY; + else + the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_FIFO; + + if ( _Attributes_Is_binary_semaphore( attribute_set ) ) { + the_mutex_attr.priority_ceiling = priority_ceiling; + the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES; + the_mutex_attr.only_owner_release = false; + + if ( the_mutex_attr.discipline == CORE_MUTEX_DISCIPLINES_PRIORITY ) { + if ( _Attributes_Is_inherit_priority( attribute_set ) ) { + the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT; + the_mutex_attr.only_owner_release = true; + } else if ( _Attributes_Is_priority_ceiling( attribute_set ) ) { + the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING; + the_mutex_attr.only_owner_release = true; + } + } + } else /* must be simple binary semaphore */ { + the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_BLOCKS; + the_mutex_attr.only_owner_release = false; + } + + mutex_status = _CORE_mutex_Initialize( + &the_semaphore->Core_control.mutex, + &the_mutex_attr, + (count == 1) ? CORE_MUTEX_UNLOCKED : CORE_MUTEX_LOCKED + ); + + if ( mutex_status == CORE_MUTEX_STATUS_CEILING_VIOLATED ) { + _Semaphore_Free( the_semaphore ); + _Thread_Enable_dispatch(); + return RTEMS_INVALID_PRIORITY; + } + } + + /* + * Whether we initialized it as a mutex or counting semaphore, it is + * now ready to be "offered" for use as a Classic API Semaphore. + */ + _Objects_Open( + &_Semaphore_Information, + &the_semaphore->Object, + (Objects_Name) name + ); + + *id = the_semaphore->Object.id; + +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( attribute_set ) ) + _Semaphore_MP_Send_process_packet( + SEMAPHORE_MP_ANNOUNCE_CREATE, + the_semaphore->Object.id, + name, + 0 /* Not used */ + ); +#endif + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/semdata.c b/cpukit/rtems/src/semdata.c new file mode 100644 index 0000000000..cc4126db15 --- /dev/null +++ b/cpukit/rtems/src/semdata.c @@ -0,0 +1,22 @@ +/* + * Semaphore Manager -- Data Instantiation + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate semaphore data */ +#define RTEMS_SEM_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/sem.h> diff --git a/cpukit/rtems/src/semdelete.c b/cpukit/rtems/src/semdelete.c new file mode 100644 index 0000000000..d9c81fc56b --- /dev/null +++ b/cpukit/rtems/src/semdelete.c @@ -0,0 +1,136 @@ +/* + * Semaphore Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Semaphore Manager. + * This manager utilizes standard Dijkstra counting semaphores to provide + * synchronization and mutual exclusion capabilities. + * + * Directives provided are: + * + * + create a semaphore + * + get an ID of a semaphore + * + delete a semaphore + * + acquire a semaphore + * + release a semaphore + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/attr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/sem.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/coresem.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/score/sysstate.h> + +#include <rtems/score/interr.h> + +/*PAGE + * + * rtems_semaphore_delete + * + * This directive allows a thread to delete a semaphore specified by + * the semaphore id. The semaphore is freed back to the inactive + * semaphore chain. + * + * Input parameters: + * id - semaphore id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +#if defined(RTEMS_MULTIPROCESSING) +#define SEMAPHORE_MP_OBJECT_WAS_DELETED _Semaphore_MP_Send_object_was_deleted +#else +#define SEMAPHORE_MP_OBJECT_WAS_DELETED NULL +#endif + +rtems_status_code rtems_semaphore_delete( + rtems_id id +) +{ + register Semaphore_Control *the_semaphore; + Objects_Locations location; + + the_semaphore = _Semaphore_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { + if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) && + !_Attributes_Is_simple_binary_semaphore( + the_semaphore->attribute_set ) ) { + _Thread_Enable_dispatch(); + return RTEMS_RESOURCE_IN_USE; + } + _CORE_mutex_Flush( + &the_semaphore->Core_control.mutex, + SEMAPHORE_MP_OBJECT_WAS_DELETED, + CORE_MUTEX_WAS_DELETED + ); + } else { + _CORE_semaphore_Flush( + &the_semaphore->Core_control.semaphore, + SEMAPHORE_MP_OBJECT_WAS_DELETED, + CORE_SEMAPHORE_WAS_DELETED + ); + } + + _Objects_Close( &_Semaphore_Information, &the_semaphore->Object ); + + _Semaphore_Free( the_semaphore ); + +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( the_semaphore->attribute_set ) ) { + + _Objects_MP_Close( &_Semaphore_Information, the_semaphore->Object.id ); + + _Semaphore_MP_Send_process_packet( + SEMAPHORE_MP_ANNOUNCE_DELETE, + the_semaphore->Object.id, + 0, /* Not used */ + 0 /* Not used */ + ); + } +#endif + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/semflush.c b/cpukit/rtems/src/semflush.c new file mode 100644 index 0000000000..120b83e0fe --- /dev/null +++ b/cpukit/rtems/src/semflush.c @@ -0,0 +1,102 @@ +/* + * rtems_semaphore_flush + * + * DESCRIPTION: + * + * This package is the implementation of the flush directive + * of the Semaphore Manager. + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/attr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/sem.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/coresem.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/score/sysstate.h> + +#include <rtems/score/interr.h> + +/*PAGE + * + * rtems_semaphore_flush + * + * This directive allows a thread to flush the threads + * pending on the semaphore. + * + * Input parameters: + * id - semaphore id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +#if defined(RTEMS_MULTIPROCESSING) +#define SEND_OBJECT_WAS_DELETED _Semaphore_MP_Send_object_was_deleted +#else +#define SEND_OBJECT_WAS_DELETED NULL +#endif + +rtems_status_code rtems_semaphore_flush( + rtems_id id +) +{ + register Semaphore_Control *the_semaphore; + Objects_Locations location; + + the_semaphore = _Semaphore_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { + _CORE_mutex_Flush( + &the_semaphore->Core_control.mutex, + SEND_OBJECT_WAS_DELETED, + CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT + ); + } else { + _CORE_semaphore_Flush( + &the_semaphore->Core_control.semaphore, + SEND_OBJECT_WAS_DELETED, + CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT + ); + } + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/semident.c b/cpukit/rtems/src/semident.c new file mode 100644 index 0000000000..56f8856da7 --- /dev/null +++ b/cpukit/rtems/src/semident.c @@ -0,0 +1,81 @@ +/* + * Semaphore Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Semaphore Manager. + * This manager utilizes standard Dijkstra counting semaphores to provide + * synchronization and mutual exclusion capabilities. + * + * Directives provided are: + * + * + create a semaphore + * + get an ID of a semaphore + * + delete a semaphore + * + acquire a semaphore + * + release a semaphore + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/attr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/sem.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/coresem.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/score/sysstate.h> + +#include <rtems/score/interr.h> + +/*PAGE + * + * rtems_semaphore_ident + * + * This directive returns the system ID associated with + * the semaphore name. + * + * Input parameters: + * name - user defined semaphore name + * node - node(s) to be searched + * id - pointer to semaphore id + * + * Output parameters: + * *id - semaphore id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_semaphore_ident( + rtems_name name, + uint32_t node, + rtems_id *id +) +{ + Objects_Name_or_id_lookup_errors status; + + status = _Objects_Name_to_id_u32( &_Semaphore_Information, name, node, id ); + + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/semmp.c b/cpukit/rtems/src/semmp.c new file mode 100644 index 0000000000..06bed8a52c --- /dev/null +++ b/cpukit/rtems/src/semmp.c @@ -0,0 +1,367 @@ +/* + * Multiprocessing Support for the Semaphore Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/score/mpci.h> +#include <rtems/score/mppkt.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/sem.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _Semaphore_MP_Send_process_packet + * + */ + +void _Semaphore_MP_Send_process_packet ( + Semaphore_MP_Remote_operations operation, + Objects_Id semaphore_id, + rtems_name name, + Objects_Id proxy_id +) +{ + Semaphore_MP_Packet *the_packet; + uint32_t node; + + switch ( operation ) { + + case SEMAPHORE_MP_ANNOUNCE_CREATE: + case SEMAPHORE_MP_ANNOUNCE_DELETE: + case SEMAPHORE_MP_EXTRACT_PROXY: + + the_packet = _Semaphore_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_SEMAPHORE; + the_packet->Prefix.length = sizeof ( Semaphore_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( Semaphore_MP_Packet ); + the_packet->operation = operation; + the_packet->Prefix.id = semaphore_id; + the_packet->name = name; + the_packet->proxy_id = proxy_id; + + if ( operation == SEMAPHORE_MP_EXTRACT_PROXY ) + node = _Objects_Get_node( semaphore_id ); + else + node = MPCI_ALL_NODES; + + _MPCI_Send_process_packet( node, &the_packet->Prefix ); + break; + + case SEMAPHORE_MP_OBTAIN_REQUEST: + case SEMAPHORE_MP_OBTAIN_RESPONSE: + case SEMAPHORE_MP_RELEASE_REQUEST: + case SEMAPHORE_MP_RELEASE_RESPONSE: + break; + } +} + +/*PAGE + * + * _Semaphore_MP_Send_request_packet + * + */ + +rtems_status_code _Semaphore_MP_Send_request_packet ( + Semaphore_MP_Remote_operations operation, + Objects_Id semaphore_id, + rtems_option option_set, + rtems_interval timeout +) +{ + Semaphore_MP_Packet *the_packet; + + switch ( operation ) { + + case SEMAPHORE_MP_OBTAIN_REQUEST: + case SEMAPHORE_MP_RELEASE_REQUEST: + + the_packet = _Semaphore_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_SEMAPHORE; + the_packet->Prefix.length = sizeof ( Semaphore_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( Semaphore_MP_Packet ); + if ( ! _Options_Is_no_wait(option_set)) + the_packet->Prefix.timeout = timeout; + + the_packet->operation = operation; + the_packet->Prefix.id = semaphore_id; + the_packet->option_set = option_set; + + return _MPCI_Send_request_packet( + _Objects_Get_node( semaphore_id ), + &the_packet->Prefix, + STATES_WAITING_FOR_SEMAPHORE + ); + break; + + case SEMAPHORE_MP_ANNOUNCE_CREATE: + case SEMAPHORE_MP_ANNOUNCE_DELETE: + case SEMAPHORE_MP_EXTRACT_PROXY: + case SEMAPHORE_MP_OBTAIN_RESPONSE: + case SEMAPHORE_MP_RELEASE_RESPONSE: + break; + + } + /* + * The following line is included to satisfy compilers which + * produce warnings when a function does not end with a return. + */ + return RTEMS_SUCCESSFUL; +} + +/*PAGE + * + * _Semaphore_MP_Send_response_packet + * + */ + +void _Semaphore_MP_Send_response_packet ( + Semaphore_MP_Remote_operations operation, + Objects_Id semaphore_id, + Thread_Control *the_thread +) +{ + Semaphore_MP_Packet *the_packet; + + switch ( operation ) { + + case SEMAPHORE_MP_OBTAIN_RESPONSE: + case SEMAPHORE_MP_RELEASE_RESPONSE: + + the_packet = ( Semaphore_MP_Packet *) the_thread->receive_packet; + +/* + * The packet being returned already contains the class, length, and + * to_convert fields, therefore they are not set in this routine. + */ + the_packet->operation = operation; + the_packet->Prefix.id = the_packet->Prefix.source_tid; + + _MPCI_Send_response_packet( + _Objects_Get_node( the_packet->Prefix.source_tid ), + &the_packet->Prefix + ); + break; + + case SEMAPHORE_MP_ANNOUNCE_CREATE: + case SEMAPHORE_MP_ANNOUNCE_DELETE: + case SEMAPHORE_MP_EXTRACT_PROXY: + case SEMAPHORE_MP_OBTAIN_REQUEST: + case SEMAPHORE_MP_RELEASE_REQUEST: + break; + + } +} + +/*PAGE + * + * + * _Semaphore_MP_Process_packet + * + */ + +void _Semaphore_MP_Process_packet ( + rtems_packet_prefix *the_packet_prefix +) +{ + Semaphore_MP_Packet *the_packet; + Thread_Control *the_thread; + bool ignored; + + the_packet = (Semaphore_MP_Packet *) the_packet_prefix; + + switch ( the_packet->operation ) { + + case SEMAPHORE_MP_ANNOUNCE_CREATE: + + ignored = _Objects_MP_Allocate_and_open( + &_Semaphore_Information, + the_packet->name, + the_packet->Prefix.id, + true + ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case SEMAPHORE_MP_ANNOUNCE_DELETE: + + _Objects_MP_Close( &_Semaphore_Information, the_packet->Prefix.id ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case SEMAPHORE_MP_EXTRACT_PROXY: + + the_thread = _Thread_MP_Find_proxy( the_packet->proxy_id ); + + if ( ! _Thread_Is_null( the_thread ) ) + _Thread_queue_Extract( the_thread->Wait.queue, the_thread ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case SEMAPHORE_MP_OBTAIN_REQUEST: + + the_packet->Prefix.return_code = rtems_semaphore_obtain( + the_packet->Prefix.id, + the_packet->option_set, + the_packet->Prefix.timeout + ); + + if ( the_packet->Prefix.return_code != RTEMS_PROXY_BLOCKING ) + _Semaphore_MP_Send_response_packet( + SEMAPHORE_MP_OBTAIN_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + + case SEMAPHORE_MP_OBTAIN_RESPONSE: + case SEMAPHORE_MP_RELEASE_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case SEMAPHORE_MP_RELEASE_REQUEST: + + the_packet->Prefix.return_code = rtems_semaphore_release( + the_packet->Prefix.id + ); + + _Semaphore_MP_Send_response_packet( + SEMAPHORE_MP_RELEASE_RESPONSE, + the_packet->Prefix.id, + _Thread_Executing + ); + break; + } +} + +/*PAGE + * + * _Semaphore_MP_Send_object_was_deleted + * + */ + +void _Semaphore_MP_Send_object_was_deleted ( + Thread_Control *the_proxy +) +{ + the_proxy->receive_packet->return_code = RTEMS_OBJECT_WAS_DELETED; + + _Semaphore_MP_Send_response_packet( + SEMAPHORE_MP_OBTAIN_RESPONSE, + the_proxy->Wait.id, + the_proxy + ); + +} + +/*PAGE + * + * _Semaphore_MP_Send_extract_proxy + * + */ + +void _Semaphore_MP_Send_extract_proxy ( + void *argument +) +{ + Thread_Control *the_thread = (Thread_Control *)argument; + + _Semaphore_MP_Send_process_packet( + SEMAPHORE_MP_EXTRACT_PROXY, + the_thread->Wait.id, + (rtems_name) 0, + the_thread->Object.id + ); + +} + +/*PAGE + * + * _Semaphore_MP_Get_packet + * + */ + +Semaphore_MP_Packet *_Semaphore_MP_Get_packet ( void ) +{ + return ( (Semaphore_MP_Packet *) _MPCI_Get_packet() ); +} + +/*PAGE + * + * _Semaphore_Core_mutex_mp_support + * + * Input parameters: + * the_thread - the remote thread the semaphore was surrendered to + * id - id of the surrendered semaphore + * + * Output parameters: NONE + */ + +#if defined(RTEMS_MULTIPROCESSING) +void _Semaphore_Core_mutex_mp_support ( + Thread_Control *the_thread, + Objects_Id id +) +{ + the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL; + + _Semaphore_MP_Send_response_packet( + SEMAPHORE_MP_OBTAIN_RESPONSE, + id, + the_thread + ); +} +#endif + + +/*PAGE + * + * _Semaphore_Core_semaphore_mp_support + * + * Input parameters: + * the_thread - the remote thread the semaphore was surrendered to + * id - id of the surrendered semaphore + * + * Output parameters: NONE + */ + +#if defined(RTEMS_MULTIPROCESSING) +void _Semaphore_Core_semaphore_mp_support ( + Thread_Control *the_thread, + Objects_Id id +) +{ + the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL; + + _Semaphore_MP_Send_response_packet( + SEMAPHORE_MP_OBTAIN_RESPONSE, + id, + the_thread + ); +} +#endif +/* end of file */ diff --git a/cpukit/rtems/src/semobtain.c b/cpukit/rtems/src/semobtain.c new file mode 100644 index 0000000000..e3f3af1b10 --- /dev/null +++ b/cpukit/rtems/src/semobtain.c @@ -0,0 +1,121 @@ +/* + * Semaphore Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Semaphore Manager. + * This manager utilizes standard Dijkstra counting semaphores to provide + * synchronization and mutual exclusion capabilities. + * + * Directives provided are: + * + * + create a semaphore + * + get an ID of a semaphore + * + delete a semaphore + * + acquire a semaphore + * + release a semaphore + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/attr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/sem.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/coresem.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/score/sysstate.h> + +#include <rtems/score/interr.h> + +/*PAGE + * + * rtems_semaphore_obtain + * + * This directive allows a thread to acquire a semaphore. + * + * Input parameters: + * id - semaphore id + * option_set - wait option + * timeout - number of ticks to wait (0 means wait forever) + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_semaphore_obtain( + rtems_id id, + rtems_option option_set, + rtems_interval timeout +) +{ + register Semaphore_Control *the_semaphore; + Objects_Locations location; + ISR_Level level; + + the_semaphore = _Semaphore_Get_interrupt_disable( id, &location, &level ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { + _CORE_mutex_Seize( + &the_semaphore->Core_control.mutex, + id, + ((_Options_Is_no_wait( option_set )) ? false : true), + timeout, + level + ); + return _Semaphore_Translate_core_mutex_return_code( + _Thread_Executing->Wait.return_code ); + } + + /* must be a counting semaphore */ + _CORE_semaphore_Seize_isr_disable( + &the_semaphore->Core_control.semaphore, + id, + ((_Options_Is_no_wait( option_set )) ? false : true), + timeout, + &level + ); + return _Semaphore_Translate_core_semaphore_return_code( + _Thread_Executing->Wait.return_code ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _Semaphore_MP_Send_request_packet( + SEMAPHORE_MP_OBTAIN_REQUEST, + id, + option_set, + timeout + ); +#endif + + case OBJECTS_ERROR: + break; + + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/semrelease.c b/cpukit/rtems/src/semrelease.c new file mode 100644 index 0000000000..6ccf0cfbbe --- /dev/null +++ b/cpukit/rtems/src/semrelease.c @@ -0,0 +1,119 @@ +/* + * Semaphore Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Semaphore Manager. + * This manager utilizes standard Dijkstra counting semaphores to provide + * synchronization and mutual exclusion capabilities. + * + * Directives provided are: + * + * + create a semaphore + * + get an ID of a semaphore + * + delete a semaphore + * + acquire a semaphore + * + release a semaphore + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/attr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/sem.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/coresem.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/score/sysstate.h> + +#include <rtems/score/interr.h> + +/*PAGE + * + * rtems_semaphore_release + * + * This directive allows a thread to release a semaphore. + * + * Input parameters: + * id - semaphore id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +#if defined(RTEMS_MULTIPROCESSING) +#define MUTEX_MP_SUPPORT _Semaphore_Core_mutex_mp_support +#else +#define MUTEX_MP_SUPPORT NULL +#endif + +rtems_status_code rtems_semaphore_release( + rtems_id id +) +{ + register Semaphore_Control *the_semaphore; + Objects_Locations location; + CORE_mutex_Status mutex_status; + CORE_semaphore_Status semaphore_status; + + the_semaphore = _Semaphore_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { + mutex_status = _CORE_mutex_Surrender( + &the_semaphore->Core_control.mutex, + id, + MUTEX_MP_SUPPORT + ); + _Thread_Enable_dispatch(); + return _Semaphore_Translate_core_mutex_return_code( mutex_status ); + } else { + semaphore_status = _CORE_semaphore_Surrender( + &the_semaphore->Core_control.semaphore, + id, + MUTEX_MP_SUPPORT + ); + _Thread_Enable_dispatch(); + return + _Semaphore_Translate_core_semaphore_return_code( semaphore_status ); + } + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _Semaphore_MP_Send_request_packet( + SEMAPHORE_MP_RELEASE_REQUEST, + id, + 0, /* Not used */ + MPCI_DEFAULT_TIMEOUT + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/semtranslatereturncode.c b/cpukit/rtems/src/semtranslatereturncode.c new file mode 100644 index 0000000000..02b665e5f6 --- /dev/null +++ b/cpukit/rtems/src/semtranslatereturncode.c @@ -0,0 +1,137 @@ +/* + * Semaphore Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Semaphore Manager. + * This manager utilizes standard Dijkstra counting semaphores to provide + * synchronization and mutual exclusion capabilities. + * + * Directives provided are: + * + * + create a semaphore + * + get an ID of a semaphore + * + delete a semaphore + * + acquire a semaphore + * + release a semaphore + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/attr.h> +#include <rtems/score/isr.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/sem.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/coresem.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/score/sysstate.h> + +#include <rtems/score/interr.h> + +/*PAGE + * + * _Semaphore_Translate_core_mutex_return_code + * + * Input parameters: + * status - mutex status code to translate + * + * Output parameters: + * rtems status code - translated RTEMS status code + * + */ + +const rtems_status_code _Semaphore_Translate_core_mutex_return_code_[] = { + RTEMS_SUCCESSFUL, /* CORE_MUTEX_STATUS_SUCCESSFUL */ + RTEMS_UNSATISFIED, /* CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT */ +#if defined(RTEMS_POSIX_API) + RTEMS_UNSATISFIED, /* CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED */ +#endif + RTEMS_NOT_OWNER_OF_RESOURCE, /* CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE */ + RTEMS_OBJECT_WAS_DELETED, /* CORE_MUTEX_WAS_DELETED */ + RTEMS_TIMEOUT, /* CORE_MUTEX_TIMEOUT */ +#if defined(__RTEMS_STRICT_ORDER_MUTEX__) + CORE_MUTEX_RELEASE_NOT_ORDER, +#endif + RTEMS_INVALID_PRIORITY /* CORE_MUTEX_STATUS_CEILING_VIOLATED */ +}; + +rtems_status_code _Semaphore_Translate_core_mutex_return_code ( + uint32_t status +) +{ + /* + * If this thread is blocking waiting for a result on a remote operation. + */ + #if defined(RTEMS_MULTIPROCESSING) + if ( _Thread_Is_proxy_blocking(status) ) + return RTEMS_PROXY_BLOCKING; + #endif + + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( status > CORE_MUTEX_STATUS_LAST ) + return RTEMS_INTERNAL_ERROR; + #endif + return _Semaphore_Translate_core_mutex_return_code_[status]; +} + +/*PAGE + * + * _Semaphore_Translate_core_semaphore_return_code + * + * Input parameters: + * status - semaphore status code to translate + * + * Output parameters: + * rtems status code - translated RTEMS status code + * + */ + +const rtems_status_code _Semaphore_Translate_core_semaphore_return_code_[] = { + RTEMS_SUCCESSFUL, /* CORE_SEMAPHORE_STATUS_SUCCESSFUL */ + RTEMS_UNSATISFIED, /* CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT */ + RTEMS_OBJECT_WAS_DELETED, /* CORE_SEMAPHORE_WAS_DELETED */ + RTEMS_TIMEOUT, /* CORE_SEMAPHORE_TIMEOUT */ + RTEMS_INTERNAL_ERROR, /* CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED */ +}; + +rtems_status_code _Semaphore_Translate_core_semaphore_return_code ( + uint32_t status +) +{ + #if defined(RTEMS_MULTIPROCESSING) + if ( _Thread_Is_proxy_blocking(status) ) + return RTEMS_PROXY_BLOCKING; + #endif + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( status > CORE_SEMAPHORE_STATUS_LAST ) + return RTEMS_INTERNAL_ERROR; + #endif + return _Semaphore_Translate_core_semaphore_return_code_[status]; +} diff --git a/cpukit/rtems/src/signal.c b/cpukit/rtems/src/signal.c new file mode 100644 index 0000000000..d54d1e2491 --- /dev/null +++ b/cpukit/rtems/src/signal.c @@ -0,0 +1,51 @@ +/* + * Signal Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/asr.h> +#include <rtems/score/isr.h> +#include <rtems/rtems/modes.h> +#include <rtems/rtems/signal.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/tasks.h> + +/*PAGE + * + * _Signal_Manager_initialization + * + * This routine initializes all signal manager related data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _Signal_Manager_initialization( void ) +{ + /* + * Register the MP Process Packet routine. + */ + +#if defined(RTEMS_MULTIPROCESSING) + _MPCI_Register_packet_processor( + MP_PACKET_SIGNAL, + _Signal_MP_Process_packet + ); +#endif +} diff --git a/cpukit/rtems/src/signalcatch.c b/cpukit/rtems/src/signalcatch.c new file mode 100644 index 0000000000..fd38e06e2f --- /dev/null +++ b/cpukit/rtems/src/signalcatch.c @@ -0,0 +1,69 @@ +/* + * Signal Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/asr.h> +#include <rtems/score/isr.h> +#include <rtems/rtems/modes.h> +#include <rtems/rtems/signal.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/tasks.h> + +/*PAGE + * + * rtems_signal_catch + * + * This directive allows a thread to specify what action to take when + * catching signals. + * + * Input parameters: + * handler - address of asynchronous signal routine (asr) + * ( NULL indicates asr is invalid ) + * mode_set - mode value for asr + * + * Output parameters: + * RTEMS_SUCCESSFUL - always succeeds + */ + +rtems_status_code rtems_signal_catch( + rtems_asr_entry asr_handler, + rtems_mode mode_set +) +{ + Thread_Control *executing; + RTEMS_API_Control *api; + ASR_Information *asr; + +/* XXX normalize mode */ + executing = _Thread_Executing; + api = (RTEMS_API_Control*)executing->API_Extensions[ THREAD_API_RTEMS ]; + asr = &api->Signal; + + _Thread_Disable_dispatch(); /* cannot reschedule while */ + /* the thread is inconsistent */ + + if ( !_ASR_Is_null_handler( asr_handler ) ) { + asr->mode_set = mode_set; + asr->handler = asr_handler; + } + else + _ASR_Initialize( asr ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/signalmp.c b/cpukit/rtems/src/signalmp.c new file mode 100644 index 0000000000..2311e9e4a0 --- /dev/null +++ b/cpukit/rtems/src/signalmp.c @@ -0,0 +1,192 @@ +/* + * Multiprocessing Support for the Signal Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/score/mpci.h> +#include <rtems/score/mppkt.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/signal.h> +#include <rtems/score/states.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _Signal_MP_Send_process_packet + * + * This subprogram is not needed since there are no process + * packets to be sent by this manager. + * + */ + +/*PAGE + * + * _Signal_MP_Send_request_packet + * + */ + +rtems_status_code _Signal_MP_Send_request_packet ( + Signal_MP_Remote_operations operation, + Objects_Id task_id, + rtems_signal_set signal_in +) +{ + Signal_MP_Packet *the_packet; + + switch ( operation ) { + + case SIGNAL_MP_SEND_REQUEST: + + the_packet = _Signal_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_SIGNAL; + the_packet->Prefix.length = sizeof ( Signal_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( Signal_MP_Packet ); + the_packet->operation = operation; + the_packet->Prefix.id = task_id; + the_packet->signal_in = signal_in; + + return _MPCI_Send_request_packet( + _Objects_Get_node( task_id ), + &the_packet->Prefix, + STATES_READY /* Not used */ + ); + break; + + case SIGNAL_MP_SEND_RESPONSE: + break; + + } + /* + * The following line is included to satisfy compilers which + * produce warnings when a function does not end with a return. + */ + return RTEMS_INTERNAL_ERROR; +} + +/*PAGE + * + * _Signal_MP_Send_response_packet + * + */ + +void _Signal_MP_Send_response_packet ( + Signal_MP_Remote_operations operation, + Thread_Control *the_thread +) +{ + Signal_MP_Packet *the_packet; + + switch ( operation ) { + + case SIGNAL_MP_SEND_RESPONSE: + + the_packet = ( Signal_MP_Packet *) the_thread->receive_packet; + +/* + * The packet being returned already contains the class, length, and + * to_convert fields, therefore they are not set in this routine. + */ + the_packet->operation = operation; + the_packet->Prefix.id = the_packet->Prefix.source_tid; + + _MPCI_Send_response_packet( + _Objects_Get_node( the_packet->Prefix.source_tid ), + &the_packet->Prefix + ); + break; + + case SIGNAL_MP_SEND_REQUEST: + break; + + } +} + +/*PAGE + * + * + * _Signal_MP_Process_packet + * + */ + +void _Signal_MP_Process_packet ( + rtems_packet_prefix *the_packet_prefix +) +{ + Signal_MP_Packet *the_packet; + Thread_Control *the_thread; + + the_packet = (Signal_MP_Packet *) the_packet_prefix; + + switch ( the_packet->operation ) { + + case SIGNAL_MP_SEND_REQUEST: + + the_packet->Prefix.return_code = rtems_signal_send( + the_packet->Prefix.id, + the_packet->signal_in + ); + + _Signal_MP_Send_response_packet( + SIGNAL_MP_SEND_RESPONSE, + _Thread_Executing + ); + break; + + case SIGNAL_MP_SEND_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + } +} + +/*PAGE + * + * _Signal_MP_Send_object_was_deleted + * + * This subprogram is not needed since there are no objects + * deleted by this manager. + * + */ + +/*PAGE + * + * _Signal_MP_Send_extract_proxy + * + * This subprogram is not needed since there are no objects + * deleted by this manager. + * + */ + +/*PAGE + * + * _Signal_MP_Get_packet + * + */ + +Signal_MP_Packet *_Signal_MP_Get_packet ( void ) +{ + return ( (Signal_MP_Packet *) _MPCI_Get_packet() ); +} + +/* end of file */ diff --git a/cpukit/rtems/src/signalsend.c b/cpukit/rtems/src/signalsend.c new file mode 100644 index 0000000000..031a18979e --- /dev/null +++ b/cpukit/rtems/src/signalsend.c @@ -0,0 +1,92 @@ +/* + * Signal Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/asr.h> +#include <rtems/score/isr.h> +#include <rtems/rtems/modes.h> +#include <rtems/rtems/signal.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/tasks.h> + +/*PAGE + * + * rtems_signal_send + * + * This directive allows a thread to send signals to a thread. + * + * Input parameters: + * id - thread id + * signal_set - signal set + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_signal_send( + rtems_id id, + rtems_signal_set signal_set +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + RTEMS_API_Control *api; + ASR_Information *asr; + + if ( !signal_set ) + return RTEMS_INVALID_NUMBER; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + asr = &api->Signal; + + if ( ! _ASR_Is_null_handler( asr->handler ) ) { + if ( asr->is_enabled ) { + _ASR_Post_signals( signal_set, &asr->signals_posted ); + + if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) ) + _Thread_Dispatch_necessary = true; + } else { + _ASR_Post_signals( signal_set, &asr->signals_pending ); + } + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); + return RTEMS_NOT_DEFINED; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _Signal_MP_Send_request_packet( + SIGNAL_MP_SEND_REQUEST, + id, + signal_set + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskcreate.c b/cpukit/rtems/src/taskcreate.c new file mode 100644 index 0000000000..c173eced29 --- /dev/null +++ b/cpukit/rtems/src/taskcreate.c @@ -0,0 +1,229 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_task_create + * + * This directive creates a thread by allocating and initializing a + * thread control block and a stack. The newly created thread is + * placed in the dormant state. + * + * Input parameters: + * name - user defined thread name + * initial_priority - thread priority + * stack_size - stack size in bytes + * initial_modes - initial thread mode + * attribute_set - thread attributes + * id - pointer to thread id + * + * Output parameters: + * id - thread id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_create( + rtems_name name, + rtems_task_priority initial_priority, + size_t stack_size, + rtems_mode initial_modes, + rtems_attribute attribute_set, + rtems_id *id +) +{ + register Thread_Control *the_thread; + bool is_fp; +#if defined(RTEMS_MULTIPROCESSING) + Objects_MP_Control *the_global_object = NULL; + bool is_global; +#endif + bool status; + rtems_attribute the_attribute_set; + Priority_Control core_priority; + RTEMS_API_Control *api; + ASR_Information *asr; + + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + + if ( !rtems_is_name_valid( name ) ) + return RTEMS_INVALID_NAME; + + /* + * Core Thread Initialize insures we get the minimum amount of + * stack space. + */ + + /* + * Fix the attribute set to match the attributes which + * this processor (1) requires and (2) is able to support. + * First add in the required flags for attribute_set + * Typically this might include FP if the platform + * or application required all tasks to be fp aware. + * Then turn off the requested bits which are not supported. + */ + + the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED ); + the_attribute_set = + _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED ); + + if ( _Attributes_Is_floating_point( the_attribute_set ) ) + is_fp = true; + else + is_fp = false; + + /* + * Validate the RTEMS API priority and convert it to the core priority range. + */ + + if ( !_Attributes_Is_system_task( the_attribute_set ) ) { + if ( !_RTEMS_tasks_Priority_is_valid( initial_priority ) ) + return RTEMS_INVALID_PRIORITY; + } + + core_priority = _RTEMS_tasks_Priority_to_Core( initial_priority ); + +#if defined(RTEMS_MULTIPROCESSING) + if ( _Attributes_Is_global( the_attribute_set ) ) { + + is_global = true; + + if ( !_System_state_Is_multiprocessing ) + return RTEMS_MP_NOT_CONFIGURED; + + } else + is_global = false; +#endif + + /* + * Make sure system is MP if this task is global + */ + + /* + * Lock the allocator mutex for protection + */ + _RTEMS_Lock_allocator(); + + /* + * Allocate the thread control block and -- if the task is global -- + * allocate a global object control block. + * + * NOTE: This routine does not use the combined allocate and open + * global object routine because this results in a lack of + * control over when memory is allocated and can be freed in + * the event of an error. + */ + + the_thread = _RTEMS_tasks_Allocate(); + + if ( !the_thread ) { + _RTEMS_Unlock_allocator(); + return RTEMS_TOO_MANY; + } + +#if defined(RTEMS_MULTIPROCESSING) + if ( is_global ) { + the_global_object = _Objects_MP_Allocate_global_object(); + + if ( _Objects_MP_Is_null_global_object( the_global_object ) ) { + _RTEMS_tasks_Free( the_thread ); + _RTEMS_Unlock_allocator(); + return RTEMS_TOO_MANY; + } + } +#endif + + /* + * Initialize the core thread for this task. + */ + + status = _Thread_Initialize( + &_RTEMS_tasks_Information, + the_thread, + NULL, + stack_size, + is_fp, + core_priority, + _Modes_Is_preempt(initial_modes) ? true : false, + _Modes_Is_timeslice(initial_modes) ? + THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE : + THREAD_CPU_BUDGET_ALGORITHM_NONE, + NULL, /* no budget algorithm callout */ + _Modes_Get_interrupt_level(initial_modes), + (Objects_Name) name + ); + + if ( !status ) { +#if defined(RTEMS_MULTIPROCESSING) + if ( is_global ) + _Objects_MP_Free_global_object( the_global_object ); +#endif + _RTEMS_tasks_Free( the_thread ); + _RTEMS_Unlock_allocator(); + return RTEMS_UNSATISFIED; + } + + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + asr = &api->Signal; + + asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? false : true; + + *id = the_thread->Object.id; + +#if defined(RTEMS_MULTIPROCESSING) + the_thread->is_global = is_global; + if ( is_global ) { + + _Objects_MP_Open( + &_RTEMS_tasks_Information, + the_global_object, + name, + the_thread->Object.id + ); + + _RTEMS_tasks_MP_Send_process_packet( + RTEMS_TASKS_MP_ANNOUNCE_CREATE, + the_thread->Object.id, + name + ); + + } +#endif + + _RTEMS_Unlock_allocator(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/taskdata.c b/cpukit/rtems/src/taskdata.c new file mode 100644 index 0000000000..13c0a1f6e1 --- /dev/null +++ b/cpukit/rtems/src/taskdata.c @@ -0,0 +1,22 @@ +/* + * RTEMS Task Manager -- Instantiate Data + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* instantiate RTEMS Classic API tasks data */ +#define RTEMS_TASKS_EXTERN + +#include <rtems/system.h> +#include <rtems/rtems/tasks.h> diff --git a/cpukit/rtems/src/taskdelete.c b/cpukit/rtems/src/taskdelete.c new file mode 100644 index 0000000000..a29ea77ac4 --- /dev/null +++ b/cpukit/rtems/src/taskdelete.c @@ -0,0 +1,110 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/apimutex.h> + +/*PAGE + * + * rtems_task_delete + * + * This directive allows a thread to delete itself or the thread + * identified in the id field. The executive halts execution + * of the thread and frees the thread control block. + * + * Input parameters: + * id - thread id + * + * Output parameters: + * nothing - if id is the requesting thread (always succeeds) + * RTEMS_SUCCESSFUL - if successful and id is + * not the requesting thread + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_delete( + rtems_id id +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + Objects_Information *the_information; + + _RTEMS_Lock_allocator(); + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + the_information = _Objects_Get_information_id( the_thread->Object.id ); + + #if defined(RTEMS_DEBUG) + if ( !the_information ) { + _Thread_Enable_dispatch(); + return RTEMS_INVALID_ID; + /* This should never happen if _Thread_Get() works right */ + } + #endif + + #if defined(RTEMS_MULTIPROCESSING) + if ( the_thread->is_global ) { + _Objects_MP_Close( &_RTEMS_tasks_Information, the_thread->Object.id ); + _RTEMS_tasks_MP_Send_process_packet( + RTEMS_TASKS_MP_ANNOUNCE_DELETE, + the_thread->Object.id, + 0 /* Not used */ + ); + } + #endif + + _Thread_Close( the_information, the_thread ); + + _RTEMS_tasks_Free( the_thread ); + + _RTEMS_Unlock_allocator(); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _RTEMS_Unlock_allocator(); + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + + _RTEMS_Unlock_allocator(); + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskgetnote.c b/cpukit/rtems/src/taskgetnote.c new file mode 100644 index 0000000000..46c28460a5 --- /dev/null +++ b/cpukit/rtems/src/taskgetnote.c @@ -0,0 +1,116 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_get_note + * + * This directive obtains the note from the specified notepad + * of the specified thread. + * + * Input parameters: + * id - thread id + * notepad - notepad number + * note - pointer to note + * + * Output parameters: + * note - filled in if successful + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_get_note( + rtems_id id, + uint32_t notepad, + uint32_t *note +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + RTEMS_API_Control *api; + + if ( !rtems_configuration_get_notepads_enabled() ) + return RTEMS_NOT_CONFIGURED; + + if ( !note ) + return RTEMS_INVALID_ADDRESS; + + /* + * NOTE: There is no check for < RTEMS_NOTEPAD_FIRST because that would + * be checking an unsigned number for being negative. + */ + + if ( notepad > RTEMS_NOTEPAD_LAST ) + return RTEMS_INVALID_NUMBER; + + /* + * Optimize the most likely case to avoid the Thread_Dispatch. + */ + + if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) || + _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) { + api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ]; + *note = api->Notepads[ notepad ]; + return RTEMS_SUCCESSFUL; + } + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + *note = api->Notepads[ notepad ]; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Executing->Wait.return_argument = note; + + return _RTEMS_tasks_MP_Send_request_packet( + RTEMS_TASKS_MP_GET_NOTE_REQUEST, + id, + 0, /* Not used */ + notepad, + 0 /* Not used */ + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskident.c b/cpukit/rtems/src/taskident.c new file mode 100644 index 0000000000..8888c77ee2 --- /dev/null +++ b/cpukit/rtems/src/taskident.c @@ -0,0 +1,72 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_ident + * + * This directive returns the system ID associated with + * the thread name. + * + * Input parameters: + * name - user defined thread name + * node - node(s) to be searched + * id - pointer to thread id + * + * Output parameters: + * *id - thread id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_ident( + rtems_name name, + uint32_t node, + rtems_id *id +) +{ + Objects_Name_or_id_lookup_errors status; + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + + if ( name == OBJECTS_ID_OF_SELF ) { + *id = _Thread_Executing->Object.id; + return RTEMS_SUCCESSFUL; + } + + status = _Objects_Name_to_id_u32( &_RTEMS_tasks_Information, name, node, id ); + + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/taskinitusers.c b/cpukit/rtems/src/taskinitusers.c new file mode 100644 index 0000000000..b0c1198421 --- /dev/null +++ b/cpukit/rtems/src/taskinitusers.c @@ -0,0 +1,92 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/rtems/rtemsapi.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * _RTEMS_tasks_Initialize_user_tasks_body + * + * This routine creates and starts all configured user + * initialzation threads. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _RTEMS_tasks_Initialize_user_tasks_body( void ) +{ + uint32_t index; + uint32_t maximum; + rtems_id id; + rtems_status_code return_value; + rtems_initialization_tasks_table *user_tasks; + + /* + * Move information into local variables + */ + user_tasks = Configuration_RTEMS_API.User_initialization_tasks_table; + maximum = Configuration_RTEMS_API.number_of_initialization_tasks; + + /* + * Verify that we have a set of user tasks to iterate + */ + if ( !user_tasks ) + return; + + /* + * Now iterate over the initialization tasks and create/start them. + */ + for ( index=0 ; index < maximum ; index++ ) { + return_value = rtems_task_create( + user_tasks[ index ].name, + user_tasks[ index ].initial_priority, + user_tasks[ index ].stack_size, + user_tasks[ index ].mode_set, + user_tasks[ index ].attribute_set, + &id + ); + if ( !rtems_is_status_successful( return_value ) ) + _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, true, return_value ); + + return_value = rtems_task_start( + id, + user_tasks[ index ].entry_point, + user_tasks[ index ].argument + ); + if ( !rtems_is_status_successful( return_value ) ) + _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, true, return_value ); + } +} diff --git a/cpukit/rtems/src/taskissuspended.c b/cpukit/rtems/src/taskissuspended.c new file mode 100644 index 0000000000..eaea72160d --- /dev/null +++ b/cpukit/rtems/src/taskissuspended.c @@ -0,0 +1,80 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_is_suspended + * + * This directive returns a status indicating whether or not + * the specified task is suspended. + * + * Input parameters: + * id - thread id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful and not suspended + * RTEMS_ALREADY_SUSPENDED - if successful and suspended + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_is_suspended( + rtems_id id +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( !_States_Is_suspended( the_thread->current_state ) ) { + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); + return RTEMS_ALREADY_SUSPENDED; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskmode.c b/cpukit/rtems/src/taskmode.c new file mode 100644 index 0000000000..40a456f2be --- /dev/null +++ b/cpukit/rtems/src/taskmode.c @@ -0,0 +1,125 @@ +/* + * RTEMS Task Manager - Change Task Mode + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/* + * rtems_task_mode + * + * This directive enables and disables several modes of + * execution for the requesting thread. + * + * Input parameters: + * mode_set - new mode + * mask - mask + * previous_mode_set - address of previous mode set + * + * Output: + * *previous_mode_set - previous mode set + * always return RTEMS_SUCCESSFUL; + */ + +rtems_status_code rtems_task_mode( + rtems_mode mode_set, + rtems_mode mask, + rtems_mode *previous_mode_set +) +{ + Thread_Control *executing; + RTEMS_API_Control *api; + ASR_Information *asr; + bool is_asr_enabled = false; + bool needs_asr_dispatching = false; + rtems_mode old_mode; + + if ( !previous_mode_set ) + return RTEMS_INVALID_ADDRESS; + + executing = _Thread_Executing; + api = executing->API_Extensions[ THREAD_API_RTEMS ]; + asr = &api->Signal; + + old_mode = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT; + + if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE ) + old_mode |= RTEMS_NO_TIMESLICE; + else + old_mode |= RTEMS_TIMESLICE; + + old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR; + old_mode |= _ISR_Get_level(); + + *previous_mode_set = old_mode; + + /* + * These are generic thread scheduling characteristics. + */ + if ( mask & RTEMS_PREEMPT_MASK ) + executing->is_preemptible = _Modes_Is_preempt(mode_set) ? true : false; + + if ( mask & RTEMS_TIMESLICE_MASK ) { + if ( _Modes_Is_timeslice(mode_set) ) { + executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE; + executing->cpu_time_budget = _Thread_Ticks_per_timeslice; + } else + executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; + } + + /* + * Set the new interrupt level + */ + if ( mask & RTEMS_INTERRUPT_MASK ) + _Modes_Set_interrupt_level( mode_set ); + + /* + * This is specific to the RTEMS API + */ + is_asr_enabled = false; + needs_asr_dispatching = false; + + if ( mask & RTEMS_ASR_MASK ) { + is_asr_enabled = _Modes_Is_asr_disabled( mode_set ) ? false : true; + if ( is_asr_enabled != asr->is_enabled ) { + asr->is_enabled = is_asr_enabled; + _ASR_Swap_signals( asr ); + if ( _ASR_Are_signals_pending( asr ) ) { + needs_asr_dispatching = true; + } + } + } + + if ( _System_state_Is_up( _System_state_Get() ) ) { + if (_Thread_Evaluate_is_dispatch_needed( needs_asr_dispatching ) ) + _Thread_Dispatch(); + } + + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/taskmp.c b/cpukit/rtems/src/taskmp.c new file mode 100644 index 0000000000..5f13860492 --- /dev/null +++ b/cpukit/rtems/src/taskmp.c @@ -0,0 +1,343 @@ +/* + * Multiprocessing Support for the RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/score/mpci.h> +#include <rtems/score/mppkt.h> +#include <rtems/score/object.h> +#include <rtems/rtems/options.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/watchdog.h> +#include <rtems/rtems/support.h> + +/*PAGE + * + * _RTEMS_tasks_MP_Send_process_packet + * + */ + +void _RTEMS_tasks_MP_Send_process_packet ( + RTEMS_tasks_MP_Remote_operations operation, + Objects_Id task_id, + rtems_name name +) +{ + RTEMS_tasks_MP_Packet *the_packet; + + switch ( operation ) { + + case RTEMS_TASKS_MP_ANNOUNCE_CREATE: + case RTEMS_TASKS_MP_ANNOUNCE_DELETE: + + the_packet = _RTEMS_tasks_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_TASKS; + the_packet->Prefix.length = sizeof ( RTEMS_tasks_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( RTEMS_tasks_MP_Packet ); + the_packet->operation = operation; + the_packet->Prefix.id = task_id; + the_packet->name = name; + + _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix ); + break; + + case RTEMS_TASKS_MP_SUSPEND_REQUEST: + case RTEMS_TASKS_MP_SUSPEND_RESPONSE: + case RTEMS_TASKS_MP_RESUME_REQUEST: + case RTEMS_TASKS_MP_RESUME_RESPONSE: + case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST: + case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE: + case RTEMS_TASKS_MP_GET_NOTE_REQUEST: + case RTEMS_TASKS_MP_GET_NOTE_RESPONSE: + case RTEMS_TASKS_MP_SET_NOTE_REQUEST: + case RTEMS_TASKS_MP_SET_NOTE_RESPONSE: + break; + } +} + +/*PAGE + * + * _RTEMS_tasks_MP_Send_request_packet + * + */ + +rtems_status_code _RTEMS_tasks_MP_Send_request_packet ( + RTEMS_tasks_MP_Remote_operations operation, + Objects_Id task_id, + rtems_task_priority new_priority, + uint32_t notepad, + uint32_t note +) +{ + RTEMS_tasks_MP_Packet *the_packet; + + switch ( operation ) { + + case RTEMS_TASKS_MP_SUSPEND_REQUEST: + case RTEMS_TASKS_MP_RESUME_REQUEST: + case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST: + case RTEMS_TASKS_MP_GET_NOTE_REQUEST: + case RTEMS_TASKS_MP_SET_NOTE_REQUEST: + + the_packet = _RTEMS_tasks_MP_Get_packet(); + the_packet->Prefix.the_class = MP_PACKET_TASKS; + the_packet->Prefix.length = sizeof ( RTEMS_tasks_MP_Packet ); + the_packet->Prefix.to_convert = sizeof ( RTEMS_tasks_MP_Packet ); + the_packet->operation = operation; + the_packet->Prefix.id = task_id; + the_packet->the_priority = new_priority; + the_packet->notepad = notepad; + the_packet->note = note; + + return _MPCI_Send_request_packet( + _Objects_Get_node( task_id ), + &the_packet->Prefix, + STATES_READY /* Not used */ + ); + break; + + case RTEMS_TASKS_MP_ANNOUNCE_CREATE: + case RTEMS_TASKS_MP_ANNOUNCE_DELETE: + case RTEMS_TASKS_MP_SUSPEND_RESPONSE: + case RTEMS_TASKS_MP_RESUME_RESPONSE: + case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE: + case RTEMS_TASKS_MP_GET_NOTE_RESPONSE: + case RTEMS_TASKS_MP_SET_NOTE_RESPONSE: + break; + + } + /* + * The following line is included to satisfy compilers which + * produce warnings when a function does not end with a return. + */ + return RTEMS_SUCCESSFUL; +} + +/*PAGE + * + * _RTEMS_tasks_MP_Send_response_packet + * + */ + +void _RTEMS_tasks_MP_Send_response_packet ( + RTEMS_tasks_MP_Remote_operations operation, + Thread_Control *the_thread +) +{ + RTEMS_tasks_MP_Packet *the_packet; + + switch ( operation ) { + + case RTEMS_TASKS_MP_SUSPEND_RESPONSE: + case RTEMS_TASKS_MP_RESUME_RESPONSE: + case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE: + case RTEMS_TASKS_MP_GET_NOTE_RESPONSE: + case RTEMS_TASKS_MP_SET_NOTE_RESPONSE: + + the_packet = (RTEMS_tasks_MP_Packet *) the_thread->receive_packet; + +/* + * The packet being returned already contains the class, length, and + * to_convert fields, therefore they are not set in this routine. + */ + the_packet->operation = operation; + the_packet->Prefix.id = the_packet->Prefix.source_tid; + + _MPCI_Send_response_packet( + _Objects_Get_node( the_packet->Prefix.source_tid ), + &the_packet->Prefix + ); + break; + + case RTEMS_TASKS_MP_ANNOUNCE_CREATE: + case RTEMS_TASKS_MP_ANNOUNCE_DELETE: + case RTEMS_TASKS_MP_SUSPEND_REQUEST: + case RTEMS_TASKS_MP_RESUME_REQUEST: + case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST: + case RTEMS_TASKS_MP_GET_NOTE_REQUEST: + case RTEMS_TASKS_MP_SET_NOTE_REQUEST: + break; + + } +} + +/*PAGE + * + * + * _RTEMS_tasks_MP_Process_packet + * + */ + +void _RTEMS_tasks_MP_Process_packet ( + rtems_packet_prefix *the_packet_prefix +) +{ + RTEMS_tasks_MP_Packet *the_packet; + Thread_Control *the_thread; + bool ignored; + + the_packet = (RTEMS_tasks_MP_Packet *) the_packet_prefix; + + switch ( the_packet->operation ) { + + case RTEMS_TASKS_MP_ANNOUNCE_CREATE: + + ignored = _Objects_MP_Allocate_and_open( + &_RTEMS_tasks_Information, + the_packet->name, + the_packet->Prefix.id, + true + ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case RTEMS_TASKS_MP_ANNOUNCE_DELETE: + + _Objects_MP_Close( &_RTEMS_tasks_Information, the_packet->Prefix.id ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case RTEMS_TASKS_MP_SUSPEND_REQUEST: + + the_packet->Prefix.return_code = rtems_task_suspend( + the_packet->Prefix.id + ); + + _RTEMS_tasks_MP_Send_response_packet( + RTEMS_TASKS_MP_SUSPEND_RESPONSE, + _Thread_Executing + ); + break; + + case RTEMS_TASKS_MP_SUSPEND_RESPONSE: + case RTEMS_TASKS_MP_RESUME_RESPONSE: + case RTEMS_TASKS_MP_SET_NOTE_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case RTEMS_TASKS_MP_RESUME_REQUEST: + + the_packet->Prefix.return_code = rtems_task_resume( + the_packet->Prefix.id + ); + + _RTEMS_tasks_MP_Send_response_packet( + RTEMS_TASKS_MP_RESUME_RESPONSE, + _Thread_Executing + ); + break; + + case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST: + + the_packet->Prefix.return_code = rtems_task_set_priority( + the_packet->Prefix.id, + the_packet->the_priority, + &the_packet->the_priority + ); + + _RTEMS_tasks_MP_Send_response_packet( + RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE, + _Thread_Executing + ); + break; + + case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + *(rtems_task_priority *)the_thread->Wait.return_argument = + the_packet->the_priority; + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case RTEMS_TASKS_MP_GET_NOTE_REQUEST: + + the_packet->Prefix.return_code = rtems_task_get_note( + the_packet->Prefix.id, + the_packet->notepad, + &the_packet->note + ); + + _RTEMS_tasks_MP_Send_response_packet( + RTEMS_TASKS_MP_GET_NOTE_RESPONSE, + _Thread_Executing + ); + break; + + case RTEMS_TASKS_MP_GET_NOTE_RESPONSE: + + the_thread = _MPCI_Process_response( the_packet_prefix ); + + *(uint32_t *)the_thread->Wait.return_argument = the_packet->note; + + _MPCI_Return_packet( the_packet_prefix ); + break; + + case RTEMS_TASKS_MP_SET_NOTE_REQUEST: + + the_packet->Prefix.return_code = rtems_task_set_note( + the_packet->Prefix.id, + the_packet->notepad, + the_packet->note + ); + + _RTEMS_tasks_MP_Send_response_packet( + RTEMS_TASKS_MP_SET_NOTE_RESPONSE, + _Thread_Executing + ); + break; + } +} + +/*PAGE + * + * _RTEMS_tasks_MP_Send_object_was_deleted + * + * This routine is not neededby the Tasks since a task + * cannot be globally deleted. + * + */ + +/*PAGE + * + * _RTEMS_tasks_MP_Send_extract_proxy + * + * This routine is not neededby the Tasks since a task + * cannot be globally deleted. + * + */ + +/*PAGE + * + * _RTEMS_tasks_MP_Get_packet + * + */ + +RTEMS_tasks_MP_Packet *_RTEMS_tasks_MP_Get_packet ( void ) +{ + return (RTEMS_tasks_MP_Packet *) _MPCI_Get_packet(); +} + +/* end of file */ diff --git a/cpukit/rtems/src/taskrestart.c b/cpukit/rtems/src/taskrestart.c new file mode 100644 index 0000000000..bc85137b23 --- /dev/null +++ b/cpukit/rtems/src/taskrestart.c @@ -0,0 +1,83 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_restart + * + * This directive readies the specified thread. It restores + * the thread environment to the original values established + * at thread creation and start time. A thread can be restarted + * from any state except the dormant state. + * + * Input parameters: + * id - thread id + * argument - thread argument + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_restart( + rtems_id id, + uint32_t argument +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( _Thread_Restart( the_thread, NULL, argument ) ) { + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); + return RTEMS_INCORRECT_STATE; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskresume.c b/cpukit/rtems/src/taskresume.c new file mode 100644 index 0000000000..1c6ef490b7 --- /dev/null +++ b/cpukit/rtems/src/taskresume.c @@ -0,0 +1,85 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_resume + * + * This directive will remove the specified thread + * from the suspended state. + * + * Input parameters: + * id - thread id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_resume( + rtems_id id +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( _States_Is_suspended( the_thread->current_state ) ) { + _Thread_Resume( the_thread ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); + return RTEMS_INCORRECT_STATE; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _RTEMS_tasks_MP_Send_request_packet( + RTEMS_TASKS_MP_RESUME_REQUEST, + id, + 0, /* Not used */ + 0, /* Not used */ + 0 /* Not used */ + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/tasks.c b/cpukit/rtems/src/tasks.c new file mode 100644 index 0000000000..e81bf72167 --- /dev/null +++ b/cpukit/rtems/src/tasks.c @@ -0,0 +1,305 @@ +/* + * RTEMS Task Manager -- Initialize Manager + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * _RTEMS_tasks_Create_extension + * + * This routine is an extension routine that is invoked as part + * of creating any type of task or thread in the system. If the + * task is created via another API, then this routine is invoked + * and this API given the opportunity to initialize its extension + * area. + */ + +bool _RTEMS_tasks_Create_extension( + Thread_Control *executing, + Thread_Control *created +) +{ + RTEMS_API_Control *api; + int i; + size_t to_allocate; + + /* + * Notepads must be the last entry in the structure and they + * can be left off if disabled in the configuration. + */ + to_allocate = sizeof( RTEMS_API_Control ); + if ( !rtems_configuration_get_notepads_enabled() ) + to_allocate -= (RTEMS_NUMBER_NOTEPADS * sizeof(uint32_t)); + + api = _Workspace_Allocate( to_allocate ); + + if ( !api ) + return false; + + created->API_Extensions[ THREAD_API_RTEMS ] = api; + + api->pending_events = EVENT_SETS_NONE_PENDING; + api->event_condition = 0; + _ASR_Initialize( &api->Signal ); + created->task_variables = NULL; + + if ( rtems_configuration_get_notepads_enabled() ) { + for (i=0; i < RTEMS_NUMBER_NOTEPADS; i++) + api->Notepads[i] = 0; + } + + return true; +} + +/*PAGE + * + * _RTEMS_tasks_Start_extension + * + * This extension routine is invoked when a task is started for the + * first time. + */ + +void _RTEMS_tasks_Start_extension( + Thread_Control *executing, + Thread_Control *started +) +{ + RTEMS_API_Control *api; + + api = started->API_Extensions[ THREAD_API_RTEMS ]; + + api->pending_events = EVENT_SETS_NONE_PENDING; +} + +/*PAGE + * + * _RTEMS_tasks_Delete_extension + * + * This extension routine is invoked when a task is deleted. + */ + +void _RTEMS_tasks_Delete_extension( + Thread_Control *executing, + Thread_Control *deleted +) +{ + rtems_task_variable_t *tvp, *next; + + /* + * Free per task variable memory + */ + + tvp = deleted->task_variables; + deleted->task_variables = NULL; + while (tvp) { + next = (rtems_task_variable_t *)tvp->next; + _RTEMS_Tasks_Invoke_task_variable_dtor( deleted, tvp ); + tvp = next; + } + + /* + * Free API specific memory + */ + + (void) _Workspace_Free( deleted->API_Extensions[ THREAD_API_RTEMS ] ); + deleted->API_Extensions[ THREAD_API_RTEMS ] = NULL; +} + +/*PAGE + * + * _RTEMS_tasks_Switch_extension + * + * This extension routine is invoked at each context switch. + */ + +void _RTEMS_tasks_Switch_extension( + Thread_Control *executing, + Thread_Control *heir +) +{ + rtems_task_variable_t *tvp; + + /* + * Per Task Variables + */ + + tvp = executing->task_variables; + while (tvp) { + tvp->tval = *tvp->ptr; + *tvp->ptr = tvp->gval; + tvp = (rtems_task_variable_t *)tvp->next; + } + + tvp = heir->task_variables; + while (tvp) { + tvp->gval = *tvp->ptr; + *tvp->ptr = tvp->tval; + tvp = (rtems_task_variable_t *)tvp->next; + } +} + +/*PAGE + * + * _RTEMS_tasks_Post_switch_extension + * + * This extension routine is invoked at each context switch. + */ + +void _RTEMS_tasks_Post_switch_extension( + Thread_Control *executing +) +{ + ISR_Level level; + RTEMS_API_Control *api; + ASR_Information *asr; + rtems_signal_set signal_set; + Modes_Control prev_mode; + + api = executing->API_Extensions[ THREAD_API_RTEMS ]; + if ( !api ) + return; + + /* + * Signal Processing + */ + + asr = &api->Signal; + + _ISR_Disable( level ); + signal_set = asr->signals_posted; + asr->signals_posted = 0; + _ISR_Enable( level ); + + + if ( !signal_set ) /* similar to _ASR_Are_signals_pending( asr ) */ + return; + + asr->nest_level += 1; + rtems_task_mode( asr->mode_set, RTEMS_ALL_MODE_MASKS, &prev_mode ); + + (*asr->handler)( signal_set ); + + asr->nest_level -= 1; + rtems_task_mode( prev_mode, RTEMS_ALL_MODE_MASKS, &prev_mode ); + +} + +API_extensions_Control _RTEMS_tasks_API_extensions = { + { NULL, NULL }, + #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API) + NULL, /* predriver */ + #endif + _RTEMS_tasks_Initialize_user_tasks, /* postdriver */ + _RTEMS_tasks_Post_switch_extension /* post switch */ +}; + +User_extensions_Control _RTEMS_tasks_User_extensions = { + { NULL, NULL }, + { { NULL, NULL }, _RTEMS_tasks_Switch_extension }, + { _RTEMS_tasks_Create_extension, /* create */ + _RTEMS_tasks_Start_extension, /* start */ + _RTEMS_tasks_Start_extension, /* restart */ + _RTEMS_tasks_Delete_extension, /* delete */ + _RTEMS_tasks_Switch_extension, /* switch */ + NULL, /* begin */ + NULL, /* exitted */ + NULL /* fatal */ + } +}; + +/*PAGE + * + * _RTEMS_tasks_Manager_initialization + * + * This routine initializes all Task Manager related data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _RTEMS_tasks_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_RTEMS_tasks_Information, /* object information table */ + OBJECTS_CLASSIC_API, /* object API */ + OBJECTS_RTEMS_TASKS, /* object class */ + Configuration_RTEMS_API.maximum_tasks, + /* maximum objects of this class */ + sizeof( Thread_Control ), /* size of this object's control block */ + false, /* true if the name is a string */ + RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */ +#if defined(RTEMS_MULTIPROCESSING) + , + true, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); + + /* + * Add all the extensions for this API + */ + + _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions ); + + _API_extensions_Add( &_RTEMS_tasks_API_extensions ); + + /* + * Register the MP Process Packet routine. + */ + +#if defined(RTEMS_MULTIPROCESSING) + _MPCI_Register_packet_processor( + MP_PACKET_TASKS, + _RTEMS_tasks_MP_Process_packet + ); +#endif + +} + +/*PAGE + * + * _RTEMS_tasks_Initialize_user_tasks + * + * This routine creates and starts all configured user + * initialzation threads. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _RTEMS_tasks_Initialize_user_tasks( void ) +{ + if ( _RTEMS_tasks_Initialize_user_tasks_p ) + (*_RTEMS_tasks_Initialize_user_tasks_p)(); +} diff --git a/cpukit/rtems/src/taskself.c b/cpukit/rtems/src/taskself.c new file mode 100644 index 0000000000..e596c15c60 --- /dev/null +++ b/cpukit/rtems/src/taskself.c @@ -0,0 +1,24 @@ +/* + * RTEMS Task Manager - Get ID of Self + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/tasks.h> + +rtems_id rtems_task_self(void) +{ + return _Thread_Executing->Object.id; +} diff --git a/cpukit/rtems/src/tasksetnote.c b/cpukit/rtems/src/tasksetnote.c new file mode 100644 index 0000000000..cd2bfb6dd1 --- /dev/null +++ b/cpukit/rtems/src/tasksetnote.c @@ -0,0 +1,109 @@ +/* + * RTEMS Task Manager + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_set_note + * + * This directive sets the specified notepad contents to the given + * note. + * + * Input parameters: + * id - thread id + * notepad - notepad number + * note - note value + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_set_note( + rtems_id id, + uint32_t notepad, + uint32_t note +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + RTEMS_API_Control *api; + + if ( !rtems_configuration_get_notepads_enabled() ) + return RTEMS_NOT_CONFIGURED; + + /* + * NOTE: There is no check for < RTEMS_NOTEPAD_FIRST because that would + * be checking an unsigned number for being negative. + */ + + if ( notepad > RTEMS_NOTEPAD_LAST ) + return RTEMS_INVALID_NUMBER; + + /* + * Optimize the most likely case to avoid the Thread_Dispatch. + */ + + if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) || + _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) { + api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ]; + api->Notepads[ notepad ] = note; + return RTEMS_SUCCESSFUL; + } + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; + api->Notepads[ notepad ] = note; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _RTEMS_tasks_MP_Send_request_packet( + RTEMS_TASKS_MP_SET_NOTE_REQUEST, + id, + 0, /* Not used */ + notepad, + note + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/tasksetpriority.c b/cpukit/rtems/src/tasksetpriority.c new file mode 100644 index 0000000000..4e85e56533 --- /dev/null +++ b/cpukit/rtems/src/tasksetpriority.c @@ -0,0 +1,102 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_set_priority + * + * This directive changes the priority of the specified thread. + * The specified thread can be any thread in the system including + * the requesting thread. + * + * Input parameters: + * id - thread id (0 indicates requesting thread) + * new_priority - thread priority (0 indicates current priority) + * old_priority - pointer to previous priority + * + * Output parameters: + * old_priority - previous priority + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_set_priority( + rtems_id id, + rtems_task_priority new_priority, + rtems_task_priority *old_priority +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + + if ( new_priority != RTEMS_CURRENT_PRIORITY && + !_RTEMS_tasks_Priority_is_valid( new_priority ) ) + return RTEMS_INVALID_PRIORITY; + + if ( !old_priority ) + return RTEMS_INVALID_ADDRESS; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + /* XXX need helper to "convert" from core priority */ + *old_priority = the_thread->current_priority; + if ( new_priority != RTEMS_CURRENT_PRIORITY ) { + the_thread->real_priority = new_priority; + if ( the_thread->resource_count == 0 || + the_thread->current_priority > new_priority ) + _Thread_Change_priority( the_thread, new_priority, false ); + } + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Executing->Wait.return_argument = old_priority; + return _RTEMS_tasks_MP_Send_request_packet( + RTEMS_TASKS_MP_SET_PRIORITY_REQUEST, + id, + new_priority, + 0, /* Not used */ + 0 /* Not used */ + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskstart.c b/cpukit/rtems/src/taskstart.c new file mode 100644 index 0000000000..9d2ce0cec4 --- /dev/null +++ b/cpukit/rtems/src/taskstart.c @@ -0,0 +1,88 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_start + * + * This directive readies the thread identified by the "id" + * based on its current priorty, to await execution. A thread + * can be started only from the dormant state. + * + * Input parameters: + * id - thread id + * entry_point - start execution address of thread + * argument - thread argument + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_start( + rtems_id id, + rtems_task_entry entry_point, + rtems_task_argument argument +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + + if ( entry_point == NULL ) + return RTEMS_INVALID_ADDRESS; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( _Thread_Start( + the_thread, THREAD_START_NUMERIC, entry_point, NULL, argument ) ) { + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); + return RTEMS_INCORRECT_STATE; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/tasksuspend.c b/cpukit/rtems/src/tasksuspend.c new file mode 100644 index 0000000000..3f7e8b7d03 --- /dev/null +++ b/cpukit/rtems/src/tasksuspend.c @@ -0,0 +1,86 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_suspend + * + * This directive will place the specified thread in the "suspended" + * state. Note that the suspended state can be in addition to + * other waiting states. + * + * Input parameters: + * id - thread id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_suspend( + rtems_id id +) +{ + register Thread_Control *the_thread; + Objects_Locations location; + + the_thread = _Thread_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( !_States_Is_suspended( the_thread->current_state ) ) { + _Thread_Suspend( the_thread ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + _Thread_Enable_dispatch(); + return RTEMS_ALREADY_SUSPENDED; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + return _RTEMS_tasks_MP_Send_request_packet( + RTEMS_TASKS_MP_SUSPEND_REQUEST, + id, + 0, /* Not used */ + 0, /* Not used */ + 0 /* Not used */ + ); +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskvariable_invoke_dtor.c b/cpukit/rtems/src/taskvariable_invoke_dtor.c new file mode 100644 index 0000000000..d348c6d90e --- /dev/null +++ b/cpukit/rtems/src/taskvariable_invoke_dtor.c @@ -0,0 +1,43 @@ +/* + * Invoke the destructor on a per-task variable + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/wkspace.h> + +void _RTEMS_Tasks_Invoke_task_variable_dtor( + Thread_Control *the_thread, + rtems_task_variable_t *tvp +) +{ + void (*dtor)(void *); + void *value; + + dtor = tvp->dtor; + if (_Thread_Is_executing(the_thread)) { + value = *tvp->ptr; + *tvp->ptr = tvp->gval; + } else { + value = tvp->tval; + } + + if ( dtor ) + (*dtor)(value); + + _Workspace_Free(tvp); +} diff --git a/cpukit/rtems/src/taskvariableadd.c b/cpukit/rtems/src/taskvariableadd.c new file mode 100644 index 0000000000..41d6bed57c --- /dev/null +++ b/cpukit/rtems/src/taskvariableadd.c @@ -0,0 +1,87 @@ +/* + * rtems_task_variable_add - Add a per-task variable + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/wkspace.h> + +/* + * rtems_task_variable_add + * + * This directive registers a task variable. + */ + +rtems_status_code rtems_task_variable_add( + rtems_id tid, + void **ptr, + void (*dtor)(void *) +) +{ + Thread_Control *the_thread; + Objects_Locations location; + rtems_task_variable_t *tvp, *new; + + if ( !ptr ) + return RTEMS_INVALID_ADDRESS; + + the_thread = _Thread_Get (tid, &location); + switch (location) { + + case OBJECTS_LOCAL: + /* + * Figure out if the variable is already in this task's list. + */ + tvp = the_thread->task_variables; + while (tvp) { + if (tvp->ptr == ptr) { + tvp->dtor = dtor; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + tvp = (rtems_task_variable_t *)tvp->next; + } + + /* + * Now allocate memory for this task variable. + */ + new = (rtems_task_variable_t *) + _Workspace_Allocate(sizeof(rtems_task_variable_t)); + if (new == NULL) { + _Thread_Enable_dispatch(); + return RTEMS_NO_MEMORY; + } + new->gval = *ptr; + new->ptr = ptr; + new->dtor = dtor; + + new->next = (struct rtems_task_variable_tt *)the_thread->task_variables; + the_thread->task_variables = new; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskvariabledelete.c b/cpukit/rtems/src/taskvariabledelete.c new file mode 100644 index 0000000000..fe34732f57 --- /dev/null +++ b/cpukit/rtems/src/taskvariabledelete.c @@ -0,0 +1,76 @@ +/* + * rtems_task_variable_delete - Delete a per-task variable + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/wkspace.h> + +/* + * rtems_task_variable_delete + * + * This directive removes a task variable. + */ + +rtems_status_code rtems_task_variable_delete( + rtems_id tid, + void **ptr +) +{ + Thread_Control *the_thread; + Objects_Locations location; + rtems_task_variable_t *tvp, *prev; + + if ( !ptr ) + return RTEMS_INVALID_ADDRESS; + + prev = NULL; + + the_thread = _Thread_Get (tid, &location); + switch (location) { + + case OBJECTS_LOCAL: + tvp = the_thread->task_variables; + while (tvp) { + if (tvp->ptr == ptr) { + if (prev) + prev->next = tvp->next; + else + the_thread->task_variables = (rtems_task_variable_t *)tvp->next; + + _RTEMS_Tasks_Invoke_task_variable_dtor( the_thread, tvp ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + prev = tvp; + tvp = (rtems_task_variable_t *)tvp->next; + } + _Thread_Enable_dispatch(); + return RTEMS_INVALID_ADDRESS; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskvariableget.c b/cpukit/rtems/src/taskvariableget.c new file mode 100644 index 0000000000..fbe3b10d7f --- /dev/null +++ b/cpukit/rtems/src/taskvariableget.c @@ -0,0 +1,78 @@ +/* + * rtems_task_variable_get - Get a per-task variable + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/wkspace.h> + +/* + * rtems_task_variable_get + * + * This directive gets the value of a task variable. + */ + +rtems_status_code rtems_task_variable_get( + rtems_id tid, + void **ptr, + void **result +) +{ + Thread_Control *the_thread; + Objects_Locations location; + rtems_task_variable_t *tvp; + + if ( !ptr ) + return RTEMS_INVALID_ADDRESS; + + if ( !result ) + return RTEMS_INVALID_ADDRESS; + + the_thread = _Thread_Get (tid, &location); + switch (location) { + + case OBJECTS_LOCAL: + /* + * Figure out if the variable is in this task's list. + */ + tvp = the_thread->task_variables; + while (tvp) { + if (tvp->ptr == ptr) { + /* + * Should this return the current (i.e not the + * saved) value if `tid' is the current task? + */ + *result = tvp->tval; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + tvp = (rtems_task_variable_t *)tvp->next; + } + _Thread_Enable_dispatch(); + return RTEMS_INVALID_ADDRESS; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + + case OBJECTS_ERROR: + break; + } + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/taskwakeafter.c b/cpukit/rtems/src/taskwakeafter.c new file mode 100644 index 0000000000..2f6fecfe5d --- /dev/null +++ b/cpukit/rtems/src/taskwakeafter.c @@ -0,0 +1,69 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/score/object.h> +#include <rtems/score/scheduler.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_wake_after + * + * This directive suspends the requesting thread for the given amount + * of ticks. + * + * Input parameters: + * ticks - number of ticks to wait + * + * Output parameters: + * RTEMS_SUCCESSFUL - always successful + */ + +rtems_status_code rtems_task_wake_after( + rtems_interval ticks +) +{ + _Thread_Disable_dispatch(); + if ( ticks == 0 ) { + _Scheduler_Yield(); + } else { + _Thread_Set_state( _Thread_Executing, STATES_DELAYING ); + _Watchdog_Initialize( + &_Thread_Executing->Timer, + _Thread_Delay_ended, + _Thread_Executing->Object.id, + NULL + ); + _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks ); + } + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/taskwakewhen.c b/cpukit/rtems/src/taskwakewhen.c new file mode 100644 index 0000000000..5496f55a73 --- /dev/null +++ b/cpukit/rtems/src/taskwakewhen.c @@ -0,0 +1,87 @@ +/* + * RTEMS Task Manager + * + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/rtems/modes.h> +#include <rtems/rtems/clock.h> +#include <rtems/score/object.h> +#include <rtems/score/stack.h> +#include <rtems/score/states.h> +#include <rtems/rtems/tasks.h> +#include <rtems/score/thread.h> +#include <rtems/score/threadq.h> +#include <rtems/score/tod.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/apiext.h> +#include <rtems/score/sysstate.h> + +/*PAGE + * + * rtems_task_wake_when + * + * This directive blocks the requesting thread until the given date and + * time is reached. + * + * Input parameters: + * time_buffer - pointer to the time and date structure + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_task_wake_when( + rtems_time_of_day *time_buffer +) +{ + Watchdog_Interval seconds; + + if ( !_TOD_Is_set ) + return RTEMS_NOT_DEFINED; + + if ( !time_buffer ) + return RTEMS_INVALID_ADDRESS; + + time_buffer->ticks = 0; + + if ( !_TOD_Validate( time_buffer ) ) + return RTEMS_INVALID_CLOCK; + + seconds = _TOD_To_seconds( time_buffer ); + + if ( seconds <= _TOD_Seconds_since_epoch() ) + return RTEMS_INVALID_CLOCK; + + _Thread_Disable_dispatch(); + _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_TIME ); + _Watchdog_Initialize( + &_Thread_Executing->Timer, + _Thread_Delay_ended, + _Thread_Executing->Object.id, + NULL + ); + _Watchdog_Insert_seconds( + &_Thread_Executing->Timer, + seconds - _TOD_Seconds_since_epoch() + ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/timercancel.c b/cpukit/rtems/src/timercancel.c new file mode 100644 index 0000000000..abab3f424c --- /dev/null +++ b/cpukit/rtems/src/timercancel.c @@ -0,0 +1,66 @@ +/* + * Timer Manager - rtems_timer_cancel directive + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_cancel + * + * This directive allows a thread to cancel a timer. + * + * Input parameters: + * id - timer id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_timer_cancel( + rtems_id id +) +{ + Timer_Control *the_timer; + Objects_Locations location; + + the_timer = _Timer_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( !_Timer_Is_dormant_class( the_timer->the_class ) ) + (void) _Watchdog_Remove( &the_timer->Ticker ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/timercreate.c b/cpukit/rtems/src/timercreate.c new file mode 100644 index 0000000000..e277768933 --- /dev/null +++ b/cpukit/rtems/src/timercreate.c @@ -0,0 +1,78 @@ +/* + * Timer Manager - rtems_timer_create directive + * + * + * COPYRIGHT (c) 1989-2002. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_create + * + * This directive creates a timer and performs some initialization. + * + * Input parameters: + * name - timer name + * id - pointer to timer id + * + * Output parameters: + * id - timer id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_timer_create( + rtems_name name, + rtems_id *id +) +{ + Timer_Control *the_timer; + + if ( !rtems_is_name_valid( name ) ) + return RTEMS_INVALID_NAME; + + if ( !id ) + return RTEMS_INVALID_ADDRESS; + + _Thread_Disable_dispatch(); /* to prevent deletion */ + + the_timer = _Timer_Allocate(); + + if ( !the_timer ) { + _Thread_Enable_dispatch(); + return RTEMS_TOO_MANY; + } + + the_timer->the_class = TIMER_DORMANT; + _Watchdog_Initialize( &the_timer->Ticker, NULL, 0, NULL ); + + _Objects_Open( + &_Timer_Information, + &the_timer->Object, + (Objects_Name) name + ); + + *id = the_timer->Object.id; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; +} diff --git a/cpukit/rtems/src/timerdelete.c b/cpukit/rtems/src/timerdelete.c new file mode 100644 index 0000000000..7dbc812a2e --- /dev/null +++ b/cpukit/rtems/src/timerdelete.c @@ -0,0 +1,67 @@ +/* + * Timer Manager - rtems_timer_delete directive + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_delete + * + * This directive allows a thread to delete a timer. + * + * Input parameters: + * id - timer id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_timer_delete( + rtems_id id +) +{ + Timer_Control *the_timer; + Objects_Locations location; + + the_timer = _Timer_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Objects_Close( &_Timer_Information, &the_timer->Object ); + (void) _Watchdog_Remove( &the_timer->Ticker ); + _Timer_Free( the_timer ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/timerfireafter.c b/cpukit/rtems/src/timerfireafter.c new file mode 100644 index 0000000000..540ede38ad --- /dev/null +++ b/cpukit/rtems/src/timerfireafter.c @@ -0,0 +1,103 @@ +/* + * Timer Manager - rtems_timer_fire_after directive + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_fire_after + * + * This directive allows a thread to start a timer. + * + * Input parameters: + * id - timer id + * ticks - interval until routine is fired + * routine - routine to schedule + * user_data - passed as argument to routine when it is fired + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_timer_fire_after( + rtems_id id, + rtems_interval ticks, + rtems_timer_service_routine_entry routine, + void *user_data +) +{ + Timer_Control *the_timer; + Objects_Locations location; + ISR_Level level; + + if ( ticks == 0 ) + return RTEMS_INVALID_NUMBER; + + if ( !routine ) + return RTEMS_INVALID_ADDRESS; + + the_timer = _Timer_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + (void) _Watchdog_Remove( &the_timer->Ticker ); + + _ISR_Disable( level ); + + /* + * Check to see if the watchdog has just been inserted by a + * higher priority interrupt. If so, abandon this insert. + */ + + if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) { + _ISR_Enable( level ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + + /* + * OK. Now we now the timer was not rescheduled by an interrupt + * so we can atomically initialize it as in use. + */ + + the_timer->the_class = TIMER_INTERVAL; + _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); + _ISR_Enable( level ); + + + _Watchdog_Insert_ticks( &the_timer->Ticker, ticks ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/timerfirewhen.c b/cpukit/rtems/src/timerfirewhen.c new file mode 100644 index 0000000000..670b39ec1b --- /dev/null +++ b/cpukit/rtems/src/timerfirewhen.c @@ -0,0 +1,91 @@ +/* + * Timer Manager - rtems_timer_fire_when directive + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_fire_when + * + * This directive allows a thread to start a timer. + * + * Input parameters: + * id - timer id + * wall_time - time of day to fire timer + * routine - routine to schedule + * user_data - passed as argument to routine when it is fired + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_timer_fire_when( + rtems_id id, + rtems_time_of_day *wall_time, + rtems_timer_service_routine_entry routine, + void *user_data +) +{ + Timer_Control *the_timer; + Objects_Locations location; + rtems_interval seconds; + + if ( !_TOD_Is_set ) + return RTEMS_NOT_DEFINED; + + if ( !_TOD_Validate( wall_time ) ) + return RTEMS_INVALID_CLOCK; + + if ( !routine ) + return RTEMS_INVALID_ADDRESS; + + seconds = _TOD_To_seconds( wall_time ); + if ( seconds <= _TOD_Seconds_since_epoch() ) + return RTEMS_INVALID_CLOCK; + + the_timer = _Timer_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + (void) _Watchdog_Remove( &the_timer->Ticker ); + the_timer->the_class = TIMER_TIME_OF_DAY; + _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); + _Watchdog_Insert_seconds( + &the_timer->Ticker, + seconds - _TOD_Seconds_since_epoch() + ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/timergetinfo.c b/cpukit/rtems/src/timergetinfo.c new file mode 100644 index 0000000000..2b648597fe --- /dev/null +++ b/cpukit/rtems/src/timergetinfo.c @@ -0,0 +1,75 @@ +/* + * Timer Manager - rtems_timer_get_information directive + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_get_information + * + * This directive allows a thread to obtain information about a timer. + * + * Input parameters: + * id - timer id + * the_info - pointer to timer information block + * + * Output parameters: + * *the_info - region information block filled in + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + * + */ + +rtems_status_code rtems_timer_get_information( + rtems_id id, + rtems_timer_information *the_info +) +{ + Timer_Control *the_timer; + Objects_Locations location; + + if ( !the_info ) + return RTEMS_INVALID_ADDRESS; + + the_timer = _Timer_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + the_info->the_class = the_timer->the_class; + the_info->initial = the_timer->Ticker.initial; + the_info->start_time = the_timer->Ticker.start_time; + the_info->stop_time = the_timer->Ticker.stop_time; + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/timerident.c b/cpukit/rtems/src/timerident.c new file mode 100644 index 0000000000..1f1ebbcd7d --- /dev/null +++ b/cpukit/rtems/src/timerident.c @@ -0,0 +1,60 @@ +/* + * Timer Manager - rtems_timer_ident directive + * + * + * COPYRIGHT (c) 1989-2002. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_ident + * + * This directive returns the system ID associated with + * the timer name. + * + * Input parameters: + * name - user defined message queue name + * id - pointer to timer id + * + * Output parameters: + * *id - message queue id + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_timer_ident( + rtems_name name, + rtems_id *id +) +{ + Objects_Name_or_id_lookup_errors status; + + status = _Objects_Name_to_id_u32( + &_Timer_Information, + name, + OBJECTS_SEARCH_LOCAL_NODE, + id + ); + + return _Status_Object_name_errors_to_status[ status ]; +} diff --git a/cpukit/rtems/src/timerreset.c b/cpukit/rtems/src/timerreset.c new file mode 100644 index 0000000000..4a3e094a08 --- /dev/null +++ b/cpukit/rtems/src/timerreset.c @@ -0,0 +1,93 @@ +/* + * Timer Manager - rtems_timer_reset directive + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_reset + * + * This directive allows a thread to reset a timer. + * + * Input parameters: + * id - timer id + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_timer_reset( + rtems_id id +) +{ + Timer_Control *the_timer; + Objects_Locations location; + rtems_status_code status = RTEMS_SUCCESSFUL; + + the_timer = _Timer_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( the_timer->the_class == TIMER_INTERVAL ) { + _Watchdog_Remove( &the_timer->Ticker ); + _Watchdog_Insert( &_Watchdog_Ticks_chain, &the_timer->Ticker ); + } else if ( the_timer->the_class == TIMER_INTERVAL_ON_TASK ) { + Timer_server_Control *timer_server = _Timer_server; + + /* + * There is no way for a timer to have this class unless + * it was scheduled as a server fire. That requires that + * the Timer Server be initiated. So this error cannot + * occur unless something is internally wrong. + */ + #if defined(RTEMS_DEBUG) + if ( !timer_server ) { + _Thread_Enable_dispatch(); + return RTEMS_INCORRECT_STATE; + } + #endif + _Watchdog_Remove( &the_timer->Ticker ); + (*timer_server->schedule_operation)( timer_server, the_timer ); + } else { + /* + * Must be dormant or time of day timer (e.g. TIMER_DORMANT, + * TIMER_TIME_OF_DAY, or TIMER_TIME_OF_DAY_ON_TASK). We + * can only reset active interval timers. + */ + status = RTEMS_NOT_DEFINED; + } + _Thread_Enable_dispatch(); + return status; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/timerserver.c b/cpukit/rtems/src/timerserver.c new file mode 100644 index 0000000000..9f8da0d5c3 --- /dev/null +++ b/cpukit/rtems/src/timerserver.c @@ -0,0 +1,583 @@ +/** + * @file timerserver.c + * + * Timer Manager - rtems_timer_initiate_server directive along with + * the Timer Server Body and support routines + * + * @note Data specific to the Timer Server is declared in this + * file as the Timer Server so it does not have to be in the + * minimum footprint. It is only really required when + * task-based timers are used. Since task-based timers can + * not be started until the server is initiated, this structure + * does not have to be initialized until then. + */ + +/* COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * Copyright (c) 2009 embedded brains GmbH. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +#include <rtems/rtems/tasks.h> +#include <rtems/rtems/support.h> +#include <rtems/score/thread.h> + +static Timer_server_Control _Timer_server_Default; + +static void _Timer_server_Stop_interval_system_watchdog( + Timer_server_Control *ts +) +{ + _Watchdog_Remove( &ts->Interval_watchdogs.System_watchdog ); +} + +static void _Timer_server_Reset_interval_system_watchdog( + Timer_server_Control *ts +) +{ + ISR_Level level; + + _Timer_server_Stop_interval_system_watchdog( ts ); + + _ISR_Disable( level ); + if ( !_Chain_Is_empty( &ts->Interval_watchdogs.Chain ) ) { + Watchdog_Interval delta_interval = + _Watchdog_First( &ts->Interval_watchdogs.Chain )->delta_interval; + _ISR_Enable( level ); + + /* + * The unit is TICKS here. + */ + _Watchdog_Insert_ticks( + &ts->Interval_watchdogs.System_watchdog, + delta_interval + ); + } else { + _ISR_Enable( level ); + } +} + +static void _Timer_server_Stop_tod_system_watchdog( + Timer_server_Control *ts +) +{ + _Watchdog_Remove( &ts->TOD_watchdogs.System_watchdog ); +} + +static void _Timer_server_Reset_tod_system_watchdog( + Timer_server_Control *ts +) +{ + ISR_Level level; + + _Timer_server_Stop_tod_system_watchdog( ts ); + + _ISR_Disable( level ); + if ( !_Chain_Is_empty( &ts->TOD_watchdogs.Chain ) ) { + Watchdog_Interval delta_interval = + _Watchdog_First( &ts->TOD_watchdogs.Chain )->delta_interval; + _ISR_Enable( level ); + + /* + * The unit is SECONDS here. + */ + _Watchdog_Insert_seconds( + &ts->TOD_watchdogs.System_watchdog, + delta_interval + ); + } else { + _ISR_Enable( level ); + } +} + +static void _Timer_server_Insert_timer( + Timer_server_Control *ts, + Timer_Control *timer +) +{ + if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) { + _Watchdog_Insert( &ts->Interval_watchdogs.Chain, &timer->Ticker ); + } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) { + _Watchdog_Insert( &ts->TOD_watchdogs.Chain, &timer->Ticker ); + } +} + +static void _Timer_server_Insert_timer_and_make_snapshot( + Timer_server_Control *ts, + Timer_Control *timer +) +{ + Watchdog_Control *first_watchdog; + Watchdog_Interval delta_interval; + Watchdog_Interval last_snapshot; + Watchdog_Interval snapshot; + Watchdog_Interval delta; + ISR_Level level; + + /* + * We have to update the time snapshots here, because otherwise we may have + * problems with the integer range of the delta values. The time delta DT + * from the last snapshot to now may be arbitrarily long. The last snapshot + * is the reference point for the delta chain. Thus if we do not update the + * reference point we have to add DT to the initial delta of the watchdog + * being inserted. This could result in an integer overflow. + */ + + _Thread_Disable_dispatch(); + + if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) { + /* + * We have to advance the last known ticks value of the server and update + * the watchdog chain accordingly. + */ + _ISR_Disable( level ); + snapshot = _Watchdog_Ticks_since_boot; + last_snapshot = ts->Interval_watchdogs.last_snapshot; + if ( !_Chain_Is_empty( &ts->Interval_watchdogs.Chain ) ) { + first_watchdog = _Watchdog_First( &ts->Interval_watchdogs.Chain ); + + /* + * We assume adequate unsigned arithmetic here. + */ + delta = snapshot - last_snapshot; + + delta_interval = first_watchdog->delta_interval; + if (delta_interval > delta) { + delta_interval -= delta; + } else { + delta_interval = 0; + } + first_watchdog->delta_interval = delta_interval; + } + ts->Interval_watchdogs.last_snapshot = snapshot; + _ISR_Enable( level ); + + _Watchdog_Insert( &ts->Interval_watchdogs.Chain, &timer->Ticker ); + + if ( !ts->active ) { + _Timer_server_Reset_interval_system_watchdog( ts ); + } + } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) { + /* + * We have to advance the last known seconds value of the server and update + * the watchdog chain accordingly. + */ + _ISR_Disable( level ); + snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch(); + last_snapshot = ts->TOD_watchdogs.last_snapshot; + if ( !_Chain_Is_empty( &ts->TOD_watchdogs.Chain ) ) { + first_watchdog = _Watchdog_First( &ts->TOD_watchdogs.Chain ); + delta_interval = first_watchdog->delta_interval; + if ( snapshot > last_snapshot ) { + /* + * We advanced in time. + */ + delta = snapshot - last_snapshot; + if (delta_interval > delta) { + delta_interval -= delta; + } else { + delta_interval = 0; + } + } else { + /* + * Someone put us in the past. + */ + delta = last_snapshot - snapshot; + delta_interval += delta; + } + first_watchdog->delta_interval = delta_interval; + } + ts->TOD_watchdogs.last_snapshot = snapshot; + _ISR_Enable( level ); + + _Watchdog_Insert( &ts->TOD_watchdogs.Chain, &timer->Ticker ); + + if ( !ts->active ) { + _Timer_server_Reset_tod_system_watchdog( ts ); + } + } + + _Thread_Enable_dispatch(); +} + +static void _Timer_server_Schedule_operation_method( + Timer_server_Control *ts, + Timer_Control *timer +) +{ + if ( ts->insert_chain == NULL ) { + _Timer_server_Insert_timer_and_make_snapshot( ts, timer ); + } else { + /* + * We interrupted a critical section of the timer server. The timer + * server is not preemptible, so we must be in interrupt context here. No + * thread dispatch will happen until the timer server finishes its + * critical section. We have to use the protected chain methods because + * we may be interrupted by a higher priority interrupt. + */ + _Chain_Append( ts->insert_chain, &timer->Object.Node ); + } +} + +static void _Timer_server_Process_interval_watchdogs( + Timer_server_Watchdogs *watchdogs, + Chain_Control *fire_chain +) +{ + Watchdog_Interval snapshot = _Watchdog_Ticks_since_boot; + + /* + * We assume adequate unsigned arithmetic here. + */ + Watchdog_Interval delta = snapshot - watchdogs->last_snapshot; + + watchdogs->last_snapshot = snapshot; + + _Watchdog_Adjust_to_chain( &watchdogs->Chain, delta, fire_chain ); +} + +static void _Timer_server_Process_tod_watchdogs( + Timer_server_Watchdogs *watchdogs, + Chain_Control *fire_chain +) +{ + Watchdog_Interval snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch(); + Watchdog_Interval last_snapshot = watchdogs->last_snapshot; + Watchdog_Interval delta; + + /* + * Process the seconds chain. Start by checking that the Time + * of Day (TOD) has not been set backwards. If it has then + * we want to adjust the watchdogs->Chain to indicate this. + */ + if ( snapshot > last_snapshot ) { + /* + * This path is for normal forward movement and cases where the + * TOD has been set forward. + */ + delta = snapshot - last_snapshot; + _Watchdog_Adjust_to_chain( &watchdogs->Chain, delta, fire_chain ); + + } else if ( snapshot < last_snapshot ) { + /* + * The current TOD is before the last TOD which indicates that + * TOD has been set backwards. + */ + delta = last_snapshot - snapshot; + _Watchdog_Adjust( &watchdogs->Chain, WATCHDOG_BACKWARD, delta ); + } + + watchdogs->last_snapshot = snapshot; +} + +static void _Timer_server_Process_insertions( Timer_server_Control *ts ) +{ + while ( true ) { + Timer_Control *timer = (Timer_Control *) _Chain_Get( ts->insert_chain ); + + if ( timer == NULL ) { + break; + } + + _Timer_server_Insert_timer( ts, timer ); + } +} + +static void _Timer_server_Get_watchdogs_that_fire_now( + Timer_server_Control *ts, + Chain_Control *insert_chain, + Chain_Control *fire_chain +) +{ + /* + * Afterwards all timer inserts are directed to this chain and the interval + * and TOD chains will be no more modified by other parties. + */ + ts->insert_chain = insert_chain; + + while ( true ) { + ISR_Level level; + + /* + * Remove all the watchdogs that need to fire so we can invoke them. + */ + _Timer_server_Process_interval_watchdogs( + &ts->Interval_watchdogs, + fire_chain + ); + _Timer_server_Process_tod_watchdogs( &ts->TOD_watchdogs, fire_chain ); + + /* + * The insertions have to take place here, because they reference the + * current time. The previous process methods take a snapshot of the + * current time. In case someone inserts a watchdog with an initial value + * of zero it will be processed in the next iteration of the timer server + * body loop. + */ + _Timer_server_Process_insertions( ts ); + + _ISR_Disable( level ); + if ( _Chain_Is_empty( insert_chain ) ) { + ts->insert_chain = NULL; + _ISR_Enable( level ); + + break; + } else { + _ISR_Enable( level ); + } + } +} + +/** + * @brief Timer server body. + * + * This is the server for task based timers. This task executes whenever a + * task-based timer should fire. It services both "after" and "when" timers. + * It is not created automatically but must be created explicitly by the + * application before task-based timers may be initiated. The parameter + * @a arg points to the corresponding timer server control block. + */ +static rtems_task _Timer_server_Body( + rtems_task_argument arg +) +{ + Timer_server_Control *ts = (Timer_server_Control *) arg; + Chain_Control insert_chain; + Chain_Control fire_chain; + + _Chain_Initialize_empty( &insert_chain ); + _Chain_Initialize_empty( &fire_chain ); + + while ( true ) { + _Timer_server_Get_watchdogs_that_fire_now( ts, &insert_chain, &fire_chain ); + + if ( !_Chain_Is_empty( &fire_chain ) ) { + /* + * Fire the watchdogs. + */ + while ( true ) { + Watchdog_Control *watchdog; + ISR_Level level; + + /* + * It is essential that interrupts are disable here since an interrupt + * service routine may remove a watchdog from the chain. + */ + _ISR_Disable( level ); + watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &fire_chain ); + if ( watchdog != NULL ) { + watchdog->state = WATCHDOG_INACTIVE; + _ISR_Enable( level ); + } else { + _ISR_Enable( level ); + + break; + } + + /* + * The timer server may block here and wait for resources or time. + * The system watchdogs are inactive and will remain inactive since + * the active flag of the timer server is true. + */ + (*watchdog->routine)( watchdog->id, watchdog->user_data ); + } + } else { + ts->active = false; + + /* + * Block until there is something to do. + */ + _Thread_Disable_dispatch(); + _Thread_Set_state( ts->thread, STATES_DELAYING ); + _Timer_server_Reset_interval_system_watchdog( ts ); + _Timer_server_Reset_tod_system_watchdog( ts ); + _Thread_Enable_dispatch(); + + ts->active = true; + + /* + * Maybe an interrupt did reset the system timers, so we have to stop + * them here. Since we are active now, there will be no more resets + * until we are inactive again. + */ + _Timer_server_Stop_interval_system_watchdog( ts ); + _Timer_server_Stop_tod_system_watchdog( ts ); + } + } +} + +/** + * @brief rtems_timer_initiate_server + * + * This directive creates and starts the server for task-based timers. + * It must be invoked before any task-based timers can be initiated. + * + * @param[in] priority is the timer server priority + * @param[in] stack_size is the stack size in bytes + * @param[in] attribute_set is the timer server attributes + * + * @return This method returns RTEMS_SUCCESSFUL if successful and an + * error code otherwise. + */ +rtems_status_code rtems_timer_initiate_server( + uint32_t priority, + uint32_t stack_size, + rtems_attribute attribute_set +) +{ + rtems_id id; + rtems_status_code status; + rtems_task_priority _priority; + static bool initialized = false; + bool tmpInitialized; + Timer_server_Control *ts = &_Timer_server_Default; + + /* + * Make sure the requested priority is valid. The if is + * structured so we check it is invalid before looking for + * a specific invalid value as the default. + */ + _priority = priority; + if ( !_RTEMS_tasks_Priority_is_valid( priority ) ) { + if ( priority != RTEMS_TIMER_SERVER_DEFAULT_PRIORITY ) + return RTEMS_INVALID_PRIORITY; + _priority = 0; + } + + /* + * Just to make sure this is only called once. + */ + _Thread_Disable_dispatch(); + tmpInitialized = initialized; + initialized = true; + _Thread_Enable_dispatch(); + + if ( tmpInitialized ) + return RTEMS_INCORRECT_STATE; + + /* + * Create the Timer Server with the name the name of "TIME". The attribute + * RTEMS_SYSTEM_TASK allows us to set a priority to 0 which will makes it + * higher than any other task in the system. It can be viewed as a low + * priority interrupt. It is also always NO_PREEMPT so it looks like + * an interrupt to other tasks. + * + * We allow the user to override the default priority because the Timer + * Server can invoke TSRs which must adhere to language run-time or + * other library rules. For example, if using a TSR written in Ada the + * Server should run at the same priority as the priority Ada task. + * Otherwise, the priority ceiling for the mutex used to protect the + * GNAT run-time is violated. + */ + status = rtems_task_create( + _Objects_Build_name('T','I','M','E'), /* "TIME" */ + _priority, /* create with priority 1 since 0 is illegal */ + stack_size, /* let user specify stack size */ + RTEMS_NO_PREEMPT, /* no preempt is like an interrupt */ + /* user may want floating point but we need */ + /* system task specified for 0 priority */ + attribute_set | RTEMS_SYSTEM_TASK, + &id /* get the id back */ + ); + if (status) { + initialized = false; + return status; + } + + /* + * Do all the data structure initialization before starting the + * Timer Server so we do not have to have a critical section. + */ + + /* + * We work with the TCB pointer, not the ID, so we need to convert + * to a TCB pointer from here out. + */ + ts->thread = (Thread_Control *)_Objects_Get_local_object( + &_RTEMS_tasks_Information, + _Objects_Get_index(id) + ); + + /* + * Initialize the timer lists that the server will manage. + */ + _Chain_Initialize_empty( &ts->Interval_watchdogs.Chain ); + _Chain_Initialize_empty( &ts->TOD_watchdogs.Chain ); + + /* + * Initialize the timers that will be used to control when the + * Timer Server wakes up and services the task-based timers. + */ + _Watchdog_Initialize( + &ts->Interval_watchdogs.System_watchdog, + _Thread_Delay_ended, + id, + NULL + ); + _Watchdog_Initialize( + &ts->TOD_watchdogs.System_watchdog, + _Thread_Delay_ended, + id, + NULL + ); + + /* + * Initialize the pointer to the timer schedule method so applications that + * do not use the Timer Server do not have to pull it in. + */ + ts->schedule_operation = _Timer_server_Schedule_operation_method; + + ts->Interval_watchdogs.last_snapshot = _Watchdog_Ticks_since_boot; + ts->TOD_watchdogs.last_snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch(); + + ts->insert_chain = NULL; + ts->active = false; + + /* + * The default timer server is now available. + */ + _Timer_server = ts; + + /* + * Start the timer server + */ + status = rtems_task_start( + id, + _Timer_server_Body, + (rtems_task_argument) ts + ); + + #if defined(RTEMS_DEBUG) + /* + * One would expect a call to rtems_task_delete() here to clean up + * but there is actually no way (in normal circumstances) that the + * start can fail. The id and starting address are known to be + * be good. If this service fails, something is weirdly wrong on the + * target such as a stray write in an ISR or incorrect memory layout. + */ + if (status) { + initialized = false; + } + #endif + + return status; +} diff --git a/cpukit/rtems/src/timerserverfireafter.c b/cpukit/rtems/src/timerserverfireafter.c new file mode 100644 index 0000000000..a0af568865 --- /dev/null +++ b/cpukit/rtems/src/timerserverfireafter.c @@ -0,0 +1,109 @@ +/* + * Timer Manager - rtems_timer_server fire_after directive + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_server_fire_after + * + * This directive allows a thread to start a timer which will by + * executed by the Timer Server when it fires. + * + * Input parameters: + * id - timer id + * ticks - interval until routine is fired + * routine - routine to schedule + * user_data - passed as argument to routine when it is fired + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_timer_server_fire_after( + rtems_id id, + rtems_interval ticks, + rtems_timer_service_routine_entry routine, + void *user_data +) +{ + Timer_Control *the_timer; + Objects_Locations location; + ISR_Level level; + Timer_server_Control *timer_server = _Timer_server; + + if ( !timer_server ) + return RTEMS_INCORRECT_STATE; + + if ( !routine ) + return RTEMS_INVALID_ADDRESS; + + if ( ticks == 0 ) + return RTEMS_INVALID_NUMBER; + + the_timer = _Timer_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + (void) _Watchdog_Remove( &the_timer->Ticker ); + + _ISR_Disable( level ); + + /* + * Check to see if the watchdog has just been inserted by a + * higher priority interrupt. If so, abandon this insert. + */ + + if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) { + _ISR_Enable( level ); + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + } + + /* + * OK. Now we now the timer was not rescheduled by an interrupt + * so we can atomically initialize it as in use. + */ + + the_timer->the_class = TIMER_INTERVAL_ON_TASK; + _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); + the_timer->Ticker.initial = ticks; + _ISR_Enable( level ); + + (*timer_server->schedule_operation)( timer_server, the_timer ); + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/timerserverfirewhen.c b/cpukit/rtems/src/timerserverfirewhen.c new file mode 100644 index 0000000000..d5e6c472a1 --- /dev/null +++ b/cpukit/rtems/src/timerserverfirewhen.c @@ -0,0 +1,96 @@ +/* + * Timer Manager - rtems_timer_server fire_when directive + * + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/support.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/rtems/timer.h> +#include <rtems/score/tod.h> +#include <rtems/score/watchdog.h> + +/*PAGE + * + * rtems_timer_server_fire_when + * + * This directive allows a thread to start a timer which will by + * executed by the Timer Server when it fires. + * + * Input parameters: + * id - timer id + * wall_time - time of day to fire timer + * routine - routine to schedule + * user_data - passed as argument to routine when it is fired + * + * Output parameters: + * RTEMS_SUCCESSFUL - if successful + * error code - if unsuccessful + */ + +rtems_status_code rtems_timer_server_fire_when( + rtems_id id, + rtems_time_of_day *wall_time, + rtems_timer_service_routine_entry routine, + void *user_data +) +{ + Timer_Control *the_timer; + Objects_Locations location; + rtems_interval seconds; + Timer_server_Control *timer_server = _Timer_server; + + if ( !timer_server ) + return RTEMS_INCORRECT_STATE; + + if ( !_TOD_Is_set ) + return RTEMS_NOT_DEFINED; + + if ( !routine ) + return RTEMS_INVALID_ADDRESS; + + if ( !_TOD_Validate( wall_time ) ) + return RTEMS_INVALID_CLOCK; + + seconds = _TOD_To_seconds( wall_time ); + if ( seconds <= _TOD_Seconds_since_epoch() ) + return RTEMS_INVALID_CLOCK; + + the_timer = _Timer_Get( id, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + (void) _Watchdog_Remove( &the_timer->Ticker ); + the_timer->the_class = TIMER_TIME_OF_DAY_ON_TASK; + _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); + the_timer->Ticker.initial = seconds - _TOD_Seconds_since_epoch(); + + (*timer_server->schedule_operation)( timer_server, the_timer ); + + _Thread_Enable_dispatch(); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} diff --git a/cpukit/rtems/src/workspace.c b/cpukit/rtems/src/workspace.c new file mode 100644 index 0000000000..e6394aca86 --- /dev/null +++ b/cpukit/rtems/src/workspace.c @@ -0,0 +1,75 @@ +/* + * Workspace Handler + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/wkspace.h> +#include <rtems/score/protectedheap.h> +#include <rtems/score/interr.h> +#include <rtems/config.h> + +#include <string.h> /* for memset */ + +bool rtems_workspace_get_information( + Heap_Information_block *the_info +) +{ + if ( !the_info ) + return false; + + return _Protected_heap_Get_information( &_Workspace_Area, the_info ); +} + +/* + * _Workspace_Allocate + */ +bool rtems_workspace_allocate( + uintptr_t bytes, + void **pointer +) +{ + void *ptr; + + /* + * check the arguments + */ + if ( !pointer ) + return false; + + if ( !bytes ) + return false; + + /* + * Allocate the memory + */ + ptr = _Protected_heap_Allocate( &_Workspace_Area, (intptr_t) bytes ); + if (!ptr) + return false; + + *pointer = ptr; + return true; +} + +/* + * _Workspace_Allocate + */ +bool rtems_workspace_free( + void *pointer +) +{ + return _Protected_heap_Free( &_Workspace_Area, pointer ); +} + |