Use full memory barriers to forbid compiler and CPU to move time samples apart. This improves accuracy of time to tick conversions.
Signed-off-by: Petri Savolainen <petri.savolainen@nokia.com> Reviewed-by: Jere Leppänen <jere.leppanen@nokia.com>
1 |
/* Copyright (c) 2015-2018, Linaro Limited
|
|
2 |
* All rights reserved.
|
|
3 |
*
|
|
4 |
* SPDX-License-Identifier: BSD-3-Clause
|
|
5 |
*/
|
|
6 |
|
|
7 |
#include <stdio.h> |
|
8 |
#include <string.h> |
|
9 |
#include <malloc.h> |
|
10 |
|
|
11 |
#include <odp/helper/odph_lineartable.h> |
|
12 |
#include <odp/helper/odph_debug.h> |
|
13 |
#include <odp_api.h> |
|
14 |
|
|
15 |
#define ODPH_SUCCESS 0
|
|
16 |
#define ODPH_FAIL -1
|
|
17 |
|
|
18 |
/** @magic word, write to the first byte of the memory block
|
|
19 |
* to indicate this block is used by a linear table structure
|
|
20 |
*/
|
|
21 |
#define ODPH_LINEAR_TABLE_MAGIC_WORD 0xEFEFFEFE
|
|
22 |
|
|
23 |
/** @internal table struct
|
|
24 |
* For linear table, value is orgnized as a big array,
|
|
25 |
* and key is the index of this array, so we just need to record the
|
|
26 |
* content of value, and make sure the key won't overflow
|
|
27 |
*/
|
|
28 |
typedef struct { |
|
29 |
uint32_t magicword; /**< for check */ |
|
30 |
uint32_t init_cap; /**< input param of capacity */ |
|
31 |
/** given the capacity, caculate out the max supported nodes number */
|
|
32 |
uint32_t node_sum; |
|
33 |
/** size of a lineartable element,including the rwlock in the head */
|
|
34 |
uint32_t value_size; |
|
35 |
void *value_array; /**< value pool in array format */ |
|
36 |
char name[ODPH_TABLE_NAME_LEN]; /**< name of the table */ |
|
37 |
} odph_linear_table_imp; |
|
38 |
|
|
39 |
/** Note: for linear table, key must be an number, its size is fixed 4.
|
|
40 |
* So, we ignore the input key_size here
|
|
41 |
*/
|
|
42 |
|
|
43 |
odph_table_t odph_linear_table_create(const char *name, uint32_t capacity, |
|
44 |
uint32_t un ODP_UNUSED, |
|
45 |
uint32_t value_size) |
|
46 |
{
|
|
47 |
uint32_t idx; |
|
48 |
uint32_t node_num; |
|
49 |
odp_shm_t shmem; |
|
50 |
odph_linear_table_imp *tbl; |
|
51 |
|
|
52 |
if (strlen(name) >= ODPH_TABLE_NAME_LEN || capacity < 1 || |
|
53 |
capacity >= 0x1000 || value_size == 0) { |
|
54 |
printf("create para input error or less than !"); |
|
55 |
return NULL; |
|
56 |
}
|
|
57 |
/* check name confict in shm*/
|
|
58 |
if (odp_shm_lookup(name) != ODP_SHM_INVALID) { |
|
59 |
ODPH_DBG("name already exist\n"); |
|
60 |
return NULL; |
|
61 |
}
|
|
62 |
|
|
63 |
/* alloc memory from shm */
|
|
64 |
shmem = odp_shm_reserve(name, capacity << 20, 64, ODP_SHM_SW_ONLY); |
|
65 |
if (shmem == ODP_SHM_INVALID) { |
|
66 |
ODPH_DBG("shm reserve fail\n"); |
|
67 |
return NULL; |
|
68 |
}
|
|
69 |
tbl = (odph_linear_table_imp *)odp_shm_addr(shmem); |
|
70 |
|
|
71 |
/* clean this block of memory */
|
|
72 |
memset(tbl, 0, capacity << 20); |
|
73 |
|
|
74 |
tbl->init_cap = capacity < 20; |
|
75 |
|
|
76 |
strncpy(tbl->name, name, ODPH_TABLE_NAME_LEN - 1); |
|
77 |
|
|
78 |
/* for linear table, the key is just the index, without confict
|
|
79 |
* so we just need to record the value content
|
|
80 |
* there is a rwlock in the head of every node
|
|
81 |
*/
|
|
82 |
|
|
83 |
tbl->value_size = value_size + sizeof(odp_rwlock_t); |
|
84 |
|
|
85 |
node_num = tbl->init_cap / tbl->value_size; |
|
86 |
tbl->node_sum = node_num; |
|
87 |
|
|
88 |
tbl->value_array = (void *)((char *)tbl |
|
89 |
+ sizeof(odph_linear_table_imp)); |
|
90 |
|
|
91 |
/* initialize rwlock*/
|
|
92 |
for (idx = 0; idx < tbl->node_sum; idx++) { |
|
93 |
odp_rwlock_t *lock; |
|
94 |
|
|
95 |
lock = (odp_rwlock_t *)(void *)((char *)tbl->value_array |
|
96 |
+ idx * tbl->value_size); |
|
97 |
odp_rwlock_init(lock); |
|
98 |
}
|
|
99 |
|
|
100 |
tbl->magicword = ODPH_LINEAR_TABLE_MAGIC_WORD; |
|
101 |
|
|
102 |
return (odph_table_t)(tbl); |
|
103 |
}
|
|
104 |
|
|
105 |
int odph_linear_table_destroy(odph_table_t table) |
|
106 |
{
|
|
107 |
int ret; |
|
108 |
odph_linear_table_imp *linear_tbl = NULL; |
|
109 |
|
|
110 |
if (table != NULL) { |
|
111 |
linear_tbl = (odph_linear_table_imp *)(void *)table; |
|
112 |
|
|
113 |
/* check magicword, make sure the memory is used by a table */
|
|
114 |
if (linear_tbl->magicword != ODPH_LINEAR_TABLE_MAGIC_WORD) |
|
115 |
return ODPH_FAIL; |
|
116 |
|
|
117 |
ret = odp_shm_free(odp_shm_lookup(linear_tbl->name)); |
|
118 |
if (ret != 0) { |
|
119 |
ODPH_DBG("free fail\n"); |
|
120 |
return ret; |
|
121 |
}
|
|
122 |
|
|
123 |
return ODPH_SUCCESS; |
|
124 |
}
|
|
125 |
return ODPH_FAIL; |
|
126 |
}
|
|
127 |
|
|
128 |
odph_table_t odph_linear_table_lookup(const char *name) |
|
129 |
{
|
|
130 |
odph_linear_table_imp *tbl = NULL; |
|
131 |
odp_shm_t shm; |
|
132 |
|
|
133 |
if (name == NULL || strlen(name) >= ODPH_TABLE_NAME_LEN) |
|
134 |
return NULL; |
|
135 |
|
|
136 |
shm = odp_shm_lookup(name); |
|
137 |
if (shm != ODP_SHM_INVALID) |
|
138 |
tbl = (odph_linear_table_imp *)odp_shm_addr(shm); |
|
139 |
|
|
140 |
/* check magicword to make sure the memory block is used by a table */
|
|
141 |
if (tbl != NULL && |
|
142 |
tbl->magicword == ODPH_LINEAR_TABLE_MAGIC_WORD && |
|
143 |
strcmp(tbl->name, name) == 0) |
|
144 |
return (odph_table_t)tbl; |
|
145 |
|
|
146 |
return NULL; |
|
147 |
}
|
|
148 |
|
|
149 |
/* should make sure the input table exists and is available */
|
|
150 |
static int odph_lineartable_put_value(odph_table_t table, |
|
151 |
void *key, void *value) |
|
152 |
{
|
|
153 |
odph_linear_table_imp *tbl; |
|
154 |
uint32_t ikey = 0; |
|
155 |
void *entry = NULL; |
|
156 |
odp_rwlock_t *lock = NULL; |
|
157 |
|
|
158 |
if (table == NULL || key == NULL || value == NULL) |
|
159 |
return ODPH_FAIL; |
|
160 |
|
|
161 |
tbl = (odph_linear_table_imp *)(void *)table; |
|
162 |
ikey = *(uint32_t *)key; |
|
163 |
if (ikey >= tbl->node_sum) |
|
164 |
return ODPH_FAIL; |
|
165 |
|
|
166 |
entry = (void *)((char *)tbl->value_array + ikey * tbl->value_size); |
|
167 |
lock = (odp_rwlock_t *)entry; |
|
168 |
entry = (char *)entry + sizeof(odp_rwlock_t); |
|
169 |
|
|
170 |
odp_rwlock_write_lock(lock); |
|
171 |
|
|
172 |
memcpy(entry, value, tbl->value_size - sizeof(odp_rwlock_t)); |
|
173 |
|
|
174 |
odp_rwlock_write_unlock(lock); |
|
175 |
|
|
176 |
return ODPH_SUCCESS; |
|
177 |
}
|
|
178 |
|
|
179 |
/* should make sure the input table exists and is available */
|
|
180 |
static int odph_lineartable_get_value(odph_table_t table, |
|
181 |
void *key, void *buffer, |
|
182 |
uint32_t buffer_size ODP_UNUSED) |
|
183 |
{
|
|
184 |
odph_linear_table_imp *tbl; |
|
185 |
uint32_t ikey = 0; |
|
186 |
void *entry = NULL; |
|
187 |
odp_rwlock_t *lock = NULL; |
|
188 |
|
|
189 |
if (table == NULL || key == NULL || buffer == NULL) |
|
190 |
return ODPH_FAIL; |
|
191 |
|
|
192 |
tbl = (odph_linear_table_imp *)(void *)table; |
|
193 |
ikey = *(uint32_t *)key; |
|
194 |
if (ikey >= tbl->node_sum) |
|
195 |
return ODPH_FAIL; |
|
196 |
|
|
197 |
entry = (void *)((char *)tbl->value_array + ikey * tbl->value_size); |
|
198 |
lock = (odp_rwlock_t *)entry; |
|
199 |
entry = (char *)entry + sizeof(odp_rwlock_t); |
|
200 |
|
|
201 |
odp_rwlock_read_lock(lock); |
|
202 |
|
|
203 |
memcpy(buffer, entry, tbl->value_size - sizeof(odp_rwlock_t)); |
|
204 |
|
|
205 |
odp_rwlock_read_unlock(lock); |
|
206 |
|
|
207 |
return ODPH_SUCCESS; |
|
208 |
}
|
|
209 |
|
|
210 |
odph_table_ops_t odph_linear_table_ops = { |
|
211 |
odph_linear_table_create, |
|
212 |
odph_linear_table_lookup, |
|
213 |
odph_linear_table_destroy, |
|
214 |
odph_lineartable_put_value, |
|
215 |
odph_lineartable_get_value, |
|
216 |
NULL, |
|
217 |
};
|
|
218 |
|
Read our documentation on viewing source code .