Boost logo

Boost :

From: Sid Sacek (ssacek_at_[hidden])
Date: 2007-10-11 15:38:48


#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