1 1.32 riastrad /* $NetBSD: list.h,v 1.32 2021/12/19 11:39:24 riastradh Exp $ */ 2 1.1 skrll 3 1.1 skrll /*- 4 1.1 skrll * Copyright (c) 2013 The NetBSD Foundation, Inc. 5 1.1 skrll * All rights reserved. 6 1.1 skrll * 7 1.1 skrll * This code is derived from software contributed to The NetBSD Foundation 8 1.1 skrll * by Taylor R. Campbell. 9 1.1 skrll * 10 1.1 skrll * Redistribution and use in source and binary forms, with or without 11 1.1 skrll * modification, are permitted provided that the following conditions 12 1.1 skrll * are met: 13 1.1 skrll * 1. Redistributions of source code must retain the above copyright 14 1.1 skrll * notice, this list of conditions and the following disclaimer. 15 1.1 skrll * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 skrll * notice, this list of conditions and the following disclaimer in the 17 1.1 skrll * documentation and/or other materials provided with the distribution. 18 1.1 skrll * 19 1.1 skrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 skrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 skrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 skrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 skrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 skrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 skrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 skrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 skrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 skrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 skrll * POSSIBILITY OF SUCH DAMAGE. 30 1.1 skrll */ 31 1.1 skrll 32 1.2 riastrad /* 33 1.2 riastrad * Notes on porting: 34 1.2 riastrad * 35 1.2 riastrad * - LIST_HEAD(x) means a declaration `struct list_head x = 36 1.2 riastrad * LIST_HEAD_INIT(x)' in Linux, but something else in NetBSD. 37 1.2 riastrad * Replace by the expansion. 38 1.2 riastrad */ 39 1.2 riastrad 40 1.1 skrll #ifndef _LINUX_LIST_H_ 41 1.1 skrll #define _LINUX_LIST_H_ 42 1.1 skrll 43 1.1 skrll #include <sys/null.h> 44 1.7 riastrad #include <sys/pslist.h> 45 1.1 skrll #include <sys/queue.h> 46 1.1 skrll 47 1.1 skrll #include <linux/kernel.h> 48 1.20 riastrad #include <linux/types.h> 49 1.1 skrll 50 1.32 riastrad #define POISON_INUSE 0x5a /* XXX */ 51 1.32 riastrad 52 1.1 skrll /* 53 1.20 riastrad * Doubly-linked lists. Type defined in <linux/types.h>. 54 1.1 skrll */ 55 1.1 skrll 56 1.1 skrll #define LIST_HEAD_INIT(name) { .prev = &(name), .next = &(name) } 57 1.1 skrll 58 1.19 riastrad #define LINUX_LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) 59 1.19 riastrad 60 1.1 skrll static inline void 61 1.1 skrll INIT_LIST_HEAD(struct list_head *head) 62 1.1 skrll { 63 1.1 skrll head->prev = head; 64 1.1 skrll head->next = head; 65 1.1 skrll } 66 1.1 skrll 67 1.1 skrll static inline struct list_head * 68 1.1 skrll list_first(const struct list_head *head) 69 1.1 skrll { 70 1.1 skrll return head->next; 71 1.1 skrll } 72 1.1 skrll 73 1.1 skrll static inline struct list_head * 74 1.5 riastrad list_last(const struct list_head *head) 75 1.5 riastrad { 76 1.5 riastrad return head->prev; 77 1.5 riastrad } 78 1.5 riastrad 79 1.5 riastrad static inline struct list_head * 80 1.1 skrll list_next(const struct list_head *node) 81 1.1 skrll { 82 1.1 skrll return node->next; 83 1.1 skrll } 84 1.1 skrll 85 1.1 skrll static inline struct list_head * 86 1.1 skrll list_prev(const struct list_head *node) 87 1.1 skrll { 88 1.1 skrll return node->prev; 89 1.1 skrll } 90 1.1 skrll 91 1.1 skrll static inline int 92 1.1 skrll list_empty(const struct list_head *head) 93 1.1 skrll { 94 1.1 skrll return (head->next == head); 95 1.1 skrll } 96 1.1 skrll 97 1.3 riastrad static inline int 98 1.3 riastrad list_is_singular(const struct list_head *head) 99 1.3 riastrad { 100 1.3 riastrad 101 1.3 riastrad if (list_empty(head)) 102 1.3 riastrad return false; 103 1.3 riastrad if (head->next != head->prev) 104 1.3 riastrad return false; 105 1.3 riastrad return true; 106 1.3 riastrad } 107 1.3 riastrad 108 1.22 riastrad static inline bool 109 1.23 riastrad list_is_first(const struct list_head *entry, const struct list_head *head) 110 1.23 riastrad { 111 1.23 riastrad return head == entry->prev; 112 1.23 riastrad } 113 1.23 riastrad 114 1.23 riastrad static inline bool 115 1.22 riastrad list_is_last(const struct list_head *entry, const struct list_head *head) 116 1.22 riastrad { 117 1.22 riastrad return head == entry->next; 118 1.22 riastrad } 119 1.22 riastrad 120 1.1 skrll static inline void 121 1.1 skrll __list_add_between(struct list_head *prev, struct list_head *node, 122 1.1 skrll struct list_head *next) 123 1.1 skrll { 124 1.1 skrll prev->next = node; 125 1.1 skrll node->prev = prev; 126 1.1 skrll node->next = next; 127 1.1 skrll next->prev = node; 128 1.1 skrll } 129 1.1 skrll 130 1.1 skrll static inline void 131 1.1 skrll list_add(struct list_head *node, struct list_head *head) 132 1.1 skrll { 133 1.1 skrll __list_add_between(head, node, head->next); 134 1.1 skrll } 135 1.1 skrll 136 1.1 skrll static inline void 137 1.30 riastrad list_add_rcu(struct list_head *node, struct list_head *head) 138 1.30 riastrad { 139 1.30 riastrad struct list_head *next = head->next; 140 1.30 riastrad 141 1.30 riastrad /* Initialize the new node first. */ 142 1.30 riastrad node->next = next; 143 1.30 riastrad node->prev = head; 144 1.30 riastrad 145 1.30 riastrad /* Now publish it. */ 146 1.30 riastrad atomic_store_release(&head->next, node); 147 1.30 riastrad 148 1.30 riastrad /* Fix up back pointers, not protected by RCU. */ 149 1.30 riastrad next->prev = node; 150 1.30 riastrad } 151 1.30 riastrad 152 1.30 riastrad static inline void 153 1.1 skrll list_add_tail(struct list_head *node, struct list_head *head) 154 1.1 skrll { 155 1.1 skrll __list_add_between(head->prev, node, head); 156 1.1 skrll } 157 1.1 skrll 158 1.1 skrll static inline void 159 1.21 riastrad __list_del_entry(struct list_head *entry) 160 1.1 skrll { 161 1.1 skrll entry->prev->next = entry->next; 162 1.1 skrll entry->next->prev = entry->prev; 163 1.1 skrll } 164 1.1 skrll 165 1.1 skrll static inline void 166 1.21 riastrad list_del(struct list_head *entry) 167 1.21 riastrad { 168 1.21 riastrad __list_del_entry(entry); 169 1.21 riastrad entry->next = (void *)(uintptr_t)1; 170 1.21 riastrad entry->prev = (void *)(uintptr_t)2; 171 1.21 riastrad } 172 1.21 riastrad 173 1.21 riastrad static inline void 174 1.1 skrll __list_splice_between(struct list_head *prev, const struct list_head *list, 175 1.1 skrll struct list_head *next) 176 1.1 skrll { 177 1.1 skrll struct list_head *first = list->next; 178 1.1 skrll struct list_head *last = list->prev; 179 1.1 skrll 180 1.1 skrll first->prev = prev; 181 1.1 skrll prev->next = first; 182 1.1 skrll 183 1.1 skrll last->next = next; 184 1.1 skrll next->prev = last; 185 1.1 skrll } 186 1.1 skrll 187 1.1 skrll static inline void 188 1.1 skrll list_splice(const struct list_head *list, struct list_head *head) 189 1.1 skrll { 190 1.1 skrll if (!list_empty(list)) 191 1.1 skrll __list_splice_between(head, list, head->next); 192 1.1 skrll } 193 1.1 skrll 194 1.1 skrll static inline void 195 1.18 riastrad list_splice_init(struct list_head *list, struct list_head *head) 196 1.18 riastrad { 197 1.18 riastrad if (!list_empty(list)) { 198 1.18 riastrad __list_splice_between(head, list, head->next); 199 1.18 riastrad INIT_LIST_HEAD(list); 200 1.18 riastrad } 201 1.18 riastrad } 202 1.18 riastrad 203 1.18 riastrad static inline void 204 1.1 skrll list_splice_tail(const struct list_head *list, struct list_head *head) 205 1.1 skrll { 206 1.1 skrll if (!list_empty(list)) 207 1.1 skrll __list_splice_between(head->prev, list, head); 208 1.1 skrll } 209 1.1 skrll 210 1.1 skrll static inline void 211 1.15 riastrad list_splice_tail_init(struct list_head *list, struct list_head *head) 212 1.15 riastrad { 213 1.15 riastrad if (!list_empty(list)) { 214 1.15 riastrad __list_splice_between(head->prev, list, head); 215 1.15 riastrad INIT_LIST_HEAD(list); 216 1.15 riastrad } 217 1.15 riastrad } 218 1.15 riastrad 219 1.15 riastrad static inline void 220 1.1 skrll list_move(struct list_head *node, struct list_head *head) 221 1.1 skrll { 222 1.1 skrll list_del(node); 223 1.1 skrll list_add(node, head); 224 1.1 skrll } 225 1.1 skrll 226 1.1 skrll static inline void 227 1.1 skrll list_move_tail(struct list_head *node, struct list_head *head) 228 1.1 skrll { 229 1.1 skrll list_del(node); 230 1.1 skrll list_add_tail(node, head); 231 1.1 skrll } 232 1.1 skrll 233 1.1 skrll static inline void 234 1.26 riastrad list_bulk_move_tail(struct list_head *head, struct list_head *first, 235 1.26 riastrad struct list_head *last) 236 1.26 riastrad { 237 1.26 riastrad 238 1.26 riastrad first->prev->next = last->next; 239 1.26 riastrad last->next->prev = first->prev; 240 1.26 riastrad 241 1.26 riastrad head->prev->next = first; 242 1.26 riastrad first->prev = head->prev; 243 1.26 riastrad 244 1.26 riastrad last->next = head; 245 1.26 riastrad head->prev = last; 246 1.26 riastrad } 247 1.26 riastrad 248 1.26 riastrad static inline void 249 1.1 skrll list_replace(struct list_head *old, struct list_head *new) 250 1.1 skrll { 251 1.1 skrll new->prev = old->prev; 252 1.1 skrll old->prev->next = new; 253 1.1 skrll new->next = old->next; 254 1.1 skrll old->next->prev = new; 255 1.1 skrll } 256 1.1 skrll 257 1.1 skrll static inline void 258 1.14 riastrad list_replace_init(struct list_head *old, struct list_head *new) 259 1.14 riastrad { 260 1.14 riastrad list_replace(old, new); 261 1.14 riastrad INIT_LIST_HEAD(old); 262 1.14 riastrad } 263 1.14 riastrad 264 1.14 riastrad static inline void 265 1.1 skrll list_del_init(struct list_head *node) 266 1.1 skrll { 267 1.1 skrll list_del(node); 268 1.1 skrll INIT_LIST_HEAD(node); 269 1.1 skrll } 270 1.1 skrll 271 1.1 skrll #define list_entry(PTR, TYPE, FIELD) container_of(PTR, TYPE, FIELD) 272 1.1 skrll #define list_first_entry(PTR, TYPE, FIELD) \ 273 1.1 skrll list_entry(list_first((PTR)), TYPE, FIELD) 274 1.10 riastrad #define list_first_entry_or_null(PTR, TYPE, FIELD) \ 275 1.10 riastrad (list_empty((PTR)) ? NULL : list_entry(list_first((PTR)), TYPE, FIELD)) 276 1.5 riastrad #define list_last_entry(PTR, TYPE, FIELD) \ 277 1.5 riastrad list_entry(list_last((PTR)), TYPE, FIELD) 278 1.3 riastrad #define list_next_entry(ENTRY, FIELD) \ 279 1.3 riastrad list_entry(list_next(&(ENTRY)->FIELD), typeof(*(ENTRY)), FIELD) 280 1.5 riastrad #define list_prev_entry(ENTRY, FIELD) \ 281 1.5 riastrad list_entry(list_prev(&(ENTRY)->FIELD), typeof(*(ENTRY)), FIELD) 282 1.1 skrll 283 1.1 skrll #define list_for_each(VAR, HEAD) \ 284 1.1 skrll for ((VAR) = list_first((HEAD)); \ 285 1.1 skrll (VAR) != (HEAD); \ 286 1.1 skrll (VAR) = list_next((VAR))) 287 1.1 skrll 288 1.31 riastrad #define list_for_each_prev(VAR, HEAD) \ 289 1.31 riastrad for ((VAR) = list_last((HEAD)); \ 290 1.31 riastrad (VAR) != (HEAD); \ 291 1.31 riastrad (VAR) = list_prev((VAR))) 292 1.31 riastrad 293 1.1 skrll #define list_for_each_safe(VAR, NEXT, HEAD) \ 294 1.1 skrll for ((VAR) = list_first((HEAD)); \ 295 1.1 skrll ((VAR) != (HEAD)) && ((NEXT) = list_next((VAR)), 1); \ 296 1.1 skrll (VAR) = (NEXT)) 297 1.1 skrll 298 1.29 riastrad #define list_safe_reset_next(VAR, NEXT, FIELD) \ 299 1.29 riastrad (NEXT) = list_next_entry(VAR, FIELD) 300 1.29 riastrad 301 1.1 skrll #define list_for_each_entry(VAR, HEAD, FIELD) \ 302 1.1 skrll for ((VAR) = list_entry(list_first((HEAD)), typeof(*(VAR)), FIELD); \ 303 1.1 skrll &(VAR)->FIELD != (HEAD); \ 304 1.1 skrll (VAR) = list_entry(list_next(&(VAR)->FIELD), typeof(*(VAR)), \ 305 1.1 skrll FIELD)) 306 1.1 skrll 307 1.1 skrll #define list_for_each_entry_safe(VAR, NEXT, HEAD, FIELD) \ 308 1.1 skrll for ((VAR) = list_entry(list_first((HEAD)), typeof(*(VAR)), FIELD); \ 309 1.1 skrll (&(VAR)->FIELD != (HEAD)) && \ 310 1.1 skrll ((NEXT) = list_entry(list_next(&(VAR)->FIELD), \ 311 1.1 skrll typeof(*(VAR)), FIELD), 1); \ 312 1.1 skrll (VAR) = (NEXT)) 313 1.1 skrll 314 1.28 riastrad #define list_for_each_entry_safe_reverse(VAR, NEXT, HEAD, FIELD) \ 315 1.28 riastrad for ((VAR) = list_entry(list_last((HEAD)), typeof(*(VAR)), FIELD); \ 316 1.28 riastrad (&(VAR)->FIELD != (HEAD)) && \ 317 1.28 riastrad ((NEXT) = list_entry(list_prev(&(VAR)->FIELD), \ 318 1.28 riastrad typeof(*(VAR)), FIELD), 1); \ 319 1.28 riastrad (VAR) = (NEXT)) 320 1.28 riastrad 321 1.28 riastrad #define list_for_each_entry_reverse(VAR, HEAD, FIELD) \ 322 1.28 riastrad for ((VAR) = list_entry(list_last((HEAD)), typeof(*(VAR)), FIELD); \ 323 1.28 riastrad &(VAR)->FIELD != (HEAD); \ 324 1.28 riastrad (VAR) = list_entry(list_prev(&(VAR)->FIELD), typeof(*(VAR)), \ 325 1.28 riastrad FIELD)) 326 1.28 riastrad 327 1.3 riastrad #define list_for_each_entry_continue(VAR, HEAD, FIELD) \ 328 1.3 riastrad for ((VAR) = list_next_entry((VAR), FIELD); \ 329 1.3 riastrad &(VAR)->FIELD != (HEAD); \ 330 1.3 riastrad (VAR) = list_next_entry((VAR), FIELD)) 331 1.3 riastrad 332 1.5 riastrad #define list_for_each_entry_continue_reverse(VAR, HEAD, FIELD) \ 333 1.5 riastrad for ((VAR) = list_prev_entry((VAR), FIELD); \ 334 1.5 riastrad &(VAR)->FIELD != (HEAD); \ 335 1.5 riastrad (VAR) = list_prev_entry((VAR), FIELD)) 336 1.5 riastrad 337 1.24 riastrad #define list_for_each_entry_from(VAR, HEAD, FIELD) \ 338 1.24 riastrad for (; \ 339 1.24 riastrad (&(VAR)->FIELD != (HEAD)); \ 340 1.24 riastrad (VAR) = list_next_entry((VAR), FIELD)) 341 1.24 riastrad 342 1.27 riastrad #define list_for_each_entry_from_reverse(VAR, HEAD, FIELD) \ 343 1.27 riastrad for (; \ 344 1.27 riastrad (&(VAR)->FIELD != (HEAD)); \ 345 1.27 riastrad (VAR) = list_prev_entry((VAR), FIELD)) 346 1.27 riastrad 347 1.4 riastrad #define list_for_each_entry_safe_from(VAR, NEXT, HEAD, FIELD) \ 348 1.4 riastrad for (; \ 349 1.4 riastrad (&(VAR)->FIELD != (HEAD)) && \ 350 1.4 riastrad ((NEXT) = list_next_entry((VAR), FIELD)); \ 351 1.4 riastrad (VAR) = (NEXT)) 352 1.4 riastrad 353 1.1 skrll /* 354 1.1 skrll * `H'ead-only/`H'ash-table doubly-linked lists. 355 1.1 skrll */ 356 1.1 skrll 357 1.7 riastrad #define hlist_head pslist_head 358 1.7 riastrad #define hlist_node pslist_entry 359 1.1 skrll 360 1.7 riastrad #define HLIST_HEAD_INIT PSLIST_INITIALIZER 361 1.7 riastrad #define INIT_HLIST_HEAD PSLIST_INIT 362 1.7 riastrad #define hlist_empty(h) (pslist_writer_first(h) == NULL) 363 1.7 riastrad #define hlist_first pslist_writer_first 364 1.7 riastrad #define hlist_next pslist_writer_next 365 1.17 riastrad 366 1.17 riastrad static inline void 367 1.17 riastrad hlist_add_head(struct hlist_node *node, struct hlist_head *head) 368 1.17 riastrad { 369 1.17 riastrad 370 1.17 riastrad pslist_entry_init(node); 371 1.17 riastrad pslist_writer_insert_head(head, node); 372 1.17 riastrad } 373 1.6 riastrad 374 1.6 riastrad static inline void 375 1.7 riastrad hlist_del(struct hlist_node *node) 376 1.6 riastrad { 377 1.6 riastrad 378 1.7 riastrad pslist_writer_remove(node); 379 1.7 riastrad /* XXX abstraction violation */ 380 1.7 riastrad node->ple_prevp = _PSLIST_POISON; 381 1.1 skrll } 382 1.1 skrll 383 1.1 skrll static inline void 384 1.7 riastrad hlist_del_init(struct hlist_node *node) 385 1.1 skrll { 386 1.1 skrll 387 1.7 riastrad /* XXX abstraction violation */ 388 1.7 riastrad if (node->ple_prevp != NULL) 389 1.7 riastrad pslist_writer_remove(node); 390 1.1 skrll } 391 1.1 skrll 392 1.1 skrll #define hlist_entry(PTR, TYPE, FIELD) container_of(PTR, TYPE, FIELD) 393 1.7 riastrad #define hlist_for_each(VAR, HEAD) \ 394 1.7 riastrad for ((VAR) = hlist_first(HEAD); (VAR) != NULL; (VAR) = hlist_next(VAR)) 395 1.7 riastrad #define hlist_for_each_safe(VAR, NEXT, HEAD) \ 396 1.16 riastrad for ((VAR) = hlist_first(HEAD); \ 397 1.16 riastrad (VAR) != NULL && ((NEXT) = hlist_next(HEAD), 1); \ 398 1.7 riastrad (VAR) = (NEXT)) 399 1.7 riastrad #define hlist_for_each_entry(VAR, HEAD, FIELD) \ 400 1.7 riastrad for ((VAR) = (hlist_first(HEAD) == NULL ? NULL : \ 401 1.7 riastrad hlist_entry(hlist_first(HEAD), typeof(*(VAR)), \ 402 1.7 riastrad FIELD)); \ 403 1.7 riastrad (VAR) != NULL; \ 404 1.9 riastrad (VAR) = (hlist_next(&(VAR)->FIELD) == NULL ? NULL : \ 405 1.8 riastrad hlist_entry(hlist_next(&(VAR)->FIELD), typeof(*(VAR)),\ 406 1.8 riastrad FIELD))) 407 1.1 skrll 408 1.6 riastrad #define hlist_for_each_entry_safe(VAR, NEXT, HEAD, FIELD) \ 409 1.7 riastrad for ((VAR) = (hlist_first(HEAD) == NULL ? NULL : \ 410 1.7 riastrad hlist_entry(hlist_first(HEAD), typeof(*(VAR)), \ 411 1.16 riastrad FIELD)); \ 412 1.16 riastrad ((VAR) != NULL && \ 413 1.16 riastrad ((NEXT) = hlist_next(&(VAR)->FIELD), 1)); \ 414 1.16 riastrad (VAR) = hlist_entry((NEXT), typeof(*(VAR)), FIELD)) 415 1.6 riastrad 416 1.17 riastrad static inline void 417 1.17 riastrad hlist_add_behind_rcu(struct hlist_node *node, struct hlist_node *prev) 418 1.17 riastrad { 419 1.17 riastrad 420 1.17 riastrad pslist_entry_init(node); 421 1.17 riastrad pslist_writer_insert_after(prev, node); 422 1.17 riastrad } 423 1.17 riastrad 424 1.17 riastrad static inline void 425 1.17 riastrad hlist_add_head_rcu(struct hlist_node *node, struct hlist_head *head) 426 1.17 riastrad { 427 1.17 riastrad 428 1.17 riastrad pslist_entry_init(node); 429 1.17 riastrad pslist_writer_insert_head(head, node); 430 1.17 riastrad } 431 1.17 riastrad 432 1.17 riastrad #define hlist_del_init_rcu hlist_del_init /* no special needs */ 433 1.7 riastrad 434 1.7 riastrad #define hlist_first_rcu pslist_reader_first 435 1.7 riastrad #define hlist_next_rcu pslist_reader_next 436 1.7 riastrad 437 1.7 riastrad #define hlist_for_each_entry_rcu(VAR, HEAD, FIELD) \ 438 1.7 riastrad for ((VAR) = (hlist_first_rcu(HEAD) == NULL ? NULL : \ 439 1.7 riastrad hlist_entry(hlist_first_rcu(HEAD), typeof(*(VAR)), \ 440 1.7 riastrad FIELD)); \ 441 1.7 riastrad (VAR) != NULL; \ 442 1.11 riastrad (VAR) = (hlist_next_rcu(&(VAR)->FIELD) == NULL ? NULL : \ 443 1.11 riastrad hlist_entry(hlist_next_rcu(&(VAR)->FIELD), \ 444 1.11 riastrad typeof(*(VAR)), FIELD))) 445 1.1 skrll 446 1.1 skrll #endif /* _LINUX_LIST_H_ */ 447