/* * Copyright (c) 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Portions of this software have been released under the following terms: * * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION * * To anyone who acknowledges that this file is provided "AS IS" * without any express or implied warranty: * permission to use, copy, modify, and distribute this file for any * purpose is hereby granted without fee, provided that the above * copyright notices and this notice appears in all source code copies, * and that none of the names of Open Software Foundation, Inc., Hewlett- * Packard Company or Digital Equipment Corporation be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. Neither Open Software * Foundation, Inc., Hewlett-Packard Company nor Digital * Equipment Corporation makes any representations about the suitability * of this software for any purpose. * * Copyright (c) 2007, Novell, Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Novell Inc. nor the names of its contributors * may be used to endorse or promote products derived from this * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @APPLE_LICENSE_HEADER_END@ */ /* ** ** NAME: ** ** rpclist.h ** ** FACILITY: ** ** Remote Procedure Call (RPC) ** ** ABSTRACT: ** ** Various types and macros for list and queue processing. ** ** */ #ifndef _RPCLIST_H #define _RPCLIST_H /***********************************************************************/ /* * List Processing. * * The RPC services maintain a number of structures in the form of lists * and queues. Lists are doubly linked with the list head containing both * a pointer to the first element of the list as well as a pointer to the * last element in the list. The elements on these lists are maintained in * first-in first-out order. By maintaining the last element pointer, * elements can be easily added to the end of the list. * * Structures which are going to be used in lists should have a member of * the type rpc_list_t as their first member. * * List descriptors are used to maintain context for lists which are going * to take advantage of memory management optimizations (lookaside lists). * Memory for these lists is obtained in large "chunks", which is then * provided to individual list elements on an as-needed basis. * * ***CAVEAT***: * * The structures kept on lists which are processed by the * RPC_LIST* macros can be kept on only one list at a time. * This is because the macros *assume* the first field of the * structure given to them is a "link" field (an rpc_list_t) * structure. It casts the structure to to a be a pointer to an * rpc_list_t structure and manipulates the fields of it ("next" and * "last"). Enqueuing a structure on a second list would effectively * remove it from the first list since the "next" and "last" fields * would be overwritten. */ /*int pthd4_get_expiration_np(struct timespec *delta, struct timespec *abstime);*/ /***********************************************************************/ /* * R P C _ L I S T _ T * * This is a list head (or a set of reference pointers in a list element). */ typedef struct { dce_pointer_t next; /* next element of list */ dce_pointer_t last; /* last element of list in a descriptor or */ /* pointer to the prior element in an element */ } rpc_list_t, *rpc_list_p_t; /***********************************************************************/ /* * R P C _ L I S T _ E L E M E N T _ A L L O C _ F N _ T * */ typedef void (*rpc_list_element_alloc_fn_t) ( dce_pointer_t /*list_element*/ ); /***********************************************************************/ /* * R P C _ L I S T _ E L E M E N T _ F R E E _ F N _ T * */ typedef void (*rpc_list_element_free_fn_t) ( dce_pointer_t /*list_element*/ ); /***********************************************************************/ /* * R P C _ L I S T _ D E S C _ T * */ typedef struct { rpc_list_t list_head; unsigned32 max_size; unsigned32 cur_size; unsigned32 element_size; unsigned32 element_type; rpc_list_element_alloc_fn_t alloc_rtn; rpc_list_element_free_fn_t free_rtn; rpc_mutex_t *mutex; rpc_cond_t *cond; boolean32 use_global_mutex; } rpc_list_desc_t, *rpc_list_desc_p_t; /***********************************************************************/ /* * R P C _ L O O K A S I D E _ R C B _ T */ typedef struct { unsigned16 res_id; unsigned16 waiter_cnt; unsigned16 max_wait_times; unsigned16 wait_time; rpc_mutex_t res_lock; rpc_cond_t wait_flg; } rpc_lookaside_rcb_t, *rpc_lookaside_rcb_p_t; #define RPC_C_LOOKASIDE_RES 1 #define RPC_C_LOOKASIDE_RES_WAIT 1 #define RPC_C_LOOKASIDE_RES_MAX_WAIT 5 EXTERNAL rpc_lookaside_rcb_t rpc_g_lookaside_rcb; /***********************************************************************/ /* * R P C _ L I S T _ M U T E X _ I N I T * * Initialize the global lookaside list mutex. * * Sample usage: * * RPC_LIST_MUTEX_INIT (0); */ #define RPC_LIST_MUTEX_INIT(junk) \ { \ RPC_MUTEX_INIT (rpc_g_lookaside_rcb.res_lock); \ RPC_COND_INIT (rpc_g_lookaside_rcb.wait_flg, \ rpc_g_lookaside_rcb.res_lock); \ } /***********************************************************************/ /* * R P C _ L I S T _ I N I T * * Initialize a list head. * * Sample usage: * * rpc_list_t list; * * RPC_LIST_INIT (list); */ #define RPC_LIST_INIT(list) \ { \ list.next = NULL; \ list.last = NULL; \ } /***********************************************************************/ /* * R P C _ L I S T _ E M P T Y * * Determine whether or not a list has any elements left. * * RETURNS: true - list has more elements * false - list has no more elements * * Sample usage: * * rpc_list_t list; * * if (RPC_LIST_EMPTY (list)) ... */ #define RPC_LIST_EMPTY(list) (list.next == NULL) /***********************************************************************/ /* * R P C _ L I S T _ A D D * * Insert an element after a specified entry in a list. * * Sample usage: * * rpc_list_t list; (listhead) * any_p_t list_element; (location to insert) * any_p_t insert_element; (element to be inserted) * * RPC_LIST_ADD (list, list_element, insert_element, any_p_t); */ #define RPC_LIST_ADD(list, list_element, insert_element, list_element_type) \ { \ ((rpc_list_p_t) (insert_element))->next = \ ((rpc_list_p_t) (list_element))->next; \ ((rpc_list_p_t) (insert_element))->last = (dce_pointer_t) (list_element); \ if (((rpc_list_p_t) (list_element))->next == NULL) \ { \ (list).last = (dce_pointer_t) (insert_element); \ } \ else \ { \ ((rpc_list_p_t) (((rpc_list_p_t) (list_element))->next))->last = \ (dce_pointer_t) (insert_element); \ } \ ((rpc_list_p_t) (list_element))->next = (dce_pointer_t) (insert_element); \ } /***********************************************************************/ /* * R P C _ L I S T _ A D D _ H E A D * * Add an entry to the beginning of a list. * * Sample usage: * * rpc_list_t list; * any_p_t list_element; * * RPC_LIST_ADD_HEAD (list, list_element, any_p_t); */ #define RPC_LIST_ADD_HEAD(list, list_element, list_element_type) \ { \ if (RPC_LIST_EMPTY (list)) \ { \ (list).next = (list).last = (dce_pointer_t) (list_element); \ ((rpc_list_p_t) (list_element))->next = NULL; \ ((rpc_list_p_t) (list_element))->last = (dce_pointer_t) &(list); \ } \ else \ { \ ((rpc_list_p_t) (list_element))->next = (dce_pointer_t) ((list).next); \ ((rpc_list_p_t) (list_element))->last = (dce_pointer_t) &(list); \ ((rpc_list_p_t)((list).next))->last = (dce_pointer_t) (list_element); \ (list).next = (dce_pointer_t) (list_element); \ } \ } /***********************************************************************/ /* * R P C _ L I S T _ A D D _ T A I L * * Add an entry to the end of a list. * * Sample usage: * * rpc_list_t list; * any_p_t list_element; * * RPC_LIST_ADD_TAIL (list, list_element, any_p_t); */ #define RPC_LIST_ADD_TAIL(list, list_element, list_element_type) \ { \ if (RPC_LIST_EMPTY (list)) \ { \ list.next = (dce_pointer_t) (list_element); \ ((rpc_list_p_t) (list_element))->last = (dce_pointer_t) &(list); \ } \ else \ { \ ((rpc_list_p_t) (list.last))->next = (dce_pointer_t) (list_element); \ ((rpc_list_p_t) (list_element))->last = list.last; \ } \ list.last = (dce_pointer_t) (list_element); \ ((rpc_list_p_t) (list_element))->next = NULL; \ } /***********************************************************************/ /* * R P C _ L I S T _ R E M O V E * * Remove an element (pointed to by list_element) from a list. * * Sample usage: * * rpc_list_t list; * any_p_t list_element; * * RPC_LIST_REMOVE (list, list_element); */ #define RPC_LIST_REMOVE(list, list_element) \ { \ if (list.last == list.next) \ { \ RPC_LIST_INIT (list); \ } \ else \ { \ if (((rpc_list_p_t) (list_element))->next == NULL) \ { \ list.last = ((rpc_list_p_t) (list_element))->last; \ } \ else \ { \ ((rpc_list_p_t) ((rpc_list_p_t) (list_element))->next)->last = \ ((rpc_list_p_t) (list_element))->last; \ } \ ((rpc_list_p_t) ((rpc_list_p_t) (list_element))->last)->next = \ ((rpc_list_p_t) (list_element))->next; \ } \ } /***********************************************************************/ /* * R P C _ L I S T _ R E M O V E _ H E A D * * Remove the first entry from a list and return it. If the list is * empty a NULL pointer is returned. Note: This is functionally * equivalent to doing RPC_LIST_EXTRACT (,,1), but is slightly more * efficient. * * Sample usage: * * rpc_list_t list; * any_p_t list_element; * * RPC_LIST_REMOVE_HEAD (list, list_element, any_p_t); */ #define RPC_LIST_REMOVE_HEAD(list, list_element, list_element_type) \ { \ if (RPC_LIST_EMPTY (list)) \ { \ list_element = NULL; \ } \ else \ { \ RPC_LIST_FIRST (list, list_element, list_element_type); \ RPC_LIST_REMOVE (list, list_element); \ } \ } /***********************************************************************/ /* * R P C _ L I S T _ R E M O V E _ T A I L * * Remove the last entry from a list and return it. If the list is * empty a NULL pointer is returned. * * Sample usage: * * rpc_list_t list; * any_p_t list_element; * * RPC_LIST_REMOVE_TAIL (list, list_element, any_p_t); */ #define RPC_LIST_REMOVE_TAIL(list, list_element, list_element_type) \ { \ if (RPC_LIST_EMPTY (list)) \ { \ list_element = NULL; \ } \ else \ { \ RPC_LIST_LAST (list, list_element, list_element_type); \ RPC_LIST_REMOVE (list, list_element); \ } \ } /***********************************************************************/ /* * R P C _ L I S T _ E X T R A C T * * Remove the nth entry on a list and return it. * If n exceeds the length of the list a NULL pointer is returned. * * Sample usage: * * rpc_list_t list; * any_p_t list_element; * * RPC_LIST_EXTRACT (list, list_element, any_p_t, n); */ #define RPC_LIST_EXTRACT(list, list_element, list_element_type, n) \ { \ RPC_LIST_LOOKUP (list, list_element, list_element_type, n); \ if (list_element != NULL) \ { \ RPC_LIST_REMOVE (list, list_element); \ } \ } /***********************************************************************/ /* * R P C _ L I S T _ F I R S T * * Returns the first element in a list (without removing it). * * Sample usage: * * rpc_list_t list; * any_p_t list_element; * * RPC_LIST_FIRST (list, list_element, any_p_t); */ #define RPC_LIST_FIRST(list, list_element, list_element_type) \ list_element = (list_element_type) (list.next); /***********************************************************************/ /* * R P C _ L I S T _ L A S T * * Return the last element in a list (without removing it). * * Sample usage: * * rpc_list_t list; * any_p_t list_element; * * RPC_LIST_LAST (list, list_element, any_p_t); */ #define RPC_LIST_LAST(list, list_element, list_element_type) \ list_element = (list_element_type) (list.last); /***********************************************************************/ /* * R P C _ L I S T _ N E X T * * Can be used iteratively to walk a list and read all entries. * When there are no more entries a NULL pointer is returned. * * Sample usage: * * any_p_t this_element; * any_p_t next_element; * * RPC_LIST_NEXT (this_element, next_element, any_p_t); */ #define RPC_LIST_NEXT(this_element, next_element, list_element_type) \ { \ if (((rpc_list_p_t) (this_element))->next == NULL) \ { \ next_element = NULL; \ } \ else \ { \ next_element = \ (list_element_type) (((rpc_list_p_t) (this_element))->next); \ } \ } /***********************************************************************/ /* * R P C _ L I S T _ L O O K U P * * Get the nth entry on a list (without removing it). * If n exceeds the length of the list a NULL pointer is returned. * * Sample usage: * * rpc_list_t list; * any_p_t list_element; * any_int n; * * RPC_LIST_LOOKUP (list, list_element, any_p_t, n); */ #define RPC_LIST_LOOKUP(list, list_element, list_element_type, n) \ { \ int _count; \ \ for (_count = (int) n, \ list_element = (list_element_type) (list.next); \ (_count > 1) && (list_element != NULL); \ list_element = \ (list_element_type) (((rpc_list_p_t) (list_element))->next), \ _count--); \ } /***********************************************************************/ /* * R P C _ L I S T _ C O U N T * * Return the number of entries on the list. * * Sample usage: * * rpc_list_t list; * unsigned32 count; * * RPC_LIST_COUNT (list, count); */ #define RPC_LIST_COUNT(list, count) \ { \ rpc_list_p_t _next_element;\ \ for (count = 0, _next_element = ((rpc_list_p_t)(list.next));\ _next_element != NULL;\ count++, _next_element = ((rpc_list_p_t)(_next_element->next)));\ } /***********************************************************************/ /* * R P C _ _ L I S T _ D E S C _ I N I T * */ PRIVATE void rpc__list_desc_init ( rpc_list_desc_p_t /*list_desc*/, unsigned32 /*max_size*/, unsigned32 /*element_size*/, unsigned32 /*element_type*/, rpc_list_element_alloc_fn_t /*alloc_rtn*/, rpc_list_element_free_fn_t /*free_rtn*/, rpc_mutex_p_t /*mutex*/, rpc_cond_p_t /*cond*/ ); /***********************************************************************/ /* * R P C _ _ L I S T _ E L E M E N T _ A L L O C * */ PRIVATE dce_pointer_t rpc__list_element_alloc ( rpc_list_desc_p_t /*list_desc*/, boolean32 /*block*/ ); /***********************************************************************/ /* * R P C _ _ L I S T _ E L E M E N T _ F R E E * */ PRIVATE void rpc__list_element_free ( rpc_list_desc_p_t /*list_desc*/, dce_pointer_t /*list_element*/ ); /***********************************************************************/ /* * R P C _ _ L I S T _ F O R K _ H A N D L E R * */ PRIVATE void rpc__list_fork_handler ( rpc_fork_stage_id_t /*stage*/ ); #endif /* _RPCLIST_H */