[ofw] [Patch 16/62] Reference implementation of NDv2
Fab Tillier
ftillier at microsoft.com
Wed Feb 20 17:32:46 PST 2013
Some of the reference count tracing logic for user-mode introduces Windows header code, which is not BSD.
This patch removes user-mode IBAL reference count tracking, but preserves kernel mode tracking.
Signed-off-by: Fab Tillier <ftillier at microsoft.com>
diff -dwup3 -x *svn* -x makefile -x sources -r c:\dev\openib\ofw\gen1\branches\mlx4_30\trunk\core\al\al_common.h .\core\al\al_common.h
--- c:\dev\openib\ofw\gen1\branches\mlx4_30\trunk\core\al\al_common.h Wed Aug 01 17:16:51 2012
+++ .\core\al\al_common.h Thu Jul 26 15:31:13 2012
@@ -269,7 +269,7 @@ typedef struct _al_obj
cl_spinlock_t lock;
cl_qlist_t obj_list;
atomic32_t ref_cnt;
-#if DBG
+#if defined(CL_KERNEL) && DBG
obj_ref_trace_t ref_trace;
#endif
cl_list_item_t list_item;
diff -dwup3 -x *svn* -x makefile -x sources -r c:\dev\openib\ofw\gen1\branches\mlx4_30\trunk\core\al\al_ref_trace.c .\core\al\al_ref_trace.c
--- c:\dev\openib\ofw\gen1\branches\mlx4_30\trunk\core\al\al_ref_trace.c Wed Aug 01 17:16:51 2012
+++ .\core\al\al_ref_trace.c Thu May 31 12:54:12 2012
@@ -38,9 +38,66 @@
#ifdef CL_KERNEL
#include <wdm.h>
-#else
-#include "Llist.h"
-#endif
+
+typedef enum {
+ AL_DATA_NODE,
+ AL_DIRTY_CHAIN_NODE
+} al_node_type_t;
+
+
+#define REF_TRACE_MAX_ENTRIES 0x2000
+#define REF_TRACE_DB_ENTRIES 0xF0000
+
+typedef struct _ref_cnt_data
+{
+ char* file_name;
+ LONG prev_ref_val;
+ uint32_t line_num;
+ uint8_t purge_type;
+ uint16_t repeat_cnt;
+ uint8_t ref_change; //al_ref_change_type_t
+ uint8_t ref_ctx; //enum e_ref_type
+
+} ref_cnt_data_t;
+
+typedef struct _ref_cnt_dirty_list
+{
+ void* p_al_obj;
+ uint32_t type;
+ long obj_list_size;
+ LIST_ENTRY dirty_list;
+} ref_cnt_dirty_list_t;
+
+
+typedef union _ref_db_entry
+{
+ ref_cnt_data_t ref_cnt_data;
+ ref_cnt_dirty_list_t ref_dirty_list;
+
+} ref_db_entry_t;
+
+typedef struct _ref_db_node
+{
+ uint8_t type; //al_node_type_t
+ ref_db_entry_t entry;
+ LIST_ENTRY list_entry;
+} ref_db_node_t;
+
+typedef struct _ref_cnt_dbg_db
+{
+ LIST_ENTRY free_chain;
+ cl_spinlock_t free_chain_lock;
+
+ LIST_ENTRY dirty_chain;
+ cl_spinlock_t dirty_chain_lock;
+
+ ULONG policy;
+ LONG max_chain_size;
+ uint32_t max_chain_obj_type;
+ int32_t needed_size;
+ volatile long objects_num;
+ ref_db_node_t ref_cnt_db[REF_TRACE_DB_ENTRIES];
+} ref_cnt_dbg_db_t;
ref_cnt_dbg_db_t g_ref_cnt_dbg_db;
@@ -49,9 +106,12 @@ ref_cnt_dbg_db_t g_ref_cnt_dbg_db;
((ULONG_PTR)address < (ULONG_PTR)(g_ref_cnt_dbg_db.ref_cnt_db)+REF_TRACE_DB_ENTRIES*sizeof(ref_db_node_t)))
+#endif // CL_KERNEL
+
void
ref_trace_db_init(ULONG policy)
{
+#ifdef CL_KERNEL
int i = 0;
cl_memclr(&g_ref_cnt_dbg_db, sizeof(g_ref_cnt_dbg_db));
@@ -72,13 +132,16 @@ ref_trace_db_init(ULONG policy)
g_ref_cnt_dbg_db.policy = policy;
g_ref_cnt_dbg_db.needed_size = REF_TRACE_DB_ENTRIES;
-
+#else // CL_KERNEL
+ UNREFERENCED_PARAMETER(policy);
+#endif // CL_KERNEL
}
void
ref_trace_init(
IN void * const p_obj)
{
+#ifdef CL_KERNEL
al_obj_t* p_al_obj = (al_obj_t*)p_obj;
InitializeListHead(&p_al_obj->ref_trace.ref_chain);
@@ -87,6 +150,9 @@ ref_trace_init(
cl_spinlock_init( &p_al_obj->ref_trace.lock );
p_al_obj->ref_trace.list_size = 0;
+#else // CL_KERNEL
+ UNREFERENCED_PARAMETER(p_obj);
+#endif // CL_KERNEL
}
// Inserts the dest_list into the beginning of the src_list
@@ -96,7 +162,7 @@ ref_trace_insert_head_list(
PLIST_ENTRY src_list,
PLIST_ENTRY dest_list)
{
-
+#ifdef CL_KERNEL
PLIST_ENTRY src_first = src_list->Flink;
PLIST_ENTRY src_last = src_list->Blink;
PLIST_ENTRY dest_first = dest_list->Flink;
@@ -106,10 +172,15 @@ ref_trace_insert_head_list(
src_last->Flink = dest_first;
dest_first->Blink = src_last;
+#else // CL_KERNEL
+ UNREFERENCED_PARAMETER(src_list);
+ UNREFERENCED_PARAMETER(dest_list);
+#endif // CL_KERNEL
}
-PLIST_ENTRY
+#ifdef CL_KERNEL
+static PLIST_ENTRY
ref_trace_alloc_entry()
{
PLIST_ENTRY free_entry;
@@ -152,7 +223,7 @@ ref_trace_alloc_entry()
}
-PLIST_ENTRY
+static PLIST_ENTRY
ref_trace_alloc_dirty_list(
IN al_obj_t * const p_obj,
OUT ref_db_node_t** ref_node)
@@ -178,19 +249,21 @@ ref_trace_alloc_dirty_list(
return &ref_entry->dirty_list;
}
-boolean_t
+
+static boolean_t
ref_trace_is_logged_obj(
IN al_obj_t * const p_obj )
{
return (p_obj->type == AL_OBJ_TYPE_H_AL);
}
-
+#endif // CL_KERNEL
// Destroys the object's ref trace chain
void
ref_trace_destroy(
IN void * const p_obj )
{
+#ifdef CL_KERNEL
al_obj_t* p_al_obj = (al_obj_t*)p_obj;
cl_spinlock_acquire(&p_al_obj->ref_trace.lock);
@@ -231,9 +304,14 @@ ref_trace_destroy(
cl_spinlock_destroy(&p_al_obj->ref_trace.lock);
InterlockedDecrement(&g_ref_cnt_dbg_db.objects_num);
+#else // CL_KERNEL
+ UNREFERENCED_PARAMETER(p_obj);
+#endif // CL_KERNEL
}
-ref_cnt_data_t*
+
+#ifdef CL_KERNEL
+static ref_cnt_data_t*
ref_trace_get_trace_data(
IN PLIST_ENTRY list_entry)
{
@@ -247,7 +325,8 @@ ref_trace_get_trace_data(
return &ref_node->entry.ref_cnt_data;
}
-boolean_t
+
+static boolean_t
ref_trace_is_equal_entry(
IN PLIST_ENTRY first_entry,
IN PLIST_ENTRY second_entry )
@@ -261,7 +340,8 @@ ref_trace_is_equal_entry(
first_ref_data->file_name == second_ref_data->file_name);
}
-boolean_t
+
+static boolean_t
ref_trace_is_same_action_entry(
IN PLIST_ENTRY first_entry,
IN PLIST_ENTRY second_entry )
@@ -276,7 +356,7 @@ ref_trace_is_same_action_entry(
// Should be called with a lock on the purged list
-boolean_t
+static boolean_t
ref_trace_purge_ref_deref_pairs(
IN PLIST_ENTRY last_deref_entry,
IN PLIST_ENTRY list_head)
@@ -320,8 +400,9 @@ ref_trace_purge_ref_deref_pairs(
return FALSE;
}
+
// Should be called with a lock on the purged list
-boolean_t
+static boolean_t
ref_trace_purge_same_entry(
IN PLIST_ENTRY last_entry,
IN PLIST_ENTRY list_head)
@@ -355,7 +436,7 @@ ref_trace_purge_same_entry(
}
-void
+static void
ref_trace_purge(
IN PLIST_ENTRY last_entry,
IN al_obj_t * p_obj)
@@ -380,6 +461,8 @@ ref_trace_purge(
cl_spinlock_release(&p_obj->ref_trace.lock);
}
+#endif // CL_KERNEL
+
int32_t
ref_trace_insert(
@@ -390,6 +473,7 @@ ref_trace_insert(
IN uint8_t ref_ctx
)
{
+#ifdef CL_KERNEL
al_obj_t* p_al_obj = (al_obj_t*)p_obj;
PLIST_ENTRY free_entry;
ref_cnt_data_t* ref_entry;
@@ -446,6 +530,14 @@ ref_trace_insert(
}
return ((change_type == AL_REF) ? ref_al_obj_inner(p_al_obj) : deref_al_obj_inner(p_al_obj));
+#else // CL_KERNEL
+ UNREFERENCED_PARAMETER(file);
+ UNREFERENCED_PARAMETER(line);
+ UNREFERENCED_PARAMETER(p_obj);
+ UNREFERENCED_PARAMETER(change_type);
+ UNREFERENCED_PARAMETER(ref_ctx);
+ return 0;
+#endif // CL_KERNEL
}
void
@@ -453,6 +545,7 @@ ref_trace_print(
IN void * const p_obj
)
{
+#ifdef CL_KERNEL
al_obj_t* p_al_obj = (al_obj_t*)p_obj;
ref_cnt_data_t* ref_entry;
PLIST_ENTRY p_entry;
@@ -480,6 +573,9 @@ ref_trace_print(
}
cl_spinlock_release(&p_al_obj->ref_trace.lock);
+#else // CL_KERNEL
+ UNREFERENCED_PARAMETER(p_obj);
+#endif // CL_KERNEL
}
void
@@ -487,6 +583,7 @@ ref_trace_dirty_print(
IN void * const p_obj
)
{
+#ifdef CL_KERNEL
al_obj_t* p_al_obj = (al_obj_t*)p_obj;
ref_db_node_t* ref_node;
ref_cnt_dirty_list_t* ref_dirty;
@@ -529,6 +626,9 @@ ref_trace_dirty_print(
}
cl_spinlock_release( &g_ref_cnt_dbg_db.dirty_chain_lock );
+#else // CL_KERNEL
+ UNREFERENCED_PARAMETER(p_obj);
+#endif // CL_KERNEL
}
#endif
diff -dwup3 -x *svn* -x makefile -x sources -r c:\dev\openib\ofw\gen1\branches\mlx4_30\trunk\core\al\al_ref_trace.h .\core\al\al_ref_trace.h
--- c:\dev\openib\ofw\gen1\branches\mlx4_30\trunk\core\al\al_ref_trace.h Thu May 31 11:22:16 2012
+++ .\core\al\al_ref_trace.h Thu May 31 12:57:10 2012
@@ -47,6 +47,7 @@ typedef enum {
AL_DEREF
} al_ref_change_type_t;
+
enum e_ref_origin {
E_REF_INIT = 1,
E_REF_CA_ADD_REMOVE,
@@ -56,10 +57,6 @@ enum e_ref_origin {
E_REF_CONSTRUCT_CHILD
};
-typedef enum {
- AL_DATA_NODE,
- AL_DIRTY_CHAIN_NODE
-} al_node_type_t;
typedef enum {
EQUAL_REF_DEREF_PAIRS = 1 << 0,
@@ -67,68 +64,14 @@ typedef enum {
} purge_policy_flags_t;
-#define REF_TRACE_MAX_ENTRIES 0x2000
-#define REF_TRACE_DB_ENTRIES 0xF0000
-
-typedef struct _ref_cnt_data
-{
- LONG prev_ref_val;
- uint32_t line_num;
- uint8_t purge_type;
- uint16_t repeat_cnt;
- uint8_t ref_change; //al_ref_change_type_t
- uint8_t ref_ctx; //enum e_ref_type
- char* file_name;
-
-} ref_cnt_data_t;
-
-typedef struct _ref_cnt_dirty_list
-{
- void* p_al_obj;
- uint32_t type;
- long obj_list_size;
- LIST_ENTRY dirty_list;
-} ref_cnt_dirty_list_t;
-
-
-typedef union _ref_db_entry
-{
- ref_cnt_data_t ref_cnt_data;
- ref_cnt_dirty_list_t ref_dirty_list;
-
-} ref_db_entry_t;
-
-typedef struct _ref_db_node
-{
- uint8_t type; //al_node_type_t
- ref_db_entry_t entry;
- LIST_ENTRY list_entry;
-} ref_db_node_t;
-
-typedef struct _ref_cnt_dbg_db
-{
- LIST_ENTRY free_chain;
- cl_spinlock_t free_chain_lock;
-
- LIST_ENTRY dirty_chain;
- cl_spinlock_t dirty_chain_lock;
-
- ULONG policy;
- LONG max_chain_size;
- uint32_t max_chain_obj_type;
- int32_t needed_size;
- volatile long objects_num;
- ref_db_node_t ref_cnt_db[REF_TRACE_DB_ENTRIES];
-} ref_cnt_dbg_db_t;
-
-
+#ifdef CL_KERNEL
typedef struct _obj_ref_trace
{
LIST_ENTRY ref_chain;
cl_spinlock_t lock;
volatile long list_size;
} obj_ref_trace_t;
-
+#endif
void
ref_trace_db_init(ULONG policy);
Index: inc/user/LLIST.H
===================================================================
--- inc/user/LLIST.H (revision 3427)
+++ inc/user/LLIST.H (working copy)
@@ -1,474 +0,0 @@
-/*++
-
- This source code may incorporate intellectual property owned by
- Microsoft Corporation. Our provision of this source code does not
- include any licenses or any other rights to you under any Microsoft
- intellectual property. If you would like a license from Microsoft
- (e.g., to rebrand, redistribute), you need to contact Microsoft
- directly.
-
-Module Name:
-
- llist.h
-
-Abstract:
-
- This module is a standalone collection of linked-list definition and
- manipulation macros originally defined within the Windows NT
- development.
-
---*/
-
-#ifndef _LLIST_
-#define _LLIST_
-#include <winsock2.h>
-
-
-
-#if !defined( _WINNT_ )
-//
-// From NTDEF.H.
-//
-
-// Doubly linked list structure. Can be used as either a list head, or as
-// link storage within a linked-list item.
-
-typedef struct _LIST_ENTRY {
- struct _LIST_ENTRY *Flink;
- struct _LIST_ENTRY *Blink;
-} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
-
-
-
-
-// LONG
-// FIELD_OFFSET(
-// IN <typename> type,
-// IN <fieldname> field
-// );
-#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
-/*++
-
-Routine Description:
-
- Calculates the byte offset of a field in a structure of type "type". The
- offset is from the beginning of the containing structure.
-
- Note that since this macro uses compile-time type knowledge, there is no
- equivalent C procedure for this macro.
-
-Arguments:
-
- type - Supplies the type name of the containing structure.
-
- field - Supplies the field name of the field whose offset is to be
- computed.
-
-Return Value:
-
- Returns the byte offset of the named field within a structure of the named
- type.
---*/
-
-
-
-
-// <typename> FAR *
-// CONTAINING_RECORD(
-// IN PVOID address,
-// IN <typename> type,
-// IN <fieldname> field
-// );
-#define CONTAINING_RECORD(address, type, field) ((type FAR *)( \
- (PCHAR)(address) - \
- (PCHAR)(&((type *)0)->field)))
-/*++
-
-Routine Description:
-
- Retrieves a typed pointer to a linked list item given the address of the
- link storage structure embedded in the linked list item, the type of the
- linked list item, and the field name of the embedded link storage
- structure.
-
- Note that since this macro uses compile-time type knowledge, there is no
- equivalent C procedure for this macro.
-
-Arguments:
-
- address - Supplies the address of a LIST_ENTRY structure embedded in an a
- linked list item.
-
- type - Supplies the type name of the containing linked list item
- structure.
-
- field - Supplies the field name if the LIST_ENTRY structure embedded
- within the linked list item structure.
-
-Return Value:
-
- Returns a pointer to the linked list item.
---*/
-
-
-#endif // !defined( _WINNT_ )
-
-
-//
-// From NTRTL.H.
-//
-
-// Doubly-linked list manipulation routines. Implemented as macros
-// but logically these are procedures.
-
-
-
-
- inline VOID
- InitializeListHead(
- IN PLIST_ENTRY ListHead
- )
-{
-
- ListHead->Flink = ListHead->Blink = ListHead;
-}
-/*++
-
-Routine Description:
-
- Initializes a PLIST_ENTRY structure to be the head of an initially empty
- linked list.
-
-Arguments:
-
- ListHead - Supplies a reference to the structure to be initialized.
-
-Return Value:
-
- None
---*/
-
- inline VOID
- RemoveEntryList(
- IN PLIST_ENTRY Entry
- ) {
- PLIST_ENTRY _EX_Blink;
- PLIST_ENTRY _EX_Flink;
- _EX_Flink = Entry->Flink;
- _EX_Blink = Entry->Blink;
- _EX_Blink->Flink = _EX_Flink;
- _EX_Flink->Blink = _EX_Blink;
- }
-
-
-// BOOLEAN
-// IsListEmpty(
-// IN PLIST_ENTRY ListHead
-// );
-#define IsListEmpty(ListHead) \
- ((ListHead)->Flink == (ListHead))
-/*++
-
-Routine Description:
-
- Determines whether or not a list is empty.
-
-Arguments:
-
- ListHead - Supplies a reference to the head of the linked list to be
- examined.
-
-Return Value:
-
- TRUE - The linked list is empty.
-
- FALSE - The linked list contains at least one item.
---*/
-
-
-
-
-inline PLIST_ENTRY
- RemoveHeadList(
- IN PLIST_ENTRY ListHead
- )
-{
- PLIST_ENTRY _Entry = ListHead->Flink;
- ListHead->Flink = _Entry->Flink;
- ListHead->Flink->Blink = ListHead;
- return _Entry;
-}
-/*++
-
-Routine Description:
-
- Removes the "head" (first) item from a linked list, returning the pointer
- to the removed entry's embedded linkage structure. Attempting to remove
- the head item from a (properly initialized) linked list is a no-op,
- returning the pointer to the head of the linked list.
-
- The caller may use the CONTAINING_RECORD macro to amplify the returned
- linkage structure pointer to the containing linked list item structure.
-
-Arguments:
-
- ListHead - Supplies a reference to the head of the linked list to be
- operated upon.
-
-Return Value:
-
- Returns a pointer to the newly removed linked list item's embedded linkage
- structure, or the linked list head in the case of an empty list.
---*/
-
-
-
-inline PLIST_ENTRY
- RemoveTailList(
- IN PLIST_ENTRY ListHead
- )
-{
- PLIST_ENTRY _ENTRY = ListHead->Blink;
- ListHead->Blink = _ENTRY->Blink;
- _ENTRY->Blink->Flink = ListHead;
- return _ENTRY;
-}
-/*++
-
-Routine Description:
-
- Removes the "tail" (last) item from a linked list, returning the pointer to
- the removed entry's embedded linkage structure. Attempting to remove the
- tail item from a (properly initialized) linked list is a no-op, returning
- the pointer to the head of the linked list.
-
- The caller may use the CONTAINING_RECORD macro to amplify the returned
- linkage structure pointer to the containing linked list item structure.
-
-Arguments:
-
- ListHead - Supplies a reference to the head of the linked list to be
- operated upon.
-
-Return Value:
-
- Returns a pointer to the newly removed linked list item's embedded linkage
- structure, or the linked list head in the case of an empty list.
---*/
-
-
-
-
-
-/*++
-
-Routine Description:
-
- Removes an item from a linked list. Attempting to remove the head of an
- empty list is a no-op.
-
-Arguments:
-
- Entry - Supplies a reference to the linkage structure embedded in a linked
- list item structure.
-
-Return Value:
-
- None
---*/
-
-
-
-
- inline VOID
- InsertTailList(
- IN PLIST_ENTRY ListHead,
- IN PLIST_ENTRY Entry
- )
-{
-// #define InsertTailList(ListHead,Entry) {
- PLIST_ENTRY _EX_Blink;
- PLIST_ENTRY _EX_ListHead;
- _EX_ListHead = (ListHead);
- _EX_Blink = _EX_ListHead->Blink;
- Entry->Flink = _EX_ListHead;
- Entry->Blink = _EX_Blink;
- _EX_Blink->Flink = (Entry);
- _EX_ListHead->Blink = (Entry);
- }
-/*++
-
-Routine Description:
-
- Inserts a new item as the "tail" (last) item of a linked list.
-
-Arguments:
-
- ListHead - Supplies a reference to the head of the linked list to be
- operated upon.
-
- Entry - Supplies a reference to the linkage structure embedded in the
- linked list item to be added to the linked list.
-
-Return Value:
-
- None
---*/
-
-
-
-
- inline VOID
- InsertHeadList(
- IN PLIST_ENTRY ListHead,
- IN PLIST_ENTRY Entry
- )
-{
-// #define InsertHeadList(ListHead,Entry) {
- PLIST_ENTRY _EX_Flink;
- PLIST_ENTRY _EX_ListHead;
- _EX_ListHead = (ListHead);
- _EX_Flink = _EX_ListHead->Flink;
- (Entry)->Flink = _EX_Flink;
- (Entry)->Blink = _EX_ListHead;
- _EX_Flink->Blink = (Entry);
- _EX_ListHead->Flink = (Entry);
-}
-/*++
-
-Routine Description:
-
- Inserts a new item as the "head" (first) item of a linked list.
-
-Arguments:
-
- ListHead - Supplies a reference to the head of the linked list to be
- operated upon.
-
- Entry - Supplies a reference to the linkage structure embedded in the
- linked list item to be added to the linked list.
-
-Return Value:
-
- None
---*/
-
-
-
-//
-//
-// PSINGLE_LIST_ENTRY
-// PopEntryList(
-// PSINGLE_LIST_ENTRY ListHead
-// );
-//
-
-#define PopEntryList(ListHead) \
- (ListHead)->Next;\
- {\
- PSINGLE_LIST_ENTRY FirstEntry;\
- FirstEntry = (ListHead)->Next;\
- if (FirstEntry != NULL) { \
- (ListHead)->Next = FirstEntry->Next;\
- } \
- }
-
-
-//
-// VOID
-// PushEntryList(
-// PSINGLE_LIST_ENTRY ListHead,
-// PSINGLE_LIST_ENTRY Entry
-// );
-//
-
-#define PushEntryList(ListHead,Entry) \
- (Entry)->Next = (ListHead)->Next; \
- (ListHead)->Next = (Entry)
-
-
-// Samples:
-//
-// //
-// // Define a list head.
-// //
-//
-// LIST_ENTRY FooList;
-//
-// //
-// // Define a structure that will be on the list.
-// //
-// // NOTE: For debugging purposes, it usually makes life simpler to make the
-// // LIST_ENTRY the first field of the structure, but this is not a
-// // requirement.
-// //
-//
-// typedef struct _FOO
-// {
-// LIST_ENTRY FooListEntry;
-// .
-// .
-// .
-//
-// } FOO, * PFOO;
-//
-// //
-// // Initialize an empty list.
-// //
-//
-// InitializeListHead( &FooList );
-//
-// //
-// // Create an object, append it to the end of the list.
-// //
-//
-// PFOO foo;
-//
-// foo = ALLOC( sizeof(FOO) );
-// {check for errors, initialize FOO structure}
-//
-// InsertTailList( &FooList, &foo->FooListEntry );
-//
-// //
-// // Scan list and delete selected items.
-// //
-//
-// PFOO foo;
-// PLIST_ENTRY listEntry;
-//
-// listEntry = FooList.Flink;
-//
-// while( listEntry != &FooList )
-// {
-// foo = CONTAINING_RECORD( listEntry,
-// FOO,
-// FooListEntry );
-// listEntry = listEntry->Flink;
-//
-// if( SomeFunction( foo ) )
-// {
-// RemoveEntryList( &foo->FooListEntry );
-// FREE( foo );
-// }
-// }
-//
-// //
-// // Purge all items from a list.
-// //
-//
-// PFOO foo;
-// PLIST_ENTRY listEntry;
-//
-// while( !IsListEmpty( &FooList ) )
-// {
-// listEntry = RemoveHeadList( &FooList );
-// foo = CONTAINING_RECORD( listEntry,
-// FOO,
-// FooListEntry );
-//
-// FREE( foo );
-// }
-
-
-#endif // _LLIST_
-
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ndv2.16.patch
Type: application/octet-stream
Size: 21286 bytes
Desc: ndv2.16.patch
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20130221/ef6edaac/attachment.obj>
More information about the ofw
mailing list