diff options
Diffstat (limited to 'include/linux/rculist.h')
| -rw-r--r-- | include/linux/rculist.h | 69 | 
1 files changed, 49 insertions, 20 deletions
diff --git a/include/linux/rculist.h b/include/linux/rculist.h index 5ed540986019..e99d834545b6 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -179,32 +179,31 @@ static inline void list_replace_rcu(struct list_head *old,  }  /** - * list_splice_init_rcu - splice an RCU-protected list into an existing list. + * __list_splice_init_rcu - join an RCU-protected list into an existing list.   * @list:	the RCU-protected list to splice - * @head:	the place in the list to splice the first list into + * @prev:	points to the last element of the existing list + * @next:	points to the first element of the existing list   * @sync:	function to sync: synchronize_rcu(), synchronize_sched(), ...   * - * @head can be RCU-read traversed concurrently with this function. + * The list pointed to by @prev and @next can be RCU-read traversed + * concurrently with this function.   *   * Note that this function blocks.   * - * Important note: the caller must take whatever action is necessary to - *	prevent any other updates to @head.  In principle, it is possible - *	to modify the list as soon as sync() begins execution. - *	If this sort of thing becomes necessary, an alternative version - *	based on call_rcu() could be created.  But only if -really- - *	needed -- there is no shortage of RCU API members. + * Important note: the caller must take whatever action is necessary to prevent + * any other updates to the existing list.  In principle, it is possible to + * modify the list as soon as sync() begins execution. If this sort of thing + * becomes necessary, an alternative version based on call_rcu() could be + * created.  But only if -really- needed -- there is no shortage of RCU API + * members.   */ -static inline void list_splice_init_rcu(struct list_head *list, -					struct list_head *head, -					void (*sync)(void)) +static inline void __list_splice_init_rcu(struct list_head *list, +					  struct list_head *prev, +					  struct list_head *next, +					  void (*sync)(void))  {  	struct list_head *first = list->next;  	struct list_head *last = list->prev; -	struct list_head *at = head->next; - -	if (list_empty(list)) -		return;  	/*  	 * "first" and "last" tracking list, so initialize it.  RCU readers @@ -231,10 +230,40 @@ static inline void list_splice_init_rcu(struct list_head *list,  	 * this function.  	 */ -	last->next = at; -	rcu_assign_pointer(list_next_rcu(head), first); -	first->prev = head; -	at->prev = last; +	last->next = next; +	rcu_assign_pointer(list_next_rcu(prev), first); +	first->prev = prev; +	next->prev = last; +} + +/** + * list_splice_init_rcu - splice an RCU-protected list into an existing list, + *                        designed for stacks. + * @list:	the RCU-protected list to splice + * @head:	the place in the existing list to splice the first list into + * @sync:	function to sync: synchronize_rcu(), synchronize_sched(), ... + */ +static inline void list_splice_init_rcu(struct list_head *list, +					struct list_head *head, +					void (*sync)(void)) +{ +	if (!list_empty(list)) +		__list_splice_init_rcu(list, head, head->next, sync); +} + +/** + * list_splice_tail_init_rcu - splice an RCU-protected list into an existing + *                             list, designed for queues. + * @list:	the RCU-protected list to splice + * @head:	the place in the existing list to splice the first list into + * @sync:	function to sync: synchronize_rcu(), synchronize_sched(), ... + */ +static inline void list_splice_tail_init_rcu(struct list_head *list, +					     struct list_head *head, +					     void (*sync)(void)) +{ +	if (!list_empty(list)) +		__list_splice_init_rcu(list, head->prev, head, sync);  }  /**  | 
