summaryrefslogtreecommitdiff
path: root/drivers/staging/nmf-cm/cm/engine/utils/src/table.c
blob: 708396a01b29bdce0f4a308d549c4c557af29668 (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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Copyright (C) ST-Ericsson SA 2010
 * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
 * License terms: GNU General Public License (GPL) version 2.
 */
/*
 *
 */
#include <cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h>
#include <cm/engine/trace/inc/trace.h>
#include <cm/engine/utils/inc/mem.h>
#include <cm/engine/utils/inc/table.h>

/*
 * Methods
 */
t_cm_error cm_initTable(t_nmf_table* table)
{
	table->idxMax = TABLE_DEF_SIZE / sizeof(table->entries);

	table->entries = OSAL_Alloc_Zero(table->idxMax*sizeof(table->entries));

	if (table->entries == NULL) {
		table->idxMax = 0;
		return CM_NO_MORE_MEMORY;
	}

	return CM_OK;
}

void cm_destroyTable(t_nmf_table* table)
{
	if (table->idxNb) {
		ERROR("Attempt to free non-empty table !!!\n", 0, 0, 0, 0, 0, 0);
		return;
	}
	OSAL_Free(table->entries);
	table->idxMax = 0;
}

static t_cm_error cm_increaseTable(t_nmf_table* table)
{
	t_uint32 new_max;
	void *mem;

	if (table->idxMax == INDEX_MASK) {
		ERROR("CM_NO_MORE_MEMORY: Maximum table entries reached\n", 0, 0, 0, 0, 0, 0);
		return CM_NO_MORE_MEMORY;
	}

	new_max = table->idxMax
		+ TABLE_DEF_SIZE / sizeof(table->entries);

	if (new_max > INDEX_MAX)
		new_max = INDEX_MAX;

	mem = OSAL_Alloc(new_max * sizeof(table->entries));

	if (mem == NULL) {
		ERROR("CM_NO_MORE_MEMORY: Unable to allocate memory for a table\n", 0, 0, 0, 0, 0, 0);
		return CM_NO_MORE_MEMORY;
	}

	cm_MemCopy(mem, table->entries,
		   table->idxMax*sizeof(table->entries));
	cm_MemSet((void *)((t_uint32) mem + table->idxMax*sizeof(*table->entries)), 0,
		  (new_max-table->idxMax) * sizeof(*table->entries));

	OSAL_Free(table->entries);
	table->entries = mem;
	table->idxMax = new_max;

	return CM_OK;
}

/** cm_addEntry - Add an local pointer to an element to the list
 *
 *  1. Increase the size of the list if it's full
 *  2. Search an empty entry
 *  3. Add the element to the list
 *  4. Compute and return the "user handle"
 */
t_uint32 cm_addEntry(t_nmf_table *table, void *entry)
{
	unsigned int i;
	t_uint32 hdl = 0;

	if (table->idxNb == table->idxMax)
		cm_increaseTable(table);

	for (i = table->idxCur;
	     table->entries[i] != 0 && i != (table->idxCur-1);
	     i = (i+1)%table->idxMax);

	if (table->entries[i] == 0) {
		table->entries[i] = entry;
		table->idxCur = (i+1) % table->idxMax;
		table->idxNb++;
		hdl = ENTRY2HANDLE(entry, i);
	} else
		ERROR("No free entry found in table\n", 0, 0, 0, 0, 0, 0);

	return hdl;
}

/** cm_delEntry - remove the given element from the list
 *
 *  1. Check if the handle is valid
 *  2. Search the entry and free it
 */
void cm_delEntry(t_nmf_table *table, t_uint32 idx)
{
	table->entries[idx] = NULL;
	table->idxNb--;
}

/** cm_lookupEntry - search the entry corresponding to
 *                   the user handle.
 *
 * 1. Check if the handle is valid
 * 2. Return a pointer to the element
 */
void *cm_lookupEntry(const t_nmf_table *table, const t_uint32 hdl)
{
	unsigned int idx = hdl & INDEX_MASK;

	if ((idx >= table->idxMax)
	    || (((unsigned int)table->entries[idx] << INDEX_SHIFT) != (hdl & ~INDEX_MASK)))
		return NULL;
	else
		return table->entries[idx];
}

/** cm_lookupHandle - search the handle corresponding
 *                    to the given element
 *
 * 1. Check if the handler is valid or is a special handler
 * 2. Loop in the table to retrieve the entry matching and return its value
 */
t_uint32 cm_lookupHandle(const t_nmf_table *table, const void *entry)
{
	t_uint32 i;

	/* NULL is an invalid value that must be handle separatly
	   as it'll match all used/free entries value */
	if (entry == NULL)
		return 0;

	for (i=0; i < table->idxMax; i++) {
		if (table->entries[i] == entry)
			return ENTRY2HANDLE(table->entries[i], i);
	}

	return 0;
}