4 * (C) Copyright Linus Torvalds 2003-2005
8 // Pointer list manipulation
9 // -------------------------
11 // The data structure handled here is designed to hold pointers
12 // but two special cases need to be avoided or need special care:
13 // * NULL is used by {PREPARE,NEXT}_PTR_LIST() to indicate the end-of-list.
14 // Thus, NULL can't be stored in lists using this API but is fine to
15 // use with FOR_EACH_PTR() and its variants.
16 // * VOID is used to replace a removed pseudo 'usage'. Since phi-nodes
17 // (OP_PHI) use a list to store their operands, a VOID in a phi-node
18 // list must be ignored since it represents a removed operand. As
19 // consequence, VOIDs must never be used as phi-node operand.
20 // This is fine since phi-nodes make no sense with void values
21 // but VOID is also used for invalid types and in case of errors.
31 __DECLARE_ALLOCATOR(struct ptr_list
, ptrlist
);
32 __ALLOCATOR(struct ptr_list
, "ptr list", ptrlist
);
33 __ALLOCATOR(struct ptr_list
, "rl ptr list", rl_ptrlist
);
36 // get the size of a ptrlist
37 // @head: the head of the list
38 // @return: the size of the list given by @head.
39 int ptr_list_size(struct ptr_list
*head
)
44 struct ptr_list
*list
= head
;
46 nr
+= list
->nr
- list
->rm
;
47 } while ((list
= list
->next
) != head
);
53 // test if a list is empty
54 // @head: the head of the list
55 // @return: ``true`` if the list is empty, ``false`` otherwise.
56 bool ptr_list_empty(const struct ptr_list
*head
)
58 const struct ptr_list
*list
= head
;
64 if (list
->nr
- list
->rm
)
66 } while ((list
= list
->next
) != head
);
72 // test is a list contains more than one element
73 // @head: the head of the list
74 // @return: ``true`` if the list has more than 1 element, ``false`` otherwise.
75 bool ptr_list_multiple(const struct ptr_list
*head
)
77 const struct ptr_list
*list
= head
;
84 nr
+= list
->nr
- list
->rm
;
87 } while ((list
= list
->next
) != head
);
93 // get the first element of a ptrlist
94 // @head: the head of the list
95 // @return: the first element of the list or ``NULL`` if the list is empty
96 void *first_ptr_list(struct ptr_list
*head
)
98 struct ptr_list
*list
= head
;
103 while (list
->nr
== 0) {
108 return PTR_ENTRY_NOTAG(list
, 0);
112 // get the last element of a ptrlist
113 // @head: the head of the list
114 // @return: the last element of the list or ``NULL`` if the list is empty
115 void *last_ptr_list(struct ptr_list
*head
)
117 struct ptr_list
*list
;
122 while (list
->nr
== 0) {
127 return PTR_ENTRY_NOTAG(list
, list
->nr
-1);
131 // get the nth element of a ptrlist
132 // @head: the head of the list
133 // @return: the nth element of the list or ``NULL`` if the list is too short.
134 void *ptr_list_nth_entry(struct ptr_list
*list
, unsigned int idx
)
136 struct ptr_list
*head
= list
;
142 unsigned int nr
= list
->nr
;
145 return list
->list
[idx
];
148 } while ((list
= list
->next
) != head
);
153 // linearize the entries of a list
155 // @head: the list to be linearized
156 // @arr: a ``void*`` array to fill with @head's entries
157 // @max: the maximum number of entries to store into @arr
158 // @return: the number of entries in the list.
160 // Linearize the entries of a list up to a total of @max,
161 // and return the number of entries in the list.
163 // The array to linearize into (@arr) should really
164 // be ``void *x[]``, but we want to let people fill in any kind
165 // of pointer array, so let's just call it ``void **``.
166 int linearize_ptr_list(struct ptr_list
*head
, void **arr
, int max
)
169 if (head
&& max
> 0) {
170 struct ptr_list
*list
= head
;
179 memcpy(arr
, list
->list
, i
*sizeof(void *));
182 } while ((list
= list
->next
) != head
);
190 // @listp: a pointer to the list to be packed.
192 // When we've walked the list and deleted entries,
193 // we may need to re-pack it so that we don't have
194 // any empty blocks left (empty blocks upset the
196 void pack_ptr_list(struct ptr_list
**listp
)
198 struct ptr_list
*head
= *listp
;
201 struct ptr_list
*entry
= head
;
203 struct ptr_list
*next
;
207 struct ptr_list
*prev
;
209 __free_ptrlist(entry
);
216 __free_ptrlist(entry
);
225 } while (entry
!= head
);
230 // split a ptrlist block
231 // @head: the ptrlist block to be split
233 // A new block is inserted just after @head and the entries
234 // at the half end of @head are moved to this new block.
235 // The goal being to create space inside @head for a new entry.
236 void split_ptr_list_head(struct ptr_list
*head
)
238 int old
= head
->nr
, nr
= old
/ 2;
239 struct ptr_list
*newlist
= __alloc_ptrlist(0);
240 struct ptr_list
*next
= head
->next
;
244 newlist
->next
= next
;
245 next
->prev
= newlist
;
246 newlist
->prev
= head
;
247 head
->next
= newlist
;
249 memcpy(newlist
->list
, head
->list
+ old
, nr
* sizeof(void *));
250 memset(head
->list
+ old
, 0xf0, nr
* sizeof(void *));
255 // add an entry to a ptrlist
256 // @listp: a pointer to the list
257 // @ptr: the entry to add to the list
258 // @return: the address where the new entry is stored.
260 // :note: code must not use this function and should use
261 // :func:`add_ptr_list` instead.
262 void **__add_ptr_list(struct ptr_list
**listp
, void *ptr
)
264 struct ptr_list
*list
= *listp
;
265 struct ptr_list
*last
= NULL
; /* gcc complains needlessly */
269 if (!list
|| (nr
= (last
= list
->prev
)->nr
) >= LIST_NODE_NR
) {
270 struct ptr_list
*newlist
;
273 newlist
= __alloc_rl_ptrlist(0);
275 newlist
= __alloc_ptrlist(0);
277 newlist
->next
= newlist
;
278 newlist
->prev
= newlist
;
281 newlist
->prev
= last
;
282 newlist
->next
= list
;
283 list
->prev
= newlist
;
284 last
->next
= newlist
;
289 ret
= last
->list
+ nr
;
297 // add a tagged entry to a ptrlist
298 // @listp: a pointer to the list
299 // @ptr: the entry to add to the list
300 // @tag: the tag to add to @ptr
301 // @return: the address where the new entry is stored.
303 // :note: code must not use this function and should use
304 // :func:`add_ptr_list_tag` instead.
305 void **__add_ptr_list_tag(struct ptr_list
**listp
, void *ptr
, unsigned long tag
)
307 /* The low two bits are reserved for tags */
308 assert((3 & (unsigned long)ptr
) == 0);
309 assert((~3 & tag
) == 0);
311 ptr
= (void *)(tag
| (unsigned long)ptr
);
313 return __add_ptr_list(listp
, ptr
);
317 // test if some entry is already present in a ptrlist
318 // @list: the head of the list
319 // @entry: the entry to test
320 // @return: ``true`` if the entry is already present, ``false`` otherwise.
321 bool lookup_ptr_list_entry(const struct ptr_list
*head
, const void *entry
)
323 const struct ptr_list
*list
= head
;
330 for (i
= 0; i
< nr
; i
++)
331 if (list
->list
[i
] == entry
)
333 } while ((list
= list
->next
) != head
);
338 // delete an entry from a ptrlist
339 // @list: a pointer to the list
340 // @entry: the item to be deleted
341 // @count: the minimum number of times @entry should be deleted or 0.
342 int delete_ptr_list_entry(struct ptr_list
**list
, void *entry
, int count
)
346 FOR_EACH_PTR(*list
, ptr
) {
348 DELETE_CURRENT_PTR(ptr
);
352 } END_FOR_EACH_PTR(ptr
);
360 // replace an entry in a ptrlist
361 // @list: a pointer to the list
362 // @old_ptr: the entry to be replaced
363 // @new_ptr: the new entry
364 // @count: the minimum number of times @entry should be deleted or 0.
365 int replace_ptr_list_entry(struct ptr_list
**list
, void *old_ptr
,
366 void *new_ptr
, int count
)
370 FOR_EACH_PTR(*list
, ptr
) {
372 REPLACE_CURRENT_PTR(ptr
, new_ptr
);
376 }END_FOR_EACH_PTR(ptr
);
383 // remove the last entry of a ptrlist
384 // @head: a pointer to the list
385 // @return: the last element of the list or NULL if the list is empty.
387 // :note: this doesn't repack the list
388 void * undo_ptr_list_last(struct ptr_list
**head
)
390 struct ptr_list
*last
, *first
= *head
;
400 ptr
= last
->list
[nr
];
401 last
->list
[nr
] = (void *)0xf1f1f1f1;
404 } while (last
!= first
);
409 // remove the last entry and repack the list
410 // @head: a pointer to the list
411 // @return: the last element of the list or NULL if the list is empty.
412 void * delete_ptr_list_last(struct ptr_list
**head
)
415 struct ptr_list
*last
, *first
= *head
;
421 ptr
= last
->list
[--last
->nr
];
423 first
->prev
= last
->prev
;
424 last
->prev
->next
= first
;
427 __free_ptrlist(last
);
433 // concat two ptrlists
434 // @a: the source list
435 // @b: a pointer to the destination list.
436 // The element of @a are added at the end of @b.
437 void concat_ptr_list(struct ptr_list
*a
, struct ptr_list
**b
)
440 FOR_EACH_PTR(a
, entry
) {
441 add_ptr_list(b
, entry
);
442 } END_FOR_EACH_PTR(entry
);
446 // copy the elements of a list at the end of another list.
447 // @listp: a pointer to the destination list.
448 // @src: the head of the source list.
449 void copy_ptr_list(struct ptr_list
**listp
, struct ptr_list
*src
)
451 struct ptr_list
*head
, *tail
;
452 struct ptr_list
*cur
= src
;
466 struct ptr_list
*next
;
469 for (i
= 0; i
< nr
;) {
470 void *ptr
= cur
->list
[i
++];
473 if (idx
>= LIST_NODE_NR
) {
474 struct ptr_list
*prev
= tail
;
475 tail
= __alloc_ptrlist(0);
481 tail
->list
[idx
++] = ptr
;
487 } while (cur
!= src
);
496 // @listp: a pointer to the list
497 // Each blocks of the list are freed (but the entries
498 // themselves are not freed).
500 // :note: code must not use this function and should use
501 // the macro :func:`free_ptr_list` instead.
502 void __free_ptr_list(struct ptr_list
**listp
)
504 struct ptr_list
*tmp
, *list
= *listp
;
509 list
->prev
->next
= NULL
;