Sequences of read and write instructions can often be executed more quickly if run in an order that’s different from the program text (Corbet et al., 2005). As a result, modern processors customarily reorder read and write instructions. However, this optimization can foul up drivers performing PMIO and MMIO. To prevent instruction reordering, memory barriers are employed. Memory barriers ensure that all instructions before the barrier conclude before any instruction after the barrier. For PMIO and MMIO operations, the bus_barrier
function provides this ability:
#include <sys/bus.h> #include <machine/bus.h> void bus_barrier(struct resource *r, bus_size_t offset, bus_size_t length, int flags);
The bus_barrier
function inserts a memory barrier that enforces the ordering of read or write operations on a region in r
, which is described by the offset
and length
arguments. The flags
argument specifies the type of operation to be ordered. Valid values for this argument are shown in Table 10-1.
Table 10-1. bus_barrier Symbolic Constants
Constant | Description |
---|---|
| Synchronizes read operations |
| Synchronizes write operations |
Note that these flags can be ORed to enforce ordering on both read and write operations. An exemplary use of bus_barrier
looks something like this:
bus_write_1(r, 0, data0); bus_barrier(r, 0, 1, BUS_SPACE_BARRIER_WRITE); bus_write_1(r, 0, data1); bus_barrier(r, 0, 2, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); data2 = bus_read_1(r, 1); bus_barrier(r, 1, 1, BUS_SPACE_BARRIER_READ); data3 = bus_read_1(r, 1);
Here, the calls to bus_barrier
guarantee that the writes and reads conclude in the order written.
3.141.198.146