aboutsummaryrefslogtreecommitdiff
path: root/include/odp/api/spec/sync.h
blob: 18272af88adb545e3fc1a6cda0107d8550229ad6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright (c) 2013-2018 Linaro Limited
 * Copyright (c) 2023 Nokia
 */

/**
 * @file
 *
 * ODP memory barriers
 */

#ifndef ODP_API_SPEC_SYNC_H_
#define ODP_API_SPEC_SYNC_H_
#include <odp/visibility_begin.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @addtogroup odp_barrier
 * @details
 * <b> Memory barriers </b>
 *
 * A memory barrier enforces the order between memory accesses (loads and/or stores)
 * specified (in program order) before the barrier with those specified after the barrier.
 * A barrier may affect both compiler optimizations and CPU out-of-order execution. Depending
 * on the used HW platform and barrier types, heavy usage of barriers may cause significant
 * performance degradation.
 *
 * An application may use these memory barrier functions e.g. to build a synchronization
 * mechanism between its threads in shared memory, or when it accesses memory mapped registers
 * of a device.
 *
 * An application does not need to use these memory barriers when using other ODP APIs for thread
 * synchronization (execution barriers, spinlocks, etc.), or when exchanging data through ODP API
 * mechanisms (queues, stashes, etc.). Those ODP calls include necessary (acquire and release)
 * memory barriers to maintain coherency between data producers and consumers.
 *
 * Some ODP atomic operations include a memory barrier - see for example odp_atomic_load_acq_u32()
 * or odp_atomic_store_rel_u32(). Application may use also those (non-relaxed) atomic operations
 * to enforce memory ordering while using atomic variables.
 *
 *  @{
 */

/**
 * Memory barrier for release operations
 *
 * This memory barrier has release semantics. It synchronizes with a pairing
 * barrier for acquire operations. The releasing and acquiring threads
 * synchronize through shared memory. The releasing thread must call this
 * barrier before signaling the acquiring thread. After the acquiring thread
 * receives the signal, it must call odp_mb_acquire() before it reads the
 * memory written by the releasing thread.
 *
 * This call is not needed when using ODP defined synchronization mechanisms.
 *
 * @see odp_mb_acquire()
 */
void odp_mb_release(void);

/**
 * Memory barrier for acquire operations
 *
 * This memory barrier has acquire semantics. It synchronizes with a pairing
 * barrier for release operations. The releasing and acquiring threads
 * synchronize through shared memory. The releasing thread must call
 * odp_mb_release() before signaling the acquiring thread. After the acquiring
 * thread receives the signal, it must call this barrier before it reads the
 * memory written by the releasing thread.
 *
 * This call is not needed when using ODP defined synchronization mechanisms.
 *
 * @see odp_mb_release()
 */
void odp_mb_acquire(void);

/**
 * Full memory barrier
 *
 * This is a full memory barrier. It guarantees that all load and store
 * operations specified before it are visible to other threads before
 * all load and store operations specified after it.
 *
 * This call is not needed when using ODP defined synchronization mechanisms.
 */
void odp_mb_full(void);

/**
 * Memory barrier for load and store synchronization
 *
 * This memory barrier ensures that all memory accesses (loads and stores) specified before the
 * barrier (in program order) are complete prior to any memory access specified after the barrier
 * begins execution.
 *
 * This is a stronger barrier than odp_mb_full(), as in addition to visibility order also memory
 * access completion is ensured. The barrier may be useful e.g. when synchronizing loads and stores
 * into memory mapped registers of a device.
 */
void odp_mb_sync(void);

/**
 * Memory barrier for load synchronization
 *
 * This memory barrier ensures that all memory loads specified before the barrier (in program
 * order) are complete prior to any memory load specified after the barrier begins execution.
 *
 * The barrier may be useful e.g. when synchronizing loads from memory mapped registers of a device.
 */
void odp_mb_sync_load(void);

/**
 * Memory synchronization barrier for stores
 *
 * This memory barrier ensures that all memory stores specified before the barrier (in program
 * order) are complete prior to any memory store specified after the barrier begins execution.
 *
 * The barrier may be useful e.g. when synchronizing stores to memory mapped registers of a device.
 */
void odp_mb_sync_store(void);

/**
 * @}
 */

#ifdef __cplusplus
}
#endif

#include <odp/visibility_end.h>
#endif