2011-03-21 09:58:24 +00:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 2010 Isilon Systems, Inc.
|
|
|
|
* Copyright (c) 2010 iX Systems, Inc.
|
|
|
|
* Copyright (c) 2010 Panasas, Inc.
|
2016-01-26 15:12:31 +00:00
|
|
|
* Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
|
2011-03-21 09:58:24 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice unmodified, this list of conditions, and the following
|
|
|
|
* disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2015-10-20 19:08:26 +00:00
|
|
|
*
|
|
|
|
* $FreeBSD$
|
2011-03-21 09:58:24 +00:00
|
|
|
*/
|
|
|
|
#ifndef _LINUX_LIST_H_
|
|
|
|
#define _LINUX_LIST_H_
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since LIST_HEAD conflicts with the linux definition we must include any
|
|
|
|
* FreeBSD header which requires it here so it is resolved with the correct
|
|
|
|
* definition prior to the undef.
|
|
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/queue.h>
|
Commit the support for removing cpumask_t and replacing it directly with
cpuset_t objects.
That is going to offer the underlying support for a simple bump of
MAXCPU and then support for number of cpus > 32 (as it is today).
Right now, cpumask_t is an int, 32 bits on all our supported architecture.
cpumask_t on the other side is implemented as an array of longs, and
easilly extendible by definition.
The architectures touched by this commit are the following:
- amd64
- i386
- pc98
- arm
- ia64
- XEN
while the others are still missing.
Userland is believed to be fully converted with the changes contained
here.
Some technical notes:
- This commit may be considered an ABI nop for all the architectures
different from amd64 and ia64 (and sparc64 in the future)
- per-cpu members, which are now converted to cpuset_t, needs to be
accessed avoiding migration, because the size of cpuset_t should be
considered unknown
- size of cpuset_t objects is different from kernel and userland (this is
primirally done in order to leave some more space in userland to cope
with KBI extensions). If you need to access kernel cpuset_t from the
userland please refer to example in this patch on how to do that
correctly (kgdb may be a good source, for example).
- Support for other architectures is going to be added soon
- Only MAXCPU for amd64 is bumped now
The patch has been tested by sbruno and Nicholas Esborn on opteron
4 x 12 pack CPUs. More testing on big SMP is expected to came soon.
pluknet tested the patch with his 8-ways on both amd64 and i386.
Tested by: pluknet, sbruno, gianni, Nicholas Esborn
Reviewed by: jeff, jhb, sbruno
2011-05-05 14:39:14 +00:00
|
|
|
#include <sys/cpuset.h>
|
2014-12-08 07:25:59 +00:00
|
|
|
#include <sys/jail.h>
|
2011-03-21 09:58:24 +00:00
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/mutex.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/vnode.h>
|
|
|
|
#include <sys/conf.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
|
|
|
|
#include <net/bpf.h>
|
|
|
|
#include <net/if.h>
|
2013-10-26 17:58:36 +00:00
|
|
|
#include <net/if_var.h>
|
2011-03-21 09:58:24 +00:00
|
|
|
#include <net/if_types.h>
|
|
|
|
#include <net/if_media.h>
|
2014-12-08 07:25:59 +00:00
|
|
|
#include <net/vnet.h>
|
2011-03-21 09:58:24 +00:00
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_pcb.h>
|
2015-01-06 10:02:14 +00:00
|
|
|
#include <netinet/in_var.h>
|
2016-04-01 06:43:05 +00:00
|
|
|
#include <netinet/tcp_lro.h>
|
2011-03-21 09:58:24 +00:00
|
|
|
|
|
|
|
#include <netinet6/in6_var.h>
|
|
|
|
#include <netinet6/nd6.h>
|
|
|
|
|
|
|
|
#include <vm/vm.h>
|
|
|
|
#include <vm/vm_object.h>
|
2015-11-12 09:18:22 +00:00
|
|
|
#include <vm/pmap.h>
|
2011-03-21 09:58:24 +00:00
|
|
|
|
|
|
|
#define prefetch(x)
|
|
|
|
|
|
|
|
struct list_head {
|
|
|
|
struct list_head *next;
|
|
|
|
struct list_head *prev;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
INIT_LIST_HEAD(struct list_head *list)
|
|
|
|
{
|
|
|
|
|
|
|
|
list->next = list->prev = list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
list_empty(const struct list_head *head)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (head->next == head);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_del(struct list_head *entry)
|
|
|
|
{
|
|
|
|
|
|
|
|
entry->next->prev = entry->prev;
|
|
|
|
entry->prev->next = entry->next;
|
|
|
|
}
|
|
|
|
|
2015-10-19 11:57:33 +00:00
|
|
|
static inline void
|
|
|
|
list_replace(struct list_head *old, struct list_head *new)
|
|
|
|
{
|
|
|
|
new->next = old->next;
|
|
|
|
new->next->prev = new;
|
|
|
|
new->prev = old->prev;
|
|
|
|
new->prev->next = new;
|
|
|
|
}
|
|
|
|
|
2016-05-23 12:03:40 +00:00
|
|
|
static inline void
|
|
|
|
list_replace_init(struct list_head *old, struct list_head *new)
|
|
|
|
{
|
|
|
|
list_replace(old, new);
|
|
|
|
INIT_LIST_HEAD(old);
|
|
|
|
}
|
|
|
|
|
2011-03-21 09:58:24 +00:00
|
|
|
static inline void
|
2016-01-26 15:12:31 +00:00
|
|
|
linux_list_add(struct list_head *new, struct list_head *prev,
|
2011-03-21 09:58:24 +00:00
|
|
|
struct list_head *next)
|
|
|
|
{
|
|
|
|
|
|
|
|
next->prev = new;
|
|
|
|
new->next = next;
|
|
|
|
new->prev = prev;
|
|
|
|
prev->next = new;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_del_init(struct list_head *entry)
|
|
|
|
{
|
|
|
|
|
|
|
|
list_del(entry);
|
|
|
|
INIT_LIST_HEAD(entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define list_entry(ptr, type, field) container_of(ptr, type, field)
|
|
|
|
|
2013-09-29 00:35:03 +00:00
|
|
|
#define list_first_entry(ptr, type, member) \
|
|
|
|
list_entry((ptr)->next, type, member)
|
|
|
|
|
2016-05-23 12:03:40 +00:00
|
|
|
#define list_last_entry(ptr, type, member) \
|
|
|
|
list_entry((ptr)->prev, type, member)
|
|
|
|
|
|
|
|
#define list_first_entry_or_null(ptr, type, member) \
|
|
|
|
(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
|
|
|
|
|
2015-10-19 11:57:33 +00:00
|
|
|
#define list_next_entry(ptr, member) \
|
|
|
|
list_entry(((ptr)->member.next), typeof(*(ptr)), member)
|
|
|
|
|
2016-05-23 12:03:40 +00:00
|
|
|
#define list_prev_entry(ptr, member) \
|
|
|
|
list_entry(((ptr)->member.prev), typeof(*(ptr)), member)
|
|
|
|
|
2011-03-21 09:58:24 +00:00
|
|
|
#define list_for_each(p, head) \
|
2016-01-26 15:12:31 +00:00
|
|
|
for (p = (head)->next; p != (head); p = (p)->next)
|
2011-03-21 09:58:24 +00:00
|
|
|
|
|
|
|
#define list_for_each_safe(p, n, head) \
|
2016-01-26 15:12:31 +00:00
|
|
|
for (p = (head)->next, n = (p)->next; p != (head); p = n, n = (p)->next)
|
2011-03-21 09:58:24 +00:00
|
|
|
|
|
|
|
#define list_for_each_entry(p, h, field) \
|
2016-01-26 15:12:31 +00:00
|
|
|
for (p = list_entry((h)->next, typeof(*p), field); &(p)->field != (h); \
|
|
|
|
p = list_entry((p)->field.next, typeof(*p), field))
|
2011-03-21 09:58:24 +00:00
|
|
|
|
|
|
|
#define list_for_each_entry_safe(p, n, h, field) \
|
|
|
|
for (p = list_entry((h)->next, typeof(*p), field), \
|
2016-01-26 15:12:31 +00:00
|
|
|
n = list_entry((p)->field.next, typeof(*p), field); &(p)->field != (h);\
|
2011-03-21 09:58:24 +00:00
|
|
|
p = n, n = list_entry(n->field.next, typeof(*n), field))
|
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
#define list_for_each_entry_from(p, h, field) \
|
|
|
|
for ( ; &(p)->field != (h); \
|
|
|
|
p = list_entry((p)->field.next, typeof(*p), field))
|
|
|
|
|
2015-10-19 11:57:33 +00:00
|
|
|
#define list_for_each_entry_continue(p, h, field) \
|
2016-01-26 15:12:31 +00:00
|
|
|
for (p = list_next_entry((p), field); &(p)->field != (h); \
|
2015-10-19 11:57:33 +00:00
|
|
|
p = list_next_entry((p), field))
|
|
|
|
|
|
|
|
#define list_for_each_entry_safe_from(pos, n, head, member) \
|
2016-01-26 15:12:31 +00:00
|
|
|
for (n = list_entry((pos)->member.next, typeof(*pos), member); \
|
|
|
|
&(pos)->member != (head); \
|
2015-10-19 11:57:33 +00:00
|
|
|
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
|
|
|
|
2011-03-21 09:58:24 +00:00
|
|
|
#define list_for_each_entry_reverse(p, h, field) \
|
2016-01-26 15:12:31 +00:00
|
|
|
for (p = list_entry((h)->prev, typeof(*p), field); &(p)->field != (h); \
|
|
|
|
p = list_entry((p)->field.prev, typeof(*p), field))
|
|
|
|
|
|
|
|
#define list_for_each_entry_continue_reverse(p, h, field) \
|
|
|
|
for (p = list_entry((p)->field.prev, typeof(*p), field); &(p)->field != (h); \
|
|
|
|
p = list_entry((p)->field.prev, typeof(*p), field))
|
2011-03-21 09:58:24 +00:00
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
#define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = (p)->prev)
|
2011-03-21 09:58:24 +00:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_add(struct list_head *new, struct list_head *head)
|
|
|
|
{
|
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
linux_list_add(new, head, head->next);
|
2011-03-21 09:58:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_add_tail(struct list_head *new, struct list_head *head)
|
|
|
|
{
|
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
linux_list_add(new, head->prev, head);
|
2011-03-21 09:58:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_move(struct list_head *list, struct list_head *head)
|
|
|
|
{
|
|
|
|
|
|
|
|
list_del(list);
|
|
|
|
list_add(list, head);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_move_tail(struct list_head *entry, struct list_head *head)
|
|
|
|
{
|
|
|
|
|
|
|
|
list_del(entry);
|
|
|
|
list_add_tail(entry, head);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2016-01-26 15:12:31 +00:00
|
|
|
linux_list_splice(const struct list_head *list, struct list_head *prev,
|
2011-03-21 09:58:24 +00:00
|
|
|
struct list_head *next)
|
|
|
|
{
|
|
|
|
struct list_head *first;
|
|
|
|
struct list_head *last;
|
|
|
|
|
|
|
|
if (list_empty(list))
|
|
|
|
return;
|
|
|
|
first = list->next;
|
|
|
|
last = list->prev;
|
|
|
|
first->prev = prev;
|
|
|
|
prev->next = first;
|
|
|
|
last->next = next;
|
|
|
|
next->prev = last;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_splice(const struct list_head *list, struct list_head *head)
|
|
|
|
{
|
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
linux_list_splice(list, head, head->next);
|
2011-03-21 09:58:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_splice_tail(struct list_head *list, struct list_head *head)
|
|
|
|
{
|
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
linux_list_splice(list, head->prev, head);
|
2011-03-21 09:58:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_splice_init(struct list_head *list, struct list_head *head)
|
|
|
|
{
|
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
linux_list_splice(list, head, head->next);
|
2011-03-21 09:58:24 +00:00
|
|
|
INIT_LIST_HEAD(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
list_splice_tail_init(struct list_head *list, struct list_head *head)
|
|
|
|
{
|
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
linux_list_splice(list, head->prev, head);
|
2011-03-21 09:58:24 +00:00
|
|
|
INIT_LIST_HEAD(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef LIST_HEAD
|
|
|
|
#define LIST_HEAD(name) struct list_head name = { &(name), &(name) }
|
|
|
|
|
|
|
|
|
|
|
|
struct hlist_head {
|
|
|
|
struct hlist_node *first;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct hlist_node {
|
|
|
|
struct hlist_node *next, **pprev;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define HLIST_HEAD_INIT { }
|
|
|
|
#define HLIST_HEAD(name) struct hlist_head name = HLIST_HEAD_INIT
|
|
|
|
#define INIT_HLIST_HEAD(head) (head)->first = NULL
|
|
|
|
#define INIT_HLIST_NODE(node) \
|
|
|
|
do { \
|
|
|
|
(node)->next = NULL; \
|
|
|
|
(node)->pprev = NULL; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
hlist_unhashed(const struct hlist_node *h)
|
|
|
|
{
|
|
|
|
|
|
|
|
return !h->pprev;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
hlist_empty(const struct hlist_head *h)
|
|
|
|
{
|
|
|
|
|
|
|
|
return !h->first;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
hlist_del(struct hlist_node *n)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (n->next)
|
|
|
|
n->next->pprev = n->pprev;
|
|
|
|
*n->pprev = n->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
hlist_del_init(struct hlist_node *n)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (hlist_unhashed(n))
|
|
|
|
return;
|
|
|
|
hlist_del(n);
|
|
|
|
INIT_HLIST_NODE(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
hlist_add_head(struct hlist_node *n, struct hlist_head *h)
|
|
|
|
{
|
|
|
|
|
|
|
|
n->next = h->first;
|
|
|
|
if (h->first)
|
|
|
|
h->first->pprev = &n->next;
|
|
|
|
h->first = n;
|
|
|
|
n->pprev = &h->first;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
hlist_add_before(struct hlist_node *n, struct hlist_node *next)
|
|
|
|
{
|
|
|
|
|
|
|
|
n->pprev = next->pprev;
|
|
|
|
n->next = next;
|
|
|
|
next->pprev = &n->next;
|
|
|
|
*(n->pprev) = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
hlist_add_after(struct hlist_node *n, struct hlist_node *next)
|
|
|
|
{
|
|
|
|
|
|
|
|
next->next = n->next;
|
|
|
|
n->next = next;
|
|
|
|
next->pprev = &n->next;
|
|
|
|
if (next->next)
|
|
|
|
next->next->pprev = &next->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
hlist_move_list(struct hlist_head *old, struct hlist_head *new)
|
|
|
|
{
|
|
|
|
|
|
|
|
new->first = old->first;
|
|
|
|
if (new->first)
|
|
|
|
new->first->pprev = &new->first;
|
|
|
|
old->first = NULL;
|
|
|
|
}
|
2014-08-27 13:21:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* list_is_singular - tests whether a list has just one entry.
|
|
|
|
* @head: the list to test.
|
|
|
|
*/
|
|
|
|
static inline int list_is_singular(const struct list_head *head)
|
|
|
|
{
|
|
|
|
return !list_empty(head) && (head->next == head->prev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void __list_cut_position(struct list_head *list,
|
|
|
|
struct list_head *head, struct list_head *entry)
|
|
|
|
{
|
|
|
|
struct list_head *new_first = entry->next;
|
|
|
|
list->next = head->next;
|
|
|
|
list->next->prev = list;
|
|
|
|
list->prev = entry;
|
|
|
|
entry->next = list;
|
|
|
|
head->next = new_first;
|
|
|
|
new_first->prev = head;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* list_cut_position - cut a list into two
|
|
|
|
* @list: a new list to add all removed entries
|
|
|
|
* @head: a list with entries
|
|
|
|
* @entry: an entry within head, could be the head itself
|
|
|
|
* and if so we won't cut the list
|
|
|
|
*
|
|
|
|
* This helper moves the initial part of @head, up to and
|
|
|
|
* including @entry, from @head to @list. You should
|
|
|
|
* pass on @entry an element you know is on @head. @list
|
|
|
|
* should be an empty list or a list you do not care about
|
|
|
|
* losing its data.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static inline void list_cut_position(struct list_head *list,
|
|
|
|
struct list_head *head, struct list_head *entry)
|
|
|
|
{
|
|
|
|
if (list_empty(head))
|
|
|
|
return;
|
|
|
|
if (list_is_singular(head) &&
|
|
|
|
(head->next != entry && head != entry))
|
|
|
|
return;
|
|
|
|
if (entry == head)
|
|
|
|
INIT_LIST_HEAD(list);
|
|
|
|
else
|
|
|
|
__list_cut_position(list, head, entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* list_is_last - tests whether @list is the last entry in list @head
|
|
|
|
* @list: the entry to test
|
|
|
|
* @head: the head of the list
|
|
|
|
*/
|
|
|
|
static inline int list_is_last(const struct list_head *list,
|
|
|
|
const struct list_head *head)
|
|
|
|
{
|
|
|
|
return list->next == head;
|
|
|
|
}
|
2011-03-21 09:58:24 +00:00
|
|
|
|
|
|
|
#define hlist_entry(ptr, type, field) container_of(ptr, type, field)
|
|
|
|
|
|
|
|
#define hlist_for_each(p, head) \
|
2016-01-26 15:12:31 +00:00
|
|
|
for (p = (head)->first; p; p = (p)->next)
|
2011-03-21 09:58:24 +00:00
|
|
|
|
|
|
|
#define hlist_for_each_safe(p, n, head) \
|
2016-01-26 15:12:31 +00:00
|
|
|
for (p = (head)->first; p && ({ n = (p)->next; 1; }); p = n)
|
2011-03-21 09:58:24 +00:00
|
|
|
|
2015-10-19 11:57:33 +00:00
|
|
|
#define hlist_entry_safe(ptr, type, member) \
|
|
|
|
((ptr) ? hlist_entry(ptr, type, member) : NULL)
|
|
|
|
|
|
|
|
#define hlist_for_each_entry(pos, head, member) \
|
|
|
|
for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
|
|
|
|
pos; \
|
|
|
|
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
|
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
#define hlist_for_each_entry_continue(pos, member) \
|
|
|
|
for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member); \
|
|
|
|
(pos); \
|
|
|
|
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
|
2011-03-21 09:58:24 +00:00
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
#define hlist_for_each_entry_from(pos, member) \
|
|
|
|
for (; (pos); \
|
|
|
|
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
|
2015-10-19 11:57:33 +00:00
|
|
|
|
2016-01-26 15:12:31 +00:00
|
|
|
#define hlist_for_each_entry_safe(pos, n, head, member) \
|
|
|
|
for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member); \
|
|
|
|
(pos) && ({ n = (pos)->member.next; 1; }); \
|
|
|
|
pos = hlist_entry_safe(n, typeof(*(pos)), member))
|
2015-10-19 11:57:33 +00:00
|
|
|
|
2016-05-23 12:03:40 +00:00
|
|
|
extern void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv,
|
|
|
|
struct list_head *a, struct list_head *b));
|
|
|
|
|
2011-03-21 09:58:24 +00:00
|
|
|
#endif /* _LINUX_LIST_H_ */
|