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
);
19 int ptr_list_size(struct ptr_list
*head
)
24 struct ptr_list
*list
= head
;
26 nr
+= list
->nr
- list
->rm
;
27 } while ((list
= list
->next
) != head
);
33 * Linearize the entries of a list up to a total of 'max',
34 * and return the nr of entries linearized.
36 * The array to linearize into (second argument) should really
37 * be "void *x[]", but we want to let people fill in any kind
38 * of pointer array, so let's just call it "void **".
40 int linearize_ptr_list(struct ptr_list
*head
, void **arr
, int max
)
43 if (head
&& max
> 0) {
44 struct ptr_list
*list
= head
;
50 memcpy(arr
, list
->list
, i
*sizeof(void *));
56 } while ((list
= list
->next
) != head
);
62 * When we've walked the list and deleted entries,
63 * we may need to re-pack it so that we don't have
64 * any empty blocks left (empty blocks upset the
67 void pack_ptr_list(struct ptr_list
**listp
)
69 struct ptr_list
*head
= *listp
;
72 struct ptr_list
*entry
= head
;
74 struct ptr_list
*next
;
78 struct ptr_list
*prev
;
80 __free_ptrlist(entry
);
87 __free_ptrlist(entry
);
96 } while (entry
!= head
);
100 void split_ptr_list_head(struct ptr_list
*head
)
102 int old
= head
->nr
, nr
= old
/ 2;
103 struct ptr_list
*newlist
= __alloc_ptrlist(0);
104 struct ptr_list
*next
= head
->next
;
108 newlist
->next
= next
;
109 next
->prev
= newlist
;
110 newlist
->prev
= head
;
111 head
->next
= newlist
;
113 memcpy(newlist
->list
, head
->list
+ old
, nr
* sizeof(void *));
114 memset(head
->list
+ old
, 0xf0, nr
* sizeof(void *));
117 void **__add_ptr_list(struct ptr_list
**listp
, void *ptr
, unsigned long tag
)
119 struct ptr_list
*list
= *listp
;
120 struct ptr_list
*last
= NULL
; /* gcc complains needlessly */
124 /* The low two bits are reserved for tags */
125 assert((3 & (unsigned long)ptr
) == 0);
126 assert((~3 & tag
) == 0);
127 ptr
= (void *)(tag
| (unsigned long)ptr
);
129 if (!list
|| (nr
= (last
= list
->prev
)->nr
) >= LIST_NODE_NR
) {
130 struct ptr_list
*newlist
= __alloc_ptrlist(0);
132 newlist
->next
= newlist
;
133 newlist
->prev
= newlist
;
136 newlist
->prev
= last
;
137 newlist
->next
= list
;
138 list
->prev
= newlist
;
139 last
->next
= newlist
;
144 ret
= last
->list
+ nr
;
151 int delete_ptr_list_entry(struct ptr_list
**list
, void *entry
, int count
)
155 FOR_EACH_PTR(*list
, ptr
) {
157 DELETE_CURRENT_PTR(ptr
);
161 } END_FOR_EACH_PTR(ptr
);
168 int replace_ptr_list_entry(struct ptr_list
**list
, void *old_ptr
, void *new_ptr
, int count
)
172 FOR_EACH_PTR(*list
, ptr
) {
174 REPLACE_CURRENT_PTR(ptr
, new_ptr
);
178 }END_FOR_EACH_PTR(ptr
);
184 /* This removes the last entry, but doesn't pack the ptr list */
185 void * undo_ptr_list_last(struct ptr_list
**head
)
187 struct ptr_list
*last
, *first
= *head
;
197 ptr
= last
->list
[nr
];
198 last
->list
[nr
] = (void *)0xf1f1f1f1;
201 } while (last
!= first
);
205 void * delete_ptr_list_last(struct ptr_list
**head
)
208 struct ptr_list
*last
, *first
= *head
;
214 ptr
= last
->list
[--last
->nr
];
216 first
->prev
= last
->prev
;
217 last
->prev
->next
= first
;
220 __free_ptrlist(last
);
225 void concat_ptr_list(struct ptr_list
*a
, struct ptr_list
**b
)
228 FOR_EACH_PTR(a
, entry
) {
229 add_ptr_list(b
, entry
);
230 } END_FOR_EACH_PTR(entry
);
233 void __free_ptr_list(struct ptr_list
**listp
)
235 struct ptr_list
*tmp
, *list
= *listp
;
240 list
->prev
->next
= NULL
;