[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Wed Feb 10 17:51:12 MST 2010


The branch, master has been updated
       via  ed0e0a2... Fix bad use when freeing linked list. Todd Stecher (Original author) please check !
       via  91cb7b7... test:local added LOCAL-DLINKLIST testsuite (cherry picked from commit 95a5bee2c30a67a35604b0456ab7836f6dc67702)
       via  32809bd... util: rewrite dlinklist.h so that DLIST_ADD_END() is O(1)
       via  13ac4ad... s3-smbd: update to use new DLIST macros (cherry picked from commit 365b408c458c848a818637d9b36a0423aeb1ba54)
       via  aa52a09... s3-registry: update to use new DLIST macros (cherry picked from commit 3437713ad7e5bccafde30553a8232119fd2a9eb9)
       via  f592d42... s3-perfcount: update to use new DLIST macros (cherry picked from commit a13b507f2d8be7f90c8872094cd0732926a6fcbb)
       via  4689826... s3-locking: update to use DLIST_ADD_AFTER() (cherry picked from commit 6c6df527e14514027cbcaa6deac25adf04363926)
       via  d550621... s3-libsmb: update libsmb to use new DLIST macros
       via  7842b39... s3-memcache: update memcache to use new DLIST macros
       via  54fc99e... s3-ldb: update the old ldb in s3 to use new DLIST macros (cherry picked from commit a7d8bfd373392eecf4fff33d39b85e1b55ad901d)
       via  ece7089... s3-nmbd: update nmbd to use new DLIST_ macros (cherry picked from commit 4d23d777bc6d4fad20d0f3084fe658635812bee9)
       via  a5d2fb7... s4-ldb: update ldb_tdb to use new DLIST_ macros (cherry picked from commit 6ede911654566a7e21ded70dacac68df3b6a1bca)
       via  f017edc... s4-dsdb: update repl_meta_data.c to use new DLIST_ macros
       via  32575ed... Temporary changes to dlinklist to keep the implementation static whilst uses of (list)->prev are moved over to DLIST_PREV. This will be replaced when the final (new) version of the dlinklist.h header is added.
      from  f2d7d97... Revert "Change the default of "nmbd bind explicit broadcast" to "no""

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit ed0e0a20059aeadddd69c4618d35dfb3aca69ba4
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Feb 10 16:23:33 2010 -0800

    Fix bad use when freeing linked list. Todd Stecher (Original author) please check !
    
    Jeremy.

commit 91cb7b7c604d6d3c0dcb3dbcdabb0a6db6097035
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sun Feb 7 16:06:31 2010 +1100

    test:local added LOCAL-DLINKLIST testsuite
    (cherry picked from commit 95a5bee2c30a67a35604b0456ab7836f6dc67702)

commit 32809bd8c17c9c522338722177539aa3d60c4cbc
Author: Andrew Tridgell <tridge at samba.org>
Date:   Wed Feb 10 15:53:58 2010 -0800

    util: rewrite dlinklist.h so that DLIST_ADD_END() is O(1)
    
    This changes the meaning of the ->prev pointer in our doubly linked
    lists to point at the end of the list from the front of the list. That
    allows us to implement DLIST_ADD_END() and related functions in O(1)
    time, which can be a huge saving in many places in Samba.
    
    This also means that the 'type' argument to various DLIST_*() macros
    is no longer needed, but I have left it in for now to keep the
    patchset small, which will make it easier to revert if any problems
    are found. In the future we should remove the 'type' arguments.
    
    (jra. Move the one use of DLIST_TAIL over to the new macros).

commit 13ac4ad52187df7093904d4ad9c47d51bd1eda6f
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Feb 6 12:42:29 2010 +1100

    s3-smbd: update to use new DLIST macros
    (cherry picked from commit 365b408c458c848a818637d9b36a0423aeb1ba54)

commit aa52a0925d4c07117cc6eb62c6e80eda24f8cc40
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Feb 6 12:41:57 2010 +1100

    s3-registry: update to use new DLIST macros
    (cherry picked from commit 3437713ad7e5bccafde30553a8232119fd2a9eb9)

commit f592d42047d0b5d7ea115b9cd44a55ee443b64f7
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Feb 6 12:41:39 2010 +1100

    s3-perfcount: update to use new DLIST macros
    (cherry picked from commit a13b507f2d8be7f90c8872094cd0732926a6fcbb)

commit 4689826e391eb83ac639b9afdae641a6e3f34b9a
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Feb 6 12:41:07 2010 +1100

    s3-locking: update to use DLIST_ADD_AFTER()
    (cherry picked from commit 6c6df527e14514027cbcaa6deac25adf04363926)

commit d5506215610f95c161ad45dba00a0b180de3a00b
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Feb 6 12:40:38 2010 +1100

    s3-libsmb: update libsmb to use new DLIST macros
    
    manipulating p->prev directly is not safe any more
    (cherry picked from commit 3c650ac1e3e1cdbbabecfddcd29325f20b5dcb48)

commit 7842b391b9ad1f6aaa77c0b8397e1dcc0b79e7e7
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Feb 6 12:40:03 2010 +1100

    s3-memcache: update memcache to use new DLIST macros
    
    we don't need a separate lru pointer any more
    (cherry picked from commit 4ffd7aca3e38728077bd80c2a65c4efbcfd216fc)

commit 54fc99e04b3475a9cc04274fa365edbd700d3491
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Feb 6 12:38:47 2010 +1100

    s3-ldb: update the old ldb in s3 to use new DLIST macros
    (cherry picked from commit a7d8bfd373392eecf4fff33d39b85e1b55ad901d)

commit ece7089918e37f407f84d13df9d816d5a6d90f2e
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Feb 6 12:38:24 2010 +1100

    s3-nmbd: update nmbd to use new DLIST_ macros
    (cherry picked from commit 4d23d777bc6d4fad20d0f3084fe658635812bee9)

commit a5d2fb752cdb7e27a4949635b6486834d9fac313
Author: Andrew Tridgell <tridge at samba.org>
Date:   Sat Feb 6 12:37:48 2010 +1100

    s4-ldb: update ldb_tdb to use new DLIST_ macros
    (cherry picked from commit 6ede911654566a7e21ded70dacac68df3b6a1bca)

commit f017edc59f06121db08dcbdfaa0b75b808560955
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Feb 10 15:35:38 2010 -0800

    s4-dsdb: update repl_meta_data.c to use new DLIST_ macros

commit 32575ed70f3210a2fe10edfd801ad1cb8f5caffa
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Feb 10 15:30:59 2010 -0800

    Temporary changes to dlinklist to keep the implementation static whilst
    uses of (list)->prev are moved over to DLIST_PREV. This will be replaced
    when the final (new) version of the dlinklist.h header is added.
    
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 lib/util/dlinklist.h                            |  164 ++++++++++++++++-------
 lib/util/tests/dlinklist.c                      |  130 ++++++++++++++++++
 source3/lib/ldb/include/dlinklist.h             |  164 ++++++++++++++++-------
 source3/lib/ldb/ldb_tdb/ldb_tdb_wrap.c          |   17 +--
 source3/lib/ldb/modules/paged_results.c         |   17 +--
 source3/lib/memcache.c                          |   21 +---
 source3/libsmb/clidfs.c                         |    2 +-
 source3/libsmb/clientgen.c                      |   46 ++++---
 source3/locking/posix.c                         |    6 +-
 source3/modules/perfcount_onefs.c               |    2 +-
 source3/modules/perfcount_test.c                |   15 +-
 source3/nmbd/asyncdns.c                         |   18 +--
 source3/nmbd/nmbd_packets.c                     |   20 +---
 source3/nmbd/nmbd_serverlistdb.c                |   35 +-----
 source3/nmbd/nmbd_workgroupdb.c                 |    9 +-
 source3/registry/regfio.c                       |    4 +-
 source3/smbd/dir.c                              |    7 +-
 source3/smbd/posix_acls.c                       |    4 +-
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c |    6 +-
 source4/lib/ldb/include/dlinklist.h             |  164 ++++++++++++++++-------
 source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c          |   18 +--
 source4/torture/local/config.mk                 |    1 +
 source4/torture/local/local.c                   |    1 +
 23 files changed, 543 insertions(+), 328 deletions(-)
 create mode 100644 lib/util/tests/dlinklist.c


Changeset truncated at 500 lines:

diff --git a/lib/util/dlinklist.h b/lib/util/dlinklist.h
index 693b43d..6d525f9 100644
--- a/lib/util/dlinklist.h
+++ b/lib/util/dlinklist.h
@@ -1,7 +1,8 @@
 /* 
    Unix SMB/CIFS implementation.
    some simple double linked list macros
-   Copyright (C) Andrew Tridgell 1998
+
+   Copyright (C) Andrew Tridgell 1998-2010
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -23,55 +24,94 @@
 #ifndef _DLINKLIST_H
 #define _DLINKLIST_H
 
+/*
+  February 2010 - changed list format to have a prev pointer from the
+  list head. This makes DLIST_ADD_END() O(1) even though we only have
+  one list pointer.
+
+  The scheme is as follows:
+
+     1) with no entries in the list:
+          list_head == NULL
+
+     2) with 1 entry in the list:
+          list_head->next == NULL
+          list_head->prev == list_head
+
+     3) with 2 entries in the list:
+          list_head->next == element2
+          list_head->prev == element2
+	  element2->prev == list_head
+	  element2->next == NULL
+
+     4) with N entries in the list:
+          list_head->next == element2
+          list_head->prev == elementN
+	  elementN->prev == element{N-1}
+	  elementN->next == NULL
 
-/* hook into the front of the list */
+  This allows us to find the tail of the list by using
+  list_head->prev, which means we can add to the end of the list in
+  O(1) time
+
+
+  Note that the 'type' arguments below are no longer needed, but
+  are kept for now to prevent an incompatible argument change
+ */
+
+
+/*
+   add an element at the front of a list
+*/
 #define DLIST_ADD(list, p) \
 do { \
         if (!(list)) { \
-		(list) = (p); \
-		(p)->next = (p)->prev = NULL; \
+		(p)->prev = (list) = (p);  \
+		(p)->next = NULL; \
 	} else { \
+		(p)->prev = (list)->prev; \
 		(list)->prev = (p); \
 		(p)->next = (list); \
-		(p)->prev = NULL; \
 		(list) = (p); \
-	}\
+	} \
 } while (0)
 
-/* remove an element from a list - element doesn't have to be in list. */
+/*
+   remove an element from a list
+   Note that the element doesn't have to be in the list. If it
+   isn't then this is a no-op
+*/
 #define DLIST_REMOVE(list, p) \
 do { \
 	if ((p) == (list)) { \
+		if ((p)->next) (p)->next->prev = (p)->prev; \
 		(list) = (p)->next; \
-		if (list) (list)->prev = NULL; \
+	} else if ((list) && (p) == (list)->prev) {	\
+		(p)->prev->next = NULL; \
+		(list)->prev = (p)->prev; \
 	} else { \
 		if ((p)->prev) (p)->prev->next = (p)->next; \
 		if ((p)->next) (p)->next->prev = (p)->prev; \
 	} \
-	if ((p) != (list)) (p)->next = (p)->prev = NULL; \
+	if ((p) != (list)) (p)->next = (p)->prev = NULL;	\
 } while (0)
 
-/* promote an element to the top of the list */
-#define DLIST_PROMOTE(list, p) \
+/*
+   find the head of the list given any element in it.
+   Note that this costs O(N), so you should avoid this macro
+   if at all possible!
+*/
+#define DLIST_HEAD(p, result_head) \
 do { \
-          DLIST_REMOVE(list, p); \
-          DLIST_ADD(list, p); \
-} while (0)
+       (result_head) = (p); \
+       while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \
+} while(0)
 
-/* hook into the end of the list - needs the entry type */
-#define DLIST_ADD_END(list, p, type) \
-do { \
-		if (!(list)) { \
-			(list) = (p); \
-			(p)->next = (p)->prev = NULL; \
-		} else { \
-			type tmp; \
-			for (tmp = (list); tmp->next; tmp = tmp->next) ; \
-			tmp->next = (p); \
-			(p)->next = NULL; \
-			(p)->prev = tmp; \
-		} \
-} while (0)
+/* return the last element in the list */
+#define DLIST_TAIL(list) ((list)?(list)->prev:NULL)
+
+/* return the previous element in the list. */
+#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL)
 
 /* insert 'p' after the given element 'el' in a list. If el is NULL then
    this is the same as a DLIST_ADD() */
@@ -80,34 +120,62 @@ do { \
         if (!(list) || !(el)) { \
 		DLIST_ADD(list, p); \
 	} else { \
-		p->prev = el; \
-		p->next = el->next; \
-		el->next = p; \
-		if (p->next) p->next->prev = p; \
+		(p)->prev = (el);   \
+		(p)->next = (el)->next;		\
+		(el)->next = (p);		\
+		if ((p)->next) (p)->next->prev = (p);	\
+		if ((list)->prev == (el)) (list)->prev = (p); \
 	}\
 } while (0)
 
-/* demote an element to the end of the list, needs the entry type */
-#define DLIST_DEMOTE(list, p, type) \
+
+/*
+   add to the end of a list.
+   Note that 'type' is ignored
+*/
+#define DLIST_ADD_END(list, p, type)			\
 do { \
-		DLIST_REMOVE(list, p); \
-		DLIST_ADD_END(list, p, type); \
+	if (!(list)) { \
+		DLIST_ADD(list, p); \
+	} else { \
+		DLIST_ADD_AFTER(list, p, (list)->prev); \
+	} \
 } while (0)
 
-/* concatenate two lists - putting all elements of the 2nd list at the
-   end of the first list */
-#define DLIST_CONCATENATE(list1, list2, type) \
+/* promote an element to the from of a list */
+#define DLIST_PROMOTE(list, p) \
 do { \
-		if (!(list1)) { \
-			(list1) = (list2); \
-		} else { \
-			type tmp; \
-			for (tmp = (list1); tmp->next; tmp = tmp->next) ; \
-			tmp->next = (list2); \
-			if (list2) { \
-				(list2)->prev = tmp;	\
-			} \
+          DLIST_REMOVE(list, p); \
+          DLIST_ADD(list, p); \
+} while (0)
+
+/*
+   demote an element to the end of a list.
+   Note that 'type' is ignored
+*/
+#define DLIST_DEMOTE(list, p, type)			\
+do { \
+	DLIST_REMOVE(list, p); \
+	DLIST_ADD_END(list, p, NULL);		\
+} while (0)
+
+/*
+   concatenate two lists - putting all elements of the 2nd list at the
+   end of the first list.
+   Note that 'type' is ignored
+*/
+#define DLIST_CONCATENATE(list1, list2, type)	\
+do { \
+	if (!(list1)) { \
+		(list1) = (list2); \
+	} else { \
+		(list1)->prev->next = (list2); \
+		if (list2) { \
+			void *_tmplist = (void *)(list1)->prev; \
+			(list1)->prev = (list2)->prev; \
+			(list2)->prev = _tmplist; \
 		} \
+	} \
 } while (0)
 
 #endif /* _DLINKLIST_H */
diff --git a/lib/util/tests/dlinklist.c b/lib/util/tests/dlinklist.c
new file mode 100644
index 0000000..8816dba
--- /dev/null
+++ b/lib/util/tests/dlinklist.c
@@ -0,0 +1,130 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   local testing of DLIST_*() macros
+
+   Copyright (C) Andrew Tridgell 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "torture/torture.h"
+#include "lib/util/dlinklist.h"
+
+struct listel {
+	struct listel *next, *prev;
+};
+
+static bool torture_local_dlinklist_simple(struct torture_context *tctx)
+{
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	struct listel *l1 = NULL, *l2 = NULL, *el, *el2;
+	int i;
+
+	torture_comment(tctx, "add 5 elements at front\n");
+	for (i=0; i<5; i++) {
+		el = talloc(mem_ctx, struct listel);
+		DLIST_ADD(l1, el);
+	}
+
+	torture_comment(tctx, "add 5 elements at end\n");
+	for (i=0; i<5; i++) {
+		el = talloc(mem_ctx, struct listel);
+		DLIST_ADD_END(l1, el, NULL);
+	}
+
+	torture_comment(tctx, "delete 3 from front\n");
+	for (i=0; i < 3; i++) {
+		el = l1;
+		DLIST_REMOVE(l1, l1);
+		DLIST_ADD(l2, el);
+	}
+
+	torture_comment(tctx, "delete 3 from back\n");
+	for (i=0; i < 3; i++) {
+		el = DLIST_TAIL(l1);
+		DLIST_REMOVE(l1, el);
+		DLIST_ADD_END(l2, el, NULL);
+	}
+
+	torture_comment(tctx, "count forward\n");
+	for (i=0,el=l1; el; el=el->next) i++;
+	torture_assert_int_equal(tctx, i, 4, "should have 4 elements");
+
+	torture_comment(tctx, "count backwards\n");
+	for (i=0,el=DLIST_TAIL(l1); el; el=DLIST_PREV(el)) i++;
+	torture_assert_int_equal(tctx, i, 4, "should have 4 elements");
+
+	torture_comment(tctx, "check DLIST_HEAD\n");
+	el = DLIST_TAIL(l1);
+	DLIST_HEAD(el, el2);
+	torture_assert(tctx, el2 == l1, "should find head");
+
+	torture_comment(tctx, "check DLIST_ADD_AFTER\n");
+	el  = talloc(mem_ctx, struct listel);
+	el2 = talloc(mem_ctx, struct listel);
+	DLIST_ADD_AFTER(l1, el, l1);
+	DLIST_ADD_AFTER(l1, el2, el);
+	torture_assert(tctx, l1->next == el, "2nd in list");
+	torture_assert(tctx, el->next == el2, "3rd in list");
+
+	torture_comment(tctx, "check DLIST_PROMOTE\n");
+	DLIST_PROMOTE(l1, el2);
+	torture_assert(tctx, el2==l1, "1st in list");
+	torture_assert(tctx, el2->next->next == el, "3rd in list");
+
+	torture_comment(tctx, "check DLIST_DEMOTE\n");
+	DLIST_DEMOTE(l1, el, NULL);
+	torture_assert(tctx, el->next == NULL, "last in list");
+	torture_assert(tctx, el2->prev == el, "backlink from head");
+
+	torture_comment(tctx, "count forward\n");
+	for (i=0,el=l1; el; el=el->next) i++;
+	torture_assert_int_equal(tctx, i, 6, "should have 6 elements");
+
+	torture_comment(tctx, "count backwards\n");
+	for (i=0,el=DLIST_TAIL(l1); el; el=DLIST_PREV(el)) i++;
+	torture_assert_int_equal(tctx, i, 6, "should have 6 elements");
+
+	torture_comment(tctx, "check DLIST_CONCATENATE\n");
+	DLIST_CONCATENATE(l1, l2, NULL);
+	torture_comment(tctx, "count forward\n");
+	for (i=0,el=l1; el; el=el->next) i++;
+	torture_assert_int_equal(tctx, i, 12, "should have 12 elements");
+
+	torture_comment(tctx, "count backwards\n");
+	for (i=0,el=DLIST_TAIL(l1); el; el=DLIST_PREV(el)) i++;
+	torture_assert_int_equal(tctx, i, 12, "should have 12 elements");
+
+	torture_comment(tctx, "free forwards\n");
+	for (el=l1; el; el=el2) {
+		el2 = el->next;
+		DLIST_REMOVE(l1, el);
+		talloc_free(el);
+	}
+
+	torture_assert(tctx, l1 == NULL, "list empty");
+	torture_assert_int_equal(tctx, talloc_total_blocks(mem_ctx), 1, "1 block");
+
+	talloc_free(mem_ctx);
+	return true;
+}
+
+struct torture_suite *torture_local_dlinklist(TALLOC_CTX *mem_ctx)
+{
+	struct torture_suite *suite = torture_suite_create(mem_ctx, "DLINKLIST");
+	torture_suite_add_simple_test(suite, "dlinklist", torture_local_dlinklist_simple);
+	return suite;
+}
diff --git a/source3/lib/ldb/include/dlinklist.h b/source3/lib/ldb/include/dlinklist.h
index 62f885d..6d525f9 100644
--- a/source3/lib/ldb/include/dlinklist.h
+++ b/source3/lib/ldb/include/dlinklist.h
@@ -1,7 +1,8 @@
 /* 
    Unix SMB/CIFS implementation.
    some simple double linked list macros
-   Copyright (C) Andrew Tridgell 1998
+
+   Copyright (C) Andrew Tridgell 1998-2010
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -23,55 +24,94 @@
 #ifndef _DLINKLIST_H
 #define _DLINKLIST_H
 
+/*
+  February 2010 - changed list format to have a prev pointer from the
+  list head. This makes DLIST_ADD_END() O(1) even though we only have
+  one list pointer.
+
+  The scheme is as follows:
+
+     1) with no entries in the list:
+          list_head == NULL
+
+     2) with 1 entry in the list:
+          list_head->next == NULL
+          list_head->prev == list_head
+
+     3) with 2 entries in the list:
+          list_head->next == element2
+          list_head->prev == element2
+	  element2->prev == list_head
+	  element2->next == NULL
+
+     4) with N entries in the list:
+          list_head->next == element2
+          list_head->prev == elementN
+	  elementN->prev == element{N-1}
+	  elementN->next == NULL
 
-/* hook into the front of the list */
+  This allows us to find the tail of the list by using
+  list_head->prev, which means we can add to the end of the list in
+  O(1) time
+
+
+  Note that the 'type' arguments below are no longer needed, but
+  are kept for now to prevent an incompatible argument change
+ */
+
+
+/*
+   add an element at the front of a list
+*/
 #define DLIST_ADD(list, p) \
 do { \
         if (!(list)) { \
-		(list) = (p); \
-		(p)->next = (p)->prev = NULL; \
+		(p)->prev = (list) = (p);  \
+		(p)->next = NULL; \
 	} else { \
+		(p)->prev = (list)->prev; \
 		(list)->prev = (p); \
 		(p)->next = (list); \
-		(p)->prev = NULL; \
 		(list) = (p); \
-	}\
+	} \
 } while (0)
 
-/* remove an element from a list - element doesn't have to be in list. */
+/*
+   remove an element from a list
+   Note that the element doesn't have to be in the list. If it
+   isn't then this is a no-op
+*/
 #define DLIST_REMOVE(list, p) \
 do { \
 	if ((p) == (list)) { \
+		if ((p)->next) (p)->next->prev = (p)->prev; \
 		(list) = (p)->next; \
-		if (list) (list)->prev = NULL; \
+	} else if ((list) && (p) == (list)->prev) {	\
+		(p)->prev->next = NULL; \
+		(list)->prev = (p)->prev; \
 	} else { \
 		if ((p)->prev) (p)->prev->next = (p)->next; \
 		if ((p)->next) (p)->next->prev = (p)->prev; \
 	} \
-	if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
+	if ((p) != (list)) (p)->next = (p)->prev = NULL;	\
 } while (0)
 
-/* promote an element to the top of the list */
-#define DLIST_PROMOTE(list, p) \
+/*
+   find the head of the list given any element in it.
+   Note that this costs O(N), so you should avoid this macro
+   if at all possible!
+*/
+#define DLIST_HEAD(p, result_head) \
 do { \
-          DLIST_REMOVE(list, p); \
-          DLIST_ADD(list, p); \
-} while (0)
+       (result_head) = (p); \
+       while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \
+} while(0)
 
-/* hook into the end of the list - needs the entry type */
-#define DLIST_ADD_END(list, p, type) \
-do { \
-		if (!(list)) { \
-			(list) = (p); \
-			(p)->next = (p)->prev = NULL; \
-		} else { \
-			type tmp; \
-			for (tmp = (list); tmp->next; tmp = tmp->next) ; \
-			tmp->next = (p); \
-			(p)->next = NULL; \
-			(p)->prev = tmp; \
-		} \
-} while (0)
+/* return the last element in the list */
+#define DLIST_TAIL(list) ((list)?(list)->prev:NULL)
+
+/* return the previous element in the list. */
+#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL)
 
 /* insert 'p' after the given element 'el' in a list. If el is NULL then
    this is the same as a DLIST_ADD() */
@@ -80,34 +120,62 @@ do { \
         if (!(list) || !(el)) { \
 		DLIST_ADD(list, p); \
 	} else { \
-		p->prev = el; \
-		p->next = el->next; \
-		el->next = p; \
-		if (p->next) p->next->prev = p; \
+		(p)->prev = (el);   \


-- 
Samba Shared Repository


More information about the samba-cvs mailing list