4 * Pointer list manipulation
6 * (C) Copyright Linus Torvalds 2003-2005
16 __DECLARE_ALLOCATOR(struct ptr_list
, ptrlist
);
17 __ALLOCATOR(struct ptr_list
, "ptr list", ptrlist
);
18 __ALLOCATOR(struct ptr_list
, "rl ptr list", rl_ptrlist
);
20 int ptr_list_size(struct ptr_list
*head
)
25 struct ptr_list
*list
= head
;
27 nr
+= list
->nr
- list
->rm
;
28 } while ((list
= list
->next
) != head
);
34 * Linearize the entries of a list up to a total of 'max',
35 * and return the nr of entries linearized.
37 * The array to linearize into (second argument) should really
38 * be "void *x[]", but we want to let people fill in any kind
39 * of pointer array, so let's just call it "void **".
41 int linearize_ptr_list(struct ptr_list
*head
, void **arr
, int max
)
44 if (head
&& max
> 0) {
45 struct ptr_list
*list
= head
;
51 memcpy(arr
, list
->list
, i
*sizeof(void *));
57 } while ((list
= list
->next
) != head
);
63 * When we've walked the list and deleted entries,
64 * we may need to re-pack it so that we don't have
65 * any empty blocks left (empty blocks upset the
68 void pack_ptr_list(struct ptr_list
**listp
)
70 struct ptr_list
*head
= *listp
;
73 struct ptr_list
*entry
= head
;
75 struct ptr_list
*next
;
79 struct ptr_list
*prev
;
81 __free_ptrlist(entry
);
88 __free_ptrlist(entry
);
97 } while (entry
!= head
);
101 void split_ptr_list_head(struct ptr_list
*head
)
103 int old
= head
->nr
, nr
= old
/ 2;
104 struct ptr_list
*newlist
= __alloc_ptrlist(0);
105 struct ptr_list
*next
= head
->next
;
109 newlist
->next
= next
;
110 next
->prev
= newlist
;
111 newlist
->prev
= head
;
112 head
->next
= newlist
;
114 memcpy(newlist
->list
, head
->list
+ old
, nr
* sizeof(void *));
115 memset(head
->list
+ old
, 0xf0, nr
* sizeof(void *));
119 void **__add_ptr_list(struct ptr_list
**listp
, void *ptr
, unsigned long tag
)
121 struct ptr_list
*list
= *listp
;
122 struct ptr_list
*last
= NULL
; /* gcc complains needlessly */
126 /* The low two bits are reserved for tags */
127 assert((3 & (unsigned long)ptr
) == 0);
128 assert((~3 & tag
) == 0);
129 ptr
= (void *)(tag
| (unsigned long)ptr
);
131 if (!list
|| (nr
= (last
= list
->prev
)->nr
) >= LIST_NODE_NR
) {
132 struct ptr_list
*newlist
;
135 newlist
= __alloc_rl_ptrlist(0);
137 newlist
= __alloc_ptrlist(0);
139 newlist
->next
= newlist
;
140 newlist
->prev
= newlist
;
143 newlist
->prev
= last
;
144 newlist
->next
= list
;
145 list
->prev
= newlist
;
146 last
->next
= newlist
;
151 ret
= last
->list
+ nr
;
158 int delete_ptr_list_entry(struct ptr_list
**list
, void *entry
, int count
)
162 FOR_EACH_PTR(*list
, ptr
) {
164 DELETE_CURRENT_PTR(ptr
);
168 } END_FOR_EACH_PTR(ptr
);
175 int replace_ptr_list_entry(struct ptr_list
**list
, void *old_ptr
, void *new_ptr
, int count
)
179 FOR_EACH_PTR(*list
, ptr
) {
181 REPLACE_CURRENT_PTR(ptr
, new_ptr
);
185 }END_FOR_EACH_PTR(ptr
);
191 /* This removes the last entry, but doesn't pack the ptr list */
192 void * undo_ptr_list_last(struct ptr_list
**head
)
194 struct ptr_list
*last
, *first
= *head
;
204 ptr
= last
->list
[nr
];
205 last
->list
[nr
] = (void *)0xf1f1f1f1;
208 } while (last
!= first
);
212 void * delete_ptr_list_last(struct ptr_list
**head
)
215 struct ptr_list
*last
, *first
= *head
;
221 ptr
= last
->list
[--last
->nr
];
223 first
->prev
= last
->prev
;
224 last
->prev
->next
= first
;
227 __free_ptrlist(last
);
232 void concat_ptr_list(struct ptr_list
*a
, struct ptr_list
**b
)
235 FOR_EACH_PTR(a
, entry
) {
236 add_ptr_list(b
, entry
);
237 } END_FOR_EACH_PTR(entry
);
240 void __free_ptr_list(struct ptr_list
**listp
)
242 struct ptr_list
*tmp
, *list
= *listp
;
247 list
->prev
->next
= NULL
;