/*
 * Copyright 2016, NICTA
 *
 * This software may be distributed and modified according to the terms of
 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
 * See "LICENSE_BSD2.txt" for details.
 *
 * @TAG(NICTA_BSD)
 */

#pragma once

/* macros for forcing the compiler to leave in statments it would
 * normally optimize away */

#include <utils/attribute.h>
#include <utils/stringify.h>

/* Macro for doing dummy reads
 *
 * Expands to a volatile, unused variable which is set to the value at
 * a given address. It's volatile to prevent the compiler optimizing
 * away a variable that is written but never read, and it's unused to
 * prevent warnings about a variable that's never read.
 */
#define FORCE_READ(address) \
        volatile UNUSED typeof(*address) JOIN(__force__read, __COUNTER__) = *(address)

/*
 * Copyright 2016, NICTA
 *
 * This software may be distributed and modified according to the terms of
 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
 * See "LICENSE_BSD2.txt" for details.
 *
 * @TAG(NICTA_BSD)
 */

#pragma once

/* macros for forcing the compiler to leave in statments it would
 * normally optimize away */

#include <utils/attribute.h>
#include <utils/stringify.h>

/* Macro for doing dummy reads
 *
 * Forces a memory read access to the given address.
 */
#define FORCE_READ(address) \
    do { \
        typeof(*(address)) *_ptr = (address); \
        asm volatile ("" : "=m"(*_ptr) : "r"(*_ptr)); \
    } while (0)

Rephrase FORCE_READ into something safer.
libutils: Rephrase FORCE_READ into something safer.

This commit rephrases the `FORCE_READ` macro to avoid an unorthodox use of
`volatile`. The change makes the read less malleable from the compiler's point
of view.

It also has the unintended side effect of slightly optimising this operation. On
x86, an optimising compiler now generates a single load, rather than a load
followed by a store to the (unused) local variable. On ARM, there is a similar
improvement, but we also save two instructions for stack pointer manipulation
depending on the context in which the macro is expanded.
