forked from Imagelibrary/rtems
Split Heap and Time of Day Handlers.
This commit is contained in:
@@ -22,6 +22,9 @@ INSTALL_CHANGE = @INSTALL_CHANGE@
|
||||
MP_C_PIECES_yes_V = mpci objectmp threadmp
|
||||
MP_C_PIECES = $(MP_C_PIECES_$(HAS_MP)_V)
|
||||
|
||||
HEAP_C_PIECES = heap heapallocate heapextend heapfree \
|
||||
heapsizeofuserarea heapwalk
|
||||
|
||||
OBJECT_C_PIECES = object objectallocate objectallocatebyindex \
|
||||
objectclearname objectcomparenameraw objectcomparenamestring \
|
||||
objectcopynameraw objectcopynamestring objectextendinformation \
|
||||
@@ -42,9 +45,13 @@ THREADQ_C_PIECES= threadq threadqdequeue threadqdequeuefifo \
|
||||
threadqextractpriority threadqextractwithproxy threadqfirst \
|
||||
threadqfirstfifo threadqfirstpriority threadqflush threadqtimeout
|
||||
|
||||
TOD_C_PIECES= coretod coretodset coretodtickle coretodtoseconds \
|
||||
coretodvalidate
|
||||
|
||||
# C and C++ source names, if any, go here -- minus the .c or .cc
|
||||
C_PIECES = apiext chain coremsg coremutex coresem coretod heap interr isr \
|
||||
$(OBJECT_C_PIECES) $(THREAD_C_PIECES) $(THREADQ_C_PIECES) userext \
|
||||
C_PIECES = apiext chain coremsg coremutex coresem $(HEAP_C_PIECES) interr isr \
|
||||
$(OBJECT_C_PIECES) $(THREAD_C_PIECES) $(THREADQ_C_PIECES) \
|
||||
$(TOD_C_PIECES) userext \
|
||||
watchdog wkspace $(MP_C_PIECES)
|
||||
C_FILES = $(C_PIECES:%=%.c)
|
||||
C_O_FILES = $(C_PIECES:%=${ARCH}/%.o)
|
||||
|
||||
@@ -58,181 +58,3 @@ void _TOD_Handler_initialization(
|
||||
_TOD_Is_set = FALSE;
|
||||
_TOD_Activate( _TOD_Ticks_per_second );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _TOD_Set
|
||||
*
|
||||
* This rountine sets the current date and time with the specified
|
||||
* new date and time structure.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_tod - pointer to the time and date structure
|
||||
* seconds_since_epoch - seconds since system epoch
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
void _TOD_Set(
|
||||
TOD_Control *the_tod,
|
||||
Watchdog_Interval seconds_since_epoch
|
||||
)
|
||||
{
|
||||
Watchdog_Interval ticks_until_next_second;
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
_TOD_Deactivate();
|
||||
|
||||
if ( seconds_since_epoch < _TOD_Seconds_since_epoch )
|
||||
_Watchdog_Adjust_seconds( WATCHDOG_BACKWARD,
|
||||
_TOD_Seconds_since_epoch - seconds_since_epoch );
|
||||
else
|
||||
_Watchdog_Adjust_seconds( WATCHDOG_FORWARD,
|
||||
seconds_since_epoch - _TOD_Seconds_since_epoch );
|
||||
|
||||
ticks_until_next_second = _TOD_Ticks_per_second;
|
||||
if ( ticks_until_next_second > _TOD_Current.ticks )
|
||||
ticks_until_next_second -= _TOD_Current.ticks;
|
||||
|
||||
_TOD_Current = *the_tod;
|
||||
_TOD_Seconds_since_epoch = seconds_since_epoch;
|
||||
_TOD_Is_set = TRUE;
|
||||
_TOD_Activate( ticks_until_next_second );
|
||||
|
||||
_Thread_Enable_dispatch();
|
||||
}
|
||||
|
||||
/*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.
|
||||
*/
|
||||
|
||||
boolean _TOD_Validate(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 days_in_month;
|
||||
|
||||
if ((the_tod->ticks >= _TOD_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;
|
||||
}
|
||||
|
||||
/*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
|
||||
*/
|
||||
|
||||
unsigned32 _TOD_To_seconds(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 time;
|
||||
unsigned32 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;
|
||||
|
||||
return( time );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _TOD_Tickle
|
||||
*
|
||||
* This routine updates the calendar time and tickles the
|
||||
* per second watchdog timer chain.
|
||||
*
|
||||
* Input parameters:
|
||||
* ignored - this parameter is ignored
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* NOTE: This routine only works for leap-years through 2099.
|
||||
*/
|
||||
|
||||
void _TOD_Tickle(
|
||||
Objects_Id id,
|
||||
void *ignored
|
||||
)
|
||||
{
|
||||
unsigned32 leap;
|
||||
|
||||
_TOD_Current.ticks = 0;
|
||||
++_TOD_Seconds_since_epoch;
|
||||
if ( ++_TOD_Current.second >= TOD_SECONDS_PER_MINUTE ) {
|
||||
_TOD_Current.second = 0;
|
||||
if ( ++_TOD_Current.minute >= TOD_MINUTES_PER_HOUR ) {
|
||||
_TOD_Current.minute = 0;
|
||||
if ( ++_TOD_Current.hour >= TOD_HOURS_PER_DAY ) {
|
||||
_TOD_Current.hour = 0;
|
||||
if ( _TOD_Current.year & 0x3 ) leap = 0;
|
||||
else leap = 1;
|
||||
if ( ++_TOD_Current.day >
|
||||
_TOD_Days_per_month[ leap ][ _TOD_Current.month ]) {
|
||||
_TOD_Current.day = 1;
|
||||
if ( ++_TOD_Current.month > TOD_MONTHS_PER_YEAR ) {
|
||||
_TOD_Current.month = 1;
|
||||
_TOD_Current.year++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_Watchdog_Tickle_seconds();
|
||||
_Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, _TOD_Ticks_per_second );
|
||||
}
|
||||
|
||||
64
c/src/exec/score/src/coretodset.c
Normal file
64
c/src/exec/score/src/coretodset.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _TOD_Set
|
||||
*
|
||||
* This rountine sets the current date and time with the specified
|
||||
* new date and time structure.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_tod - pointer to the time and date structure
|
||||
* seconds_since_epoch - seconds since system epoch
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
void _TOD_Set(
|
||||
TOD_Control *the_tod,
|
||||
Watchdog_Interval seconds_since_epoch
|
||||
)
|
||||
{
|
||||
Watchdog_Interval ticks_until_next_second;
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
_TOD_Deactivate();
|
||||
|
||||
if ( seconds_since_epoch < _TOD_Seconds_since_epoch )
|
||||
_Watchdog_Adjust_seconds( WATCHDOG_BACKWARD,
|
||||
_TOD_Seconds_since_epoch - seconds_since_epoch );
|
||||
else
|
||||
_Watchdog_Adjust_seconds( WATCHDOG_FORWARD,
|
||||
seconds_since_epoch - _TOD_Seconds_since_epoch );
|
||||
|
||||
ticks_until_next_second = _TOD_Ticks_per_second;
|
||||
if ( ticks_until_next_second > _TOD_Current.ticks )
|
||||
ticks_until_next_second -= _TOD_Current.ticks;
|
||||
|
||||
_TOD_Current = *the_tod;
|
||||
_TOD_Seconds_since_epoch = seconds_since_epoch;
|
||||
_TOD_Is_set = TRUE;
|
||||
_TOD_Activate( ticks_until_next_second );
|
||||
|
||||
_Thread_Enable_dispatch();
|
||||
}
|
||||
|
||||
68
c/src/exec/score/src/coretodtickle.c
Normal file
68
c/src/exec/score/src/coretodtickle.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _TOD_Tickle
|
||||
*
|
||||
* This routine updates the calendar time and tickles the
|
||||
* per second watchdog timer chain.
|
||||
*
|
||||
* Input parameters:
|
||||
* ignored - this parameter is ignored
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* NOTE: This routine only works for leap-years through 2099.
|
||||
*/
|
||||
|
||||
void _TOD_Tickle(
|
||||
Objects_Id id,
|
||||
void *ignored
|
||||
)
|
||||
{
|
||||
unsigned32 leap;
|
||||
|
||||
_TOD_Current.ticks = 0;
|
||||
++_TOD_Seconds_since_epoch;
|
||||
if ( ++_TOD_Current.second >= TOD_SECONDS_PER_MINUTE ) {
|
||||
_TOD_Current.second = 0;
|
||||
if ( ++_TOD_Current.minute >= TOD_MINUTES_PER_HOUR ) {
|
||||
_TOD_Current.minute = 0;
|
||||
if ( ++_TOD_Current.hour >= TOD_HOURS_PER_DAY ) {
|
||||
_TOD_Current.hour = 0;
|
||||
if ( _TOD_Current.year & 0x3 ) leap = 0;
|
||||
else leap = 1;
|
||||
if ( ++_TOD_Current.day >
|
||||
_TOD_Days_per_month[ leap ][ _TOD_Current.month ]) {
|
||||
_TOD_Current.day = 1;
|
||||
if ( ++_TOD_Current.month > TOD_MONTHS_PER_YEAR ) {
|
||||
_TOD_Current.month = 1;
|
||||
_TOD_Current.year++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_Watchdog_Tickle_seconds();
|
||||
_Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, _TOD_Ticks_per_second );
|
||||
}
|
||||
65
c/src/exec/score/src/coretodtoseconds.c
Normal file
65
c/src/exec/score/src/coretodtoseconds.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*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
|
||||
*/
|
||||
|
||||
unsigned32 _TOD_To_seconds(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 time;
|
||||
unsigned32 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;
|
||||
|
||||
return( time );
|
||||
}
|
||||
|
||||
64
c/src/exec/score/src/coretodvalidate.c
Normal file
64
c/src/exec/score/src/coretodvalidate.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*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.
|
||||
*/
|
||||
|
||||
boolean _TOD_Validate(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 days_in_month;
|
||||
|
||||
if ((the_tod->ticks >= _TOD_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;
|
||||
}
|
||||
|
||||
@@ -92,447 +92,3 @@ unsigned32 _Heap_Initialize(
|
||||
return ( the_size - HEAP_BLOCK_USED_OVERHEAD );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Extend
|
||||
*
|
||||
* This routine grows the_heap memory area using the size bytes which
|
||||
* begin at starting_address.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header.
|
||||
* starting_address - pointer to the memory area.
|
||||
* size - size in bytes of the memory block to allocate.
|
||||
*
|
||||
* Output parameters:
|
||||
* *amount_extended - amount of memory added to the_heap
|
||||
*/
|
||||
|
||||
Heap_Extend_status _Heap_Extend(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address,
|
||||
unsigned32 size,
|
||||
unsigned32 *amount_extended
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
unsigned32 *p;
|
||||
|
||||
/*
|
||||
* The overhead was taken from the original heap memory.
|
||||
*/
|
||||
|
||||
Heap_Block *old_final;
|
||||
Heap_Block *new_final;
|
||||
|
||||
/*
|
||||
* There are five possibilities for the location of starting
|
||||
* address:
|
||||
*
|
||||
* 1. non-contiguous lower address (NOT SUPPORTED)
|
||||
* 2. contiguous lower address (NOT SUPPORTED)
|
||||
* 3. in the heap (ERROR)
|
||||
* 4. contiguous higher address (SUPPORTED)
|
||||
* 5. non-contiguous higher address (NOT SUPPORTED)
|
||||
*
|
||||
* As noted, this code only supports (4).
|
||||
*/
|
||||
|
||||
if ( starting_address >= (void *) the_heap->start && /* case 3 */
|
||||
starting_address <= (void *) the_heap->final
|
||||
)
|
||||
return HEAP_EXTEND_ERROR;
|
||||
|
||||
if ( starting_address < (void *) the_heap->start ) { /* cases 1 and 2 */
|
||||
|
||||
return HEAP_EXTEND_NOT_IMPLEMENTED; /* cases 1 and 2 */
|
||||
|
||||
} else { /* cases 4 and 5 */
|
||||
|
||||
the_block = (Heap_Block *)
|
||||
_Addresses_Subtract_offset( starting_address, HEAP_OVERHEAD );
|
||||
if ( the_block != the_heap->final )
|
||||
return HEAP_EXTEND_NOT_IMPLEMENTED; /* case 5 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently only case 4 should make it to this point.
|
||||
* The basic trick is to make the extend area look like a used
|
||||
* block and free it.
|
||||
*/
|
||||
|
||||
*amount_extended = size;
|
||||
|
||||
old_final = the_heap->final;
|
||||
new_final = _Addresses_Add_offset( old_final, size );
|
||||
/* SAME AS: _Addresses_Add_offset( starting_address, size-HEAP_OVERHEAD ); */
|
||||
|
||||
the_heap->final = new_final;
|
||||
|
||||
old_final->front_flag =
|
||||
new_final->back_flag = _Heap_Build_flag( size, HEAP_BLOCK_USED );
|
||||
new_final->front_flag = HEAP_DUMMY_FLAG;
|
||||
|
||||
/*
|
||||
* Must pass in address of "user" area
|
||||
* So add in the offset field.
|
||||
*/
|
||||
|
||||
p = (unsigned32 *) &old_final->next;
|
||||
*p = sizeof(unsigned32);
|
||||
p++;
|
||||
_Heap_Free( the_heap, p );
|
||||
|
||||
return HEAP_EXTEND_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Allocate
|
||||
*
|
||||
* This kernel routine allocates the requested size of memory
|
||||
* from the specified heap.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header.
|
||||
* size - size in bytes of the memory block to allocate.
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - starting address of memory block allocated
|
||||
*/
|
||||
|
||||
void *_Heap_Allocate(
|
||||
Heap_Control *the_heap,
|
||||
unsigned32 size
|
||||
)
|
||||
{
|
||||
unsigned32 excess;
|
||||
unsigned32 the_size;
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
Heap_Block *temporary_block;
|
||||
void *ptr;
|
||||
unsigned32 offset;
|
||||
|
||||
excess = size % the_heap->page_size;
|
||||
the_size = size + the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD;
|
||||
|
||||
if ( excess )
|
||||
the_size += the_heap->page_size - excess;
|
||||
|
||||
if ( the_size < sizeof( Heap_Block ) )
|
||||
the_size = sizeof( Heap_Block );
|
||||
|
||||
for ( the_block = the_heap->first;
|
||||
;
|
||||
the_block = the_block->next ) {
|
||||
if ( the_block == _Heap_Tail( the_heap ) )
|
||||
return( NULL );
|
||||
if ( the_block->front_flag >= the_size )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (the_block->front_flag - the_size) >
|
||||
(the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD) ) {
|
||||
the_block->front_flag -= the_size;
|
||||
next_block = _Heap_Next_block( the_block );
|
||||
next_block->back_flag = the_block->front_flag;
|
||||
|
||||
temporary_block = _Heap_Block_at( next_block, the_size );
|
||||
temporary_block->back_flag =
|
||||
next_block->front_flag = _Heap_Build_flag( the_size,
|
||||
HEAP_BLOCK_USED );
|
||||
ptr = _Heap_Start_of_user_area( next_block );
|
||||
} else {
|
||||
next_block = _Heap_Next_block( the_block );
|
||||
next_block->back_flag = _Heap_Build_flag( the_block->front_flag,
|
||||
HEAP_BLOCK_USED );
|
||||
the_block->front_flag = next_block->back_flag;
|
||||
the_block->next->previous = the_block->previous;
|
||||
the_block->previous->next = the_block->next;
|
||||
ptr = _Heap_Start_of_user_area( the_block );
|
||||
}
|
||||
|
||||
/*
|
||||
* round ptr up to a multiple of page size
|
||||
* Have to save the bump amount in the buffer so that free can figure it out
|
||||
*/
|
||||
|
||||
offset = the_heap->page_size - (((unsigned32) ptr) & (the_heap->page_size - 1));
|
||||
ptr = _Addresses_Add_offset( ptr, offset );
|
||||
*(((unsigned32 *) ptr) - 1) = offset;
|
||||
|
||||
#ifdef RTEMS_DEBUG
|
||||
{
|
||||
unsigned32 ptr_u32;
|
||||
ptr_u32 = (unsigned32) ptr;
|
||||
if (ptr_u32 & (the_heap->page_size - 1))
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Size_of_user_area
|
||||
*
|
||||
* This kernel routine returns the size of the memory area
|
||||
* given heap block.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* starting_address - starting address of the memory block to free.
|
||||
* size - pointer to size of area
|
||||
*
|
||||
* Output parameters:
|
||||
* size - size of area filled in
|
||||
* TRUE - if starting_address is valid heap address
|
||||
* FALSE - if starting_address is invalid heap address
|
||||
*/
|
||||
|
||||
boolean _Heap_Size_of_user_area(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address,
|
||||
unsigned32 *size
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
unsigned32 the_size;
|
||||
|
||||
the_block = _Heap_User_block_at( starting_address );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, the_block ) ||
|
||||
_Heap_Is_block_free( the_block ) )
|
||||
return( FALSE );
|
||||
|
||||
the_size = _Heap_Block_size( the_block );
|
||||
next_block = _Heap_Block_at( the_block, the_size );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, next_block ) ||
|
||||
(the_block->front_flag != next_block->back_flag) )
|
||||
return( FALSE );
|
||||
|
||||
*size = the_size;
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Free
|
||||
*
|
||||
* This kernel routine returns the memory designated by the
|
||||
* given heap and given starting address to the memory pool.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* starting_address - starting address of the memory block to free.
|
||||
*
|
||||
* Output parameters:
|
||||
* TRUE - if starting_address is valid heap address
|
||||
* FALSE - if starting_address is invalid heap address
|
||||
*/
|
||||
|
||||
boolean _Heap_Free(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
Heap_Block *new_next_block;
|
||||
Heap_Block *previous_block;
|
||||
Heap_Block *temporary_block;
|
||||
unsigned32 the_size;
|
||||
|
||||
the_block = _Heap_User_block_at( starting_address );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, the_block ) ||
|
||||
_Heap_Is_block_free( the_block ) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
the_size = _Heap_Block_size( the_block );
|
||||
next_block = _Heap_Block_at( the_block, the_size );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, next_block ) ||
|
||||
(the_block->front_flag != next_block->back_flag) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( _Heap_Is_previous_block_free( the_block ) ) {
|
||||
previous_block = _Heap_Previous_block( the_block );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, previous_block ) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( _Heap_Is_block_free( next_block ) ) { /* coalesce both */
|
||||
previous_block->front_flag += next_block->front_flag + the_size;
|
||||
temporary_block = _Heap_Next_block( previous_block );
|
||||
temporary_block->back_flag = previous_block->front_flag;
|
||||
next_block->next->previous = next_block->previous;
|
||||
next_block->previous->next = next_block->next;
|
||||
}
|
||||
else { /* coalesce prev */
|
||||
previous_block->front_flag =
|
||||
next_block->back_flag = previous_block->front_flag + the_size;
|
||||
}
|
||||
}
|
||||
else if ( _Heap_Is_block_free( next_block ) ) { /* coalesce next */
|
||||
the_block->front_flag = the_size + next_block->front_flag;
|
||||
new_next_block = _Heap_Next_block( the_block );
|
||||
new_next_block->back_flag = the_block->front_flag;
|
||||
the_block->next = next_block->next;
|
||||
the_block->previous = next_block->previous;
|
||||
next_block->previous->next = the_block;
|
||||
next_block->next->previous = the_block;
|
||||
|
||||
if (the_heap->first == next_block)
|
||||
the_heap->first = the_block;
|
||||
}
|
||||
else { /* no coalesce */
|
||||
next_block->back_flag =
|
||||
the_block->front_flag = the_size;
|
||||
the_block->previous = _Heap_Head( the_heap );
|
||||
the_block->next = the_heap->first;
|
||||
the_heap->first = the_block;
|
||||
the_block->next->previous = the_block;
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Walk
|
||||
*
|
||||
* This kernel routine walks the heap and verifies its correctness.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* source - a numeric indicator of the invoker of this routine
|
||||
* do_dump - when TRUE print the information
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
#ifndef RTEMS_DEBUG
|
||||
|
||||
void _Heap_Walk(
|
||||
Heap_Control *the_heap,
|
||||
int source,
|
||||
boolean do_dump
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void _Heap_Walk(
|
||||
Heap_Control *the_heap,
|
||||
int source,
|
||||
boolean do_dump
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block = 0; /* avoid warnings */
|
||||
Heap_Block *next_block = 0; /* avoid warnings */
|
||||
int notdone = 1;
|
||||
int error = 0;
|
||||
int passes = 0;
|
||||
|
||||
/*
|
||||
* We don't want to allow walking the heap until we have
|
||||
* transferred control to the user task so we watch the
|
||||
* system state.
|
||||
*/
|
||||
|
||||
if ( !_System_state_Is_up( _System_state_Get() ) )
|
||||
return;
|
||||
|
||||
the_block = the_heap->start;
|
||||
|
||||
if (do_dump == TRUE) {
|
||||
printf("\nPASS: %d start @ 0x%p final 0x%p, first 0x%p last 0x%p\n",
|
||||
source, the_heap->start, the_heap->final,
|
||||
the_heap->first, the_heap->last
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the 1st block
|
||||
*/
|
||||
|
||||
if (the_block->back_flag != HEAP_DUMMY_FLAG) {
|
||||
printf("PASS: %d Back flag of 1st block isn't HEAP_DUMMY_FLAG\n", source);
|
||||
error = 1;
|
||||
}
|
||||
|
||||
while (notdone) {
|
||||
passes++;
|
||||
if (error && (passes > 10))
|
||||
abort();
|
||||
|
||||
if (do_dump == TRUE) {
|
||||
printf("PASS: %d Block @ 0x%p Back %d, Front %d",
|
||||
source, the_block,
|
||||
the_block->back_flag, the_block->front_flag);
|
||||
if ( _Heap_Is_block_free(the_block) ) {
|
||||
printf( " Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the last block
|
||||
*/
|
||||
|
||||
if ( the_block->front_flag != HEAP_DUMMY_FLAG ) {
|
||||
next_block = _Heap_Next_block(the_block);
|
||||
if ( the_block->front_flag != next_block->back_flag ) {
|
||||
error = 1;
|
||||
printf("PASS: %d Front and back flags don't match\n", source);
|
||||
printf(" Current Block (%p): Back - %d, Front - %d",
|
||||
the_block, the_block->back_flag, the_block->front_flag);
|
||||
if (do_dump == TRUE) {
|
||||
if (_Heap_Is_block_free(the_block)) {
|
||||
printf(" Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
printf(" Next Block (%p): Back - %d, Front - %d",
|
||||
next_block, next_block->back_flag, next_block->front_flag);
|
||||
if (do_dump == TRUE) {
|
||||
if (_Heap_Is_block_free(next_block)) {
|
||||
printf(" Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (the_block->front_flag == HEAP_DUMMY_FLAG)
|
||||
notdone = 0;
|
||||
else
|
||||
the_block = next_block;
|
||||
}
|
||||
|
||||
if (error)
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
107
c/src/exec/score/src/heapallocate.c
Normal file
107
c/src/exec/score/src/heapallocate.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Allocate
|
||||
*
|
||||
* This kernel routine allocates the requested size of memory
|
||||
* from the specified heap.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header.
|
||||
* size - size in bytes of the memory block to allocate.
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - starting address of memory block allocated
|
||||
*/
|
||||
|
||||
void *_Heap_Allocate(
|
||||
Heap_Control *the_heap,
|
||||
unsigned32 size
|
||||
)
|
||||
{
|
||||
unsigned32 excess;
|
||||
unsigned32 the_size;
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
Heap_Block *temporary_block;
|
||||
void *ptr;
|
||||
unsigned32 offset;
|
||||
|
||||
excess = size % the_heap->page_size;
|
||||
the_size = size + the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD;
|
||||
|
||||
if ( excess )
|
||||
the_size += the_heap->page_size - excess;
|
||||
|
||||
if ( the_size < sizeof( Heap_Block ) )
|
||||
the_size = sizeof( Heap_Block );
|
||||
|
||||
for ( the_block = the_heap->first;
|
||||
;
|
||||
the_block = the_block->next ) {
|
||||
if ( the_block == _Heap_Tail( the_heap ) )
|
||||
return( NULL );
|
||||
if ( the_block->front_flag >= the_size )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (the_block->front_flag - the_size) >
|
||||
(the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD) ) {
|
||||
the_block->front_flag -= the_size;
|
||||
next_block = _Heap_Next_block( the_block );
|
||||
next_block->back_flag = the_block->front_flag;
|
||||
|
||||
temporary_block = _Heap_Block_at( next_block, the_size );
|
||||
temporary_block->back_flag =
|
||||
next_block->front_flag = _Heap_Build_flag( the_size,
|
||||
HEAP_BLOCK_USED );
|
||||
ptr = _Heap_Start_of_user_area( next_block );
|
||||
} else {
|
||||
next_block = _Heap_Next_block( the_block );
|
||||
next_block->back_flag = _Heap_Build_flag( the_block->front_flag,
|
||||
HEAP_BLOCK_USED );
|
||||
the_block->front_flag = next_block->back_flag;
|
||||
the_block->next->previous = the_block->previous;
|
||||
the_block->previous->next = the_block->next;
|
||||
ptr = _Heap_Start_of_user_area( the_block );
|
||||
}
|
||||
|
||||
/*
|
||||
* round ptr up to a multiple of page size
|
||||
* Have to save the bump amount in the buffer so that free can figure it out
|
||||
*/
|
||||
|
||||
offset = the_heap->page_size - (((unsigned32) ptr) & (the_heap->page_size - 1));
|
||||
ptr = _Addresses_Add_offset( ptr, offset );
|
||||
*(((unsigned32 *) ptr) - 1) = offset;
|
||||
|
||||
#ifdef RTEMS_DEBUG
|
||||
{
|
||||
unsigned32 ptr_u32;
|
||||
ptr_u32 = (unsigned32) ptr;
|
||||
if (ptr_u32 & (the_heap->page_size - 1))
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
113
c/src/exec/score/src/heapextend.c
Normal file
113
c/src/exec/score/src/heapextend.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Extend
|
||||
*
|
||||
* This routine grows the_heap memory area using the size bytes which
|
||||
* begin at starting_address.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header.
|
||||
* starting_address - pointer to the memory area.
|
||||
* size - size in bytes of the memory block to allocate.
|
||||
*
|
||||
* Output parameters:
|
||||
* *amount_extended - amount of memory added to the_heap
|
||||
*/
|
||||
|
||||
Heap_Extend_status _Heap_Extend(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address,
|
||||
unsigned32 size,
|
||||
unsigned32 *amount_extended
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
unsigned32 *p;
|
||||
|
||||
/*
|
||||
* The overhead was taken from the original heap memory.
|
||||
*/
|
||||
|
||||
Heap_Block *old_final;
|
||||
Heap_Block *new_final;
|
||||
|
||||
/*
|
||||
* There are five possibilities for the location of starting
|
||||
* address:
|
||||
*
|
||||
* 1. non-contiguous lower address (NOT SUPPORTED)
|
||||
* 2. contiguous lower address (NOT SUPPORTED)
|
||||
* 3. in the heap (ERROR)
|
||||
* 4. contiguous higher address (SUPPORTED)
|
||||
* 5. non-contiguous higher address (NOT SUPPORTED)
|
||||
*
|
||||
* As noted, this code only supports (4).
|
||||
*/
|
||||
|
||||
if ( starting_address >= (void *) the_heap->start && /* case 3 */
|
||||
starting_address <= (void *) the_heap->final
|
||||
)
|
||||
return HEAP_EXTEND_ERROR;
|
||||
|
||||
if ( starting_address < (void *) the_heap->start ) { /* cases 1 and 2 */
|
||||
|
||||
return HEAP_EXTEND_NOT_IMPLEMENTED; /* cases 1 and 2 */
|
||||
|
||||
} else { /* cases 4 and 5 */
|
||||
|
||||
the_block = (Heap_Block *)
|
||||
_Addresses_Subtract_offset( starting_address, HEAP_OVERHEAD );
|
||||
if ( the_block != the_heap->final )
|
||||
return HEAP_EXTEND_NOT_IMPLEMENTED; /* case 5 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently only case 4 should make it to this point.
|
||||
* The basic trick is to make the extend area look like a used
|
||||
* block and free it.
|
||||
*/
|
||||
|
||||
*amount_extended = size;
|
||||
|
||||
old_final = the_heap->final;
|
||||
new_final = _Addresses_Add_offset( old_final, size );
|
||||
/* SAME AS: _Addresses_Add_offset( starting_address, size-HEAP_OVERHEAD ); */
|
||||
|
||||
the_heap->final = new_final;
|
||||
|
||||
old_final->front_flag =
|
||||
new_final->back_flag = _Heap_Build_flag( size, HEAP_BLOCK_USED );
|
||||
new_final->front_flag = HEAP_DUMMY_FLAG;
|
||||
|
||||
/*
|
||||
* Must pass in address of "user" area
|
||||
* So add in the offset field.
|
||||
*/
|
||||
|
||||
p = (unsigned32 *) &old_final->next;
|
||||
*p = sizeof(unsigned32);
|
||||
p++;
|
||||
_Heap_Free( the_heap, p );
|
||||
|
||||
return HEAP_EXTEND_SUCCESSFUL;
|
||||
}
|
||||
|
||||
105
c/src/exec/score/src/heapfree.c
Normal file
105
c/src/exec/score/src/heapfree.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Free
|
||||
*
|
||||
* This kernel routine returns the memory designated by the
|
||||
* given heap and given starting address to the memory pool.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* starting_address - starting address of the memory block to free.
|
||||
*
|
||||
* Output parameters:
|
||||
* TRUE - if starting_address is valid heap address
|
||||
* FALSE - if starting_address is invalid heap address
|
||||
*/
|
||||
|
||||
boolean _Heap_Free(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
Heap_Block *new_next_block;
|
||||
Heap_Block *previous_block;
|
||||
Heap_Block *temporary_block;
|
||||
unsigned32 the_size;
|
||||
|
||||
the_block = _Heap_User_block_at( starting_address );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, the_block ) ||
|
||||
_Heap_Is_block_free( the_block ) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
the_size = _Heap_Block_size( the_block );
|
||||
next_block = _Heap_Block_at( the_block, the_size );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, next_block ) ||
|
||||
(the_block->front_flag != next_block->back_flag) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( _Heap_Is_previous_block_free( the_block ) ) {
|
||||
previous_block = _Heap_Previous_block( the_block );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, previous_block ) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( _Heap_Is_block_free( next_block ) ) { /* coalesce both */
|
||||
previous_block->front_flag += next_block->front_flag + the_size;
|
||||
temporary_block = _Heap_Next_block( previous_block );
|
||||
temporary_block->back_flag = previous_block->front_flag;
|
||||
next_block->next->previous = next_block->previous;
|
||||
next_block->previous->next = next_block->next;
|
||||
}
|
||||
else { /* coalesce prev */
|
||||
previous_block->front_flag =
|
||||
next_block->back_flag = previous_block->front_flag + the_size;
|
||||
}
|
||||
}
|
||||
else if ( _Heap_Is_block_free( next_block ) ) { /* coalesce next */
|
||||
the_block->front_flag = the_size + next_block->front_flag;
|
||||
new_next_block = _Heap_Next_block( the_block );
|
||||
new_next_block->back_flag = the_block->front_flag;
|
||||
the_block->next = next_block->next;
|
||||
the_block->previous = next_block->previous;
|
||||
next_block->previous->next = the_block;
|
||||
next_block->next->previous = the_block;
|
||||
|
||||
if (the_heap->first == next_block)
|
||||
the_heap->first = the_block;
|
||||
}
|
||||
else { /* no coalesce */
|
||||
next_block->back_flag =
|
||||
the_block->front_flag = the_size;
|
||||
the_block->previous = _Heap_Head( the_heap );
|
||||
the_block->next = the_heap->first;
|
||||
the_heap->first = the_block;
|
||||
the_block->next->previous = the_block;
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
64
c/src/exec/score/src/heapsizeofuserarea.c
Normal file
64
c/src/exec/score/src/heapsizeofuserarea.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Size_of_user_area
|
||||
*
|
||||
* This kernel routine returns the size of the memory area
|
||||
* given heap block.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* starting_address - starting address of the memory block to free.
|
||||
* size - pointer to size of area
|
||||
*
|
||||
* Output parameters:
|
||||
* size - size of area filled in
|
||||
* TRUE - if starting_address is valid heap address
|
||||
* FALSE - if starting_address is invalid heap address
|
||||
*/
|
||||
|
||||
boolean _Heap_Size_of_user_area(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address,
|
||||
unsigned32 *size
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
unsigned32 the_size;
|
||||
|
||||
the_block = _Heap_User_block_at( starting_address );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, the_block ) ||
|
||||
_Heap_Is_block_free( the_block ) )
|
||||
return( FALSE );
|
||||
|
||||
the_size = _Heap_Block_size( the_block );
|
||||
next_block = _Heap_Block_at( the_block, the_size );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, next_block ) ||
|
||||
(the_block->front_flag != next_block->back_flag) )
|
||||
return( FALSE );
|
||||
|
||||
*size = the_size;
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
150
c/src/exec/score/src/heapwalk.c
Normal file
150
c/src/exec/score/src/heapwalk.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Walk
|
||||
*
|
||||
* This kernel routine walks the heap and verifies its correctness.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* source - a numeric indicator of the invoker of this routine
|
||||
* do_dump - when TRUE print the information
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
#ifndef RTEMS_DEBUG
|
||||
|
||||
void _Heap_Walk(
|
||||
Heap_Control *the_heap,
|
||||
int source,
|
||||
boolean do_dump
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void _Heap_Walk(
|
||||
Heap_Control *the_heap,
|
||||
int source,
|
||||
boolean do_dump
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block = 0; /* avoid warnings */
|
||||
Heap_Block *next_block = 0; /* avoid warnings */
|
||||
int notdone = 1;
|
||||
int error = 0;
|
||||
int passes = 0;
|
||||
|
||||
/*
|
||||
* We don't want to allow walking the heap until we have
|
||||
* transferred control to the user task so we watch the
|
||||
* system state.
|
||||
*/
|
||||
|
||||
if ( !_System_state_Is_up( _System_state_Get() ) )
|
||||
return;
|
||||
|
||||
the_block = the_heap->start;
|
||||
|
||||
if (do_dump == TRUE) {
|
||||
printf("\nPASS: %d start @ 0x%p final 0x%p, first 0x%p last 0x%p\n",
|
||||
source, the_heap->start, the_heap->final,
|
||||
the_heap->first, the_heap->last
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the 1st block
|
||||
*/
|
||||
|
||||
if (the_block->back_flag != HEAP_DUMMY_FLAG) {
|
||||
printf("PASS: %d Back flag of 1st block isn't HEAP_DUMMY_FLAG\n", source);
|
||||
error = 1;
|
||||
}
|
||||
|
||||
while (notdone) {
|
||||
passes++;
|
||||
if (error && (passes > 10))
|
||||
abort();
|
||||
|
||||
if (do_dump == TRUE) {
|
||||
printf("PASS: %d Block @ 0x%p Back %d, Front %d",
|
||||
source, the_block,
|
||||
the_block->back_flag, the_block->front_flag);
|
||||
if ( _Heap_Is_block_free(the_block) ) {
|
||||
printf( " Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the last block
|
||||
*/
|
||||
|
||||
if ( the_block->front_flag != HEAP_DUMMY_FLAG ) {
|
||||
next_block = _Heap_Next_block(the_block);
|
||||
if ( the_block->front_flag != next_block->back_flag ) {
|
||||
error = 1;
|
||||
printf("PASS: %d Front and back flags don't match\n", source);
|
||||
printf(" Current Block (%p): Back - %d, Front - %d",
|
||||
the_block, the_block->back_flag, the_block->front_flag);
|
||||
if (do_dump == TRUE) {
|
||||
if (_Heap_Is_block_free(the_block)) {
|
||||
printf(" Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
printf(" Next Block (%p): Back - %d, Front - %d",
|
||||
next_block, next_block->back_flag, next_block->front_flag);
|
||||
if (do_dump == TRUE) {
|
||||
if (_Heap_Is_block_free(next_block)) {
|
||||
printf(" Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (the_block->front_flag == HEAP_DUMMY_FLAG)
|
||||
notdone = 0;
|
||||
else
|
||||
the_block = next_block;
|
||||
}
|
||||
|
||||
if (error)
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
@@ -70,916 +70,3 @@ void _Thread_queue_Initialize(
|
||||
}
|
||||
|
||||
}
|
||||
#if 0
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Enqueue
|
||||
*
|
||||
* This routine blocks a thread, places it on a thread, and optionally
|
||||
* starts a timeout timer.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
* timeout - interval to wait
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* only case
|
||||
*/
|
||||
|
||||
void _Thread_queue_Enqueue(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Watchdog_Interval timeout
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
|
||||
the_thread = _Thread_Executing;
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet )
|
||||
the_thread = _Thread_MP_Allocate_proxy( the_thread_queue->state );
|
||||
else
|
||||
#endif
|
||||
_Thread_Set_state( the_thread, the_thread_queue->state );
|
||||
|
||||
if ( timeout ) {
|
||||
_Watchdog_Initialize(
|
||||
&the_thread->Timer,
|
||||
_Thread_queue_Timeout,
|
||||
the_thread->Object.id,
|
||||
NULL
|
||||
);
|
||||
|
||||
_Watchdog_Insert_ticks( &the_thread->Timer, timeout );
|
||||
}
|
||||
|
||||
switch( the_thread_queue->discipline ) {
|
||||
case THREAD_QUEUE_DISCIPLINE_FIFO:
|
||||
_Thread_queue_Enqueue_fifo( the_thread_queue, the_thread, timeout );
|
||||
break;
|
||||
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
|
||||
_Thread_queue_Enqueue_priority( the_thread_queue, the_thread, timeout );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Dequeue
|
||||
*
|
||||
* This routine removes a thread from the specified threadq. If the
|
||||
* threadq discipline is FIFO, it unblocks a thread, and cancels its
|
||||
* timeout timer. Priority discipline is processed elsewhere.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - thread dequeued or NULL
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* check sync
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_Dequeue(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
|
||||
switch ( the_thread_queue->discipline ) {
|
||||
case THREAD_QUEUE_DISCIPLINE_FIFO:
|
||||
the_thread = _Thread_queue_Dequeue_fifo( the_thread_queue );
|
||||
break;
|
||||
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
|
||||
the_thread = _Thread_queue_Dequeue_priority( the_thread_queue );
|
||||
break;
|
||||
default: /* this is only to prevent warnings */
|
||||
the_thread = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return( the_thread );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Extract_with_proxy
|
||||
*
|
||||
* This routine extracts the_thread from the_thread_queue
|
||||
* and insures that if there is a proxy for this task on
|
||||
* another node, it is also dealt with.
|
||||
*
|
||||
* XXX
|
||||
*/
|
||||
|
||||
boolean _Thread_queue_Extract_with_proxy(
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
States_Control state;
|
||||
Objects_Classes the_class;
|
||||
Thread_queue_Extract_callout proxy_extract_callout;
|
||||
|
||||
state = the_thread->current_state;
|
||||
|
||||
if ( _States_Is_waiting_on_thread_queue( state ) ) {
|
||||
if ( _States_Is_waiting_for_rpc_reply( state ) &&
|
||||
_States_Is_locally_blocked( state ) ) {
|
||||
|
||||
the_class = _Objects_Get_class( the_thread->Wait.id );
|
||||
|
||||
proxy_extract_callout = _Thread_queue_Extract_table[ the_class ];
|
||||
|
||||
if ( proxy_extract_callout )
|
||||
(*proxy_extract_callout)( the_thread );
|
||||
}
|
||||
_Thread_queue_Extract( the_thread->Wait.queue, the_thread );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Extract
|
||||
*
|
||||
* This routine removes a specific thread from the specified threadq,
|
||||
* deletes any timeout, and unblocks the thread.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to a threadq header
|
||||
* the_thread - pointer to a thread control block
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY: NONE
|
||||
*/
|
||||
|
||||
void _Thread_queue_Extract(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
switch ( the_thread_queue->discipline ) {
|
||||
case THREAD_QUEUE_DISCIPLINE_FIFO:
|
||||
_Thread_queue_Extract_fifo( the_thread_queue, the_thread );
|
||||
break;
|
||||
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
|
||||
_Thread_queue_Extract_priority( the_thread_queue, the_thread );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Flush
|
||||
*
|
||||
* This kernel routine flushes the given thread queue.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq to be flushed
|
||||
* remote_extract_callout - pointer to routine which extracts a remote thread
|
||||
* status - status to return to the thread
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
void _Thread_queue_Flush(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_queue_Flush_callout remote_extract_callout,
|
||||
unsigned32 status
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
|
||||
while ( (the_thread = _Thread_queue_Dequeue( the_thread_queue )) ) {
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
( *remote_extract_callout )( the_thread );
|
||||
else
|
||||
#endif
|
||||
the_thread->Wait.return_code = status;
|
||||
}
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_First
|
||||
*
|
||||
* This routines returns a pointer to the first thread on the
|
||||
* specified threadq.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to thread queue
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - first thread or NULL
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_First(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
|
||||
switch ( the_thread_queue->discipline ) {
|
||||
case THREAD_QUEUE_DISCIPLINE_FIFO:
|
||||
the_thread = _Thread_queue_First_fifo( the_thread_queue );
|
||||
break;
|
||||
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
|
||||
the_thread = _Thread_queue_First_priority( the_thread_queue );
|
||||
break;
|
||||
default: /* this is only to prevent warnings */
|
||||
the_thread = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return the_thread;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Timeout
|
||||
*
|
||||
* This routine processes a thread which timeouts while waiting on
|
||||
* a thread queue. It is called by the watchdog handler.
|
||||
*
|
||||
* Input parameters:
|
||||
* id - thread id
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
void _Thread_queue_Timeout(
|
||||
Objects_Id id,
|
||||
void *ignored
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
Thread_queue_Control *the_thread_queue;
|
||||
Objects_Locations location;
|
||||
|
||||
the_thread = _Thread_Get( id, &location );
|
||||
switch ( location ) {
|
||||
case OBJECTS_ERROR:
|
||||
case OBJECTS_REMOTE: /* impossible */
|
||||
break;
|
||||
case OBJECTS_LOCAL:
|
||||
the_thread_queue = the_thread->Wait.queue;
|
||||
|
||||
/*
|
||||
* If the_thread_queue 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.
|
||||
*/
|
||||
|
||||
if ( the_thread_queue->sync_state != THREAD_QUEUE_SYNCHRONIZED &&
|
||||
_Thread_Is_executing( the_thread ) ) {
|
||||
if ( the_thread_queue->sync_state != THREAD_QUEUE_SATISFIED )
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_TIMEOUT;
|
||||
} else {
|
||||
the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
|
||||
_Thread_queue_Extract( the_thread->Wait.queue, the_thread );
|
||||
}
|
||||
_Thread_Unnest_dispatch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Enqueue_fifo
|
||||
*
|
||||
* This routine blocks a thread, places it on a thread, and optionally
|
||||
* starts a timeout timer.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
* the_thread - pointer to the thread to block
|
||||
* timeout - interval to wait
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* only case
|
||||
*/
|
||||
|
||||
void _Thread_queue_Enqueue_fifo (
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread,
|
||||
Watchdog_Interval timeout
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
Thread_queue_States sync_state;
|
||||
|
||||
_ISR_Disable( level );
|
||||
|
||||
sync_state = the_thread_queue->sync_state;
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
|
||||
|
||||
switch ( sync_state ) {
|
||||
case THREAD_QUEUE_SYNCHRONIZED:
|
||||
/*
|
||||
* This should never happen. It indicates that someone did not
|
||||
* enter a thread queue critical section.
|
||||
*/
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_NOTHING_HAPPENED:
|
||||
_Chain_Append_unprotected(
|
||||
&the_thread_queue->Queues.Fifo,
|
||||
&the_thread->Object.Node
|
||||
);
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
|
||||
case THREAD_QUEUE_TIMEOUT:
|
||||
the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
|
||||
_ISR_Enable( level );
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_SATISFIED:
|
||||
if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
|
||||
_Watchdog_Deactivate( &the_thread->Timer );
|
||||
_ISR_Enable( level );
|
||||
(void) _Watchdog_Remove( &the_thread->Timer );
|
||||
} else
|
||||
_ISR_Enable( level );
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global objects with thread queue's should not be operated on from an
|
||||
* ISR. But the sync code still must allow short timeouts to be processed
|
||||
* correctly.
|
||||
*/
|
||||
|
||||
_Thread_Unblock( the_thread );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Dequeue_fifo
|
||||
*
|
||||
* This routine removes a thread from the specified threadq.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - thread dequeued or NULL
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* check sync
|
||||
* FIFO
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_Dequeue_fifo(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
Thread_Control *the_thread;
|
||||
|
||||
_ISR_Disable( level );
|
||||
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {
|
||||
|
||||
the_thread = (Thread_Control *)
|
||||
_Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
|
||||
return the_thread;
|
||||
}
|
||||
|
||||
switch ( the_thread_queue->sync_state ) {
|
||||
case THREAD_QUEUE_SYNCHRONIZED:
|
||||
case THREAD_QUEUE_SATISFIED:
|
||||
_ISR_Enable( level );
|
||||
return NULL;
|
||||
|
||||
case THREAD_QUEUE_NOTHING_HAPPENED:
|
||||
case THREAD_QUEUE_TIMEOUT:
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
|
||||
_ISR_Enable( level );
|
||||
return _Thread_Executing;
|
||||
}
|
||||
return NULL; /* this is only to prevent warnings */
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Extract_fifo
|
||||
*
|
||||
* This routine removes a specific thread from the specified threadq,
|
||||
* deletes any timeout, and unblocks the thread.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to a threadq header
|
||||
* the_thread - pointer to the thread to block
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* EXTRACT_FIFO
|
||||
*/
|
||||
|
||||
void _Thread_queue_Extract_fifo(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
|
||||
_ISR_Disable( level );
|
||||
|
||||
if ( !_States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
}
|
||||
|
||||
_Chain_Extract_unprotected( &the_thread->Object.Node );
|
||||
|
||||
if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
|
||||
_ISR_Enable( level );
|
||||
} else {
|
||||
_Watchdog_Deactivate( &the_thread->Timer );
|
||||
_ISR_Enable( level );
|
||||
(void) _Watchdog_Remove( &the_thread->Timer );
|
||||
}
|
||||
|
||||
_Thread_Unblock( the_thread );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_First_fifo
|
||||
*
|
||||
* This routines returns a pointer to the first thread on the
|
||||
* specified threadq.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - first thread or NULL
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_First_fifo(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) )
|
||||
return (Thread_Control *) the_thread_queue->Queues.Fifo.first;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Enqueue_priority
|
||||
*
|
||||
* This routine blocks a thread, places it on a thread, and optionally
|
||||
* starts a timeout timer.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
* thread - thread to insert
|
||||
* timeout - timeout interval in ticks
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* forward less than
|
||||
* forward equal
|
||||
*/
|
||||
|
||||
void _Thread_queue_Enqueue_priority(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread,
|
||||
Watchdog_Interval timeout
|
||||
)
|
||||
{
|
||||
Priority_Control search_priority;
|
||||
Thread_Control *search_thread;
|
||||
ISR_Level level;
|
||||
Chain_Control *header;
|
||||
unsigned32 header_index;
|
||||
Chain_Node *the_node;
|
||||
Chain_Node *next_node;
|
||||
Chain_Node *previous_node;
|
||||
Chain_Node *search_node;
|
||||
Priority_Control priority;
|
||||
States_Control block_state;
|
||||
Thread_queue_States sync_state;
|
||||
|
||||
_Chain_Initialize_empty( &the_thread->Wait.Block2n );
|
||||
|
||||
priority = the_thread->current_priority;
|
||||
header_index = _Thread_queue_Header_number( priority );
|
||||
header = &the_thread_queue->Queues.Priority[ header_index ];
|
||||
block_state = the_thread_queue->state;
|
||||
|
||||
if ( _Thread_queue_Is_reverse_search( priority ) )
|
||||
goto restart_reverse_search;
|
||||
|
||||
restart_forward_search:
|
||||
search_priority = PRIORITY_MINIMUM - 1;
|
||||
_ISR_Disable( level );
|
||||
search_thread = (Thread_Control *) header->first;
|
||||
while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
|
||||
search_priority = search_thread->current_priority;
|
||||
if ( priority <= search_priority )
|
||||
break;
|
||||
|
||||
#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
|
||||
search_thread = (Thread_Control *) search_thread->Object.Node.next;
|
||||
if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
|
||||
break;
|
||||
search_priority = search_thread->current_priority;
|
||||
if ( priority <= search_priority )
|
||||
break;
|
||||
#endif
|
||||
_ISR_Flash( level );
|
||||
if ( !_States_Are_set( search_thread->current_state, block_state) ) {
|
||||
_ISR_Enable( level );
|
||||
goto restart_forward_search;
|
||||
}
|
||||
search_thread =
|
||||
(Thread_Control *)search_thread->Object.Node.next;
|
||||
}
|
||||
|
||||
if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
|
||||
goto synchronize;
|
||||
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
|
||||
|
||||
if ( priority == search_priority )
|
||||
goto equal_priority;
|
||||
|
||||
search_node = (Chain_Node *) search_thread;
|
||||
previous_node = search_node->previous;
|
||||
the_node = (Chain_Node *) the_thread;
|
||||
|
||||
the_node->next = search_node;
|
||||
the_node->previous = previous_node;
|
||||
previous_node->next = the_node;
|
||||
search_node->previous = the_node;
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
|
||||
restart_reverse_search:
|
||||
search_priority = PRIORITY_MAXIMUM + 1;
|
||||
|
||||
_ISR_Disable( level );
|
||||
search_thread = (Thread_Control *) header->last;
|
||||
while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
|
||||
search_priority = search_thread->current_priority;
|
||||
if ( priority >= search_priority )
|
||||
break;
|
||||
#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
|
||||
search_thread = (Thread_Control *) search_thread->Object.Node.previous;
|
||||
if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
|
||||
break;
|
||||
search_priority = search_thread->current_priority;
|
||||
if ( priority >= search_priority )
|
||||
break;
|
||||
#endif
|
||||
_ISR_Flash( level );
|
||||
if ( !_States_Are_set( search_thread->current_state, block_state) ) {
|
||||
_ISR_Enable( level );
|
||||
goto restart_reverse_search;
|
||||
}
|
||||
search_thread = (Thread_Control *)
|
||||
search_thread->Object.Node.previous;
|
||||
}
|
||||
|
||||
if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
|
||||
goto synchronize;
|
||||
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
|
||||
|
||||
if ( priority == search_priority )
|
||||
goto equal_priority;
|
||||
|
||||
search_node = (Chain_Node *) search_thread;
|
||||
next_node = search_node->next;
|
||||
the_node = (Chain_Node *) the_thread;
|
||||
|
||||
the_node->next = next_node;
|
||||
the_node->previous = search_node;
|
||||
search_node->next = the_node;
|
||||
next_node->previous = the_node;
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
|
||||
equal_priority: /* add at end of priority group */
|
||||
search_node = _Chain_Tail( &search_thread->Wait.Block2n );
|
||||
previous_node = search_node->previous;
|
||||
the_node = (Chain_Node *) the_thread;
|
||||
|
||||
the_node->next = search_node;
|
||||
the_node->previous = previous_node;
|
||||
previous_node->next = the_node;
|
||||
search_node->previous = the_node;
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
|
||||
synchronize:
|
||||
|
||||
sync_state = the_thread_queue->sync_state;
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
|
||||
|
||||
switch ( sync_state ) {
|
||||
case THREAD_QUEUE_SYNCHRONIZED:
|
||||
/*
|
||||
* This should never happen. It indicates that someone did not
|
||||
* enter a thread queue critical section.
|
||||
*/
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_NOTHING_HAPPENED:
|
||||
/*
|
||||
* This should never happen. All of this was dealt with above.
|
||||
*/
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_TIMEOUT:
|
||||
the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
|
||||
_ISR_Enable( level );
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_SATISFIED:
|
||||
if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
|
||||
_Watchdog_Deactivate( &the_thread->Timer );
|
||||
_ISR_Enable( level );
|
||||
(void) _Watchdog_Remove( &the_thread->Timer );
|
||||
} else
|
||||
_ISR_Enable( level );
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global objects with thread queue's should not be operated on from an
|
||||
* ISR. But the sync code still must allow short timeouts to be processed
|
||||
* correctly.
|
||||
*/
|
||||
|
||||
_Thread_Unblock( the_thread );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Dequeue_priority
|
||||
*
|
||||
* This routine removes a thread from the specified PRIORITY based
|
||||
* threadq, unblocks it, and cancels its timeout timer.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to thread queue
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - thread dequeued or NULL
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* only case
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_Dequeue_priority(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
unsigned32 index;
|
||||
ISR_Level level;
|
||||
Thread_Control *the_thread = NULL; /* just to remove warnings */
|
||||
Thread_Control *new_first_thread;
|
||||
Chain_Node *new_first_node;
|
||||
Chain_Node *new_second_node;
|
||||
Chain_Node *last_node;
|
||||
Chain_Node *next_node;
|
||||
Chain_Node *previous_node;
|
||||
|
||||
_ISR_Disable( level );
|
||||
for( index=0 ;
|
||||
index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
|
||||
index++ ) {
|
||||
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
|
||||
the_thread = (Thread_Control *)
|
||||
the_thread_queue->Queues.Priority[ index ].first;
|
||||
goto dequeue;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( the_thread_queue->sync_state ) {
|
||||
case THREAD_QUEUE_SYNCHRONIZED:
|
||||
case THREAD_QUEUE_SATISFIED:
|
||||
_ISR_Enable( level );
|
||||
return NULL;
|
||||
|
||||
case THREAD_QUEUE_NOTHING_HAPPENED:
|
||||
case THREAD_QUEUE_TIMEOUT:
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
|
||||
_ISR_Enable( level );
|
||||
return _Thread_Executing;
|
||||
}
|
||||
|
||||
dequeue:
|
||||
new_first_node = the_thread->Wait.Block2n.first;
|
||||
new_first_thread = (Thread_Control *) new_first_node;
|
||||
next_node = the_thread->Object.Node.next;
|
||||
previous_node = the_thread->Object.Node.previous;
|
||||
|
||||
if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
|
||||
last_node = the_thread->Wait.Block2n.last;
|
||||
new_second_node = new_first_node->next;
|
||||
|
||||
previous_node->next = new_first_node;
|
||||
next_node->previous = new_first_node;
|
||||
new_first_node->next = next_node;
|
||||
new_first_node->previous = previous_node;
|
||||
|
||||
if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
|
||||
/* > two threads on 2-n */
|
||||
new_second_node->previous =
|
||||
_Chain_Head( &new_first_thread->Wait.Block2n );
|
||||
|
||||
new_first_thread->Wait.Block2n.first = new_second_node;
|
||||
new_first_thread->Wait.Block2n.last = last_node;
|
||||
|
||||
last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
|
||||
}
|
||||
} else {
|
||||
previous_node->next = next_node;
|
||||
next_node->previous = previous_node;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
return( the_thread );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Extract_priority
|
||||
*
|
||||
* This routine removes a specific thread from the specified threadq,
|
||||
* deletes any timeout, and unblocks the thread.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to a threadq header
|
||||
* the_thread - pointer to a thread control block
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* EXTRACT_PRIORITY
|
||||
*/
|
||||
|
||||
void _Thread_queue_Extract_priority(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
Chain_Node *the_node;
|
||||
Chain_Node *next_node;
|
||||
Chain_Node *previous_node;
|
||||
Thread_Control *new_first_thread;
|
||||
Chain_Node *new_first_node;
|
||||
Chain_Node *new_second_node;
|
||||
Chain_Node *last_node;
|
||||
|
||||
the_node = (Chain_Node *) the_thread;
|
||||
_ISR_Disable( level );
|
||||
if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
|
||||
next_node = the_node->next;
|
||||
previous_node = the_node->previous;
|
||||
|
||||
if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
|
||||
new_first_node = the_thread->Wait.Block2n.first;
|
||||
new_first_thread = (Thread_Control *) new_first_node;
|
||||
last_node = the_thread->Wait.Block2n.last;
|
||||
new_second_node = new_first_node->next;
|
||||
|
||||
previous_node->next = new_first_node;
|
||||
next_node->previous = new_first_node;
|
||||
new_first_node->next = next_node;
|
||||
new_first_node->previous = previous_node;
|
||||
|
||||
if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
|
||||
/* > two threads on 2-n */
|
||||
new_second_node->previous =
|
||||
_Chain_Head( &new_first_thread->Wait.Block2n );
|
||||
new_first_thread->Wait.Block2n.first = new_second_node;
|
||||
|
||||
new_first_thread->Wait.Block2n.last = last_node;
|
||||
last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
|
||||
}
|
||||
} else {
|
||||
previous_node->next = next_node;
|
||||
next_node->previous = previous_node;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
_ISR_Enable( level );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_First_priority
|
||||
*
|
||||
* This routines returns a pointer to the first thread on the
|
||||
* specified threadq.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to thread queue
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - first thread or NULL
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_First_priority (
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
unsigned32 index;
|
||||
|
||||
for( index=0 ;
|
||||
index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
|
||||
index++ ) {
|
||||
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) )
|
||||
return (Thread_Control *)
|
||||
the_thread_queue->Queues.Priority[ index ].first;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
65
cpukit/rtems/src/clocktodtoseconds.c
Normal file
65
cpukit/rtems/src/clocktodtoseconds.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*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
|
||||
*/
|
||||
|
||||
unsigned32 _TOD_To_seconds(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 time;
|
||||
unsigned32 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;
|
||||
|
||||
return( time );
|
||||
}
|
||||
|
||||
64
cpukit/rtems/src/clocktodvalidate.c
Normal file
64
cpukit/rtems/src/clocktodvalidate.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*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.
|
||||
*/
|
||||
|
||||
boolean _TOD_Validate(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 days_in_month;
|
||||
|
||||
if ((the_tod->ticks >= _TOD_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;
|
||||
}
|
||||
|
||||
@@ -58,181 +58,3 @@ void _TOD_Handler_initialization(
|
||||
_TOD_Is_set = FALSE;
|
||||
_TOD_Activate( _TOD_Ticks_per_second );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _TOD_Set
|
||||
*
|
||||
* This rountine sets the current date and time with the specified
|
||||
* new date and time structure.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_tod - pointer to the time and date structure
|
||||
* seconds_since_epoch - seconds since system epoch
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
void _TOD_Set(
|
||||
TOD_Control *the_tod,
|
||||
Watchdog_Interval seconds_since_epoch
|
||||
)
|
||||
{
|
||||
Watchdog_Interval ticks_until_next_second;
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
_TOD_Deactivate();
|
||||
|
||||
if ( seconds_since_epoch < _TOD_Seconds_since_epoch )
|
||||
_Watchdog_Adjust_seconds( WATCHDOG_BACKWARD,
|
||||
_TOD_Seconds_since_epoch - seconds_since_epoch );
|
||||
else
|
||||
_Watchdog_Adjust_seconds( WATCHDOG_FORWARD,
|
||||
seconds_since_epoch - _TOD_Seconds_since_epoch );
|
||||
|
||||
ticks_until_next_second = _TOD_Ticks_per_second;
|
||||
if ( ticks_until_next_second > _TOD_Current.ticks )
|
||||
ticks_until_next_second -= _TOD_Current.ticks;
|
||||
|
||||
_TOD_Current = *the_tod;
|
||||
_TOD_Seconds_since_epoch = seconds_since_epoch;
|
||||
_TOD_Is_set = TRUE;
|
||||
_TOD_Activate( ticks_until_next_second );
|
||||
|
||||
_Thread_Enable_dispatch();
|
||||
}
|
||||
|
||||
/*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.
|
||||
*/
|
||||
|
||||
boolean _TOD_Validate(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 days_in_month;
|
||||
|
||||
if ((the_tod->ticks >= _TOD_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;
|
||||
}
|
||||
|
||||
/*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
|
||||
*/
|
||||
|
||||
unsigned32 _TOD_To_seconds(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 time;
|
||||
unsigned32 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;
|
||||
|
||||
return( time );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _TOD_Tickle
|
||||
*
|
||||
* This routine updates the calendar time and tickles the
|
||||
* per second watchdog timer chain.
|
||||
*
|
||||
* Input parameters:
|
||||
* ignored - this parameter is ignored
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* NOTE: This routine only works for leap-years through 2099.
|
||||
*/
|
||||
|
||||
void _TOD_Tickle(
|
||||
Objects_Id id,
|
||||
void *ignored
|
||||
)
|
||||
{
|
||||
unsigned32 leap;
|
||||
|
||||
_TOD_Current.ticks = 0;
|
||||
++_TOD_Seconds_since_epoch;
|
||||
if ( ++_TOD_Current.second >= TOD_SECONDS_PER_MINUTE ) {
|
||||
_TOD_Current.second = 0;
|
||||
if ( ++_TOD_Current.minute >= TOD_MINUTES_PER_HOUR ) {
|
||||
_TOD_Current.minute = 0;
|
||||
if ( ++_TOD_Current.hour >= TOD_HOURS_PER_DAY ) {
|
||||
_TOD_Current.hour = 0;
|
||||
if ( _TOD_Current.year & 0x3 ) leap = 0;
|
||||
else leap = 1;
|
||||
if ( ++_TOD_Current.day >
|
||||
_TOD_Days_per_month[ leap ][ _TOD_Current.month ]) {
|
||||
_TOD_Current.day = 1;
|
||||
if ( ++_TOD_Current.month > TOD_MONTHS_PER_YEAR ) {
|
||||
_TOD_Current.month = 1;
|
||||
_TOD_Current.year++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_Watchdog_Tickle_seconds();
|
||||
_Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, _TOD_Ticks_per_second );
|
||||
}
|
||||
|
||||
64
cpukit/score/src/coretodset.c
Normal file
64
cpukit/score/src/coretodset.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _TOD_Set
|
||||
*
|
||||
* This rountine sets the current date and time with the specified
|
||||
* new date and time structure.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_tod - pointer to the time and date structure
|
||||
* seconds_since_epoch - seconds since system epoch
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
void _TOD_Set(
|
||||
TOD_Control *the_tod,
|
||||
Watchdog_Interval seconds_since_epoch
|
||||
)
|
||||
{
|
||||
Watchdog_Interval ticks_until_next_second;
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
_TOD_Deactivate();
|
||||
|
||||
if ( seconds_since_epoch < _TOD_Seconds_since_epoch )
|
||||
_Watchdog_Adjust_seconds( WATCHDOG_BACKWARD,
|
||||
_TOD_Seconds_since_epoch - seconds_since_epoch );
|
||||
else
|
||||
_Watchdog_Adjust_seconds( WATCHDOG_FORWARD,
|
||||
seconds_since_epoch - _TOD_Seconds_since_epoch );
|
||||
|
||||
ticks_until_next_second = _TOD_Ticks_per_second;
|
||||
if ( ticks_until_next_second > _TOD_Current.ticks )
|
||||
ticks_until_next_second -= _TOD_Current.ticks;
|
||||
|
||||
_TOD_Current = *the_tod;
|
||||
_TOD_Seconds_since_epoch = seconds_since_epoch;
|
||||
_TOD_Is_set = TRUE;
|
||||
_TOD_Activate( ticks_until_next_second );
|
||||
|
||||
_Thread_Enable_dispatch();
|
||||
}
|
||||
|
||||
68
cpukit/score/src/coretodtickle.c
Normal file
68
cpukit/score/src/coretodtickle.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _TOD_Tickle
|
||||
*
|
||||
* This routine updates the calendar time and tickles the
|
||||
* per second watchdog timer chain.
|
||||
*
|
||||
* Input parameters:
|
||||
* ignored - this parameter is ignored
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* NOTE: This routine only works for leap-years through 2099.
|
||||
*/
|
||||
|
||||
void _TOD_Tickle(
|
||||
Objects_Id id,
|
||||
void *ignored
|
||||
)
|
||||
{
|
||||
unsigned32 leap;
|
||||
|
||||
_TOD_Current.ticks = 0;
|
||||
++_TOD_Seconds_since_epoch;
|
||||
if ( ++_TOD_Current.second >= TOD_SECONDS_PER_MINUTE ) {
|
||||
_TOD_Current.second = 0;
|
||||
if ( ++_TOD_Current.minute >= TOD_MINUTES_PER_HOUR ) {
|
||||
_TOD_Current.minute = 0;
|
||||
if ( ++_TOD_Current.hour >= TOD_HOURS_PER_DAY ) {
|
||||
_TOD_Current.hour = 0;
|
||||
if ( _TOD_Current.year & 0x3 ) leap = 0;
|
||||
else leap = 1;
|
||||
if ( ++_TOD_Current.day >
|
||||
_TOD_Days_per_month[ leap ][ _TOD_Current.month ]) {
|
||||
_TOD_Current.day = 1;
|
||||
if ( ++_TOD_Current.month > TOD_MONTHS_PER_YEAR ) {
|
||||
_TOD_Current.month = 1;
|
||||
_TOD_Current.year++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_Watchdog_Tickle_seconds();
|
||||
_Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, _TOD_Ticks_per_second );
|
||||
}
|
||||
65
cpukit/score/src/coretodtoseconds.c
Normal file
65
cpukit/score/src/coretodtoseconds.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*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
|
||||
*/
|
||||
|
||||
unsigned32 _TOD_To_seconds(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 time;
|
||||
unsigned32 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;
|
||||
|
||||
return( time );
|
||||
}
|
||||
|
||||
64
cpukit/score/src/coretodvalidate.c
Normal file
64
cpukit/score/src/coretodvalidate.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Time of Day (TOD) Handler
|
||||
*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/tod.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
/*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.
|
||||
*/
|
||||
|
||||
boolean _TOD_Validate(
|
||||
TOD_Control *the_tod
|
||||
)
|
||||
{
|
||||
unsigned32 days_in_month;
|
||||
|
||||
if ((the_tod->ticks >= _TOD_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;
|
||||
}
|
||||
|
||||
@@ -92,447 +92,3 @@ unsigned32 _Heap_Initialize(
|
||||
return ( the_size - HEAP_BLOCK_USED_OVERHEAD );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Extend
|
||||
*
|
||||
* This routine grows the_heap memory area using the size bytes which
|
||||
* begin at starting_address.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header.
|
||||
* starting_address - pointer to the memory area.
|
||||
* size - size in bytes of the memory block to allocate.
|
||||
*
|
||||
* Output parameters:
|
||||
* *amount_extended - amount of memory added to the_heap
|
||||
*/
|
||||
|
||||
Heap_Extend_status _Heap_Extend(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address,
|
||||
unsigned32 size,
|
||||
unsigned32 *amount_extended
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
unsigned32 *p;
|
||||
|
||||
/*
|
||||
* The overhead was taken from the original heap memory.
|
||||
*/
|
||||
|
||||
Heap_Block *old_final;
|
||||
Heap_Block *new_final;
|
||||
|
||||
/*
|
||||
* There are five possibilities for the location of starting
|
||||
* address:
|
||||
*
|
||||
* 1. non-contiguous lower address (NOT SUPPORTED)
|
||||
* 2. contiguous lower address (NOT SUPPORTED)
|
||||
* 3. in the heap (ERROR)
|
||||
* 4. contiguous higher address (SUPPORTED)
|
||||
* 5. non-contiguous higher address (NOT SUPPORTED)
|
||||
*
|
||||
* As noted, this code only supports (4).
|
||||
*/
|
||||
|
||||
if ( starting_address >= (void *) the_heap->start && /* case 3 */
|
||||
starting_address <= (void *) the_heap->final
|
||||
)
|
||||
return HEAP_EXTEND_ERROR;
|
||||
|
||||
if ( starting_address < (void *) the_heap->start ) { /* cases 1 and 2 */
|
||||
|
||||
return HEAP_EXTEND_NOT_IMPLEMENTED; /* cases 1 and 2 */
|
||||
|
||||
} else { /* cases 4 and 5 */
|
||||
|
||||
the_block = (Heap_Block *)
|
||||
_Addresses_Subtract_offset( starting_address, HEAP_OVERHEAD );
|
||||
if ( the_block != the_heap->final )
|
||||
return HEAP_EXTEND_NOT_IMPLEMENTED; /* case 5 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently only case 4 should make it to this point.
|
||||
* The basic trick is to make the extend area look like a used
|
||||
* block and free it.
|
||||
*/
|
||||
|
||||
*amount_extended = size;
|
||||
|
||||
old_final = the_heap->final;
|
||||
new_final = _Addresses_Add_offset( old_final, size );
|
||||
/* SAME AS: _Addresses_Add_offset( starting_address, size-HEAP_OVERHEAD ); */
|
||||
|
||||
the_heap->final = new_final;
|
||||
|
||||
old_final->front_flag =
|
||||
new_final->back_flag = _Heap_Build_flag( size, HEAP_BLOCK_USED );
|
||||
new_final->front_flag = HEAP_DUMMY_FLAG;
|
||||
|
||||
/*
|
||||
* Must pass in address of "user" area
|
||||
* So add in the offset field.
|
||||
*/
|
||||
|
||||
p = (unsigned32 *) &old_final->next;
|
||||
*p = sizeof(unsigned32);
|
||||
p++;
|
||||
_Heap_Free( the_heap, p );
|
||||
|
||||
return HEAP_EXTEND_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Allocate
|
||||
*
|
||||
* This kernel routine allocates the requested size of memory
|
||||
* from the specified heap.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header.
|
||||
* size - size in bytes of the memory block to allocate.
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - starting address of memory block allocated
|
||||
*/
|
||||
|
||||
void *_Heap_Allocate(
|
||||
Heap_Control *the_heap,
|
||||
unsigned32 size
|
||||
)
|
||||
{
|
||||
unsigned32 excess;
|
||||
unsigned32 the_size;
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
Heap_Block *temporary_block;
|
||||
void *ptr;
|
||||
unsigned32 offset;
|
||||
|
||||
excess = size % the_heap->page_size;
|
||||
the_size = size + the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD;
|
||||
|
||||
if ( excess )
|
||||
the_size += the_heap->page_size - excess;
|
||||
|
||||
if ( the_size < sizeof( Heap_Block ) )
|
||||
the_size = sizeof( Heap_Block );
|
||||
|
||||
for ( the_block = the_heap->first;
|
||||
;
|
||||
the_block = the_block->next ) {
|
||||
if ( the_block == _Heap_Tail( the_heap ) )
|
||||
return( NULL );
|
||||
if ( the_block->front_flag >= the_size )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (the_block->front_flag - the_size) >
|
||||
(the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD) ) {
|
||||
the_block->front_flag -= the_size;
|
||||
next_block = _Heap_Next_block( the_block );
|
||||
next_block->back_flag = the_block->front_flag;
|
||||
|
||||
temporary_block = _Heap_Block_at( next_block, the_size );
|
||||
temporary_block->back_flag =
|
||||
next_block->front_flag = _Heap_Build_flag( the_size,
|
||||
HEAP_BLOCK_USED );
|
||||
ptr = _Heap_Start_of_user_area( next_block );
|
||||
} else {
|
||||
next_block = _Heap_Next_block( the_block );
|
||||
next_block->back_flag = _Heap_Build_flag( the_block->front_flag,
|
||||
HEAP_BLOCK_USED );
|
||||
the_block->front_flag = next_block->back_flag;
|
||||
the_block->next->previous = the_block->previous;
|
||||
the_block->previous->next = the_block->next;
|
||||
ptr = _Heap_Start_of_user_area( the_block );
|
||||
}
|
||||
|
||||
/*
|
||||
* round ptr up to a multiple of page size
|
||||
* Have to save the bump amount in the buffer so that free can figure it out
|
||||
*/
|
||||
|
||||
offset = the_heap->page_size - (((unsigned32) ptr) & (the_heap->page_size - 1));
|
||||
ptr = _Addresses_Add_offset( ptr, offset );
|
||||
*(((unsigned32 *) ptr) - 1) = offset;
|
||||
|
||||
#ifdef RTEMS_DEBUG
|
||||
{
|
||||
unsigned32 ptr_u32;
|
||||
ptr_u32 = (unsigned32) ptr;
|
||||
if (ptr_u32 & (the_heap->page_size - 1))
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Size_of_user_area
|
||||
*
|
||||
* This kernel routine returns the size of the memory area
|
||||
* given heap block.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* starting_address - starting address of the memory block to free.
|
||||
* size - pointer to size of area
|
||||
*
|
||||
* Output parameters:
|
||||
* size - size of area filled in
|
||||
* TRUE - if starting_address is valid heap address
|
||||
* FALSE - if starting_address is invalid heap address
|
||||
*/
|
||||
|
||||
boolean _Heap_Size_of_user_area(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address,
|
||||
unsigned32 *size
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
unsigned32 the_size;
|
||||
|
||||
the_block = _Heap_User_block_at( starting_address );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, the_block ) ||
|
||||
_Heap_Is_block_free( the_block ) )
|
||||
return( FALSE );
|
||||
|
||||
the_size = _Heap_Block_size( the_block );
|
||||
next_block = _Heap_Block_at( the_block, the_size );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, next_block ) ||
|
||||
(the_block->front_flag != next_block->back_flag) )
|
||||
return( FALSE );
|
||||
|
||||
*size = the_size;
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Free
|
||||
*
|
||||
* This kernel routine returns the memory designated by the
|
||||
* given heap and given starting address to the memory pool.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* starting_address - starting address of the memory block to free.
|
||||
*
|
||||
* Output parameters:
|
||||
* TRUE - if starting_address is valid heap address
|
||||
* FALSE - if starting_address is invalid heap address
|
||||
*/
|
||||
|
||||
boolean _Heap_Free(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
Heap_Block *new_next_block;
|
||||
Heap_Block *previous_block;
|
||||
Heap_Block *temporary_block;
|
||||
unsigned32 the_size;
|
||||
|
||||
the_block = _Heap_User_block_at( starting_address );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, the_block ) ||
|
||||
_Heap_Is_block_free( the_block ) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
the_size = _Heap_Block_size( the_block );
|
||||
next_block = _Heap_Block_at( the_block, the_size );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, next_block ) ||
|
||||
(the_block->front_flag != next_block->back_flag) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( _Heap_Is_previous_block_free( the_block ) ) {
|
||||
previous_block = _Heap_Previous_block( the_block );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, previous_block ) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( _Heap_Is_block_free( next_block ) ) { /* coalesce both */
|
||||
previous_block->front_flag += next_block->front_flag + the_size;
|
||||
temporary_block = _Heap_Next_block( previous_block );
|
||||
temporary_block->back_flag = previous_block->front_flag;
|
||||
next_block->next->previous = next_block->previous;
|
||||
next_block->previous->next = next_block->next;
|
||||
}
|
||||
else { /* coalesce prev */
|
||||
previous_block->front_flag =
|
||||
next_block->back_flag = previous_block->front_flag + the_size;
|
||||
}
|
||||
}
|
||||
else if ( _Heap_Is_block_free( next_block ) ) { /* coalesce next */
|
||||
the_block->front_flag = the_size + next_block->front_flag;
|
||||
new_next_block = _Heap_Next_block( the_block );
|
||||
new_next_block->back_flag = the_block->front_flag;
|
||||
the_block->next = next_block->next;
|
||||
the_block->previous = next_block->previous;
|
||||
next_block->previous->next = the_block;
|
||||
next_block->next->previous = the_block;
|
||||
|
||||
if (the_heap->first == next_block)
|
||||
the_heap->first = the_block;
|
||||
}
|
||||
else { /* no coalesce */
|
||||
next_block->back_flag =
|
||||
the_block->front_flag = the_size;
|
||||
the_block->previous = _Heap_Head( the_heap );
|
||||
the_block->next = the_heap->first;
|
||||
the_heap->first = the_block;
|
||||
the_block->next->previous = the_block;
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Walk
|
||||
*
|
||||
* This kernel routine walks the heap and verifies its correctness.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* source - a numeric indicator of the invoker of this routine
|
||||
* do_dump - when TRUE print the information
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
#ifndef RTEMS_DEBUG
|
||||
|
||||
void _Heap_Walk(
|
||||
Heap_Control *the_heap,
|
||||
int source,
|
||||
boolean do_dump
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void _Heap_Walk(
|
||||
Heap_Control *the_heap,
|
||||
int source,
|
||||
boolean do_dump
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block = 0; /* avoid warnings */
|
||||
Heap_Block *next_block = 0; /* avoid warnings */
|
||||
int notdone = 1;
|
||||
int error = 0;
|
||||
int passes = 0;
|
||||
|
||||
/*
|
||||
* We don't want to allow walking the heap until we have
|
||||
* transferred control to the user task so we watch the
|
||||
* system state.
|
||||
*/
|
||||
|
||||
if ( !_System_state_Is_up( _System_state_Get() ) )
|
||||
return;
|
||||
|
||||
the_block = the_heap->start;
|
||||
|
||||
if (do_dump == TRUE) {
|
||||
printf("\nPASS: %d start @ 0x%p final 0x%p, first 0x%p last 0x%p\n",
|
||||
source, the_heap->start, the_heap->final,
|
||||
the_heap->first, the_heap->last
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the 1st block
|
||||
*/
|
||||
|
||||
if (the_block->back_flag != HEAP_DUMMY_FLAG) {
|
||||
printf("PASS: %d Back flag of 1st block isn't HEAP_DUMMY_FLAG\n", source);
|
||||
error = 1;
|
||||
}
|
||||
|
||||
while (notdone) {
|
||||
passes++;
|
||||
if (error && (passes > 10))
|
||||
abort();
|
||||
|
||||
if (do_dump == TRUE) {
|
||||
printf("PASS: %d Block @ 0x%p Back %d, Front %d",
|
||||
source, the_block,
|
||||
the_block->back_flag, the_block->front_flag);
|
||||
if ( _Heap_Is_block_free(the_block) ) {
|
||||
printf( " Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the last block
|
||||
*/
|
||||
|
||||
if ( the_block->front_flag != HEAP_DUMMY_FLAG ) {
|
||||
next_block = _Heap_Next_block(the_block);
|
||||
if ( the_block->front_flag != next_block->back_flag ) {
|
||||
error = 1;
|
||||
printf("PASS: %d Front and back flags don't match\n", source);
|
||||
printf(" Current Block (%p): Back - %d, Front - %d",
|
||||
the_block, the_block->back_flag, the_block->front_flag);
|
||||
if (do_dump == TRUE) {
|
||||
if (_Heap_Is_block_free(the_block)) {
|
||||
printf(" Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
printf(" Next Block (%p): Back - %d, Front - %d",
|
||||
next_block, next_block->back_flag, next_block->front_flag);
|
||||
if (do_dump == TRUE) {
|
||||
if (_Heap_Is_block_free(next_block)) {
|
||||
printf(" Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (the_block->front_flag == HEAP_DUMMY_FLAG)
|
||||
notdone = 0;
|
||||
else
|
||||
the_block = next_block;
|
||||
}
|
||||
|
||||
if (error)
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
107
cpukit/score/src/heapallocate.c
Normal file
107
cpukit/score/src/heapallocate.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Allocate
|
||||
*
|
||||
* This kernel routine allocates the requested size of memory
|
||||
* from the specified heap.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header.
|
||||
* size - size in bytes of the memory block to allocate.
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - starting address of memory block allocated
|
||||
*/
|
||||
|
||||
void *_Heap_Allocate(
|
||||
Heap_Control *the_heap,
|
||||
unsigned32 size
|
||||
)
|
||||
{
|
||||
unsigned32 excess;
|
||||
unsigned32 the_size;
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
Heap_Block *temporary_block;
|
||||
void *ptr;
|
||||
unsigned32 offset;
|
||||
|
||||
excess = size % the_heap->page_size;
|
||||
the_size = size + the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD;
|
||||
|
||||
if ( excess )
|
||||
the_size += the_heap->page_size - excess;
|
||||
|
||||
if ( the_size < sizeof( Heap_Block ) )
|
||||
the_size = sizeof( Heap_Block );
|
||||
|
||||
for ( the_block = the_heap->first;
|
||||
;
|
||||
the_block = the_block->next ) {
|
||||
if ( the_block == _Heap_Tail( the_heap ) )
|
||||
return( NULL );
|
||||
if ( the_block->front_flag >= the_size )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (the_block->front_flag - the_size) >
|
||||
(the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD) ) {
|
||||
the_block->front_flag -= the_size;
|
||||
next_block = _Heap_Next_block( the_block );
|
||||
next_block->back_flag = the_block->front_flag;
|
||||
|
||||
temporary_block = _Heap_Block_at( next_block, the_size );
|
||||
temporary_block->back_flag =
|
||||
next_block->front_flag = _Heap_Build_flag( the_size,
|
||||
HEAP_BLOCK_USED );
|
||||
ptr = _Heap_Start_of_user_area( next_block );
|
||||
} else {
|
||||
next_block = _Heap_Next_block( the_block );
|
||||
next_block->back_flag = _Heap_Build_flag( the_block->front_flag,
|
||||
HEAP_BLOCK_USED );
|
||||
the_block->front_flag = next_block->back_flag;
|
||||
the_block->next->previous = the_block->previous;
|
||||
the_block->previous->next = the_block->next;
|
||||
ptr = _Heap_Start_of_user_area( the_block );
|
||||
}
|
||||
|
||||
/*
|
||||
* round ptr up to a multiple of page size
|
||||
* Have to save the bump amount in the buffer so that free can figure it out
|
||||
*/
|
||||
|
||||
offset = the_heap->page_size - (((unsigned32) ptr) & (the_heap->page_size - 1));
|
||||
ptr = _Addresses_Add_offset( ptr, offset );
|
||||
*(((unsigned32 *) ptr) - 1) = offset;
|
||||
|
||||
#ifdef RTEMS_DEBUG
|
||||
{
|
||||
unsigned32 ptr_u32;
|
||||
ptr_u32 = (unsigned32) ptr;
|
||||
if (ptr_u32 & (the_heap->page_size - 1))
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
113
cpukit/score/src/heapextend.c
Normal file
113
cpukit/score/src/heapextend.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Extend
|
||||
*
|
||||
* This routine grows the_heap memory area using the size bytes which
|
||||
* begin at starting_address.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header.
|
||||
* starting_address - pointer to the memory area.
|
||||
* size - size in bytes of the memory block to allocate.
|
||||
*
|
||||
* Output parameters:
|
||||
* *amount_extended - amount of memory added to the_heap
|
||||
*/
|
||||
|
||||
Heap_Extend_status _Heap_Extend(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address,
|
||||
unsigned32 size,
|
||||
unsigned32 *amount_extended
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
unsigned32 *p;
|
||||
|
||||
/*
|
||||
* The overhead was taken from the original heap memory.
|
||||
*/
|
||||
|
||||
Heap_Block *old_final;
|
||||
Heap_Block *new_final;
|
||||
|
||||
/*
|
||||
* There are five possibilities for the location of starting
|
||||
* address:
|
||||
*
|
||||
* 1. non-contiguous lower address (NOT SUPPORTED)
|
||||
* 2. contiguous lower address (NOT SUPPORTED)
|
||||
* 3. in the heap (ERROR)
|
||||
* 4. contiguous higher address (SUPPORTED)
|
||||
* 5. non-contiguous higher address (NOT SUPPORTED)
|
||||
*
|
||||
* As noted, this code only supports (4).
|
||||
*/
|
||||
|
||||
if ( starting_address >= (void *) the_heap->start && /* case 3 */
|
||||
starting_address <= (void *) the_heap->final
|
||||
)
|
||||
return HEAP_EXTEND_ERROR;
|
||||
|
||||
if ( starting_address < (void *) the_heap->start ) { /* cases 1 and 2 */
|
||||
|
||||
return HEAP_EXTEND_NOT_IMPLEMENTED; /* cases 1 and 2 */
|
||||
|
||||
} else { /* cases 4 and 5 */
|
||||
|
||||
the_block = (Heap_Block *)
|
||||
_Addresses_Subtract_offset( starting_address, HEAP_OVERHEAD );
|
||||
if ( the_block != the_heap->final )
|
||||
return HEAP_EXTEND_NOT_IMPLEMENTED; /* case 5 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently only case 4 should make it to this point.
|
||||
* The basic trick is to make the extend area look like a used
|
||||
* block and free it.
|
||||
*/
|
||||
|
||||
*amount_extended = size;
|
||||
|
||||
old_final = the_heap->final;
|
||||
new_final = _Addresses_Add_offset( old_final, size );
|
||||
/* SAME AS: _Addresses_Add_offset( starting_address, size-HEAP_OVERHEAD ); */
|
||||
|
||||
the_heap->final = new_final;
|
||||
|
||||
old_final->front_flag =
|
||||
new_final->back_flag = _Heap_Build_flag( size, HEAP_BLOCK_USED );
|
||||
new_final->front_flag = HEAP_DUMMY_FLAG;
|
||||
|
||||
/*
|
||||
* Must pass in address of "user" area
|
||||
* So add in the offset field.
|
||||
*/
|
||||
|
||||
p = (unsigned32 *) &old_final->next;
|
||||
*p = sizeof(unsigned32);
|
||||
p++;
|
||||
_Heap_Free( the_heap, p );
|
||||
|
||||
return HEAP_EXTEND_SUCCESSFUL;
|
||||
}
|
||||
|
||||
105
cpukit/score/src/heapfree.c
Normal file
105
cpukit/score/src/heapfree.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Free
|
||||
*
|
||||
* This kernel routine returns the memory designated by the
|
||||
* given heap and given starting address to the memory pool.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* starting_address - starting address of the memory block to free.
|
||||
*
|
||||
* Output parameters:
|
||||
* TRUE - if starting_address is valid heap address
|
||||
* FALSE - if starting_address is invalid heap address
|
||||
*/
|
||||
|
||||
boolean _Heap_Free(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
Heap_Block *new_next_block;
|
||||
Heap_Block *previous_block;
|
||||
Heap_Block *temporary_block;
|
||||
unsigned32 the_size;
|
||||
|
||||
the_block = _Heap_User_block_at( starting_address );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, the_block ) ||
|
||||
_Heap_Is_block_free( the_block ) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
the_size = _Heap_Block_size( the_block );
|
||||
next_block = _Heap_Block_at( the_block, the_size );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, next_block ) ||
|
||||
(the_block->front_flag != next_block->back_flag) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( _Heap_Is_previous_block_free( the_block ) ) {
|
||||
previous_block = _Heap_Previous_block( the_block );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, previous_block ) ) {
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( _Heap_Is_block_free( next_block ) ) { /* coalesce both */
|
||||
previous_block->front_flag += next_block->front_flag + the_size;
|
||||
temporary_block = _Heap_Next_block( previous_block );
|
||||
temporary_block->back_flag = previous_block->front_flag;
|
||||
next_block->next->previous = next_block->previous;
|
||||
next_block->previous->next = next_block->next;
|
||||
}
|
||||
else { /* coalesce prev */
|
||||
previous_block->front_flag =
|
||||
next_block->back_flag = previous_block->front_flag + the_size;
|
||||
}
|
||||
}
|
||||
else if ( _Heap_Is_block_free( next_block ) ) { /* coalesce next */
|
||||
the_block->front_flag = the_size + next_block->front_flag;
|
||||
new_next_block = _Heap_Next_block( the_block );
|
||||
new_next_block->back_flag = the_block->front_flag;
|
||||
the_block->next = next_block->next;
|
||||
the_block->previous = next_block->previous;
|
||||
next_block->previous->next = the_block;
|
||||
next_block->next->previous = the_block;
|
||||
|
||||
if (the_heap->first == next_block)
|
||||
the_heap->first = the_block;
|
||||
}
|
||||
else { /* no coalesce */
|
||||
next_block->back_flag =
|
||||
the_block->front_flag = the_size;
|
||||
the_block->previous = _Heap_Head( the_heap );
|
||||
the_block->next = the_heap->first;
|
||||
the_heap->first = the_block;
|
||||
the_block->next->previous = the_block;
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
64
cpukit/score/src/heapsizeofuserarea.c
Normal file
64
cpukit/score/src/heapsizeofuserarea.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Size_of_user_area
|
||||
*
|
||||
* This kernel routine returns the size of the memory area
|
||||
* given heap block.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* starting_address - starting address of the memory block to free.
|
||||
* size - pointer to size of area
|
||||
*
|
||||
* Output parameters:
|
||||
* size - size of area filled in
|
||||
* TRUE - if starting_address is valid heap address
|
||||
* FALSE - if starting_address is invalid heap address
|
||||
*/
|
||||
|
||||
boolean _Heap_Size_of_user_area(
|
||||
Heap_Control *the_heap,
|
||||
void *starting_address,
|
||||
unsigned32 *size
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block;
|
||||
Heap_Block *next_block;
|
||||
unsigned32 the_size;
|
||||
|
||||
the_block = _Heap_User_block_at( starting_address );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, the_block ) ||
|
||||
_Heap_Is_block_free( the_block ) )
|
||||
return( FALSE );
|
||||
|
||||
the_size = _Heap_Block_size( the_block );
|
||||
next_block = _Heap_Block_at( the_block, the_size );
|
||||
|
||||
if ( !_Heap_Is_block_in( the_heap, next_block ) ||
|
||||
(the_block->front_flag != next_block->back_flag) )
|
||||
return( FALSE );
|
||||
|
||||
*size = the_size;
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
150
cpukit/score/src/heapwalk.c
Normal file
150
cpukit/score/src/heapwalk.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Heap Handler
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/sysstate.h>
|
||||
#include <rtems/score/heap.h>
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Heap_Walk
|
||||
*
|
||||
* This kernel routine walks the heap and verifies its correctness.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_heap - pointer to heap header
|
||||
* source - a numeric indicator of the invoker of this routine
|
||||
* do_dump - when TRUE print the information
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
#ifndef RTEMS_DEBUG
|
||||
|
||||
void _Heap_Walk(
|
||||
Heap_Control *the_heap,
|
||||
int source,
|
||||
boolean do_dump
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void _Heap_Walk(
|
||||
Heap_Control *the_heap,
|
||||
int source,
|
||||
boolean do_dump
|
||||
)
|
||||
{
|
||||
Heap_Block *the_block = 0; /* avoid warnings */
|
||||
Heap_Block *next_block = 0; /* avoid warnings */
|
||||
int notdone = 1;
|
||||
int error = 0;
|
||||
int passes = 0;
|
||||
|
||||
/*
|
||||
* We don't want to allow walking the heap until we have
|
||||
* transferred control to the user task so we watch the
|
||||
* system state.
|
||||
*/
|
||||
|
||||
if ( !_System_state_Is_up( _System_state_Get() ) )
|
||||
return;
|
||||
|
||||
the_block = the_heap->start;
|
||||
|
||||
if (do_dump == TRUE) {
|
||||
printf("\nPASS: %d start @ 0x%p final 0x%p, first 0x%p last 0x%p\n",
|
||||
source, the_heap->start, the_heap->final,
|
||||
the_heap->first, the_heap->last
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the 1st block
|
||||
*/
|
||||
|
||||
if (the_block->back_flag != HEAP_DUMMY_FLAG) {
|
||||
printf("PASS: %d Back flag of 1st block isn't HEAP_DUMMY_FLAG\n", source);
|
||||
error = 1;
|
||||
}
|
||||
|
||||
while (notdone) {
|
||||
passes++;
|
||||
if (error && (passes > 10))
|
||||
abort();
|
||||
|
||||
if (do_dump == TRUE) {
|
||||
printf("PASS: %d Block @ 0x%p Back %d, Front %d",
|
||||
source, the_block,
|
||||
the_block->back_flag, the_block->front_flag);
|
||||
if ( _Heap_Is_block_free(the_block) ) {
|
||||
printf( " Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the last block
|
||||
*/
|
||||
|
||||
if ( the_block->front_flag != HEAP_DUMMY_FLAG ) {
|
||||
next_block = _Heap_Next_block(the_block);
|
||||
if ( the_block->front_flag != next_block->back_flag ) {
|
||||
error = 1;
|
||||
printf("PASS: %d Front and back flags don't match\n", source);
|
||||
printf(" Current Block (%p): Back - %d, Front - %d",
|
||||
the_block, the_block->back_flag, the_block->front_flag);
|
||||
if (do_dump == TRUE) {
|
||||
if (_Heap_Is_block_free(the_block)) {
|
||||
printf(" Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
printf(" Next Block (%p): Back - %d, Front - %d",
|
||||
next_block, next_block->back_flag, next_block->front_flag);
|
||||
if (do_dump == TRUE) {
|
||||
if (_Heap_Is_block_free(next_block)) {
|
||||
printf(" Prev 0x%p, Next 0x%p\n",
|
||||
the_block->previous, the_block->next);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (the_block->front_flag == HEAP_DUMMY_FLAG)
|
||||
notdone = 0;
|
||||
else
|
||||
the_block = next_block;
|
||||
}
|
||||
|
||||
if (error)
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
@@ -70,916 +70,3 @@ void _Thread_queue_Initialize(
|
||||
}
|
||||
|
||||
}
|
||||
#if 0
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Enqueue
|
||||
*
|
||||
* This routine blocks a thread, places it on a thread, and optionally
|
||||
* starts a timeout timer.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
* timeout - interval to wait
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* only case
|
||||
*/
|
||||
|
||||
void _Thread_queue_Enqueue(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Watchdog_Interval timeout
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
|
||||
the_thread = _Thread_Executing;
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet )
|
||||
the_thread = _Thread_MP_Allocate_proxy( the_thread_queue->state );
|
||||
else
|
||||
#endif
|
||||
_Thread_Set_state( the_thread, the_thread_queue->state );
|
||||
|
||||
if ( timeout ) {
|
||||
_Watchdog_Initialize(
|
||||
&the_thread->Timer,
|
||||
_Thread_queue_Timeout,
|
||||
the_thread->Object.id,
|
||||
NULL
|
||||
);
|
||||
|
||||
_Watchdog_Insert_ticks( &the_thread->Timer, timeout );
|
||||
}
|
||||
|
||||
switch( the_thread_queue->discipline ) {
|
||||
case THREAD_QUEUE_DISCIPLINE_FIFO:
|
||||
_Thread_queue_Enqueue_fifo( the_thread_queue, the_thread, timeout );
|
||||
break;
|
||||
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
|
||||
_Thread_queue_Enqueue_priority( the_thread_queue, the_thread, timeout );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Dequeue
|
||||
*
|
||||
* This routine removes a thread from the specified threadq. If the
|
||||
* threadq discipline is FIFO, it unblocks a thread, and cancels its
|
||||
* timeout timer. Priority discipline is processed elsewhere.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - thread dequeued or NULL
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* check sync
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_Dequeue(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
|
||||
switch ( the_thread_queue->discipline ) {
|
||||
case THREAD_QUEUE_DISCIPLINE_FIFO:
|
||||
the_thread = _Thread_queue_Dequeue_fifo( the_thread_queue );
|
||||
break;
|
||||
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
|
||||
the_thread = _Thread_queue_Dequeue_priority( the_thread_queue );
|
||||
break;
|
||||
default: /* this is only to prevent warnings */
|
||||
the_thread = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return( the_thread );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Extract_with_proxy
|
||||
*
|
||||
* This routine extracts the_thread from the_thread_queue
|
||||
* and insures that if there is a proxy for this task on
|
||||
* another node, it is also dealt with.
|
||||
*
|
||||
* XXX
|
||||
*/
|
||||
|
||||
boolean _Thread_queue_Extract_with_proxy(
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
States_Control state;
|
||||
Objects_Classes the_class;
|
||||
Thread_queue_Extract_callout proxy_extract_callout;
|
||||
|
||||
state = the_thread->current_state;
|
||||
|
||||
if ( _States_Is_waiting_on_thread_queue( state ) ) {
|
||||
if ( _States_Is_waiting_for_rpc_reply( state ) &&
|
||||
_States_Is_locally_blocked( state ) ) {
|
||||
|
||||
the_class = _Objects_Get_class( the_thread->Wait.id );
|
||||
|
||||
proxy_extract_callout = _Thread_queue_Extract_table[ the_class ];
|
||||
|
||||
if ( proxy_extract_callout )
|
||||
(*proxy_extract_callout)( the_thread );
|
||||
}
|
||||
_Thread_queue_Extract( the_thread->Wait.queue, the_thread );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Extract
|
||||
*
|
||||
* This routine removes a specific thread from the specified threadq,
|
||||
* deletes any timeout, and unblocks the thread.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to a threadq header
|
||||
* the_thread - pointer to a thread control block
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY: NONE
|
||||
*/
|
||||
|
||||
void _Thread_queue_Extract(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
switch ( the_thread_queue->discipline ) {
|
||||
case THREAD_QUEUE_DISCIPLINE_FIFO:
|
||||
_Thread_queue_Extract_fifo( the_thread_queue, the_thread );
|
||||
break;
|
||||
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
|
||||
_Thread_queue_Extract_priority( the_thread_queue, the_thread );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Flush
|
||||
*
|
||||
* This kernel routine flushes the given thread queue.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq to be flushed
|
||||
* remote_extract_callout - pointer to routine which extracts a remote thread
|
||||
* status - status to return to the thread
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
void _Thread_queue_Flush(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_queue_Flush_callout remote_extract_callout,
|
||||
unsigned32 status
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
|
||||
while ( (the_thread = _Thread_queue_Dequeue( the_thread_queue )) ) {
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
( *remote_extract_callout )( the_thread );
|
||||
else
|
||||
#endif
|
||||
the_thread->Wait.return_code = status;
|
||||
}
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_First
|
||||
*
|
||||
* This routines returns a pointer to the first thread on the
|
||||
* specified threadq.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to thread queue
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - first thread or NULL
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_First(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
|
||||
switch ( the_thread_queue->discipline ) {
|
||||
case THREAD_QUEUE_DISCIPLINE_FIFO:
|
||||
the_thread = _Thread_queue_First_fifo( the_thread_queue );
|
||||
break;
|
||||
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
|
||||
the_thread = _Thread_queue_First_priority( the_thread_queue );
|
||||
break;
|
||||
default: /* this is only to prevent warnings */
|
||||
the_thread = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return the_thread;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Timeout
|
||||
*
|
||||
* This routine processes a thread which timeouts while waiting on
|
||||
* a thread queue. It is called by the watchdog handler.
|
||||
*
|
||||
* Input parameters:
|
||||
* id - thread id
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
void _Thread_queue_Timeout(
|
||||
Objects_Id id,
|
||||
void *ignored
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
Thread_queue_Control *the_thread_queue;
|
||||
Objects_Locations location;
|
||||
|
||||
the_thread = _Thread_Get( id, &location );
|
||||
switch ( location ) {
|
||||
case OBJECTS_ERROR:
|
||||
case OBJECTS_REMOTE: /* impossible */
|
||||
break;
|
||||
case OBJECTS_LOCAL:
|
||||
the_thread_queue = the_thread->Wait.queue;
|
||||
|
||||
/*
|
||||
* If the_thread_queue 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.
|
||||
*/
|
||||
|
||||
if ( the_thread_queue->sync_state != THREAD_QUEUE_SYNCHRONIZED &&
|
||||
_Thread_Is_executing( the_thread ) ) {
|
||||
if ( the_thread_queue->sync_state != THREAD_QUEUE_SATISFIED )
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_TIMEOUT;
|
||||
} else {
|
||||
the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
|
||||
_Thread_queue_Extract( the_thread->Wait.queue, the_thread );
|
||||
}
|
||||
_Thread_Unnest_dispatch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Enqueue_fifo
|
||||
*
|
||||
* This routine blocks a thread, places it on a thread, and optionally
|
||||
* starts a timeout timer.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
* the_thread - pointer to the thread to block
|
||||
* timeout - interval to wait
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* only case
|
||||
*/
|
||||
|
||||
void _Thread_queue_Enqueue_fifo (
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread,
|
||||
Watchdog_Interval timeout
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
Thread_queue_States sync_state;
|
||||
|
||||
_ISR_Disable( level );
|
||||
|
||||
sync_state = the_thread_queue->sync_state;
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
|
||||
|
||||
switch ( sync_state ) {
|
||||
case THREAD_QUEUE_SYNCHRONIZED:
|
||||
/*
|
||||
* This should never happen. It indicates that someone did not
|
||||
* enter a thread queue critical section.
|
||||
*/
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_NOTHING_HAPPENED:
|
||||
_Chain_Append_unprotected(
|
||||
&the_thread_queue->Queues.Fifo,
|
||||
&the_thread->Object.Node
|
||||
);
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
|
||||
case THREAD_QUEUE_TIMEOUT:
|
||||
the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
|
||||
_ISR_Enable( level );
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_SATISFIED:
|
||||
if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
|
||||
_Watchdog_Deactivate( &the_thread->Timer );
|
||||
_ISR_Enable( level );
|
||||
(void) _Watchdog_Remove( &the_thread->Timer );
|
||||
} else
|
||||
_ISR_Enable( level );
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global objects with thread queue's should not be operated on from an
|
||||
* ISR. But the sync code still must allow short timeouts to be processed
|
||||
* correctly.
|
||||
*/
|
||||
|
||||
_Thread_Unblock( the_thread );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Dequeue_fifo
|
||||
*
|
||||
* This routine removes a thread from the specified threadq.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - thread dequeued or NULL
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* check sync
|
||||
* FIFO
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_Dequeue_fifo(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
Thread_Control *the_thread;
|
||||
|
||||
_ISR_Disable( level );
|
||||
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {
|
||||
|
||||
the_thread = (Thread_Control *)
|
||||
_Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
|
||||
return the_thread;
|
||||
}
|
||||
|
||||
switch ( the_thread_queue->sync_state ) {
|
||||
case THREAD_QUEUE_SYNCHRONIZED:
|
||||
case THREAD_QUEUE_SATISFIED:
|
||||
_ISR_Enable( level );
|
||||
return NULL;
|
||||
|
||||
case THREAD_QUEUE_NOTHING_HAPPENED:
|
||||
case THREAD_QUEUE_TIMEOUT:
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
|
||||
_ISR_Enable( level );
|
||||
return _Thread_Executing;
|
||||
}
|
||||
return NULL; /* this is only to prevent warnings */
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Extract_fifo
|
||||
*
|
||||
* This routine removes a specific thread from the specified threadq,
|
||||
* deletes any timeout, and unblocks the thread.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to a threadq header
|
||||
* the_thread - pointer to the thread to block
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* EXTRACT_FIFO
|
||||
*/
|
||||
|
||||
void _Thread_queue_Extract_fifo(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
|
||||
_ISR_Disable( level );
|
||||
|
||||
if ( !_States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
}
|
||||
|
||||
_Chain_Extract_unprotected( &the_thread->Object.Node );
|
||||
|
||||
if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
|
||||
_ISR_Enable( level );
|
||||
} else {
|
||||
_Watchdog_Deactivate( &the_thread->Timer );
|
||||
_ISR_Enable( level );
|
||||
(void) _Watchdog_Remove( &the_thread->Timer );
|
||||
}
|
||||
|
||||
_Thread_Unblock( the_thread );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_First_fifo
|
||||
*
|
||||
* This routines returns a pointer to the first thread on the
|
||||
* specified threadq.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - first thread or NULL
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_First_fifo(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) )
|
||||
return (Thread_Control *) the_thread_queue->Queues.Fifo.first;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Enqueue_priority
|
||||
*
|
||||
* This routine blocks a thread, places it on a thread, and optionally
|
||||
* starts a timeout timer.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to threadq
|
||||
* thread - thread to insert
|
||||
* timeout - timeout interval in ticks
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* forward less than
|
||||
* forward equal
|
||||
*/
|
||||
|
||||
void _Thread_queue_Enqueue_priority(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread,
|
||||
Watchdog_Interval timeout
|
||||
)
|
||||
{
|
||||
Priority_Control search_priority;
|
||||
Thread_Control *search_thread;
|
||||
ISR_Level level;
|
||||
Chain_Control *header;
|
||||
unsigned32 header_index;
|
||||
Chain_Node *the_node;
|
||||
Chain_Node *next_node;
|
||||
Chain_Node *previous_node;
|
||||
Chain_Node *search_node;
|
||||
Priority_Control priority;
|
||||
States_Control block_state;
|
||||
Thread_queue_States sync_state;
|
||||
|
||||
_Chain_Initialize_empty( &the_thread->Wait.Block2n );
|
||||
|
||||
priority = the_thread->current_priority;
|
||||
header_index = _Thread_queue_Header_number( priority );
|
||||
header = &the_thread_queue->Queues.Priority[ header_index ];
|
||||
block_state = the_thread_queue->state;
|
||||
|
||||
if ( _Thread_queue_Is_reverse_search( priority ) )
|
||||
goto restart_reverse_search;
|
||||
|
||||
restart_forward_search:
|
||||
search_priority = PRIORITY_MINIMUM - 1;
|
||||
_ISR_Disable( level );
|
||||
search_thread = (Thread_Control *) header->first;
|
||||
while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
|
||||
search_priority = search_thread->current_priority;
|
||||
if ( priority <= search_priority )
|
||||
break;
|
||||
|
||||
#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
|
||||
search_thread = (Thread_Control *) search_thread->Object.Node.next;
|
||||
if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
|
||||
break;
|
||||
search_priority = search_thread->current_priority;
|
||||
if ( priority <= search_priority )
|
||||
break;
|
||||
#endif
|
||||
_ISR_Flash( level );
|
||||
if ( !_States_Are_set( search_thread->current_state, block_state) ) {
|
||||
_ISR_Enable( level );
|
||||
goto restart_forward_search;
|
||||
}
|
||||
search_thread =
|
||||
(Thread_Control *)search_thread->Object.Node.next;
|
||||
}
|
||||
|
||||
if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
|
||||
goto synchronize;
|
||||
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
|
||||
|
||||
if ( priority == search_priority )
|
||||
goto equal_priority;
|
||||
|
||||
search_node = (Chain_Node *) search_thread;
|
||||
previous_node = search_node->previous;
|
||||
the_node = (Chain_Node *) the_thread;
|
||||
|
||||
the_node->next = search_node;
|
||||
the_node->previous = previous_node;
|
||||
previous_node->next = the_node;
|
||||
search_node->previous = the_node;
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
|
||||
restart_reverse_search:
|
||||
search_priority = PRIORITY_MAXIMUM + 1;
|
||||
|
||||
_ISR_Disable( level );
|
||||
search_thread = (Thread_Control *) header->last;
|
||||
while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
|
||||
search_priority = search_thread->current_priority;
|
||||
if ( priority >= search_priority )
|
||||
break;
|
||||
#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
|
||||
search_thread = (Thread_Control *) search_thread->Object.Node.previous;
|
||||
if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
|
||||
break;
|
||||
search_priority = search_thread->current_priority;
|
||||
if ( priority >= search_priority )
|
||||
break;
|
||||
#endif
|
||||
_ISR_Flash( level );
|
||||
if ( !_States_Are_set( search_thread->current_state, block_state) ) {
|
||||
_ISR_Enable( level );
|
||||
goto restart_reverse_search;
|
||||
}
|
||||
search_thread = (Thread_Control *)
|
||||
search_thread->Object.Node.previous;
|
||||
}
|
||||
|
||||
if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
|
||||
goto synchronize;
|
||||
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
|
||||
|
||||
if ( priority == search_priority )
|
||||
goto equal_priority;
|
||||
|
||||
search_node = (Chain_Node *) search_thread;
|
||||
next_node = search_node->next;
|
||||
the_node = (Chain_Node *) the_thread;
|
||||
|
||||
the_node->next = next_node;
|
||||
the_node->previous = search_node;
|
||||
search_node->next = the_node;
|
||||
next_node->previous = the_node;
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
|
||||
equal_priority: /* add at end of priority group */
|
||||
search_node = _Chain_Tail( &search_thread->Wait.Block2n );
|
||||
previous_node = search_node->previous;
|
||||
the_node = (Chain_Node *) the_thread;
|
||||
|
||||
the_node->next = search_node;
|
||||
the_node->previous = previous_node;
|
||||
previous_node->next = the_node;
|
||||
search_node->previous = the_node;
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
|
||||
synchronize:
|
||||
|
||||
sync_state = the_thread_queue->sync_state;
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
|
||||
|
||||
switch ( sync_state ) {
|
||||
case THREAD_QUEUE_SYNCHRONIZED:
|
||||
/*
|
||||
* This should never happen. It indicates that someone did not
|
||||
* enter a thread queue critical section.
|
||||
*/
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_NOTHING_HAPPENED:
|
||||
/*
|
||||
* This should never happen. All of this was dealt with above.
|
||||
*/
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_TIMEOUT:
|
||||
the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
|
||||
_ISR_Enable( level );
|
||||
break;
|
||||
|
||||
case THREAD_QUEUE_SATISFIED:
|
||||
if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
|
||||
_Watchdog_Deactivate( &the_thread->Timer );
|
||||
_ISR_Enable( level );
|
||||
(void) _Watchdog_Remove( &the_thread->Timer );
|
||||
} else
|
||||
_ISR_Enable( level );
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global objects with thread queue's should not be operated on from an
|
||||
* ISR. But the sync code still must allow short timeouts to be processed
|
||||
* correctly.
|
||||
*/
|
||||
|
||||
_Thread_Unblock( the_thread );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Dequeue_priority
|
||||
*
|
||||
* This routine removes a thread from the specified PRIORITY based
|
||||
* threadq, unblocks it, and cancels its timeout timer.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to thread queue
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - thread dequeued or NULL
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* only case
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_Dequeue_priority(
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
unsigned32 index;
|
||||
ISR_Level level;
|
||||
Thread_Control *the_thread = NULL; /* just to remove warnings */
|
||||
Thread_Control *new_first_thread;
|
||||
Chain_Node *new_first_node;
|
||||
Chain_Node *new_second_node;
|
||||
Chain_Node *last_node;
|
||||
Chain_Node *next_node;
|
||||
Chain_Node *previous_node;
|
||||
|
||||
_ISR_Disable( level );
|
||||
for( index=0 ;
|
||||
index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
|
||||
index++ ) {
|
||||
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
|
||||
the_thread = (Thread_Control *)
|
||||
the_thread_queue->Queues.Priority[ index ].first;
|
||||
goto dequeue;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( the_thread_queue->sync_state ) {
|
||||
case THREAD_QUEUE_SYNCHRONIZED:
|
||||
case THREAD_QUEUE_SATISFIED:
|
||||
_ISR_Enable( level );
|
||||
return NULL;
|
||||
|
||||
case THREAD_QUEUE_NOTHING_HAPPENED:
|
||||
case THREAD_QUEUE_TIMEOUT:
|
||||
the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
|
||||
_ISR_Enable( level );
|
||||
return _Thread_Executing;
|
||||
}
|
||||
|
||||
dequeue:
|
||||
new_first_node = the_thread->Wait.Block2n.first;
|
||||
new_first_thread = (Thread_Control *) new_first_node;
|
||||
next_node = the_thread->Object.Node.next;
|
||||
previous_node = the_thread->Object.Node.previous;
|
||||
|
||||
if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
|
||||
last_node = the_thread->Wait.Block2n.last;
|
||||
new_second_node = new_first_node->next;
|
||||
|
||||
previous_node->next = new_first_node;
|
||||
next_node->previous = new_first_node;
|
||||
new_first_node->next = next_node;
|
||||
new_first_node->previous = previous_node;
|
||||
|
||||
if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
|
||||
/* > two threads on 2-n */
|
||||
new_second_node->previous =
|
||||
_Chain_Head( &new_first_thread->Wait.Block2n );
|
||||
|
||||
new_first_thread->Wait.Block2n.first = new_second_node;
|
||||
new_first_thread->Wait.Block2n.last = last_node;
|
||||
|
||||
last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
|
||||
}
|
||||
} else {
|
||||
previous_node->next = next_node;
|
||||
next_node->previous = previous_node;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
return( the_thread );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_Extract_priority
|
||||
*
|
||||
* This routine removes a specific thread from the specified threadq,
|
||||
* deletes any timeout, and unblocks the thread.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to a threadq header
|
||||
* the_thread - pointer to a thread control block
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*
|
||||
* INTERRUPT LATENCY:
|
||||
* EXTRACT_PRIORITY
|
||||
*/
|
||||
|
||||
void _Thread_queue_Extract_priority(
|
||||
Thread_queue_Control *the_thread_queue,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
Chain_Node *the_node;
|
||||
Chain_Node *next_node;
|
||||
Chain_Node *previous_node;
|
||||
Thread_Control *new_first_thread;
|
||||
Chain_Node *new_first_node;
|
||||
Chain_Node *new_second_node;
|
||||
Chain_Node *last_node;
|
||||
|
||||
the_node = (Chain_Node *) the_thread;
|
||||
_ISR_Disable( level );
|
||||
if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
|
||||
next_node = the_node->next;
|
||||
previous_node = the_node->previous;
|
||||
|
||||
if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
|
||||
new_first_node = the_thread->Wait.Block2n.first;
|
||||
new_first_thread = (Thread_Control *) new_first_node;
|
||||
last_node = the_thread->Wait.Block2n.last;
|
||||
new_second_node = new_first_node->next;
|
||||
|
||||
previous_node->next = new_first_node;
|
||||
next_node->previous = new_first_node;
|
||||
new_first_node->next = next_node;
|
||||
new_first_node->previous = previous_node;
|
||||
|
||||
if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
|
||||
/* > two threads on 2-n */
|
||||
new_second_node->previous =
|
||||
_Chain_Head( &new_first_thread->Wait.Block2n );
|
||||
new_first_thread->Wait.Block2n.first = new_second_node;
|
||||
|
||||
new_first_thread->Wait.Block2n.last = last_node;
|
||||
last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
|
||||
}
|
||||
} else {
|
||||
previous_node->next = next_node;
|
||||
next_node->previous = previous_node;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
|
||||
_Thread_MP_Free_proxy( the_thread );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
_ISR_Enable( level );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Thread_queue_First_priority
|
||||
*
|
||||
* This routines returns a pointer to the first thread on the
|
||||
* specified threadq.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_thread_queue - pointer to thread queue
|
||||
*
|
||||
* Output parameters:
|
||||
* returns - first thread or NULL
|
||||
*/
|
||||
|
||||
Thread_Control *_Thread_queue_First_priority (
|
||||
Thread_queue_Control *the_thread_queue
|
||||
)
|
||||
{
|
||||
unsigned32 index;
|
||||
|
||||
for( index=0 ;
|
||||
index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
|
||||
index++ ) {
|
||||
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) )
|
||||
return (Thread_Control *)
|
||||
the_thread_queue->Queues.Priority[ index ].first;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user