User space build fixes:
- Add list handling compatibility library - Drop uu_* list handling in favor of local list implementation - libtoolize - generic makefile cleanup git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@3 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c
This commit is contained in:
parent
8f48c2c853
commit
564f6d1509
|
@ -1,6 +1,8 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
find . -type d -name .deps | xargs rm -rf
|
find . -type d -name .deps | xargs rm -rf
|
||||||
|
rm -rf config.guess config.sub ltmain.sh
|
||||||
|
libtoolize
|
||||||
aclocal 2>/dev/null &&
|
aclocal 2>/dev/null &&
|
||||||
autoheader &&
|
autoheader &&
|
||||||
automake --add-missing --include-deps # 2>/dev/null &&
|
automake --add-missing --include-deps # 2>/dev/null &&
|
||||||
|
|
17
configure.ac
17
configure.ac
|
@ -6,6 +6,7 @@ AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
ver=`uname -r`
|
ver=`uname -r`
|
||||||
KERNELCFLAGS=
|
KERNELCFLAGS=
|
||||||
|
@ -88,21 +89,6 @@ else
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_MSG_CHECKING([if inode has i_private field])
|
|
||||||
if egrep -qw "i_private" $kernelsrc/include/linux/fs.h; then
|
|
||||||
AC_DEFINE(HAVE_I_PRIVATE, 1, [inode has i_private field])
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([if inode has i_mutex field ])
|
|
||||||
if egrep -qw "i_mutex" $kernelsrc/include/linux/fs.h; then
|
|
||||||
AC_DEFINE(HAVE_I_MUTEX, 1, [inode has i_mutex field])
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([if kernel has mutex.h ])
|
AC_MSG_CHECKING([if kernel has mutex.h ])
|
||||||
if test -f $kernelsrc/include/linux/mutex.h; then
|
if test -f $kernelsrc/include/linux/mutex.h; then
|
||||||
|
@ -122,6 +108,7 @@ AC_SUBST(KERNELCFLAGS)
|
||||||
|
|
||||||
AC_CONFIG_FILES([ Makefile
|
AC_CONFIG_FILES([ Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
|
src/lib/Makefile
|
||||||
src/cmd/Makefile
|
src/cmd/Makefile
|
||||||
src/spl/Makefile
|
src/spl/Makefile
|
||||||
src/splat/Makefile
|
src/splat/Makefile
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
EXTRA_DIST = spl.h splat.h splat-ctl.h
|
EXTRA_DIST = spl.h
|
||||||
|
EXTRA_DIST += splat.h splat-ctl.h
|
||||||
EXTRA_DIST += linux-condvar.h linux-kmem.h linux-random.h linux-thread.h
|
EXTRA_DIST += linux-condvar.h linux-kmem.h linux-random.h linux-thread.h
|
||||||
EXTRA_DIST += linux-types.h linux-cred.h linux-kstat.h linux-rwlock.h
|
EXTRA_DIST += linux-types.h linux-cred.h linux-kstat.h linux-rwlock.h
|
||||||
EXTRA_DIST += linux-time.h linux-callb.h linux-generic.h linux-mutex.h
|
EXTRA_DIST += linux-time.h linux-callb.h linux-generic.h linux-mutex.h
|
||||||
EXTRA_DIST += linux-taskq.h linux-timer.h
|
EXTRA_DIST += linux-taskq.h linux-timer.h
|
||||||
|
EXTRA_DIST += list.h
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* $Id: list.h 2899 2002-12-11 19:00:36Z dun $
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 2001-2002 The Regents of the University of California.
|
||||||
|
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||||
|
* Written by Chris Dunlap <cdunlap@llnl.gov>.
|
||||||
|
*
|
||||||
|
* This file is from LSD-Tools, the LLNL Software Development Toolbox.
|
||||||
|
*
|
||||||
|
* LSD-Tools 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 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* LSD-Tools 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 LSD-Tools; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LSD_LIST_H
|
||||||
|
#define LSD_LIST_H
|
||||||
|
|
||||||
|
|
||||||
|
/***********
|
||||||
|
* Notes *
|
||||||
|
***********/
|
||||||
|
/*
|
||||||
|
* If NDEBUG is not defined, internal debug code will be enabled. This is
|
||||||
|
* intended for development use only and production code should define NDEBUG.
|
||||||
|
*
|
||||||
|
* If WITH_LSD_FATAL_ERROR_FUNC is defined, the linker will expect to
|
||||||
|
* find an external lsd_fatal_error(file,line,mesg) function. By default,
|
||||||
|
* lsd_fatal_error(file,line,mesg) is a macro definition that outputs an
|
||||||
|
* error message to stderr. This macro may be redefined to invoke another
|
||||||
|
* routine instead.
|
||||||
|
*
|
||||||
|
* If WITH_LSD_NOMEM_ERROR_FUNC is defined, the linker will expect to
|
||||||
|
* find an external lsd_nomem_error(file,line,mesg) function. By default,
|
||||||
|
* lsd_nomem_error(file,line,mesg) is a macro definition that returns NULL.
|
||||||
|
* This macro may be redefined to invoke another routine instead.
|
||||||
|
*
|
||||||
|
* If WITH_PTHREADS is defined, these routines will be thread-safe.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Data Types *
|
||||||
|
****************/
|
||||||
|
|
||||||
|
typedef struct list * List;
|
||||||
|
/*
|
||||||
|
* List opaque data type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct listIterator * ListIterator;
|
||||||
|
/*
|
||||||
|
* List Iterator opaque data type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void (*ListDelF) (void *x);
|
||||||
|
/*
|
||||||
|
* Function prototype to deallocate data stored in a list.
|
||||||
|
* This function is responsible for freeing all memory associated
|
||||||
|
* with an item, including all subordinate items (if applicable).
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int (*ListCmpF) (void *x, void *y);
|
||||||
|
/*
|
||||||
|
* Function prototype for comparing two items in a list.
|
||||||
|
* Returns less-than-zero if (x<y), zero if (x==y), and
|
||||||
|
* greather-than-zero if (x>y).
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int (*ListFindF) (void *x, void *key);
|
||||||
|
/*
|
||||||
|
* Function prototype for matching items in a list.
|
||||||
|
* Returns non-zero if (x==key); o/w returns zero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int (*ListForF) (void *x, void *arg);
|
||||||
|
/*
|
||||||
|
* Function prototype for operating on each item in a list.
|
||||||
|
* Returns less-than-zero on error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
* General-Purpose Functions *
|
||||||
|
*******************************/
|
||||||
|
|
||||||
|
List list_create (ListDelF f);
|
||||||
|
/*
|
||||||
|
* Creates and returns a new empty list, or lsd_nomem_error() on failure.
|
||||||
|
* The deletion function [f] is used to deallocate memory used by items
|
||||||
|
* in the list; if this is NULL, memory associated with these items
|
||||||
|
* will not be freed when the list is destroyed.
|
||||||
|
* Note: Abandoning a list without calling list_destroy() will result
|
||||||
|
* in a memory leak.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void list_destroy (List l);
|
||||||
|
/*
|
||||||
|
* Destroys list [l], freeing memory used for list iterators and the
|
||||||
|
* list itself; if a deletion function was specified when the list
|
||||||
|
* was created, it will be called for each item in the list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int list_is_empty (List l);
|
||||||
|
/*
|
||||||
|
* Returns non-zero if list [l] is empty; o/w returns zero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int list_count (List l);
|
||||||
|
/*
|
||||||
|
* Returns the number of items in list [l].
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/***************************
|
||||||
|
* List Access Functions *
|
||||||
|
***************************/
|
||||||
|
|
||||||
|
void * list_append (List l, void *x);
|
||||||
|
/*
|
||||||
|
* Inserts data [x] at the end of list [l].
|
||||||
|
* Returns the data's ptr, or lsd_nomem_error() if insertion failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * list_prepend (List l, void *x);
|
||||||
|
/*
|
||||||
|
* Inserts data [x] at the beginning of list [l].
|
||||||
|
* Returns the data's ptr, or lsd_nomem_error() if insertion failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * list_find_first (List l, ListFindF f, void *key);
|
||||||
|
/*
|
||||||
|
* Traverses list [l] using [f] to match each item with [key].
|
||||||
|
* Returns a ptr to the first item for which the function [f]
|
||||||
|
* returns non-zero, or NULL if no such item is found.
|
||||||
|
* Note: This function differs from list_find() in that it does not require
|
||||||
|
* a list iterator; it should only be used when all list items are known
|
||||||
|
* to be unique (according to the function [f]).
|
||||||
|
*/
|
||||||
|
|
||||||
|
int list_delete_all (List l, ListFindF f, void *key);
|
||||||
|
/*
|
||||||
|
* Traverses list [l] using [f] to match each item with [key].
|
||||||
|
* Removes all items from the list for which the function [f] returns
|
||||||
|
* non-zero; if a deletion function was specified when the list was
|
||||||
|
* created, it will be called to deallocate each item being removed.
|
||||||
|
* Returns a count of the number of items removed from the list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int list_for_each (List l, ListForF f, void *arg);
|
||||||
|
/*
|
||||||
|
* For each item in list [l], invokes the function [f] with [arg].
|
||||||
|
* Returns a count of the number of items on which [f] was invoked.
|
||||||
|
* If [f] returns <0 for a given item, the iteration is aborted and the
|
||||||
|
* function returns the negative of that item's position in the list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void list_sort (List l, ListCmpF f);
|
||||||
|
/*
|
||||||
|
* Sorts list [l] into ascending order according to the function [f].
|
||||||
|
* Note: Sorting a list resets all iterators associated with the list.
|
||||||
|
* Note: The sort algorithm is stable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/****************************
|
||||||
|
* Stack Access Functions *
|
||||||
|
****************************/
|
||||||
|
|
||||||
|
void * list_push (List l, void *x);
|
||||||
|
/*
|
||||||
|
* Pushes data [x] onto the top of stack [l].
|
||||||
|
* Returns the data's ptr, or lsd_nomem_error() if insertion failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * list_pop (List l);
|
||||||
|
/*
|
||||||
|
* Pops the data item at the top of the stack [l].
|
||||||
|
* Returns the data's ptr, or NULL if the stack is empty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * list_peek (List l);
|
||||||
|
/*
|
||||||
|
* Peeks at the data item at the top of the stack (or head of the queue) [l].
|
||||||
|
* Returns the data's ptr, or NULL if the stack (or queue) is empty.
|
||||||
|
* Note: The item is not removed from the list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/****************************
|
||||||
|
* Queue Access Functions *
|
||||||
|
****************************/
|
||||||
|
|
||||||
|
void * list_enqueue (List l, void *x);
|
||||||
|
/*
|
||||||
|
* Enqueues data [x] at the tail of queue [l].
|
||||||
|
* Returns the data's ptr, or lsd_nomem_error() if insertion failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * list_dequeue (List l);
|
||||||
|
/*
|
||||||
|
* Dequeues the data item at the head of the queue [l].
|
||||||
|
* Returns the data's ptr, or NULL if the queue is empty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
* List Iterator Functions *
|
||||||
|
*****************************/
|
||||||
|
|
||||||
|
ListIterator list_iterator_create (List l);
|
||||||
|
/*
|
||||||
|
* Creates and returns a list iterator for non-destructively traversing
|
||||||
|
* list [l], or lsd_nomem_error() on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void list_iterator_reset (ListIterator i);
|
||||||
|
/*
|
||||||
|
* Resets the list iterator [i] to start traversal at the beginning
|
||||||
|
* of the list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void list_iterator_destroy (ListIterator i);
|
||||||
|
/*
|
||||||
|
* Destroys the list iterator [i]; list iterators not explicitly destroyed
|
||||||
|
* in this manner will be destroyed when the list is deallocated via
|
||||||
|
* list_destroy().
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * list_next (ListIterator i);
|
||||||
|
/*
|
||||||
|
* Returns a ptr to the next item's data,
|
||||||
|
* or NULL once the end of the list is reached.
|
||||||
|
* Example: i=list_iterator_create(i); while ((x=list_next(i))) {...}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * list_insert (ListIterator i, void *x);
|
||||||
|
/*
|
||||||
|
* Inserts data [x] immediately before the last item returned via list
|
||||||
|
* iterator [i]; once the list iterator reaches the end of the list,
|
||||||
|
* insertion is made at the list's end.
|
||||||
|
* Returns the data's ptr, or lsd_nomem_error() if insertion failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * list_find (ListIterator i, ListFindF f, void *key);
|
||||||
|
/*
|
||||||
|
* Traverses the list from the point of the list iterator [i]
|
||||||
|
* using [f] to match each item with [key].
|
||||||
|
* Returns a ptr to the next item for which the function [f]
|
||||||
|
* returns non-zero, or NULL once the end of the list is reached.
|
||||||
|
* Example: i=list_iterator_reset(i); while ((x=list_find(i,f,k))) {...}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void * list_remove (ListIterator i);
|
||||||
|
/*
|
||||||
|
* Removes from the list the last item returned via list iterator [i]
|
||||||
|
* and returns the data's ptr.
|
||||||
|
* Note: The client is responsible for freeing the returned data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int list_delete (ListIterator i);
|
||||||
|
/*
|
||||||
|
* Removes from the list the last item returned via list iterator [i];
|
||||||
|
* if a deletion function was specified when the list was created,
|
||||||
|
* it will be called to deallocate the item being removed.
|
||||||
|
* Returns a count of the number of items removed from the list
|
||||||
|
* (ie, '1' if the item was removed, and '0' otherwise).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !LSD_LIST_H */
|
|
@ -1,7 +1,8 @@
|
||||||
#ifndef _KZT_H
|
#ifndef _SPLAT_H
|
||||||
#define _KZT_H
|
#define _SPLAT_H
|
||||||
|
|
||||||
#include <sys/splat-ctl.h>
|
#include "list.h"
|
||||||
|
#include "splat-ctl.h"
|
||||||
|
|
||||||
#define DEV_NAME "/dev/kztctl"
|
#define DEV_NAME "/dev/kztctl"
|
||||||
#define COLOR_BLACK "\033[0;30m"
|
#define COLOR_BLACK "\033[0;30m"
|
||||||
|
@ -23,13 +24,11 @@
|
||||||
#define COLOR_RESET "\033[0m"
|
#define COLOR_RESET "\033[0m"
|
||||||
|
|
||||||
typedef struct subsystem {
|
typedef struct subsystem {
|
||||||
uu_list_node_t sub_node; /* Linkage for global subsystem list */
|
|
||||||
kzt_user_t sub_desc; /* Subsystem description */
|
kzt_user_t sub_desc; /* Subsystem description */
|
||||||
uu_list_t *sub_tests; /* Assocated subsystem tests list */
|
List sub_tests; /* Assocated subsystem tests list */
|
||||||
} subsystem_t;
|
} subsystem_t;
|
||||||
|
|
||||||
typedef struct test {
|
typedef struct test {
|
||||||
uu_list_node_t test_node; /* Linkage for globals test list */
|
|
||||||
kzt_user_t test_desc; /* Test description */
|
kzt_user_t test_desc; /* Test description */
|
||||||
subsystem_t *test_sub; /* Parent subsystem */
|
subsystem_t *test_sub; /* Parent subsystem */
|
||||||
} test_t;
|
} test_t;
|
||||||
|
@ -40,8 +39,8 @@ typedef struct cmd_args {
|
||||||
int args_do_all; /* Run all tests flag */
|
int args_do_all; /* Run all tests flag */
|
||||||
int args_do_color; /* Colorize output */
|
int args_do_color; /* Colorize output */
|
||||||
int args_exit_on_error; /* Exit on first error flag */
|
int args_exit_on_error; /* Exit on first error flag */
|
||||||
uu_list_t *args_tests; /* Requested subsystems/tests */
|
List args_tests; /* Requested subsystems/tests */
|
||||||
} cmd_args_t;
|
} cmd_args_t;
|
||||||
|
|
||||||
#endif /* _KZT_H */
|
#endif /* _SPLAT_H */
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
SUBDIRS = cmd spl splat
|
SUBDIRS = lib cmd spl splat
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
AM_CFLAGS = @EXTRA_CFLAGS@ -g -O2 -W -Wall -Wstrict-prototypes -Wshadow
|
AM_CFLAGS = -g -O2 -W -Wall -Wstrict-prototypes -Wshadow
|
||||||
|
INCLUDES = -I$(top_srcdir)/include
|
||||||
sbin_PROGRAMS = splat
|
sbin_PROGRAMS = splat
|
||||||
splat_SOURCES = splat.c
|
splat_SOURCES = splat.c
|
||||||
|
splat_LDFLAGS = $(top_builddir)/src/lib/libcommon.la
|
||||||
|
|
214
src/cmd/splat.c
214
src/cmd/splat.c
|
@ -1,4 +1,4 @@
|
||||||
/* Kernel ZFS Test (KZT) user space command interface */
|
/* Solaris Porting Layer Aggressive Test (SPLAT) userspace interface */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -8,7 +8,6 @@
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <libuutil.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -29,17 +28,17 @@ static const struct option longOpts[] = {
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static uu_list_t *subsystems; /* Subsystem/tests */
|
static List subsystems; /* Subsystem/tests */
|
||||||
static uu_list_pool_t *subsystem_pool; /* Subsystem pool */
|
|
||||||
static uu_list_pool_t *test_pool; /* Test pool */
|
|
||||||
static int kztctl_fd; /* Control file descriptor */
|
static int kztctl_fd; /* Control file descriptor */
|
||||||
static char kzt_version[KZT_VERSION_SIZE]; /* Kernel version string */
|
static char kzt_version[KZT_VERSION_SIZE]; /* Kernel version string */
|
||||||
static char *kzt_buffer = NULL; /* Scratch space area */
|
static char *kzt_buffer = NULL; /* Scratch space area */
|
||||||
static int kzt_buffer_size = 0; /* Scratch space size */
|
static int kzt_buffer_size = 0; /* Scratch space size */
|
||||||
|
|
||||||
|
|
||||||
static void test_list(uu_list_t *, int);
|
static void test_list(List, int);
|
||||||
static int dev_clear(void);
|
static int dev_clear(void);
|
||||||
|
static void subsystem_fini(subsystem_t *);
|
||||||
|
static void test_fini(test_t *);
|
||||||
|
|
||||||
|
|
||||||
static int usage(void) {
|
static int usage(void) {
|
||||||
|
@ -69,9 +68,8 @@ static subsystem_t *subsystem_init(kzt_user_t *desc)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memcpy(&sub->sub_desc, desc, sizeof(*desc));
|
memcpy(&sub->sub_desc, desc, sizeof(*desc));
|
||||||
uu_list_node_init(sub, &sub->sub_node, subsystem_pool);
|
|
||||||
|
|
||||||
sub->sub_tests = uu_list_create(test_pool, NULL, 0);
|
sub->sub_tests = list_create((ListDelF)test_fini);
|
||||||
if (sub->sub_tests == NULL) {
|
if (sub->sub_tests == NULL) {
|
||||||
free(sub);
|
free(sub);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -83,8 +81,6 @@ static subsystem_t *subsystem_init(kzt_user_t *desc)
|
||||||
static void subsystem_fini(subsystem_t *sub)
|
static void subsystem_fini(subsystem_t *sub)
|
||||||
{
|
{
|
||||||
assert(sub != NULL);
|
assert(sub != NULL);
|
||||||
|
|
||||||
uu_list_node_fini(sub, &sub->sub_node, subsystem_pool);
|
|
||||||
free(sub);
|
free(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,13 +145,15 @@ static int subsystem_setup(void)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
uu_list_insert(subsystems, sub, 0);
|
list_append(subsystems, sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(cfg);
|
free(cfg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX - Commented out until we sort the lists */
|
||||||
|
#if 0
|
||||||
static int subsystem_compare(const void *l_arg, const void *r_arg, void *private)
|
static int subsystem_compare(const void *l_arg, const void *r_arg, void *private)
|
||||||
{
|
{
|
||||||
const subsystem_t *l = l_arg;
|
const subsystem_t *l = l_arg;
|
||||||
|
@ -169,9 +167,11 @@ static int subsystem_compare(const void *l_arg, const void *r_arg, void *private
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void subsystem_list(uu_list_t *list, int indent)
|
static void subsystem_list(List l, int indent)
|
||||||
{
|
{
|
||||||
|
ListIterator i;
|
||||||
subsystem_t *sub;
|
subsystem_t *sub;
|
||||||
|
|
||||||
fprintf(stdout,
|
fprintf(stdout,
|
||||||
|
@ -179,8 +179,9 @@ static void subsystem_list(uu_list_t *list, int indent)
|
||||||
"Available KZT Tests "
|
"Available KZT Tests "
|
||||||
"-------------------------------\n");
|
"-------------------------------\n");
|
||||||
|
|
||||||
for (sub = uu_list_first(list); sub != NULL;
|
i = list_iterator_create(l);
|
||||||
sub = uu_list_next(list, sub)) {
|
|
||||||
|
while ((sub = list_next(i))) {
|
||||||
fprintf(stdout, "%*s0x%0*x %-*s ---- %s ----\n",
|
fprintf(stdout, "%*s0x%0*x %-*s ---- %s ----\n",
|
||||||
indent, "",
|
indent, "",
|
||||||
4, sub->sub_desc.id,
|
4, sub->sub_desc.id,
|
||||||
|
@ -188,6 +189,8 @@ static void subsystem_list(uu_list_t *list, int indent)
|
||||||
sub->sub_desc.desc);
|
sub->sub_desc.desc);
|
||||||
test_list(sub->sub_tests, indent + 7);
|
test_list(sub->sub_tests, indent + 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_iterator_destroy(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static test_t *test_init(subsystem_t *sub, kzt_user_t *desc)
|
static test_t *test_init(subsystem_t *sub, kzt_user_t *desc)
|
||||||
|
@ -200,7 +203,6 @@ static test_t *test_init(subsystem_t *sub, kzt_user_t *desc)
|
||||||
|
|
||||||
test->test_sub = sub;
|
test->test_sub = sub;
|
||||||
memcpy(&test->test_desc, desc, sizeof(*desc));
|
memcpy(&test->test_desc, desc, sizeof(*desc));
|
||||||
uu_list_node_init(test, &test->test_node, test_pool);
|
|
||||||
|
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
@ -208,8 +210,6 @@ static test_t *test_init(subsystem_t *sub, kzt_user_t *desc)
|
||||||
static void test_fini(test_t *test)
|
static void test_fini(test_t *test)
|
||||||
{
|
{
|
||||||
assert(test != NULL);
|
assert(test != NULL);
|
||||||
|
|
||||||
uu_list_node_fini(test, &test->test_node, test_pool);
|
|
||||||
free(test);
|
free(test);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,13 +274,15 @@ static int test_setup(subsystem_t *sub)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
uu_list_insert(sub->sub_tests, test, 0);
|
list_append(sub->sub_tests, test);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(cfg);
|
free(cfg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX - Commented out until we sort the lists */
|
||||||
|
#if 0
|
||||||
static int test_compare(const void *l_arg, const void *r_arg, void *private)
|
static int test_compare(const void *l_arg, const void *r_arg, void *private)
|
||||||
{
|
{
|
||||||
const test_t *l = l_arg;
|
const test_t *l = l_arg;
|
||||||
|
@ -294,27 +296,33 @@ static int test_compare(const void *l_arg, const void *r_arg, void *private)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static test_t *test_copy(test_t *test)
|
static test_t *test_copy(test_t *test)
|
||||||
{
|
{
|
||||||
return test_init(test->test_sub, &test->test_desc);
|
return test_init(test->test_sub, &test->test_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_list(uu_list_t *list, int indent)
|
static void test_list(List l, int indent)
|
||||||
{
|
{
|
||||||
|
ListIterator i;
|
||||||
test_t *test;
|
test_t *test;
|
||||||
|
|
||||||
for (test = uu_list_first(list); test != NULL;
|
i = list_iterator_create(l);
|
||||||
test = uu_list_next(list, test))
|
|
||||||
|
while ((test = list_next(i)))
|
||||||
fprintf(stdout, "%*s0x%0*x %-*s %-*s\n",
|
fprintf(stdout, "%*s0x%0*x %-*s %-*s\n",
|
||||||
indent, "",
|
indent, "",
|
||||||
04, test->test_desc.id,
|
04, test->test_desc.id,
|
||||||
KZT_NAME_SIZE, test->test_desc.name,
|
KZT_NAME_SIZE, test->test_desc.name,
|
||||||
KZT_DESC_SIZE, test->test_desc.desc);
|
KZT_DESC_SIZE, test->test_desc.desc);
|
||||||
|
|
||||||
|
list_iterator_destroy(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static test_t *test_find(char *sub_str, char *test_str)
|
static test_t *test_find(char *sub_str, char *test_str)
|
||||||
{
|
{
|
||||||
|
ListIterator si, ti;
|
||||||
subsystem_t *sub;
|
subsystem_t *sub;
|
||||||
test_t *test;
|
test_t *test;
|
||||||
int sub_num, test_num;
|
int sub_num, test_num;
|
||||||
|
@ -326,22 +334,31 @@ static test_t *test_find(char *sub_str, char *test_str)
|
||||||
sub_num = strtol(sub_str, NULL, 0);
|
sub_num = strtol(sub_str, NULL, 0);
|
||||||
test_num = strtol(test_str, NULL, 0);
|
test_num = strtol(test_str, NULL, 0);
|
||||||
|
|
||||||
for (sub = uu_list_first(subsystems); sub != NULL;
|
si = list_iterator_create(subsystems);
|
||||||
sub = uu_list_next(subsystems, sub)) {
|
|
||||||
|
while ((sub = list_next(si))) {
|
||||||
|
|
||||||
if (strncmp(sub->sub_desc.name, sub_str, KZT_NAME_SIZE) &&
|
if (strncmp(sub->sub_desc.name, sub_str, KZT_NAME_SIZE) &&
|
||||||
sub->sub_desc.id != sub_num)
|
sub->sub_desc.id != sub_num)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (test = uu_list_first(sub->sub_tests); test != NULL;
|
ti = list_iterator_create(sub->sub_tests);
|
||||||
test = uu_list_next(sub->sub_tests, test)) {
|
|
||||||
|
while ((test = list_next(ti))) {
|
||||||
|
|
||||||
if (!strncmp(test->test_desc.name, test_str,
|
if (!strncmp(test->test_desc.name, test_str,
|
||||||
KZT_NAME_SIZE) || test->test_desc.id == test_num)
|
KZT_NAME_SIZE) || test->test_desc.id == test_num) {
|
||||||
|
list_iterator_destroy(ti);
|
||||||
|
list_iterator_destroy(si);
|
||||||
return test;
|
return test;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_iterator_destroy(ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_iterator_destroy(si);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,27 +370,35 @@ static int test_add(cmd_args_t *args, test_t *test)
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
uu_list_insert(args->args_tests, tmp, 0);
|
list_append(args->args_tests, tmp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_add_all(cmd_args_t *args)
|
static int test_add_all(cmd_args_t *args)
|
||||||
{
|
{
|
||||||
|
ListIterator si, ti;
|
||||||
subsystem_t *sub;
|
subsystem_t *sub;
|
||||||
test_t *test;
|
test_t *test;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
for (sub = uu_list_first(subsystems); sub != NULL;
|
si = list_iterator_create(subsystems);
|
||||||
sub = uu_list_next(subsystems, sub)) {
|
|
||||||
|
|
||||||
for (test = uu_list_first(sub->sub_tests); test != NULL;
|
while ((sub = list_next(si))) {
|
||||||
test = uu_list_next(sub->sub_tests, test)) {
|
ti = list_iterator_create(sub->sub_tests);
|
||||||
|
|
||||||
if (rc = test_add(args, test))
|
while ((test = list_next(ti))) {
|
||||||
|
if ((rc = test_add(args, test))) {
|
||||||
|
list_iterator_destroy(ti);
|
||||||
|
list_iterator_destroy(si);
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_iterator_destroy(ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_iterator_destroy(si);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,6 +453,7 @@ static int test_run(cmd_args_t *args, test_t *test)
|
||||||
|
|
||||||
static int tests_run(cmd_args_t *args)
|
static int tests_run(cmd_args_t *args)
|
||||||
{
|
{
|
||||||
|
ListIterator i;
|
||||||
test_t *test;
|
test_t *test;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -436,19 +462,23 @@ static int tests_run(cmd_args_t *args)
|
||||||
"Running KZT Tests "
|
"Running KZT Tests "
|
||||||
"-------------------------------\n");
|
"-------------------------------\n");
|
||||||
|
|
||||||
for (test = uu_list_first(args->args_tests); test != NULL;
|
i = list_iterator_create(args->args_tests);
|
||||||
test = uu_list_next(args->args_tests, test)) {
|
|
||||||
|
|
||||||
|
while ((test = list_next(i))) {
|
||||||
rc = test_run(args, test);
|
rc = test_run(args, test);
|
||||||
if (rc && args->args_exit_on_error)
|
if (rc && args->args_exit_on_error) {
|
||||||
|
list_iterator_destroy(i);
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_iterator_destroy(i);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int args_parse_test(cmd_args_t *args, char *str)
|
static int args_parse_test(cmd_args_t *args, char *str)
|
||||||
{
|
{
|
||||||
|
ListIterator si, ti;
|
||||||
subsystem_t *s;
|
subsystem_t *s;
|
||||||
test_t *t;
|
test_t *t;
|
||||||
char *sub_str, *test_str;
|
char *sub_str, *test_str;
|
||||||
|
@ -476,21 +506,26 @@ static int args_parse_test(cmd_args_t *args, char *str)
|
||||||
if (!strncasecmp(test_str, "all", strlen(test_str)) || (test_num == -1))
|
if (!strncasecmp(test_str, "all", strlen(test_str)) || (test_num == -1))
|
||||||
test_all = 1;
|
test_all = 1;
|
||||||
|
|
||||||
|
si = list_iterator_create(subsystems);
|
||||||
|
|
||||||
if (sub_all) {
|
if (sub_all) {
|
||||||
if (test_all) {
|
if (test_all) {
|
||||||
/* Add all tests from all subsystems */
|
/* Add all tests from all subsystems */
|
||||||
for (s = uu_list_first(subsystems); s != NULL;
|
while ((s = list_next(si))) {
|
||||||
s = uu_list_next(subsystems, s))
|
ti = list_iterator_create(s->sub_tests);
|
||||||
for (t = uu_list_first(s->sub_tests);t != NULL;
|
while ((t = list_next(ti))) {
|
||||||
t = uu_list_next(s->sub_tests, t))
|
if ((rc = test_add(args, t))) {
|
||||||
if (rc = test_add(args, t))
|
list_iterator_destroy(ti);
|
||||||
goto error_run;
|
goto error_run;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_iterator_destroy(ti);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Add a specific test from all subsystems */
|
/* Add a specific test from all subsystems */
|
||||||
for (s = uu_list_first(subsystems); s != NULL;
|
while ((s = list_next(si))) {
|
||||||
s = uu_list_next(subsystems, s)) {
|
if ((t = test_find(s->sub_desc.name,test_str))) {
|
||||||
if (t = test_find(s->sub_desc.name,test_str)) {
|
if ((rc = test_add(args, t)))
|
||||||
if (rc = test_add(args, t))
|
|
||||||
goto error_run;
|
goto error_run;
|
||||||
|
|
||||||
flag = 1;
|
flag = 1;
|
||||||
|
@ -504,21 +539,24 @@ static int args_parse_test(cmd_args_t *args, char *str)
|
||||||
} else {
|
} else {
|
||||||
if (test_all) {
|
if (test_all) {
|
||||||
/* Add all tests from a specific subsystem */
|
/* Add all tests from a specific subsystem */
|
||||||
for (s = uu_list_first(subsystems); s != NULL;
|
while ((s = list_next(si))) {
|
||||||
s = uu_list_next(subsystems, s)) {
|
|
||||||
if (strncasecmp(sub_str, s->sub_desc.name,
|
if (strncasecmp(sub_str, s->sub_desc.name,
|
||||||
strlen(sub_str)))
|
strlen(sub_str)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (t = uu_list_first(s->sub_tests);t != NULL;
|
ti = list_iterator_create(s->sub_tests);
|
||||||
t = uu_list_next(s->sub_tests, t))
|
while ((t = list_next(ti))) {
|
||||||
if (rc = test_add(args, t))
|
if ((rc = test_add(args, t))) {
|
||||||
|
list_iterator_destroy(ti);
|
||||||
goto error_run;
|
goto error_run;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_iterator_destroy(ti);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Add a specific test from a specific subsystem */
|
/* Add a specific test from a specific subsystem */
|
||||||
if (t = test_find(sub_str, test_str)) {
|
if ((t = test_find(sub_str, test_str))) {
|
||||||
if (rc = test_add(args, t))
|
if ((rc = test_add(args, t)))
|
||||||
goto error_run;
|
goto error_run;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Test '%s:%s' could not be "
|
fprintf(stderr, "Test '%s:%s' could not be "
|
||||||
|
@ -528,25 +566,25 @@ static int args_parse_test(cmd_args_t *args, char *str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_iterator_destroy(si);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_run:
|
error_run:
|
||||||
|
list_iterator_destroy(si);
|
||||||
|
|
||||||
fprintf(stderr, "Test '%s:%s' not added to run list: %d\n",
|
fprintf(stderr, "Test '%s:%s' not added to run list: %d\n",
|
||||||
sub_str, test_str, rc);
|
sub_str, test_str, rc);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void args_fini(cmd_args_t *args)
|
static void args_fini(cmd_args_t *args)
|
||||||
{
|
{
|
||||||
struct cmd_test *ptr1, *ptr2;
|
|
||||||
|
|
||||||
assert(args != NULL);
|
assert(args != NULL);
|
||||||
|
|
||||||
|
if (args->args_tests != NULL)
|
||||||
|
list_destroy(args->args_tests);
|
||||||
if (args->args_tests != NULL) {
|
|
||||||
uu_list_destroy(args->args_tests);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(args);
|
free(args);
|
||||||
}
|
}
|
||||||
|
@ -573,7 +611,7 @@ args_init(int argc, char **argv)
|
||||||
args->args_do_all = 0;
|
args->args_do_all = 0;
|
||||||
args->args_do_color = 1;
|
args->args_do_color = 1;
|
||||||
args->args_exit_on_error = 0;
|
args->args_exit_on_error = 0;
|
||||||
args->args_tests = uu_list_create(test_pool, NULL, 0);
|
args->args_tests = list_create((ListDelF)test_fini);
|
||||||
if (args->args_tests == NULL) {
|
if (args->args_tests == NULL) {
|
||||||
args_fini(args);
|
args_fini(args);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -674,6 +712,7 @@ dev_fini(void)
|
||||||
static int
|
static int
|
||||||
dev_init(void)
|
dev_init(void)
|
||||||
{
|
{
|
||||||
|
ListIterator i;
|
||||||
subsystem_t *sub;
|
subsystem_t *sub;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -690,7 +729,7 @@ dev_init(void)
|
||||||
if ((rc = read(kztctl_fd, kzt_version, KZT_VERSION_SIZE - 1)) == -1)
|
if ((rc = read(kztctl_fd, kzt_version, KZT_VERSION_SIZE - 1)) == -1)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (rc = dev_clear())
|
if ((rc = dev_clear()))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if ((rc = dev_size(0)) < 0)
|
if ((rc = dev_size(0)) < 0)
|
||||||
|
@ -710,11 +749,16 @@ dev_init(void)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Determine available tests for all subsystems */
|
/* Determine available tests for all subsystems */
|
||||||
for (sub = uu_list_first(subsystems); sub != NULL;
|
i = list_iterator_create(subsystems);
|
||||||
sub = uu_list_next(subsystems, sub))
|
|
||||||
if ((rc = test_setup(sub)) != 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
|
while ((sub = list_next(i))) {
|
||||||
|
if ((rc = test_setup(sub)) != 0) {
|
||||||
|
list_iterator_destroy(i);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list_iterator_destroy(i);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -731,42 +775,20 @@ error:
|
||||||
int
|
int
|
||||||
init(void)
|
init(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc = 0;
|
||||||
|
|
||||||
/* Configure the subsystem pool */
|
|
||||||
subsystem_pool = uu_list_pool_create("sub_pool", sizeof(subsystem_t),
|
|
||||||
offsetof(subsystem_t, sub_node),
|
|
||||||
subsystem_compare, 0);
|
|
||||||
if (subsystem_pool == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* Configure the test pool */
|
|
||||||
test_pool = uu_list_pool_create("test_pool", sizeof(test_t),
|
|
||||||
offsetof(test_t, test_node),
|
|
||||||
test_compare, 0);
|
|
||||||
if (test_pool == NULL) {
|
|
||||||
uu_list_pool_destroy(subsystem_pool);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate the subsystem list */
|
/* Allocate the subsystem list */
|
||||||
subsystems = uu_list_create(subsystem_pool, NULL, 0);
|
subsystems = list_create((ListDelF)subsystem_fini);
|
||||||
if (subsystems == NULL) {
|
if (subsystems == NULL)
|
||||||
uu_list_pool_destroy(test_pool);
|
rc = ENOMEM;
|
||||||
uu_list_pool_destroy(subsystem_pool);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fini(void)
|
fini(void)
|
||||||
{
|
{
|
||||||
/* XXX - Cleanup destroy lists release memory */
|
list_destroy(subsystems);
|
||||||
|
|
||||||
/* XXX - Remove contents of list first */
|
|
||||||
uu_list_destroy(subsystems);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -777,11 +799,11 @@ main(int argc, char **argv)
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
/* General init */
|
/* General init */
|
||||||
if (rc = init())
|
if ((rc = init()))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* Device specific init */
|
/* Device specific init */
|
||||||
if (rc = dev_init())
|
if ((rc = dev_init()))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Argument init and parsing */
|
/* Argument init and parsing */
|
||||||
|
@ -802,12 +824,12 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
/* Add all available test to the list of tests to run */
|
/* Add all available test to the list of tests to run */
|
||||||
if (args->args_do_all) {
|
if (args->args_do_all) {
|
||||||
if (rc = test_add_all(args))
|
if ((rc = test_add_all(args)))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run all the requested tests */
|
/* Run all the requested tests */
|
||||||
if (rc = tests_run(args))
|
if ((rc = tests_run(args)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
INCLUDES = -I$(top_srcdir)/include
|
||||||
|
noinst_LTLIBRARIES = libcommon.la
|
||||||
|
libcommon_la_SOURCES = list.c
|
|
@ -0,0 +1,833 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* $Id: list.c 3709 2006-11-29 00:51:22Z dun $
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 2001-2002 The Regents of the University of California.
|
||||||
|
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||||
|
* Written by Chris Dunlap <cdunlap@llnl.gov>.
|
||||||
|
*
|
||||||
|
* This file is from LSD-Tools, the LLNL Software Development Toolbox.
|
||||||
|
*
|
||||||
|
* LSD-Tools 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 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* LSD-Tools 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 LSD-Tools; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||||
|
*****************************************************************************
|
||||||
|
* Refer to "list.h" for documentation on public functions.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#ifdef WITH_PTHREADS
|
||||||
|
# include <pthread.h>
|
||||||
|
#endif /* WITH_PTHREADS */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* lsd_fatal_error *
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#ifdef WITH_LSD_FATAL_ERROR_FUNC
|
||||||
|
# undef lsd_fatal_error
|
||||||
|
extern void lsd_fatal_error(char *file, int line, char *mesg);
|
||||||
|
#else /* !WITH_LSD_FATAL_ERROR_FUNC */
|
||||||
|
# ifndef lsd_fatal_error
|
||||||
|
# include <errno.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <string.h>
|
||||||
|
# define lsd_fatal_error(file, line, mesg) \
|
||||||
|
do { \
|
||||||
|
fprintf(stderr, "ERROR: [%s:%d] %s: %s\n", \
|
||||||
|
file, line, mesg, strerror(errno)); \
|
||||||
|
} while (0)
|
||||||
|
# endif /* !lsd_fatal_error */
|
||||||
|
#endif /* !WITH_LSD_FATAL_ERROR_FUNC */
|
||||||
|
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* lsd_nomem_error *
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#ifdef WITH_LSD_NOMEM_ERROR_FUNC
|
||||||
|
# undef lsd_nomem_error
|
||||||
|
extern void * lsd_nomem_error(char *file, int line, char *mesg);
|
||||||
|
#else /* !WITH_LSD_NOMEM_ERROR_FUNC */
|
||||||
|
# ifndef lsd_nomem_error
|
||||||
|
# define lsd_nomem_error(file, line, mesg) (NULL)
|
||||||
|
# endif /* !lsd_nomem_error */
|
||||||
|
#endif /* !WITH_LSD_NOMEM_ERROR_FUNC */
|
||||||
|
|
||||||
|
|
||||||
|
/***************
|
||||||
|
* Constants *
|
||||||
|
***************/
|
||||||
|
|
||||||
|
#define LIST_ALLOC 32
|
||||||
|
#define LIST_MAGIC 0xDEADBEEF
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Data Types *
|
||||||
|
****************/
|
||||||
|
|
||||||
|
struct listNode {
|
||||||
|
void *data; /* node's data */
|
||||||
|
struct listNode *next; /* next node in list */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct listIterator {
|
||||||
|
struct list *list; /* the list being iterated */
|
||||||
|
struct listNode *pos; /* the next node to be iterated */
|
||||||
|
struct listNode **prev; /* addr of 'next' ptr to prv It node */
|
||||||
|
struct listIterator *iNext; /* iterator chain for list_destroy() */
|
||||||
|
#ifndef NDEBUG
|
||||||
|
unsigned int magic; /* sentinel for asserting validity */
|
||||||
|
#endif /* !NDEBUG */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct list {
|
||||||
|
struct listNode *head; /* head of the list */
|
||||||
|
struct listNode **tail; /* addr of last node's 'next' ptr */
|
||||||
|
struct listIterator *iNext; /* iterator chain for list_destroy() */
|
||||||
|
ListDelF fDel; /* function to delete node data */
|
||||||
|
int count; /* number of nodes in list */
|
||||||
|
#ifdef WITH_PTHREADS
|
||||||
|
pthread_mutex_t mutex; /* mutex to protect access to list */
|
||||||
|
#endif /* WITH_PTHREADS */
|
||||||
|
#ifndef NDEBUG
|
||||||
|
unsigned int magic; /* sentinel for asserting validity */
|
||||||
|
#endif /* !NDEBUG */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct listNode * ListNode;
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Prototypes *
|
||||||
|
****************/
|
||||||
|
|
||||||
|
static void * list_node_create (List l, ListNode *pp, void *x);
|
||||||
|
static void * list_node_destroy (List l, ListNode *pp);
|
||||||
|
static List list_alloc (void);
|
||||||
|
static void list_free (List l);
|
||||||
|
static ListNode list_node_alloc (void);
|
||||||
|
static void list_node_free (ListNode p);
|
||||||
|
static ListIterator list_iterator_alloc (void);
|
||||||
|
static void list_iterator_free (ListIterator i);
|
||||||
|
static void * list_alloc_aux (int size, void *pfreelist);
|
||||||
|
static void list_free_aux (void *x, void *pfreelist);
|
||||||
|
|
||||||
|
|
||||||
|
/***************
|
||||||
|
* Variables *
|
||||||
|
***************/
|
||||||
|
|
||||||
|
static List list_free_lists = NULL;
|
||||||
|
static ListNode list_free_nodes = NULL;
|
||||||
|
static ListIterator list_free_iterators = NULL;
|
||||||
|
|
||||||
|
#ifdef WITH_PTHREADS
|
||||||
|
static pthread_mutex_t list_free_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
#endif /* WITH_PTHREADS */
|
||||||
|
|
||||||
|
|
||||||
|
/************
|
||||||
|
* Macros *
|
||||||
|
************/
|
||||||
|
|
||||||
|
#ifdef WITH_PTHREADS
|
||||||
|
|
||||||
|
# define list_mutex_init(mutex) \
|
||||||
|
do { \
|
||||||
|
int e = pthread_mutex_init(mutex, NULL); \
|
||||||
|
if (e != 0) { \
|
||||||
|
errno = e; \
|
||||||
|
lsd_fatal_error(__FILE__, __LINE__, "list mutex init"); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
# define list_mutex_lock(mutex) \
|
||||||
|
do { \
|
||||||
|
int e = pthread_mutex_lock(mutex); \
|
||||||
|
if (e != 0) { \
|
||||||
|
errno = e; \
|
||||||
|
lsd_fatal_error(__FILE__, __LINE__, "list mutex lock"); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
# define list_mutex_unlock(mutex) \
|
||||||
|
do { \
|
||||||
|
int e = pthread_mutex_unlock(mutex); \
|
||||||
|
if (e != 0) { \
|
||||||
|
errno = e; \
|
||||||
|
lsd_fatal_error(__FILE__, __LINE__, "list mutex unlock"); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
# define list_mutex_destroy(mutex) \
|
||||||
|
do { \
|
||||||
|
int e = pthread_mutex_destroy(mutex); \
|
||||||
|
if (e != 0) { \
|
||||||
|
errno = e; \
|
||||||
|
lsd_fatal_error(__FILE__, __LINE__, "list mutex destroy"); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
# ifndef NDEBUG
|
||||||
|
static int list_mutex_is_locked (pthread_mutex_t *mutex);
|
||||||
|
# endif /* !NDEBUG */
|
||||||
|
|
||||||
|
#else /* !WITH_PTHREADS */
|
||||||
|
|
||||||
|
# define list_mutex_init(mutex)
|
||||||
|
# define list_mutex_lock(mutex)
|
||||||
|
# define list_mutex_unlock(mutex)
|
||||||
|
# define list_mutex_destroy(mutex)
|
||||||
|
# define list_mutex_is_locked(mutex) (1)
|
||||||
|
|
||||||
|
#endif /* !WITH_PTHREADS */
|
||||||
|
|
||||||
|
|
||||||
|
/***************
|
||||||
|
* Functions *
|
||||||
|
***************/
|
||||||
|
|
||||||
|
List
|
||||||
|
list_create (ListDelF f)
|
||||||
|
{
|
||||||
|
List l;
|
||||||
|
|
||||||
|
if (!(l = list_alloc()))
|
||||||
|
return(lsd_nomem_error(__FILE__, __LINE__, "list create"));
|
||||||
|
l->head = NULL;
|
||||||
|
l->tail = &l->head;
|
||||||
|
l->iNext = NULL;
|
||||||
|
l->fDel = f;
|
||||||
|
l->count = 0;
|
||||||
|
list_mutex_init(&l->mutex);
|
||||||
|
assert(l->magic = LIST_MAGIC); /* set magic via assert abuse */
|
||||||
|
return(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
list_destroy (List l)
|
||||||
|
{
|
||||||
|
ListIterator i, iTmp;
|
||||||
|
ListNode p, pTmp;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
i = l->iNext;
|
||||||
|
while (i) {
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
iTmp = i->iNext;
|
||||||
|
assert(i->magic = ~LIST_MAGIC); /* clear magic via assert abuse */
|
||||||
|
list_iterator_free(i);
|
||||||
|
i = iTmp;
|
||||||
|
}
|
||||||
|
p = l->head;
|
||||||
|
while (p) {
|
||||||
|
pTmp = p->next;
|
||||||
|
if (p->data && l->fDel)
|
||||||
|
l->fDel(p->data);
|
||||||
|
list_node_free(p);
|
||||||
|
p = pTmp;
|
||||||
|
}
|
||||||
|
assert(l->magic = ~LIST_MAGIC); /* clear magic via assert abuse */
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
list_mutex_destroy(&l->mutex);
|
||||||
|
list_free(l);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
list_is_empty (List l)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
n = l->count;
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(n == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
list_count (List l)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
n = l->count;
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_append (List l, void *x)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(x != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
v = list_node_create(l, l->tail, x);
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_prepend (List l, void *x)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(x != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
v = list_node_create(l, &l->head, x);
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_find_first (List l, ListFindF f, void *key)
|
||||||
|
{
|
||||||
|
ListNode p;
|
||||||
|
void *v = NULL;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(f != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
for (p=l->head; p; p=p->next) {
|
||||||
|
if (f(p->data, key)) {
|
||||||
|
v = p->data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
list_delete_all (List l, ListFindF f, void *key)
|
||||||
|
{
|
||||||
|
ListNode *pp;
|
||||||
|
void *v;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(f != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
pp = &l->head;
|
||||||
|
while (*pp) {
|
||||||
|
if (f((*pp)->data, key)) {
|
||||||
|
if ((v = list_node_destroy(l, pp))) {
|
||||||
|
if (l->fDel)
|
||||||
|
l->fDel(v);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pp = &(*pp)->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
list_for_each (List l, ListForF f, void *arg)
|
||||||
|
{
|
||||||
|
ListNode p;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(f != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
for (p=l->head; p; p=p->next) {
|
||||||
|
n++;
|
||||||
|
if (f(p->data, arg) < 0) {
|
||||||
|
n = -n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
list_sort (List l, ListCmpF f)
|
||||||
|
{
|
||||||
|
/* Note: Time complexity O(n^2).
|
||||||
|
*/
|
||||||
|
ListNode *pp, *ppPrev, *ppPos, pTmp;
|
||||||
|
ListIterator i;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(f != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
if (l->count > 1) {
|
||||||
|
ppPrev = &l->head;
|
||||||
|
pp = &(*ppPrev)->next;
|
||||||
|
while (*pp) {
|
||||||
|
if (f((*pp)->data, (*ppPrev)->data) < 0) {
|
||||||
|
ppPos = &l->head;
|
||||||
|
while (f((*pp)->data, (*ppPos)->data) >= 0)
|
||||||
|
ppPos = &(*ppPos)->next;
|
||||||
|
pTmp = (*pp)->next;
|
||||||
|
(*pp)->next = *ppPos;
|
||||||
|
*ppPos = *pp;
|
||||||
|
*pp = pTmp;
|
||||||
|
if (ppPrev == ppPos)
|
||||||
|
ppPrev = &(*ppPrev)->next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ppPrev = pp;
|
||||||
|
pp = &(*pp)->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l->tail = pp;
|
||||||
|
|
||||||
|
for (i=l->iNext; i; i=i->iNext) {
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
i->pos = i->list->head;
|
||||||
|
i->prev = &i->list->head;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_push (List l, void *x)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(x != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
v = list_node_create(l, &l->head, x);
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_pop (List l)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
v = list_node_destroy(l, &l->head);
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_peek (List l)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
v = (l->head) ? l->head->data : NULL;
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_enqueue (List l, void *x)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(x != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
v = list_node_create(l, l->tail, x);
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_dequeue (List l)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
v = list_node_destroy(l, &l->head);
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ListIterator
|
||||||
|
list_iterator_create (List l)
|
||||||
|
{
|
||||||
|
ListIterator i;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
if (!(i = list_iterator_alloc()))
|
||||||
|
return(lsd_nomem_error(__FILE__, __LINE__, "list iterator create"));
|
||||||
|
i->list = l;
|
||||||
|
list_mutex_lock(&l->mutex);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
i->pos = l->head;
|
||||||
|
i->prev = &l->head;
|
||||||
|
i->iNext = l->iNext;
|
||||||
|
l->iNext = i;
|
||||||
|
assert(i->magic = LIST_MAGIC); /* set magic via assert abuse */
|
||||||
|
list_mutex_unlock(&l->mutex);
|
||||||
|
return(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
list_iterator_reset (ListIterator i)
|
||||||
|
{
|
||||||
|
assert(i != NULL);
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
list_mutex_lock(&i->list->mutex);
|
||||||
|
assert(i->list->magic == LIST_MAGIC);
|
||||||
|
i->pos = i->list->head;
|
||||||
|
i->prev = &i->list->head;
|
||||||
|
list_mutex_unlock(&i->list->mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
list_iterator_destroy (ListIterator i)
|
||||||
|
{
|
||||||
|
ListIterator *pi;
|
||||||
|
|
||||||
|
assert(i != NULL);
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
list_mutex_lock(&i->list->mutex);
|
||||||
|
assert(i->list->magic == LIST_MAGIC);
|
||||||
|
for (pi=&i->list->iNext; *pi; pi=&(*pi)->iNext) {
|
||||||
|
assert((*pi)->magic == LIST_MAGIC);
|
||||||
|
if (*pi == i) {
|
||||||
|
*pi = (*pi)->iNext;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_mutex_unlock(&i->list->mutex);
|
||||||
|
assert(i->magic = ~LIST_MAGIC); /* clear magic via assert abuse */
|
||||||
|
list_iterator_free(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_next (ListIterator i)
|
||||||
|
{
|
||||||
|
ListNode p;
|
||||||
|
|
||||||
|
assert(i != NULL);
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
list_mutex_lock(&i->list->mutex);
|
||||||
|
assert(i->list->magic == LIST_MAGIC);
|
||||||
|
if ((p = i->pos))
|
||||||
|
i->pos = p->next;
|
||||||
|
if (*i->prev != p)
|
||||||
|
i->prev = &(*i->prev)->next;
|
||||||
|
list_mutex_unlock(&i->list->mutex);
|
||||||
|
return(p ? p->data : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_insert (ListIterator i, void *x)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(i != NULL);
|
||||||
|
assert(x != NULL);
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
list_mutex_lock(&i->list->mutex);
|
||||||
|
assert(i->list->magic == LIST_MAGIC);
|
||||||
|
v = list_node_create(i->list, i->prev, x);
|
||||||
|
list_mutex_unlock(&i->list->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_find (ListIterator i, ListFindF f, void *key)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(i != NULL);
|
||||||
|
assert(f != NULL);
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
while ((v=list_next(i)) && !f(v,key)) {;}
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
list_remove (ListIterator i)
|
||||||
|
{
|
||||||
|
void *v = NULL;
|
||||||
|
|
||||||
|
assert(i != NULL);
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
list_mutex_lock(&i->list->mutex);
|
||||||
|
assert(i->list->magic == LIST_MAGIC);
|
||||||
|
if (*i->prev != i->pos)
|
||||||
|
v = list_node_destroy(i->list, i->prev);
|
||||||
|
list_mutex_unlock(&i->list->mutex);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
list_delete (ListIterator i)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
assert(i != NULL);
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
if ((v = list_remove(i))) {
|
||||||
|
if (i->list->fDel)
|
||||||
|
i->list->fDel(v);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
list_node_create (List l, ListNode *pp, void *x)
|
||||||
|
{
|
||||||
|
/* Inserts data pointed to by [x] into list [l] after [pp],
|
||||||
|
* the address of the previous node's "next" ptr.
|
||||||
|
* Returns a ptr to data [x], or NULL if insertion fails.
|
||||||
|
* This routine assumes the list is already locked upon entry.
|
||||||
|
*/
|
||||||
|
ListNode p;
|
||||||
|
ListIterator i;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
assert(list_mutex_is_locked(&l->mutex));
|
||||||
|
assert(pp != NULL);
|
||||||
|
assert(x != NULL);
|
||||||
|
if (!(p = list_node_alloc()))
|
||||||
|
return(lsd_nomem_error(__FILE__, __LINE__, "list node create"));
|
||||||
|
p->data = x;
|
||||||
|
if (!(p->next = *pp))
|
||||||
|
l->tail = &p->next;
|
||||||
|
*pp = p;
|
||||||
|
l->count++;
|
||||||
|
for (i=l->iNext; i; i=i->iNext) {
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
if (i->prev == pp)
|
||||||
|
i->prev = &p->next;
|
||||||
|
else if (i->pos == p->next)
|
||||||
|
i->pos = p;
|
||||||
|
assert((i->pos == *i->prev) || (i->pos == (*i->prev)->next));
|
||||||
|
}
|
||||||
|
return(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
list_node_destroy (List l, ListNode *pp)
|
||||||
|
{
|
||||||
|
/* Removes the node pointed to by [*pp] from from list [l],
|
||||||
|
* where [pp] is the address of the previous node's "next" ptr.
|
||||||
|
* Returns the data ptr associated with list item being removed,
|
||||||
|
* or NULL if [*pp] points to the NULL element.
|
||||||
|
* This routine assumes the list is already locked upon entry.
|
||||||
|
*/
|
||||||
|
void *v;
|
||||||
|
ListNode p;
|
||||||
|
ListIterator i;
|
||||||
|
|
||||||
|
assert(l != NULL);
|
||||||
|
assert(l->magic == LIST_MAGIC);
|
||||||
|
assert(list_mutex_is_locked(&l->mutex));
|
||||||
|
assert(pp != NULL);
|
||||||
|
if (!(p = *pp))
|
||||||
|
return(NULL);
|
||||||
|
v = p->data;
|
||||||
|
if (!(*pp = p->next))
|
||||||
|
l->tail = pp;
|
||||||
|
l->count--;
|
||||||
|
for (i=l->iNext; i; i=i->iNext) {
|
||||||
|
assert(i->magic == LIST_MAGIC);
|
||||||
|
if (i->pos == p)
|
||||||
|
i->pos = p->next, i->prev = pp;
|
||||||
|
else if (i->prev == &p->next)
|
||||||
|
i->prev = pp;
|
||||||
|
assert((i->pos == *i->prev) || (i->pos == (*i->prev)->next));
|
||||||
|
}
|
||||||
|
list_node_free(p);
|
||||||
|
return(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static List
|
||||||
|
list_alloc (void)
|
||||||
|
{
|
||||||
|
return(list_alloc_aux(sizeof(struct list), &list_free_lists));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
list_free (List l)
|
||||||
|
{
|
||||||
|
list_free_aux(l, &list_free_lists);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ListNode
|
||||||
|
list_node_alloc (void)
|
||||||
|
{
|
||||||
|
return(list_alloc_aux(sizeof(struct listNode), &list_free_nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
list_node_free (ListNode p)
|
||||||
|
{
|
||||||
|
list_free_aux(p, &list_free_nodes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ListIterator
|
||||||
|
list_iterator_alloc (void)
|
||||||
|
{
|
||||||
|
return(list_alloc_aux(sizeof(struct listIterator), &list_free_iterators));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
list_iterator_free (ListIterator i)
|
||||||
|
{
|
||||||
|
list_free_aux(i, &list_free_iterators);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
list_alloc_aux (int size, void *pfreelist)
|
||||||
|
{
|
||||||
|
/* Allocates an object of [size] bytes from the freelist [*pfreelist].
|
||||||
|
* Memory is added to the freelist in chunks of size LIST_ALLOC.
|
||||||
|
* Returns a ptr to the object, or NULL if the memory request fails.
|
||||||
|
*/
|
||||||
|
void **px;
|
||||||
|
void **pfree = pfreelist;
|
||||||
|
void **plast;
|
||||||
|
|
||||||
|
assert(sizeof(char) == 1);
|
||||||
|
assert(size >= sizeof(void *));
|
||||||
|
assert(pfreelist != NULL);
|
||||||
|
assert(LIST_ALLOC > 0);
|
||||||
|
list_mutex_lock(&list_free_lock);
|
||||||
|
if (!*pfree) {
|
||||||
|
if ((*pfree = malloc(LIST_ALLOC * size))) {
|
||||||
|
px = *pfree;
|
||||||
|
plast = (void **) ((char *) *pfree + ((LIST_ALLOC - 1) * size));
|
||||||
|
while (px < plast)
|
||||||
|
*px = (char *) px + size, px = *px;
|
||||||
|
*plast = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((px = *pfree))
|
||||||
|
*pfree = *px;
|
||||||
|
else
|
||||||
|
errno = ENOMEM;
|
||||||
|
list_mutex_unlock(&list_free_lock);
|
||||||
|
return(px);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
list_free_aux (void *x, void *pfreelist)
|
||||||
|
{
|
||||||
|
/* Frees the object [x], returning it to the freelist [*pfreelist].
|
||||||
|
*/
|
||||||
|
void **px = x;
|
||||||
|
void **pfree = pfreelist;
|
||||||
|
|
||||||
|
assert(x != NULL);
|
||||||
|
assert(pfreelist != NULL);
|
||||||
|
list_mutex_lock(&list_free_lock);
|
||||||
|
*px = *pfree;
|
||||||
|
*pfree = px;
|
||||||
|
list_mutex_unlock(&list_free_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#ifdef WITH_PTHREADS
|
||||||
|
static int
|
||||||
|
list_mutex_is_locked (pthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
/* Returns true if the mutex is locked; o/w, returns false.
|
||||||
|
*/
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert(mutex != NULL);
|
||||||
|
rc = pthread_mutex_trylock(mutex);
|
||||||
|
return(rc == EBUSY ? 1 : 0);
|
||||||
|
}
|
||||||
|
#endif /* WITH_PTHREADS */
|
||||||
|
#endif /* !NDEBUG */
|
|
@ -5,8 +5,9 @@ MODULES := spl
|
||||||
DISTFILES = Makefile.in \
|
DISTFILES = Makefile.in \
|
||||||
linux-kmem.c linux-rwlock.c linux-taskq.c linux-thread.c
|
linux-kmem.c linux-rwlock.c linux-taskq.c linux-thread.c
|
||||||
|
|
||||||
|
EXTRA_CFLAGS += -I$(src)
|
||||||
|
|
||||||
# Removed '-std=gnu99' does to compile issues with i386 SPIN_LOCK_UNLOCKED
|
# Removed '-std=gnu99' does to compile issues with i386 SPIN_LOCK_UNLOCKED
|
||||||
# EXTRA_CFLAGS += -I$(src)
|
|
||||||
# EXTRA_CFLAGS += -Wall -Wno-unknown-pragmas -Wno-missing-braces \
|
# EXTRA_CFLAGS += -Wall -Wno-unknown-pragmas -Wno-missing-braces \
|
||||||
# -Wno-sign-compare -Wno-parentheses -Wno-uninitialized \
|
# -Wno-sign-compare -Wno-parentheses -Wno-uninitialized \
|
||||||
# -Wno-implicit-function-declaration -Wno-unused -Wno-trigraphs \
|
# -Wno-implicit-function-declaration -Wno-unused -Wno-trigraphs \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include <sys/linux-kmem.h>
|
#include "linux-kmem.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Memory allocation interfaces
|
* Memory allocation interfaces
|
||||||
|
|
Loading…
Reference in New Issue