Boost logo

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