157 lines
3.2 KiB
C
Executable file
157 lines
3.2 KiB
C
Executable file
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Samsung Exynos SoC series dsp driver
|
|
*
|
|
* Copyright (c) 2019 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com/
|
|
*/
|
|
|
|
#include "dl/dsp-hash.h"
|
|
|
|
void dsp_hash_tab_init(struct dsp_hash_tab *tab)
|
|
{
|
|
int idx;
|
|
|
|
for (idx = 0; idx < DSP_HASH_MAX; idx++)
|
|
dsp_list_head_init(&tab->list[idx]);
|
|
}
|
|
|
|
unsigned int dsp_hash_get_key(const char *data)
|
|
{
|
|
int len;
|
|
unsigned int hash, tmp;
|
|
int rem;
|
|
|
|
|
|
if (data == NULL)
|
|
return 0;
|
|
|
|
len = strlen(data);
|
|
if (len <= 0)
|
|
return 0;
|
|
|
|
hash = len;
|
|
|
|
rem = len & 3;
|
|
len >>= 2;
|
|
|
|
for (; len > 0; len--) {
|
|
hash += get16bits(data);
|
|
tmp = (get16bits(data + 2) << 11) ^ hash;
|
|
hash = (hash << 16) ^ tmp;
|
|
data += 2 * sizeof(unsigned short);
|
|
hash += hash >> 11;
|
|
}
|
|
|
|
switch (rem) {
|
|
case 3:
|
|
hash += get16bits(data);
|
|
hash ^= hash << 16;
|
|
hash ^= ((signed char)data[sizeof(unsigned short)]) << 18;
|
|
hash += hash >> 11;
|
|
break;
|
|
case 2:
|
|
hash += get16bits(data);
|
|
hash ^= hash << 11;
|
|
hash += hash >> 17;
|
|
break;
|
|
case 1:
|
|
hash += (signed char)(*data);
|
|
hash ^= hash << 10;
|
|
hash += hash >> 1;
|
|
}
|
|
|
|
hash ^= hash << 3;
|
|
hash += hash >> 5;
|
|
hash ^= hash << 4;
|
|
hash += hash >> 17;
|
|
hash ^= hash << 25;
|
|
hash += hash >> 6;
|
|
|
|
return hash % DSP_HASH_MAX;
|
|
}
|
|
|
|
void dsp_hash_push(struct dsp_hash_tab *tab, const char *k, void *value)
|
|
{
|
|
unsigned int key = dsp_hash_get_key(k);
|
|
struct dsp_list_head *hash_head = &tab->list[key];
|
|
struct dsp_hash_node *hash_node =
|
|
(struct dsp_hash_node *)dsp_dl_malloc(sizeof(*hash_node),
|
|
"Hash node");
|
|
|
|
hash_node->key = key;
|
|
hash_node->str = (char *)dsp_dl_malloc(strlen(k) + 1, "Hash node str");
|
|
strcpy(hash_node->str, k);
|
|
|
|
hash_node->value = value;
|
|
dsp_list_node_init(&hash_node->node);
|
|
dsp_list_node_push_back(hash_head, &hash_node->node);
|
|
}
|
|
|
|
int dsp_hash_get(struct dsp_hash_tab *tab, const char *k, void **value)
|
|
{
|
|
unsigned int key = dsp_hash_get_key(k);
|
|
struct dsp_list_node *node;
|
|
|
|
*value = NULL;
|
|
dsp_list_for_each(node, &tab->list[key]) {
|
|
struct dsp_hash_node *hash_node =
|
|
container_of(node, struct dsp_hash_node, node);
|
|
|
|
if (hash_node->key == key && strcmp(hash_node->str, k) == 0) {
|
|
*value = hash_node->value;
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void dsp_hash_pop(struct dsp_hash_tab *tab, const char *k, int free_data)
|
|
{
|
|
unsigned int key = dsp_hash_get_key(k);
|
|
struct dsp_list_node *node = tab->list[key].next;
|
|
|
|
while (node != NULL) {
|
|
struct dsp_hash_node *hash_node =
|
|
container_of(node, struct dsp_hash_node, node);
|
|
|
|
node = node->next;
|
|
|
|
if (hash_node->key == key && strcmp(hash_node->str, k) == 0) {
|
|
dsp_list_node_remove(&tab->list[key], &hash_node->node);
|
|
|
|
if (free_data)
|
|
dsp_dl_free(hash_node->value);
|
|
|
|
dsp_dl_free(hash_node->str);
|
|
dsp_dl_free(hash_node);
|
|
}
|
|
}
|
|
}
|
|
|
|
void dsp_hash_free(struct dsp_hash_tab *tab, int free_data)
|
|
{
|
|
int idx;
|
|
|
|
DL_DEBUG("Hash free(%d)\n", free_data);
|
|
|
|
for (idx = 0; idx < DSP_HASH_MAX; idx++) {
|
|
struct dsp_list_node *cur, *next;
|
|
|
|
cur = (&tab->list[idx])->next;
|
|
|
|
while (cur != NULL) {
|
|
struct dsp_hash_node *hash_node =
|
|
container_of(cur, struct dsp_hash_node, node);
|
|
|
|
next = cur->next;
|
|
|
|
if (free_data)
|
|
dsp_dl_free(hash_node->value);
|
|
|
|
dsp_dl_free(hash_node->str);
|
|
dsp_dl_free(hash_node);
|
|
cur = next;
|
|
}
|
|
}
|
|
}
|