2 *------------------------------------------------------------------
3 * index_list.c - vector-index-based lists. 64-bit pointers suck.
5 * Copyright (c) 2008-2009, 2011 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
22 //#include <clib_lite.h>
23 #include <vppinfra/vec.h>
24 #include "index_list.h"
29 * args: headp -- pointer to e.g. a hash bucket
30 * vector -- vector containing the list
31 * elsize -- size of an element in this vector
32 * offset -- offset in each vector element of this list thread
33 * index_to_add -- index in the vector to add to the list
35 * Adds new items to the head of the list. Try not to screw up the args!
37 void index_slist_addhead (index_slist_t *headp,
38 u8 *vector, u32 elsize, u32 offset, u32 index_to_add)
40 return (index_slist_addhead_inline(headp, vector, elsize, offset,
47 * args: headp -- pointer to e.g. a hash bucket
48 * vector -- vector containing the list
49 * elsize -- size of an element in this vector
50 * offset -- offset in each vector element of this list thread
51 * index_to_del -- index in the vector to delete from the list
53 * Try not to screw up the args!
56 int index_slist_remelem (index_slist_t *headp,
57 u8 *vector, u32 elsize, u32 offset,
60 return (index_slist_remelem_inline(headp, vector, elsize, offset,
68 * Append the indicated vector element to the doubly-linked list
69 * whose first element is pointed to by headp.
71 * args: head_index -- listhead vector element index.
72 * vector -- vector containing the list
73 * elsize -- size of an element in this vector
74 * offset -- offset in each vector element of this list thread
75 * index_to_add -- index in the vector to add to the list
77 * Do not call this routine to create the listhead. Simply set
78 * index_dlist->next = index_dlist->prev = index of item.
80 * Try not to screw up the args.
83 void index_dlist_addtail (u32 head_index, u8 *vector, u32 elsize,
84 u32 offset, u32 index_to_add)
87 index_dlist_t *elp_next;
90 headp = (index_dlist_t *)(vector + offset + elsize*head_index);
91 elp = (index_dlist_t *)(vector + offset + elsize*index_to_add);
92 elp->next = index_to_add;
93 elp->prev = index_to_add;
95 elp->next = headp->next;
96 headp->next = index_to_add;
98 elp_next = (index_dlist_t *)(vector + offset + elsize*elp->next);
99 elp->prev = elp_next->prev;
100 elp_next->prev = index_to_add;
103 u32 index_dlist_remelem (u32 head_index,
104 u8 *vector, u32 elsize, u32 offset,
108 index_dlist_t *headp, *elp, *elp_next;
110 elp = (index_dlist_t *)(vector + offset + elsize*index_to_delete);
112 /* Deleting the head index? */
113 if (PREDICT_FALSE(head_index == index_to_delete)) {
115 /* The only element on the list? */
116 if (PREDICT_FALSE(rv == head_index))
120 headp = (index_dlist_t *)(vector + offset + elsize*elp->prev);
121 headp->next = elp->next;
122 elp_next = (index_dlist_t *)(vector + offset + elsize*elp->next);
123 elp_next->prev = elp->prev;
125 elp->next = elp->prev = EMPTY;
139 void index_list_test_cmd(int argc, unsigned long *argv)
143 index_dlist_t *headp;
149 memset(tp, 0xa, sizeof(tp[0])*vec_len(tp));
151 /* Here's how to set up the head element... */
152 headp = &((tp + head_index)->l);
153 headp->next = headp->prev = head_index;
155 for (i = 0; i < 3; i++) {
156 index_dlist_addtail(head_index, (u8 *)tp, sizeof(tp[0]),
157 STRUCT_OFFSET_OF(tv_t, l), i);
158 printf("headp next %d prev %d\n",
159 headp->next, headp->prev);
160 for (j = 0; j <= 3; j++) {
161 printf ("[%d]: next %d prev %d\n", j,
162 tp[j].l.next, tp[j].l.prev);
164 printf("---------------\n");
168 printf("After all adds:\n");
170 printf("headp next %d prev %d\n",
171 headp->next, headp->prev);
173 for (j = 0; j <= 3; j++) {
174 printf ("[%d]: next %d prev %d\n", j,
175 tp[j].l.next, tp[j].l.prev);
177 printf("---------------\n");
179 head_index = index_dlist_remelem (head_index, (u8 *)tp, sizeof(tp[0]),
180 STRUCT_OFFSET_OF(tv_t, l), 1);
182 printf("after delete 1, head index %d\n", head_index);
183 headp = &((tp + head_index)->l);
184 printf("headp next %d prev %d\n",
185 headp->next, headp->prev);
186 for (j = 0; j <= 3; j++) {
187 printf ("[%d]: next %d prev %d\n", j,
188 tp[j].l.next, tp[j].l.prev);
190 printf("---------------\n");
192 index_dlist_addtail(head_index, (u8 *)tp, sizeof(tp[0]),
193 STRUCT_OFFSET_OF(tv_t, l), 1);
195 printf("after re-add 1, head index %d\n", head_index);
196 headp = &((tp + head_index)->l);
197 printf("headp next %d prev %d\n",
198 headp->next, headp->prev);
199 for (j = 0; j <= 3; j++) {
200 printf ("[%d]: next %d prev %d\n", j,
201 tp[j].l.next, tp[j].l.prev);
203 printf("---------------\n");
205 for (i = 3; i >= 0; i--) {
206 head_index = index_dlist_remelem (head_index, (u8 *)tp, sizeof(tp[0]),
207 STRUCT_OFFSET_OF(tv_t, l), i);
208 printf("after delete, head index %d\n", head_index);
209 if (head_index != EMPTY) {
210 headp = &((tp + head_index)->l);
211 printf("headp next %d prev %d\n",
212 headp->next, headp->prev);
213 for (j = 0; j <= 3; j++) {
214 printf ("[%d]: next %d prev %d\n", j,
215 tp[j].l.next, tp[j].l.prev);
218 printf("empty list\n");
220 printf("---------------\n");
223 #endif /* test code 2 */
233 void index_list_test_cmd(int argc, unsigned long *argv)
237 index_slist_t *buckets = 0;
239 vec_add1((u32 *)buckets, EMPTY);
242 for (i = 0; i < 10; i++) {
243 index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp),
244 STRUCT_OFFSET_OF(tv_t, l), i);
247 printf ("after adds, buckets[0] = %u\n", buckets[0]);
249 for (j = 0; j < 10; j++) {
250 printf("tp[%d] next %u\n", j, tp[j].l);
254 for (i = 0; i < 10; i++) {
255 if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp),
256 STRUCT_OFFSET_OF(tv_t, l), i))) {
257 printf("OUCH: remelem failure at index %d\n", i);
259 if (PREDICT_FALSE(tp[i].l.next != EMPTY)) {
260 printf("OUCH: post-remelem next not EMPTY, index %d\n", i);
264 printf ("after deletes, buckets[0] = %x\n", buckets[0]);
266 for (i = 0; i < 10; i++) {
267 index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp),
268 STRUCT_OFFSET_OF(tv_t, l), i);
271 printf ("after adds, buckets[0] = %u\n", buckets[0]);
273 for (j = 0; j < 10; j++) {
274 printf("tp[%d] next %u\n", j, tp[j].l);
278 for (i = 9; i >= 0; i--) {
279 if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp),
280 STRUCT_OFFSET_OF(tv_t, l), i))) {
281 printf("OUCH: remelem failure at index %d\n", i);
283 if ((tp[i].l.next != EMPTY)) {
284 printf("OUCH: post-remelem next not EMPTY, index %d\n", i);
288 printf ("after deletes, buckets[0] = %x\n", buckets[0]);
290 printf("add evens, then odds...\n");
292 for (i = 0; i < 10; i += 2) {
293 index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp),
294 STRUCT_OFFSET_OF(tv_t, l), i);
296 printf ("head = buckets[0].next = %d\n", buckets[0].next);
297 for (j = 0; j < 10; j++) {
298 printf("tp[%d] next %u\n", j, tp[j].l);
300 printf("-------------\n");
303 for (i = 1; i < 10; i += 2) {
304 index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp),
305 STRUCT_OFFSET_OF(tv_t, l), i);
307 printf ("head = buckets[0].next = %d\n", buckets[0].next);
308 for (j = 0; j < 10; j++) {
309 printf("tp[%d] next %u\n", j, tp[j].l);
311 printf("-------------\n");
314 printf ("after adds, buckets[0] = %u\n", buckets[0]);
316 for (j = 0; j < 10; j++) {
317 printf("tp[%d] next %u\n", j, tp[j].l);
321 for (i = 9; i >= 0; i--) {
322 if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp),
323 STRUCT_OFFSET_OF(tv_t, l), i))) {
324 printf("OUCH: remelem failure at index %d\n", i);
326 if (PREDICT_FALSE(tp[i].l.next != EMPTY)) {
327 printf("OUCH: post-remelem next not EMPTY, index %d\n", i);
331 printf ("after deletes, buckets[0] = %x\n", buckets[0]);
336 #endif /* test code */