Difference between pages "r7.1.1:Macro LFDS711 PAL ATOMIC DWCAS" and "r7.1.1:Function libbenchmark misc pal helper add logical processor node to topology tree"

From liblfds.org
(Difference between pages)
Jump to navigation Jump to search
m (1 revision imported)
 
m (1 revision imported)
 
Line 1: Line 1:
{{DISPLAYTITLE:macro LFDS711_PAL_ATOMIC_DWCAS}}
{{DISPLAYTITLE:function libbenchmark_misc_pal_helper_new_topology_node}}
==Source File==
==Source Files==
  └───liblfds711
  └───test_and_benchmark
     └───inc
     └───libbenchmark
         └───liblfds711
         ├───inc
                lfds711_porting_abstraction_layer_compiler.h
        │  └───libbenchmark
        │          libbenchmark_porting_abstraction_layer.h
        └───src
            └───libbenchmark_misc
                    libbenchmark_misc_pal_helpers.c


==Enums==
==Opaque Structures==
  enum [[r7.1.1:enum lfds711_misc_cas_strength|lfds711_misc_cas_strength]]
  struct [[r7.1.1:struct libbenchmark_topology_state|libbenchmark_topology_state]];
{
  LFDS711_MISC_CAS_WEAK,
  LFDS711_MISC_CAS_STRONG
};


==Macro==
==Prototype==
  #define LFDS711_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) [compiler atomic DWCAS instrinsic]
  void libbenchmark_misc_pal_helper_add_logical_processor_node_to_topology_tree( struct libbenchmark_topology_state *ts,
                                                                                lfds711_pal_uint_t logical_processor_number,
                                                                                enum flag windows_processor_group_inuse_flag,
                                                                                lfds711_pal_uint_t windows_processor_group_number );


==Parameters==
==Parameters==
''pointer_to_destination''
''struct libbenchmark_topology_state *ts''
: A pointer to an array of two ''lfds711_pal_uint_t volatile''.  The value of ''*pointer_to_destination'' is compared to the value of ''*pointer_to_compare'' and if they are equal, ''*new_value'' is written into ''*pointer_to_destination''.
: A pointer a ''struct libbenchmark_topology'' obtained from ''libbenchmark_pal_populate_topology''.


''pointer_to_compare''
''lfds711_pal_uint_t logical_processor_number''
: A pointer to an array of two ''lfds711_pal_uint_t''.  Whether or not the compare is successful (and so whether or not ''*new_value'' is written into ''*pointer_to_destination''), the original value of ''*pointer_to_destination'' is written into ''*pointer_to_compare'', i.e. the compare value is always lost.
: The logical processor number of the logical processor to add to the topology tree pointed to by ''ts''.


''pointer_to_new_destination''
''enum flag windows_processor_group_inuse_flag''
: A pointer to an array of two ''lfds711_pal_uint_t''.  This value is written into ''*pointer_to_destination'' if ''*pointer_to_destination'' and ''*pointer_to_compare'' are equal.
: An ''enum flag'' which indicates whether or not the ''windows_processor_group_number'' argument contains a valid value (for that field is only meaningful on Windows 7 and greater).


''cas_strength''
''lfds711_pal_uint_t windows_processor_group_number''
: This argument is only meaningful on LL/SC platforms, and if set to ''LFDS711_MISC_CAS_STRONG'' indicates the macro should internally retry if the LL/SC operation aborted.  See Notes.
: The Windows processor group number of the logical processor to add to the topology tree pointed to by ''ts''.  This value is only meaningful on Windows 7 and greater.  It will only be used if the ''windows_processor_group_inuse_flag'' is set to ''RAISED'', and so if not used, can be set to any value.  Zero is as good a choice as any other.
 
''result''
: A ''char unsigned'', which is set to 1 if the swap occurred, 0 if not.


==Return Value==
==Return Value==
Line 36: Line 36:


==Example==
==Example==
#define LFDS711_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )                            \
{                                                                                                                                                            \
  (result) = 0;                                                                                                                                              \
                                                                                                                                                              \
  __asm__ __volatile__                                                                                                                                      \
  (                                                                                                                                                          \
    "lock;"          /* make cmpxchg16b atomic        */                                                                                                    \
    "cmpxchg16b %0;"  /* cmpxchg16b sets ZF on success */                                                                                                    \
    "setz      %4;"  /* if ZF set, set result to 1    */                                                                                                    \
                                                                                                                                                              \
    /* output */                                                                                                                                            \
    : "+m" ((pointer_to_destination)[0]), "+m" ((pointer_to_destination)[1]), "+a" ((pointer_to_compare)[0]), "+d" ((pointer_to_compare)[1]), "=q" (result)  \
                                                                                                                                                              \
    /* input */                                                                                                                                              \
    : "b" ((pointer_to_new_destination)[0]), "c" ((pointer_to_new_destination)[1])                                                                          \
                                                                                                                                                              \
    /* clobbered */                                                                                                                                          \
    :                                                                                                                                                        \
  );                                                                                                                                                        \
}
#endif
==Optionality==
This macro is optional. If it is not given, the macro must be absent, rather than empty.


==Notes==
==Notes==
All of the atomic operation macros open and close with curley braces as some of them need to declare variables on the stack, so that they can operate in ways which match their 'prototype' (i.e. they may need a bit of temporary storage, as the way in which the macro is arranged to work doesn't map directly to the atomic intrinsic prototype for that platform).  We see this here in the example.
This helper function is used by ''libbenchmark_pal_populate_topology'' to add a logical processor node to the topology tree.
 
The actual atomic intrinsic if it does not inherently provide compiler barriers itself MUST be immediately preceeded and followed by ''LFDS711_PAL_BARRIER_COMPILER_FULL''.  This is to prevent compiler re-ordering.
 
Finally, we get to the actual atomic operation itself.  The ''liblfds711_pal_uint_t'' types need to be cast to the types the intrinsic expects, and to the maximum extent possible eschew any memory barriers.  On ARM, for example, memory barriers and atomic operations are wholly seperated and on that platform, the operation is and is only an atomic operation.  The data structures themselves issue memory barriers as and when they must, and any additional barriers issued within the atomic macros are only overhead.  On x86 and x64, sadly, memory barriers are built into the atomic operations and cannot be removed.  On Itanium, it looks like atomic operations must occur with a barrier, but it is possible to choose a load, store or full barrier, and as such on that platform, the load barrier is always used, as it is the lowest cost of the three.
 
The example here is for a platform (x64 GCC) where the processor supports DWCAS, but where the compiler has no intrinsic for this operation.  As such, it is necessary to directly issue the necessary assembly instructions.
 
If this atomic operaton is not available, the macro must be left undefined, which will lead to a placeholder version automatically being used.  This placeholder version if called first calls ''LFDS711_PAL_ASSERT'' and then, assuming execution has continued (i.e. ''LFDS711_PAL_ASSERT'' is not defined, or is defined but this is a release user-mode build and so asserts are not being checked) will attempt to write 0 into memory location 0, to deliberately crash.


==See Also==
==See Also==
* [[r7.1.1:Porting Guide (liblfds)|Porting Guide (liblfds)]]
* [[r7.1.1:Porting Guide (libbenchmark)|Porting Guide (libbenchmark)]]
* ''[[r7.1.1:function libbenchmark_pal_populate_topology|libbenchmark_pal_populate_topology]]''

Latest revision as of 20:16, 17 February 2017

Source Files

└───test_and_benchmark
    └───libbenchmark
        ├───inc
        │   └───libbenchmark
        │           libbenchmark_porting_abstraction_layer.h
        └───src
            └───libbenchmark_misc
                    libbenchmark_misc_pal_helpers.c

Opaque Structures

struct libbenchmark_topology_state;

Prototype

void libbenchmark_misc_pal_helper_add_logical_processor_node_to_topology_tree( struct libbenchmark_topology_state *ts,
                                                                               lfds711_pal_uint_t logical_processor_number,
                                                                               enum flag windows_processor_group_inuse_flag,
                                                                               lfds711_pal_uint_t windows_processor_group_number );

Parameters

struct libbenchmark_topology_state *ts

A pointer a struct libbenchmark_topology obtained from libbenchmark_pal_populate_topology.

lfds711_pal_uint_t logical_processor_number

The logical processor number of the logical processor to add to the topology tree pointed to by ts.

enum flag windows_processor_group_inuse_flag

An enum flag which indicates whether or not the windows_processor_group_number argument contains a valid value (for that field is only meaningful on Windows 7 and greater).

lfds711_pal_uint_t windows_processor_group_number

The Windows processor group number of the logical processor to add to the topology tree pointed to by ts. This value is only meaningful on Windows 7 and greater. It will only be used if the windows_processor_group_inuse_flag is set to RAISED, and so if not used, can be set to any value. Zero is as good a choice as any other.

Return Value

No return value.

Example

Notes

This helper function is used by libbenchmark_pal_populate_topology to add a logical processor node to the topology tree.

See Also