dataman: remove locking mechanism

This commit is contained in:
Igor Mišić
2023-07-24 13:10:31 +02:00
committed by Beat Küng
parent 3143f6bd0a
commit c40a38bd88
8 changed files with 183 additions and 862 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
uint64 timestamp # time since system start (microseconds)
uint8 client_id
uint8 request_type # id/read/write/clear/lock/unlock
uint8 request_type # id/read/write/clear
uint8 item # dm_item_t
uint32 index
uint8[56] data
+1 -4
View File
@@ -1,7 +1,7 @@
uint64 timestamp # time since system start (microseconds)
uint8 client_id
uint8 request_type # id/read/write/clear/lock/unlock
uint8 request_type # id/read/write/clear
uint8 item # dm_item_t
uint32 index
uint8[56] data
@@ -12,7 +12,4 @@ uint8 STATUS_FAILURE_NO_DATA = 2
uint8 STATUS_FAILURE_READ_FAILED = 3
uint8 STATUS_FAILURE_WRITE_FAILED = 4
uint8 STATUS_FAILURE_CLEAR_FAILED = 5
uint8 STATUS_ALREADY_LOCKED = 6
uint8 STATUS_ALREADY_UNLOCKED = 7
uint8 STATUS_ITEM_LOCKED = 8
uint8 status
File diff suppressed because it is too large Load Diff
+1 -42
View File
@@ -87,28 +87,6 @@ public:
*/
bool clearSync(dm_item_t item, hrt_abstime timeout = 1000_ms);
/**
* @brief Locks an item in the dataman for exclusive access.
*
* This function sends a DM_LOCK request to the dataman to lock an item for exclusive access.
* If the item is already locked, it will wait and retry until it can obtain the lock or the timeout
* is reached. Once the lock is obtained, the item can be safely modified.
*
* @param[in] item The item to be locked.
* @param[in] timeout The maximum time to wait for the lock in microseconds.
* @return true if the item is locked successfully, false otherwise.
*/
bool lockSync(dm_item_t item, hrt_abstime timeout = 1000_ms);
/**
* Unlock an item in dataman.
*
* @param[in] item: The item to unlock.
* @param[in] timeout: The timeout for the operation.
* @return True if the unlock operation was successful, false otherwise.
*/
bool unlockSync(dm_item_t item, hrt_abstime timeout = 1000_ms);
/**
* @brief Initiates an asynchronous request to read the data from dataman for a specific item and index.
*
@@ -151,25 +129,6 @@ public:
*/
bool clearAsync(dm_item_t item);
/**
* @brief Locks a dataman item asynchronously.
*
* This function sends a lock request to the dataman service, asking it to lock the specified item.
* The function returns immediately, without waiting for the lock operation to complete.
*
* @param[in] item The dataman item to be locked.
* @return True if the lock request was successfully sent, false otherwise.
*/
bool lockAsync(dm_item_t item);
/**
* @brief Unlocks the specified dataman item asynchronously.
*
* @param[in] item The item to unlock.
* @return true if the request was successfully queued, false otherwise.
*/
bool unlockAsync(dm_item_t item);
/**
* @brief Updates the state of the dataman client for asynchronous functions.
*
@@ -177,7 +136,7 @@ public:
* and updates the state accordingly. If there is no response for a request, it retries the
* request after a timeout.
*
* @see readAsync(), writeAsync(), clearAsync(), lockAsync(), unlockAsync(), lastOperationCompleted()
* @see readAsync(), writeAsync(), clearAsync(), lastOperationCompleted()
*/
void update();
+20 -81
View File
@@ -140,10 +140,6 @@ static constexpr size_t g_per_item_size_with_hdr[DM_KEY_NUM_KEYS] = {
/* Table of offset for index 0 of each item type */
static unsigned int g_key_offsets[DM_KEY_NUM_KEYS];
/* Item type lock for dataman client id*/
static uint8_t g_item_locks[DM_KEY_NUM_KEYS];
constexpr uint8_t NOT_LOCKED = 0; // dataman client id reserved for unlock state
static uint8_t dataman_clients_count = 1;
static perf_counter_t _dm_read_perf{nullptr};
@@ -633,10 +629,6 @@ task_main(int argc, char *argv[])
g_func_counts[i] = 0;
}
for (uint32_t i = 0; i < DM_KEY_NUM_KEYS; i++) {
g_item_locks[i] = false;
}
g_task_should_exit = false;
uORB::Publication<dataman_response_s> dataman_response_pub{ORB_ID(dataman_response)};
@@ -704,7 +696,7 @@ task_main(int argc, char *argv[])
switch (request.request_type) {
case DM_GET_ID:
if ((dataman_clients_count < UINT8_MAX) && (dataman_clients_count > NOT_LOCKED)) {
if (dataman_clients_count < UINT8_MAX) {
response.client_id = dataman_clients_count++;
/* Send the timestamp of the request over the data buffer so that the "dataman client"
* can distinguish whether the request was made by it. */
@@ -718,100 +710,51 @@ task_main(int argc, char *argv[])
case DM_WRITE:
if ((g_item_locks[request.item] == NOT_LOCKED) ||
(g_item_locks[request.item] == request.client_id)) {
g_func_counts[DM_WRITE]++;
result = g_dm_ops->write(static_cast<dm_item_t>(request.item), request.index,
&(request.data), request.data_length);
g_func_counts[DM_WRITE]++;
result = g_dm_ops->write(static_cast<dm_item_t>(request.item), request.index,
&(request.data), request.data_length);
if (result > 0) {
response.status = dataman_response_s::STATUS_SUCCESS;
} else if (result < 0) {
response.status = dataman_response_s::STATUS_FAILURE_WRITE_FAILED;
}
if (result > 0) {
response.status = dataman_response_s::STATUS_SUCCESS;
} else {
response.status = dataman_response_s::STATUS_ITEM_LOCKED;
response.status = dataman_response_s::STATUS_FAILURE_WRITE_FAILED;
}
break;
case DM_READ:
if ((g_item_locks[request.item] == NOT_LOCKED) ||
(g_item_locks[request.item] == request.client_id)) {
g_func_counts[DM_READ]++;
result = g_dm_ops->read(static_cast<dm_item_t>(request.item), request.index,
&(response.data), request.data_length);
g_func_counts[DM_READ]++;
result = g_dm_ops->read(static_cast<dm_item_t>(request.item), request.index,
&(response.data), request.data_length);
if (result > 0) {
response.status = dataman_response_s::STATUS_SUCCESS;
} else if (result < 0) {
response.status = dataman_response_s::STATUS_FAILURE_READ_FAILED;
}
if (result > 0) {
response.status = dataman_response_s::STATUS_SUCCESS;
} else {
response.status = dataman_response_s::STATUS_ITEM_LOCKED;
response.status = dataman_response_s::STATUS_FAILURE_READ_FAILED;
}
break;
case DM_CLEAR:
if ((g_item_locks[request.item] == NOT_LOCKED) ||
(g_item_locks[request.item] == request.client_id)) {
g_func_counts[DM_CLEAR]++;
result = g_dm_ops->clear(static_cast<dm_item_t>(request.item));
g_func_counts[DM_CLEAR]++;
result = g_dm_ops->clear(static_cast<dm_item_t>(request.item));
if (result == 0) {
response.status = dataman_response_s::STATUS_SUCCESS;
} else {
response.status = dataman_response_s::STATUS_FAILURE_CLEAR_FAILED;
}
} else {
response.status = dataman_response_s::STATUS_ITEM_LOCKED;
}
break;
case DM_LOCK:
if (g_item_locks[request.item] == NOT_LOCKED ||
(g_item_locks[request.item] == request.client_id)) {
g_func_counts[DM_LOCK]++;
g_item_locks[request.item] = request.client_id;
if (result == 0) {
response.status = dataman_response_s::STATUS_SUCCESS;
} else {
response.status = dataman_response_s::STATUS_ALREADY_LOCKED;
}
break;
case DM_UNLOCK:
if (g_item_locks[request.item] == request.client_id) {
g_func_counts[DM_UNLOCK]++;
g_item_locks[request.item] = NOT_LOCKED;
response.status = dataman_response_s::STATUS_SUCCESS;
} else if (g_item_locks[request.item] != request.client_id) {
response.status = dataman_response_s::STATUS_ALREADY_UNLOCKED;
response.status = dataman_response_s::STATUS_FAILURE_CLEAR_FAILED;
}
break;
default:
break;
}
response.timestamp = hrt_absolute_time();
@@ -875,8 +818,6 @@ status()
PX4_INFO("Writes %u", g_func_counts[DM_WRITE]);
PX4_INFO("Reads %u", g_func_counts[DM_READ]);
PX4_INFO("Clears %u", g_func_counts[DM_CLEAR]);
PX4_INFO("Locks %u", g_func_counts[DM_LOCK]);
PX4_INFO("Unlocks %u", g_func_counts[DM_LOCK]);
perf_print_counter(_dm_read_perf);
perf_print_counter(_dm_write_perf);
@@ -904,13 +845,11 @@ It is used to store structured data of different types: mission waypoints, missi
Each type has a specific type and a fixed maximum amount of storage items, so that fast random access is possible.
### Implementation
Reading and writing a single item is always atomic. If multiple items need to be read/modified atomically, there is
an additional lock per item type via `dm_lock`.
Reading and writing a single item is always atomic.
**DM_KEY_FENCE_POINTS** and **DM_KEY_SAFE_POINTS** items: the first data element is a `mission_stats_entry_s` struct,
which stores the number of items for these types. These items are always updated atomically in one transaction (from
the mavlink mission manager). During that time, navigator will try to acquire the geofence item lock, fail, and will not
check for geofence violations.
the mavlink mission manager).
)DESCR_STR");
-2
View File
@@ -59,8 +59,6 @@ typedef enum {
DM_WRITE, ///< Write index for given item
DM_READ, ///< Read index for given item
DM_CLEAR, ///< Clear all index for given item
DM_LOCK, ///< Lock all items for given item types
DM_UNLOCK, ///< Unlock all items for given item types
DM_NUMBER_OF_FUNCS
} dm_function_t;
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -81,7 +81,7 @@ const struct {
{"bezier", test_bezierQuad, 0},
{"bitset", test_bitset, 0},
{"bson", test_bson, 0},
{"dataman", test_dataman, OPT_NOJIGTEST | OPT_NOALLTEST},
{"dataman", test_dataman, OPT_NOJIGTEST | OPT_NOALLTEST},
{"file2", test_file2, OPT_NOJIGTEST},
{"float", test_float, 0},
{"hott_telemetry", test_hott_telemetry, OPT_NOJIGTEST | OPT_NOALLTEST},