Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions subsys/fs/zms/zms.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
#include <zephyr/sys/crc.h>
#include "zms_priv.h"
#ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS
#ifdef CONFIG_SETTINGS_ZMS_LEGACY
#include <settings/settings_zms_legacy.h>
#else
#include <settings/settings_zms.h>
#endif
#endif

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(fs_zms, CONFIG_ZMS_LOG_LEVEL);
Expand All @@ -34,6 +38,39 @@ static inline size_t zms_lookup_cache_pos(uint32_t id)
uint32_t hash = id;

#ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS
#ifdef CONFIG_SETTINGS_ZMS_LEGACY
/*
* 1. The ZMS settings backend uses up to (ZMS_NAME_ID_OFFSET - 1) ZMS IDs to
store keys and equal number of ZMS IDs to store values.
* 2. For each key-value pair, the value is stored at ZMS ID greater by exactly
* ZMS_NAME_ID_OFFSET than ZMS ID that holds the key.
* 3. The backend tries to minimize the range of ZMS IDs used to store keys.
* That is, ZMS IDs are allocated sequentially, and freed ZMS IDs are reused
* before allocating new ones.
*
* Therefore, to assure the least number of collisions in the lookup cache,
* the least significant bit of the hash indicates whether the given ZMS ID
* represents a key or a value, and remaining bits of the hash are set to
* the ordinal number of the key-value pair. Consequently, the hash function
* provides the following mapping:
*
* 1st settings key => hash 0
* 1st settings value => hash 1
* 2nd settings key => hash 2
* 2nd settings value => hash 3
* ...
*/
BUILD_ASSERT(IS_POWER_OF_TWO(ZMS_NAMECNT_ID), "ZMS_NAMECNT_ID is not power of 2");
BUILD_ASSERT(IS_POWER_OF_TWO(ZMS_NAME_ID_OFFSET), "ZMS_NAME_ID_OFFSET is not power of 2");

uint32_t key_value_bit;
uint32_t key_value_ord;

key_value_bit = (id >> LOG2(ZMS_NAME_ID_OFFSET)) & 1;
key_value_ord = id & (ZMS_NAME_ID_OFFSET - 1);

hash = ((key_value_ord << 1) | key_value_bit);
#else
/*
* 1. Settings subsystem is storing the name ID and the linked list node ID
* with only one bit difference at BIT(0).
Expand All @@ -58,6 +95,7 @@ static inline size_t zms_lookup_cache_pos(uint32_t id)
key_value_ll = id & BIT(0);

hash = (key_value_hash << 2) | (key_value_bit << 1) | key_value_ll;
#endif /* CONFIG_SETTINGS_ZMS_LEGACY */
#else
/* 32-bit integer hash function found by https://github.com/skeeto/hash-prospector. */
hash ^= hash >> 16;
Expand Down