xref: /onnv-gate/usr/src/lib/libtecla/common/freelist.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright (c) 2000, 2001, 2002, 2003, 2004 by Martin C. Shepherd.
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * All rights reserved.
5*0Sstevel@tonic-gate  *
6*0Sstevel@tonic-gate  * Permission is hereby granted, free of charge, to any person obtaining a
7*0Sstevel@tonic-gate  * copy of this software and associated documentation files (the
8*0Sstevel@tonic-gate  * "Software"), to deal in the Software without restriction, including
9*0Sstevel@tonic-gate  * without limitation the rights to use, copy, modify, merge, publish,
10*0Sstevel@tonic-gate  * distribute, and/or sell copies of the Software, and to permit persons
11*0Sstevel@tonic-gate  * to whom the Software is furnished to do so, provided that the above
12*0Sstevel@tonic-gate  * copyright notice(s) and this permission notice appear in all copies of
13*0Sstevel@tonic-gate  * the Software and that both the above copyright notice(s) and this
14*0Sstevel@tonic-gate  * permission notice appear in supporting documentation.
15*0Sstevel@tonic-gate  *
16*0Sstevel@tonic-gate  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17*0Sstevel@tonic-gate  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*0Sstevel@tonic-gate  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
19*0Sstevel@tonic-gate  * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20*0Sstevel@tonic-gate  * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
21*0Sstevel@tonic-gate  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
22*0Sstevel@tonic-gate  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
23*0Sstevel@tonic-gate  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
24*0Sstevel@tonic-gate  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25*0Sstevel@tonic-gate  *
26*0Sstevel@tonic-gate  * Except as contained in this notice, the name of a copyright holder
27*0Sstevel@tonic-gate  * shall not be used in advertising or otherwise to promote the sale, use
28*0Sstevel@tonic-gate  * or other dealings in this Software without prior written authorization
29*0Sstevel@tonic-gate  * of the copyright holder.
30*0Sstevel@tonic-gate  */
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <stdio.h>
35*0Sstevel@tonic-gate #include <stdlib.h>
36*0Sstevel@tonic-gate #include <errno.h>
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate #include "freelist.h"
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate typedef struct FreeListBlock FreeListBlock;
41*0Sstevel@tonic-gate struct FreeListBlock {
42*0Sstevel@tonic-gate   FreeListBlock *next;   /* The next block in the list */
43*0Sstevel@tonic-gate   char *nodes;           /* The array of free-list nodes */
44*0Sstevel@tonic-gate };
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate struct FreeList {
47*0Sstevel@tonic-gate   size_t node_size;         /* The size of a free-list node */
48*0Sstevel@tonic-gate   unsigned blocking_factor; /* The number of nodes per block */
49*0Sstevel@tonic-gate   long nbusy;               /* The number of nodes that are in use */
50*0Sstevel@tonic-gate   long ntotal;              /* The total number of nodes in the free list */
51*0Sstevel@tonic-gate   FreeListBlock *block;     /* The head of the list of free-list blocks */
52*0Sstevel@tonic-gate   void *free_list;          /* The free-list of nodes */
53*0Sstevel@tonic-gate };
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate static FreeListBlock *_new_FreeListBlock(FreeList *fl);
56*0Sstevel@tonic-gate static FreeListBlock *_del_FreeListBlock(FreeListBlock *fl);
57*0Sstevel@tonic-gate static void _thread_FreeListBlock(FreeList *fl, FreeListBlock *block);
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate /*.......................................................................
60*0Sstevel@tonic-gate  * Allocate a new free-list from blocks of 'blocking_factor' objects of size
61*0Sstevel@tonic-gate  * node_size.
62*0Sstevel@tonic-gate  *
63*0Sstevel@tonic-gate  * Input:
64*0Sstevel@tonic-gate  *  node_size         size_t    The size of the free-list nodes to be returned
65*0Sstevel@tonic-gate  *                              by _new_FreeListNode(). Use sizeof() to
66*0Sstevel@tonic-gate  *                              determine this.
67*0Sstevel@tonic-gate  *  blocking_factor unsigned    The number of objects of size 'object_size'
68*0Sstevel@tonic-gate  *                              to allocate per block.
69*0Sstevel@tonic-gate  * Output:
70*0Sstevel@tonic-gate  *  return          FreeList *  The new freelist, or NULL on error.
71*0Sstevel@tonic-gate  */
_new_FreeList(size_t node_size,unsigned blocking_factor)72*0Sstevel@tonic-gate FreeList *_new_FreeList(size_t node_size, unsigned blocking_factor)
73*0Sstevel@tonic-gate {
74*0Sstevel@tonic-gate   FreeList *fl;  /* The new free-list container */
75*0Sstevel@tonic-gate /*
76*0Sstevel@tonic-gate  * When a free-list node is on the free-list, it is used as a (void *)
77*0Sstevel@tonic-gate  * link field. Roundup node_size to a mulitple of the size of a void
78*0Sstevel@tonic-gate  * pointer. This, plus the fact that the array of nodes is obtained via
79*0Sstevel@tonic-gate  * malloc, which returns memory suitably aligned for any object, will
80*0Sstevel@tonic-gate  * ensure that the first sizeof(void *) bytes of each node will be
81*0Sstevel@tonic-gate  * suitably aligned to use as a (void *) link pointer.
82*0Sstevel@tonic-gate  */
83*0Sstevel@tonic-gate   node_size = sizeof(void *) *
84*0Sstevel@tonic-gate     ((node_size + sizeof(void *) - 1) / sizeof(void *));
85*0Sstevel@tonic-gate /*
86*0Sstevel@tonic-gate  * Enfore a minimum block size.
87*0Sstevel@tonic-gate  */
88*0Sstevel@tonic-gate   if(blocking_factor < 1)
89*0Sstevel@tonic-gate     blocking_factor = 1;
90*0Sstevel@tonic-gate /*
91*0Sstevel@tonic-gate  * Allocate the container of the free list.
92*0Sstevel@tonic-gate  */
93*0Sstevel@tonic-gate   fl = (FreeList *) malloc(sizeof(FreeList));
94*0Sstevel@tonic-gate   if(!fl) {
95*0Sstevel@tonic-gate     errno = ENOMEM;
96*0Sstevel@tonic-gate     return NULL;
97*0Sstevel@tonic-gate   };
98*0Sstevel@tonic-gate /*
99*0Sstevel@tonic-gate  * Before attempting any operation that might fail, initialize the
100*0Sstevel@tonic-gate  * container at least up to the point at which it can safely be passed
101*0Sstevel@tonic-gate  * to _del_FreeList().
102*0Sstevel@tonic-gate  */
103*0Sstevel@tonic-gate   fl->node_size = node_size;
104*0Sstevel@tonic-gate   fl->blocking_factor = blocking_factor;
105*0Sstevel@tonic-gate   fl->nbusy = 0;
106*0Sstevel@tonic-gate   fl->ntotal = 0;
107*0Sstevel@tonic-gate   fl->block = NULL;
108*0Sstevel@tonic-gate   fl->free_list = NULL;
109*0Sstevel@tonic-gate /*
110*0Sstevel@tonic-gate  * Allocate the first block of memory.
111*0Sstevel@tonic-gate  */
112*0Sstevel@tonic-gate   fl->block = _new_FreeListBlock(fl);
113*0Sstevel@tonic-gate   if(!fl->block) {
114*0Sstevel@tonic-gate     errno = ENOMEM;
115*0Sstevel@tonic-gate     return _del_FreeList(fl, 1);
116*0Sstevel@tonic-gate   };
117*0Sstevel@tonic-gate /*
118*0Sstevel@tonic-gate  * Add the new list of nodes to the free-list.
119*0Sstevel@tonic-gate  */
120*0Sstevel@tonic-gate   fl->free_list = fl->block->nodes;
121*0Sstevel@tonic-gate /*
122*0Sstevel@tonic-gate  * Return the free-list for use.
123*0Sstevel@tonic-gate  */
124*0Sstevel@tonic-gate   return fl;
125*0Sstevel@tonic-gate }
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate /*.......................................................................
128*0Sstevel@tonic-gate  * Re-thread a freelist to reclaim all allocated nodes.
129*0Sstevel@tonic-gate  * This function should not be called unless if it is known that none
130*0Sstevel@tonic-gate  * of the currently allocated nodes are still being used.
131*0Sstevel@tonic-gate  *
132*0Sstevel@tonic-gate  * Input:
133*0Sstevel@tonic-gate  *  fl          FreeList *  The free-list to be reset, or NULL.
134*0Sstevel@tonic-gate  */
_rst_FreeList(FreeList * fl)135*0Sstevel@tonic-gate void _rst_FreeList(FreeList *fl)
136*0Sstevel@tonic-gate {
137*0Sstevel@tonic-gate   if(fl) {
138*0Sstevel@tonic-gate     FreeListBlock *block;
139*0Sstevel@tonic-gate /*
140*0Sstevel@tonic-gate  * Re-thread the nodes of each block into individual free-lists.
141*0Sstevel@tonic-gate  */
142*0Sstevel@tonic-gate     for(block=fl->block; block; block=block->next)
143*0Sstevel@tonic-gate       _thread_FreeListBlock(fl, block);
144*0Sstevel@tonic-gate /*
145*0Sstevel@tonic-gate  * Link all of the block freelists into one large freelist.
146*0Sstevel@tonic-gate  */
147*0Sstevel@tonic-gate     fl->free_list = NULL;
148*0Sstevel@tonic-gate     for(block=fl->block; block; block=block->next) {
149*0Sstevel@tonic-gate /*
150*0Sstevel@tonic-gate  * Locate the last node of the current block.
151*0Sstevel@tonic-gate  */
152*0Sstevel@tonic-gate       char *last_node = block->nodes + fl->node_size *
153*0Sstevel@tonic-gate 	(fl->blocking_factor - 1);
154*0Sstevel@tonic-gate /*
155*0Sstevel@tonic-gate  * Make the link-field of the last node point to the first
156*0Sstevel@tonic-gate  * node of the current freelist, then make the first node of the
157*0Sstevel@tonic-gate  * new block the start of the freelist.
158*0Sstevel@tonic-gate  */
159*0Sstevel@tonic-gate       *(void **)last_node = fl->free_list;
160*0Sstevel@tonic-gate       fl->free_list = block->nodes;
161*0Sstevel@tonic-gate     };
162*0Sstevel@tonic-gate /*
163*0Sstevel@tonic-gate  * All allocated nodes have now been returned to the freelist.
164*0Sstevel@tonic-gate  */
165*0Sstevel@tonic-gate     fl->nbusy = 0;
166*0Sstevel@tonic-gate   };
167*0Sstevel@tonic-gate }
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate /*.......................................................................
170*0Sstevel@tonic-gate  * Delete a free-list.
171*0Sstevel@tonic-gate  *
172*0Sstevel@tonic-gate  * Input:
173*0Sstevel@tonic-gate  *  fl          FreeList *  The free-list to be deleted, or NULL.
174*0Sstevel@tonic-gate  *  force            int    If force==0 then _del_FreeList() will complain
175*0Sstevel@tonic-gate  *                           and refuse to delete the free-list if any
176*0Sstevel@tonic-gate  *                           of nodes have not been returned to the free-list.
177*0Sstevel@tonic-gate  *                          If force!=0 then _del_FreeList() will not check
178*0Sstevel@tonic-gate  *                           whether any nodes are still in use and will
179*0Sstevel@tonic-gate  *                           always delete the list.
180*0Sstevel@tonic-gate  * Output:
181*0Sstevel@tonic-gate  *  return      FreeList *  Always NULL (even if the list couldn't be
182*0Sstevel@tonic-gate  *                          deleted).
183*0Sstevel@tonic-gate  */
_del_FreeList(FreeList * fl,int force)184*0Sstevel@tonic-gate FreeList *_del_FreeList(FreeList *fl, int force)
185*0Sstevel@tonic-gate {
186*0Sstevel@tonic-gate   if(fl) {
187*0Sstevel@tonic-gate /*
188*0Sstevel@tonic-gate  * Check whether any nodes are in use.
189*0Sstevel@tonic-gate  */
190*0Sstevel@tonic-gate     if(!force && _busy_FreeListNodes(fl) != 0) {
191*0Sstevel@tonic-gate       errno = EBUSY;
192*0Sstevel@tonic-gate       return NULL;
193*0Sstevel@tonic-gate     };
194*0Sstevel@tonic-gate /*
195*0Sstevel@tonic-gate  * Delete the list blocks.
196*0Sstevel@tonic-gate  */
197*0Sstevel@tonic-gate     {
198*0Sstevel@tonic-gate       FreeListBlock *next = fl->block;
199*0Sstevel@tonic-gate       while(next) {
200*0Sstevel@tonic-gate 	FreeListBlock *block = next;
201*0Sstevel@tonic-gate 	next = block->next;
202*0Sstevel@tonic-gate 	block = _del_FreeListBlock(block);
203*0Sstevel@tonic-gate       };
204*0Sstevel@tonic-gate     };
205*0Sstevel@tonic-gate     fl->block = NULL;
206*0Sstevel@tonic-gate     fl->free_list = NULL;
207*0Sstevel@tonic-gate /*
208*0Sstevel@tonic-gate  * Discard the container.
209*0Sstevel@tonic-gate  */
210*0Sstevel@tonic-gate     free(fl);
211*0Sstevel@tonic-gate   };
212*0Sstevel@tonic-gate   return NULL;
213*0Sstevel@tonic-gate }
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate /*.......................................................................
216*0Sstevel@tonic-gate  * Allocate a new object from a free-list.
217*0Sstevel@tonic-gate  *
218*0Sstevel@tonic-gate  * Input:
219*0Sstevel@tonic-gate  *  fl        FreeList *  The free-list to return an object from.
220*0Sstevel@tonic-gate  * Output:
221*0Sstevel@tonic-gate  *  return        void *  A new object of the size that was specified via
222*0Sstevel@tonic-gate  *                        the node_size argument of _new_FreeList() when
223*0Sstevel@tonic-gate  *                        the free-list was created, or NULL if there
224*0Sstevel@tonic-gate  *                        is insufficient memory, or 'fl' is NULL.
225*0Sstevel@tonic-gate  */
_new_FreeListNode(FreeList * fl)226*0Sstevel@tonic-gate void *_new_FreeListNode(FreeList *fl)
227*0Sstevel@tonic-gate {
228*0Sstevel@tonic-gate   void *node;  /* The node to be returned */
229*0Sstevel@tonic-gate /*
230*0Sstevel@tonic-gate  * Check arguments.
231*0Sstevel@tonic-gate  */
232*0Sstevel@tonic-gate   if(!fl)
233*0Sstevel@tonic-gate     return NULL;
234*0Sstevel@tonic-gate /*
235*0Sstevel@tonic-gate  * If the free-list has been exhausted extend it by allocating
236*0Sstevel@tonic-gate  * another block of nodes.
237*0Sstevel@tonic-gate  */
238*0Sstevel@tonic-gate   if(!fl->free_list) {
239*0Sstevel@tonic-gate     FreeListBlock *block = _new_FreeListBlock(fl);
240*0Sstevel@tonic-gate     if(!block)
241*0Sstevel@tonic-gate       return NULL;
242*0Sstevel@tonic-gate /*
243*0Sstevel@tonic-gate  * Prepend the new block to the list of free-list blocks.
244*0Sstevel@tonic-gate  */
245*0Sstevel@tonic-gate     block->next = fl->block;
246*0Sstevel@tonic-gate     fl->block = block;
247*0Sstevel@tonic-gate /*
248*0Sstevel@tonic-gate  * Add the new list of nodes to the free-list.
249*0Sstevel@tonic-gate  */
250*0Sstevel@tonic-gate     fl->free_list = fl->block->nodes;
251*0Sstevel@tonic-gate   };
252*0Sstevel@tonic-gate /*
253*0Sstevel@tonic-gate  * Remove and return a node from the front of the free list.
254*0Sstevel@tonic-gate  */
255*0Sstevel@tonic-gate   node = fl->free_list;
256*0Sstevel@tonic-gate   fl->free_list = *(void **)node;
257*0Sstevel@tonic-gate /*
258*0Sstevel@tonic-gate  * Record the loss of a node from the free-list.
259*0Sstevel@tonic-gate  */
260*0Sstevel@tonic-gate   fl->nbusy++;
261*0Sstevel@tonic-gate /*
262*0Sstevel@tonic-gate  * Return the node.
263*0Sstevel@tonic-gate  */
264*0Sstevel@tonic-gate   return node;
265*0Sstevel@tonic-gate }
266*0Sstevel@tonic-gate 
267*0Sstevel@tonic-gate /*.......................................................................
268*0Sstevel@tonic-gate  * Return an object to the free-list that it was allocated from.
269*0Sstevel@tonic-gate  *
270*0Sstevel@tonic-gate  * Input:
271*0Sstevel@tonic-gate  *  fl        FreeList *  The free-list from which the object was taken.
272*0Sstevel@tonic-gate  *  object        void *  The node to be returned.
273*0Sstevel@tonic-gate  * Output:
274*0Sstevel@tonic-gate  *  return        void *  Always NULL.
275*0Sstevel@tonic-gate  */
_del_FreeListNode(FreeList * fl,void * object)276*0Sstevel@tonic-gate void *_del_FreeListNode(FreeList *fl, void *object)
277*0Sstevel@tonic-gate {
278*0Sstevel@tonic-gate /*
279*0Sstevel@tonic-gate  * Check arguments.
280*0Sstevel@tonic-gate  */
281*0Sstevel@tonic-gate   if(!fl)
282*0Sstevel@tonic-gate     return NULL;
283*0Sstevel@tonic-gate /*
284*0Sstevel@tonic-gate  * Return the node to the head of the free list.
285*0Sstevel@tonic-gate  */
286*0Sstevel@tonic-gate   if(object) {
287*0Sstevel@tonic-gate     *(void **)object = fl->free_list;
288*0Sstevel@tonic-gate     fl->free_list = object;
289*0Sstevel@tonic-gate /*
290*0Sstevel@tonic-gate  * Record the return of the node to the free-list.
291*0Sstevel@tonic-gate  */
292*0Sstevel@tonic-gate     fl->nbusy--;
293*0Sstevel@tonic-gate   };
294*0Sstevel@tonic-gate   return NULL;
295*0Sstevel@tonic-gate }
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate /*.......................................................................
298*0Sstevel@tonic-gate  * Return a count of the number of nodes that are currently allocated.
299*0Sstevel@tonic-gate  *
300*0Sstevel@tonic-gate  * Input:
301*0Sstevel@tonic-gate  *  fl      FreeList *  The list to count wrt, or NULL.
302*0Sstevel@tonic-gate  * Output:
303*0Sstevel@tonic-gate  *  return      long    The number of nodes (or 0 if fl==NULL).
304*0Sstevel@tonic-gate  */
_busy_FreeListNodes(FreeList * fl)305*0Sstevel@tonic-gate long _busy_FreeListNodes(FreeList *fl)
306*0Sstevel@tonic-gate {
307*0Sstevel@tonic-gate   return fl ? fl->nbusy : 0;
308*0Sstevel@tonic-gate }
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate /*.......................................................................
311*0Sstevel@tonic-gate  * Query the number of allocated nodes in the freelist which are
312*0Sstevel@tonic-gate  * currently unused.
313*0Sstevel@tonic-gate  *
314*0Sstevel@tonic-gate  * Input:
315*0Sstevel@tonic-gate  *  fl      FreeList *  The list to count wrt, or NULL.
316*0Sstevel@tonic-gate  * Output:
317*0Sstevel@tonic-gate  *  return      long    The number of unused nodes (or 0 if fl==NULL).
318*0Sstevel@tonic-gate  */
_idle_FreeListNodes(FreeList * fl)319*0Sstevel@tonic-gate long _idle_FreeListNodes(FreeList *fl)
320*0Sstevel@tonic-gate {
321*0Sstevel@tonic-gate   return fl ? (fl->ntotal - fl->nbusy) : 0;
322*0Sstevel@tonic-gate }
323*0Sstevel@tonic-gate 
324*0Sstevel@tonic-gate /*.......................................................................
325*0Sstevel@tonic-gate  * Allocate a new list of free-list nodes. On return the nodes will
326*0Sstevel@tonic-gate  * be linked together as a list starting with the node at the lowest
327*0Sstevel@tonic-gate  * address and ending with a NULL next pointer.
328*0Sstevel@tonic-gate  *
329*0Sstevel@tonic-gate  * Input:
330*0Sstevel@tonic-gate  *  fl          FreeList *  The free-list to allocate the list for.
331*0Sstevel@tonic-gate  * Output:
332*0Sstevel@tonic-gate  *  return FreeListBlock *  The new linked block of free-list nodes,
333*0Sstevel@tonic-gate  *                          or NULL on error.
334*0Sstevel@tonic-gate  */
_new_FreeListBlock(FreeList * fl)335*0Sstevel@tonic-gate static FreeListBlock *_new_FreeListBlock(FreeList *fl)
336*0Sstevel@tonic-gate {
337*0Sstevel@tonic-gate   FreeListBlock *block;  /* The new block to be returned */
338*0Sstevel@tonic-gate /*
339*0Sstevel@tonic-gate  * Allocate the container.
340*0Sstevel@tonic-gate  */
341*0Sstevel@tonic-gate   block = (FreeListBlock *) malloc(sizeof(FreeListBlock));
342*0Sstevel@tonic-gate   if(!block)
343*0Sstevel@tonic-gate     return NULL;
344*0Sstevel@tonic-gate /*
345*0Sstevel@tonic-gate  * Before attempting any operation that might fail, initialize the
346*0Sstevel@tonic-gate  * container at least up to the point at which it can safely be passed
347*0Sstevel@tonic-gate  * to _del_FreeListBlock().
348*0Sstevel@tonic-gate  */
349*0Sstevel@tonic-gate   block->next = NULL;
350*0Sstevel@tonic-gate   block->nodes = NULL;
351*0Sstevel@tonic-gate /*
352*0Sstevel@tonic-gate  * Allocate the block of nodes.
353*0Sstevel@tonic-gate  */
354*0Sstevel@tonic-gate   block->nodes = (char *) malloc(fl->node_size * fl->blocking_factor);
355*0Sstevel@tonic-gate   if(!block->nodes)
356*0Sstevel@tonic-gate     return _del_FreeListBlock(block);
357*0Sstevel@tonic-gate /*
358*0Sstevel@tonic-gate  * Initialize the block as a linked list of FreeListNode's.
359*0Sstevel@tonic-gate  */
360*0Sstevel@tonic-gate   _thread_FreeListBlock(fl, block);
361*0Sstevel@tonic-gate /*
362*0Sstevel@tonic-gate  * Update the record of the number of nodes in the freelist.
363*0Sstevel@tonic-gate  */
364*0Sstevel@tonic-gate   fl->ntotal += fl->blocking_factor;
365*0Sstevel@tonic-gate   return block;
366*0Sstevel@tonic-gate }
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate /*.......................................................................
369*0Sstevel@tonic-gate  * Link each node of a freelist block to the node that follows it.
370*0Sstevel@tonic-gate  *
371*0Sstevel@tonic-gate  * Input:
372*0Sstevel@tonic-gate  *  fl         FreeList *   The freelist that contains the block.
373*0Sstevel@tonic-gate  *  block FreeListBlock *   The block to be threaded.
374*0Sstevel@tonic-gate  */
_thread_FreeListBlock(FreeList * fl,FreeListBlock * block)375*0Sstevel@tonic-gate static void _thread_FreeListBlock(FreeList *fl, FreeListBlock *block)
376*0Sstevel@tonic-gate {
377*0Sstevel@tonic-gate   char *mem = block->nodes;
378*0Sstevel@tonic-gate   int i;
379*0Sstevel@tonic-gate   for(i=0; i<fl->blocking_factor - 1; i++, mem += fl->node_size)
380*0Sstevel@tonic-gate     *(void **)mem = mem + fl->node_size;  /* Link to the next node */
381*0Sstevel@tonic-gate   *(void **)mem = NULL;                   /* Terminate the list */
382*0Sstevel@tonic-gate }
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate /*.......................................................................
385*0Sstevel@tonic-gate  * Delete a free-list block.
386*0Sstevel@tonic-gate  *
387*0Sstevel@tonic-gate  * Input:
388*0Sstevel@tonic-gate  *  fl      FreeListBlock *  The block to be deleted, or NULL.
389*0Sstevel@tonic-gate  * Output:
390*0Sstevel@tonic-gate  *  return  FreeListBlock *  Always NULL.
391*0Sstevel@tonic-gate  */
_del_FreeListBlock(FreeListBlock * fl)392*0Sstevel@tonic-gate static FreeListBlock *_del_FreeListBlock(FreeListBlock *fl)
393*0Sstevel@tonic-gate {
394*0Sstevel@tonic-gate   if(fl) {
395*0Sstevel@tonic-gate     fl->next = NULL;
396*0Sstevel@tonic-gate     if(fl->nodes)
397*0Sstevel@tonic-gate       free(fl->nodes);
398*0Sstevel@tonic-gate     fl->nodes = NULL;
399*0Sstevel@tonic-gate     free(fl);
400*0Sstevel@tonic-gate   };
401*0Sstevel@tonic-gate   return NULL;
402*0Sstevel@tonic-gate }
403