|
Boost : |
From: Sid Sacek (ssacek_at_[hidden])
Date: 2007-10-11 15:12:53
#include <stdio.h>
#define CPU_SPARC ( defined( __sparc ) || defined( sparc ) )
#include "safe_access.h"
#pragma pack( 1 )
struct foo
{
unsigned char a; // doesn't need safe access
SA( unsigned int ) b; // unaligned int needs safe access
};
#pragma pack()
int main( int, char ** )
{
foo foo = { 0xAA, 0xBBBBBBBB };
unsigned char a = foo.a;
unsigned int b = foo.b;
printf( " &a = %p a = %x \n", &foo.a, a );
printf( " &b = %p b = %x \n", &foo.b, b );
foo.a = 0x12;
foo.b = 0x34567890;
printf( " a = %x \n", int( foo.a ) );
printf( " b = %x \n", int( foo.b ) );
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++
//--------------------------------------------------------------------------
-------------
// Safe Access
//
// These routines are used to access memory addresses that would cause
bus-errors on the
// SPARC platform if accessed in the normal C++ way, due to misaligned
memory addresses.
//--------------------------------------------------------------------------
-------------
#ifndef __SAFE_ACCESS_H__
#define __SAFE_ACCESS_H__
#pragma once
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++
//--------------------------------------------------------------------------
-------------
// Safe Variable Copy
//
// These routines behave like memcpy function calls, but are specialized
for data type
// sizes 2, 4, and 8 bytes. It is designed to execute in the fewest
number of assembly
// instructions without calling memcpy. Under the SUN platform using
SPARC processors,
// crashes occur with bus-alignment errors when data is located at random
addresses.
//--------------------------------------------------------------------------
-------------
template< int Sizeof_Variable > void safe_variable_copy( void *, const void
* );
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++
//--------------------------------------------------------------------------
-------------
// Specialization for sizeof( short )
//
// safe_variable_copy< 2 >( &left, &right )
//--------------------------------------------------------------------------
-------------
template<>
inline void safe_variable_copy< 2 >( void * left, const void * right )
{
static_cast< char * >( left )[ 0 ] = static_cast< const char * >(
right )[ 0 ];
static_cast< char * >( left )[ 1 ] = static_cast< const char * >(
right )[ 1 ];
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++
//--------------------------------------------------------------------------
-------------
// Specialization for sizeof( int )
//
// safe_variable_copy< 4 >( &left, &right )
//--------------------------------------------------------------------------
-------------
template<>
inline void safe_variable_copy< 4 >( void * left, const void * right )
{
static_cast< char * >( left )[ 0 ] = static_cast< const char * >(
right )[ 0 ];
static_cast< char * >( left )[ 1 ] = static_cast< const char * >(
right )[ 1 ];
static_cast< char * >( left )[ 2 ] = static_cast< const char * >(
right )[ 2 ];
static_cast< char * >( left )[ 3 ] = static_cast< const char * >(
right )[ 3 ];
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++
//--------------------------------------------------------------------------
-------------
// Specialization for sizeof( long long )
//
// safe_variable_copy< 8 >( &left, &right )
//--------------------------------------------------------------------------
-------------
template<>
inline void safe_variable_copy< 8 >( void * left, const void * right )
{
static_cast< char * >( left )[ 0 ] = static_cast< const char * >(
right )[ 0 ];
static_cast< char * >( left )[ 1 ] = static_cast< const char * >(
right )[ 1 ];
static_cast< char * >( left )[ 2 ] = static_cast< const char * >(
right )[ 2 ];
static_cast< char * >( left )[ 3 ] = static_cast< const char * >(
right )[ 3 ];
static_cast< char * >( left )[ 4 ] = static_cast< const char * >(
right )[ 4 ];
static_cast< char * >( left )[ 5 ] = static_cast< const char * >(
right )[ 5 ];
static_cast< char * >( left )[ 6 ] = static_cast< const char * >(
right )[ 6 ];
static_cast< char * >( left )[ 7 ] = static_cast< const char * >(
right )[ 7 ];
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++
//--------------------------------------------------------------------------
-------------
// Safe Access
//
// This templated function is used to prevent a bus errors under the SUN
SPARC systems.
// We wrap the misaligned variables with a function call to this routine.
//--------------------------------------------------------------------------
-------------
template< typename Ty >
inline Ty safe_access( const Ty & value )
{
Ty result; // access memory using a
memory-aligned variable
safe_variable_copy< sizeof( Ty ) >( &result, &value );
return result; // pass back the value from
misaligned variable
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++
//--------------------------------------------------------------------------
-------------
// Safe Access Data Wrapper
//
// This wrapper class is used to wrap data defined in structures that are
possibly
// misaligned for the computer's bus architecture. It is typically meant
to be used
// inside data structures that are packed using the #pragma pack(n).
//
// Example of usage:
//
#if 0
#pragma pack(1)
struct Packed_Structure
{
u8 status; // this is aligned at offset 0
SA( u32 ) value; // this is aligned at offset 1 (
can cause a bus error )
};
#pragma pack()
void foo( Packed_Structure * pk )
{
u8 var1 = pk->status;
u32 var2 = pk->value; // this can no longer cause a bus
error
}
#endif
//
// The data type 'SA( u32 )' in the above structure uses the
'safe_access' method to
// ensure that bus errors don't occur when the data is being accessed on
the fragile
// platform. Since the network structures are typically packed, and
possibly aligned
// on addresses that can cause bus errors, the structure's data elements
should use
// versions of data elements that are 'access safe'.
//--------------------------------------------------------------------------
-------------
template< typename Ty >
struct safe_access_wrapper
{
Ty m_data; // contains the data that is possibly
misaligned
operator Ty() const { return safe_access( m_data ); }
const Ty & operator = ( const Ty & value ) { safe_variable_copy<
sizeof( Ty ) >( &m_data, &value ); return m_data; }
};
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++
//--------------------------------------------------------------------------
-------------
// SAFE() Macro ( Safe Access )
// SA() Macro ( Safe Access Type Wrapper )
//
// The SA() macro is used to wrap structure elements inside packed
structures that may
// cause bus errors when accessed, like on the SPARC processors.
// Example of usage:
//
// #pragma pack(1)
// struct Packed_Structure
// {
// u8 byte_aligned; // accessing this never causes a
bus error
// SA( u32 ) mis_aligned; // accessing this can no longer
cause a bus error
// };
//
// The SAFE() macro is used to wrap access to basic data types that cause
bus errors.
// Example of usage:
//
// void foo( Packed_Structure * pk )
// {
// u32 var1 = pk->variable; // this may cause a bus error
on the SPARC chip
// u32 var2 = SAFE( pk->variable ); // this can no longer cause a
bus error
// }
//--------------------------------------------------------------------------
-------------
#if CPU_SPARC
#define SA( type ) safe_access_wrapper< type >
#define SAFE( argument ) safe_access( argument )
#else
#define SA( type ) type
#define SAFE( argument ) ( argument )
#endif
#endif // #ifndef __SAFE_ACCESS_H__
//
//--------------------------------------------------------------------------
-------------
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk