2006-09-29 12:59:00 +04:00
/*
* Copyright 2006 , Red Hat , Inc . , Dave Jones
* Released under the General Public License ( GPL ) .
*
* This file contains the linked list implementations for
* DEBUG_LIST .
*/
2011-11-17 06:29:17 +04:00
# include <linux/export.h>
2006-09-29 12:59:00 +04:00
# include <linux/list.h>
2012-01-21 03:35:53 +04:00
# include <linux/bug.h>
2012-01-21 03:46:49 +04:00
# include <linux/kernel.h>
2012-03-15 06:17:39 +04:00
# include <linux/rculist.h>
2006-09-29 12:59:00 +04:00
/*
* Insert a new entry between two known consecutive entries .
*
* This is only for internal list manipulation where we know
* the prev / next entries already !
*/
void __list_add ( struct list_head * new ,
struct list_head * prev ,
struct list_head * next )
{
2008-07-25 12:45:55 +04:00
WARN ( next - > prev ! = prev ,
" list_add corruption. next->prev should be "
" prev (%p), but was %p. (next=%p). \n " ,
prev , next - > prev , next ) ;
WARN ( prev - > next ! = next ,
" list_add corruption. prev->next should be "
" next (%p), but was %p. (prev=%p). \n " ,
next , prev - > next , prev ) ;
2012-05-30 02:07:31 +04:00
WARN ( new = = prev | | new = = next ,
" list_add double add: new=%p, prev=%p, next=%p. \n " ,
new , prev , next ) ;
2006-09-29 12:59:00 +04:00
next - > prev = new ;
new - > next = next ;
new - > prev = prev ;
2015-09-21 08:02:17 +03:00
WRITE_ONCE ( prev - > next , new ) ;
2006-09-29 12:59:00 +04:00
}
EXPORT_SYMBOL ( __list_add ) ;
2011-02-18 22:32:28 +03:00
void __list_del_entry ( struct list_head * entry )
{
struct list_head * prev , * next ;
prev = entry - > prev ;
next = entry - > next ;
if ( WARN ( next = = LIST_POISON1 ,
" list_del corruption, %p->next is LIST_POISON1 (%p) \n " ,
entry , LIST_POISON1 ) | |
WARN ( prev = = LIST_POISON2 ,
" list_del corruption, %p->prev is LIST_POISON2 (%p) \n " ,
entry , LIST_POISON2 ) | |
WARN ( prev - > next ! = entry ,
" list_del corruption. prev->next should be %p, "
" but was %p \n " , entry , prev - > next ) | |
WARN ( next - > prev ! = entry ,
" list_del corruption. next->prev should be %p, "
" but was %p \n " , entry , next - > prev ) )
return ;
__list_del ( prev , next ) ;
}
EXPORT_SYMBOL ( __list_del_entry ) ;
2006-09-29 12:59:00 +04:00
/**
* list_del - deletes entry from list .
* @ entry : the element to delete from the list .
* Note : list_empty on entry does not return true after this , the entry is
* in an undefined state .
*/
void list_del ( struct list_head * entry )
{
2011-02-18 22:32:28 +03:00
__list_del_entry ( entry ) ;
2006-09-29 12:59:00 +04:00
entry - > next = LIST_POISON1 ;
entry - > prev = LIST_POISON2 ;
}
EXPORT_SYMBOL ( list_del ) ;
2012-03-15 06:17:39 +04:00
/*
* RCU variants .
*/
void __list_add_rcu ( struct list_head * new ,
struct list_head * prev , struct list_head * next )
{
WARN ( next - > prev ! = prev ,
2012-05-18 02:12:45 +04:00
" list_add_rcu corruption. next->prev should be prev (%p), but was %p. (next=%p). \n " ,
2012-03-15 06:17:39 +04:00
prev , next - > prev , next ) ;
WARN ( prev - > next ! = next ,
2012-05-18 02:12:45 +04:00
" list_add_rcu corruption. prev->next should be next (%p), but was %p. (prev=%p). \n " ,
2012-03-15 06:17:39 +04:00
next , prev - > next , prev ) ;
new - > next = next ;
new - > prev = prev ;
rcu_assign_pointer ( list_next_rcu ( prev ) , new ) ;
next - > prev = new ;
}
EXPORT_SYMBOL ( __list_add_rcu ) ;