~n-muench/ubuntu/quantal/open-vm-tools/open-vm-tools.may2.sid-sync

« back to all changes in this revision

Viewing changes to lib/include/circList.h

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-05-30 09:48:43 UTC
  • mfrom: (1.1.5 upstream) (2.4.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090530094843-gdpza57r5iqsf124
Tags: 2009.05.22-167859-1
MergingĀ upstreamĀ versionĀ 2009.05.22-167859.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 1998 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License as published
 
6
 * by the Free Software Foundation version 2.1 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
 
11
 * License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/*
 
20
 *   circList.h --
 
21
 *
 
22
 * macros, prototypes and struct definitions for double-linked
 
23
 * circular lists.
 
24
 */
 
25
 
 
26
#ifndef _CIRCLIST_H_
 
27
#define _CIRCLIST_H_
 
28
 
 
29
#define INCLUDE_ALLOW_USERLEVEL
 
30
#define INCLUDE_ALLOW_VMMON
 
31
#define INCLUDE_ALLOW_VMCORE
 
32
#define INCLUDE_ALLOW_MODULE
 
33
#define INCLUDE_ALLOW_VMKERNEL
 
34
#include "includeCheck.h"
 
35
#include "vmware.h"
 
36
 
 
37
typedef struct ListItem {
 
38
   struct ListItem *prev;
 
39
   struct ListItem *next;
 
40
} ListItem;
 
41
 
 
42
/* A list with no elements is a null pointer. */
 
43
#define   LIST_ITEM_DEF(name)   \
 
44
   ListItem * name = NULL
 
45
 
 
46
#define   LIST_EMPTY(l)      ((l) == NULL)
 
47
 
 
48
/* initialize list item */
 
49
#define   INIT_LIST_ITEM(p)   \
 
50
   do {   \
 
51
      (p)->prev = (p)->next = (p);   \
 
52
   } while (0)
 
53
 
 
54
/* check if initialized */
 
55
#define   IS_LIST_ITEM_INITIALIZED(li)   \
 
56
   (((li) == (li)->prev) && ((li) == (li)->next))
 
57
 
 
58
/* return first element in the list */
 
59
#define   LIST_FIRST(l)      (l)
 
60
#define   LIST_FIRST_CHK(l)   (l)
 
61
 
 
62
/* return last element in the list */
 
63
#define   LIST_LAST(l)      ((l)->prev)
 
64
#define   LIST_LAST_CHK(l)   (LIST_EMPTY(l) ? NULL : LIST_LAST(l))
 
65
 
 
66
/*
 
67
 * LIST_CONTAINER - get the struct for this entry (like list_entry)
 
68
 * @ptr: the &struct ListItem pointer.
 
69
 * @type:   the type of the struct this is embedded in.
 
70
 * @member: the name of the list struct within the struct.
 
71
 */
 
72
#define LIST_CONTAINER(ptr, type, member) \
 
73
   ((type *)((char *)(ptr) - offsetof(type, member)))
 
74
 
 
75
/*
 
76
 * delete item from the list
 
77
 */
 
78
#define   LIST_DEL            DelListItem   
 
79
 
 
80
/*
 
81
 * link two lists together
 
82
 */
 
83
#define   LIST_SPLICE         SpliceLists
 
84
 
 
85
/*
 
86
 * Split a list into two lists
 
87
 */
 
88
#define   LIST_SPLIT          SplitLists
 
89
 
 
90
/*
 
91
 * Add item to front of stack. List pointer points to new head.
 
92
 */
 
93
#define   LIST_PUSH           PushListItem
 
94
 
 
95
/*
 
96
 * Add item at back of queue. List pointer only changes if list was empty.
 
97
 */
 
98
#define   LIST_QUEUE          QueueListItem
 
99
 
 
100
/*
 
101
 * Get the list size.
 
102
 */
 
103
#define   LIST_SIZE           GetListSize
 
104
 
 
105
/*
 
106
 * LIST_SCAN_FROM scans the list from "from" up until "until".
 
107
 * The loop variable p should not be destroyed in the process.
 
108
 * "from" is an element in the list where to start scanning.
 
109
 * "until" is the element where search should stop.
 
110
 * member is the field to use for the search - either "next" or "prev".
 
111
 */
 
112
#define   LIST_SCAN_FROM(p, from, until, member)   \
 
113
   for (p = (from); (p) != NULL;   \
 
114
      (p) = (((p)->member == (until)) ? NULL : (p)->member))
 
115
 
 
116
/* scan the entire list (non-destructively) */ 
 
117
#define   LIST_SCAN(p, l)   \
 
118
   LIST_SCAN_FROM(p, LIST_FIRST(l), LIST_FIRST(l), next)
 
119
 
 
120
 
 
121
/* scan a list backward from last element to first (non-destructively) */
 
122
#define   LIST_SCAN_BACK(p, l)   \
 
123
   LIST_SCAN_FROM(p, LIST_LAST_CHK(l), LIST_LAST(l), prev)
 
124
 
 
125
/* scan the entire list where loop element may be destroyed */
 
126
#define   LIST_SCAN_SAFE(p, pn, l)   \
 
127
   if (!LIST_EMPTY(l))  \
 
128
      for (p = (l), (pn) = NextListItem(p, l); (p) != NULL;   \
 
129
           (p) = (pn), (pn) = NextListItem(p, l))
 
130
 
 
131
/* scan the entire list backwards where loop element may be destroyed */
 
132
#define   LIST_SCAN_BACK_SAFE(p, pn, l)   \
 
133
   if (!LIST_EMPTY(l))  \
 
134
      for (p = LIST_LAST(l), (pn) = PrevListItem(p, l); (p) != NULL;   \
 
135
           (p) = (pn), (pn) = PrevListItem(p, l))
 
136
 
 
137
 
 
138
/* function definitions */
 
139
 
 
140
/*
 
141
 *----------------------------------------------------------------------
 
142
 *
 
143
 * NextListItem --
 
144
 *
 
145
 *      Returns the next member of a doubly linked list, or NULL if last.
 
146
 *      Assumes: p is member of the list headed by head.
 
147
 *
 
148
 * Result
 
149
 *      If head or p is NULL, return NULL. Otherwise,
 
150
 *      next list member (or null if last).
 
151
 *
 
152
 * Side effects:
 
153
 *      None.
 
154
 *
 
155
 *----------------------------------------------------------------------
 
156
 */
 
157
 
 
158
static INLINE ListItem *
 
159
NextListItem(ListItem *p,        // IN
 
160
             ListItem *head)     // IN
 
161
{
 
162
   if (head == NULL || p == NULL) {
 
163
      return NULL;
 
164
   }
 
165
   /* both p and head are non-null */
 
166
   p = p->next;
 
167
   return p == head ? NULL : p;
 
168
}
 
169
 
 
170
 
 
171
/*
 
172
 *----------------------------------------------------------------------
 
173
 *
 
174
 * PrevListItem --
 
175
 *
 
176
 *      Returns the prev member of a doubly linked list, or NULL if first.
 
177
 *      Assumes: p is member of the list headed by head.
 
178
 *
 
179
 * Result
 
180
 *      If head or prev is NULL, return NULL. Otherwise,
 
181
 *      prev list member (or null if first).
 
182
 *
 
183
 * Side effects:
 
184
 *      None.
 
185
 *
 
186
 *----------------------------------------------------------------------
 
187
 */
 
188
 
 
189
static INLINE ListItem *
 
190
PrevListItem(ListItem *p,        // IN
 
191
             ListItem *head)     // IN
 
192
{
 
193
   if (head == NULL || p == NULL) {
 
194
      return NULL;
 
195
   }
 
196
   /* both p and head are non-null */
 
197
   return p == head ? NULL : p->prev;
 
198
}
 
199
 
 
200
 
 
201
/*
 
202
 *----------------------------------------------------------------------
 
203
 *
 
204
 * DelListItem --
 
205
 *
 
206
 *      Deletes a member of a doubly linked list, possibly modifies the
 
207
 *      list header itself.
 
208
 *      Assumes neither p nor headp is null and p is a member of *headp.
 
209
 *
 
210
 * Result
 
211
 *      None
 
212
 *
 
213
 * Side effects:
 
214
 *      Modifies *headp.
 
215
 *
 
216
 *----------------------------------------------------------------------
 
217
 */
 
218
 
 
219
static INLINE void
 
220
DelListItem(ListItem *p,         // IN
 
221
            ListItem **headp)    // IN/OUT
 
222
{
 
223
   ListItem *next;
 
224
 
 
225
   ASSERT(p);
 
226
   ASSERT(headp);
 
227
 
 
228
   next = p->next;
 
229
   if (p == next) {
 
230
      *headp = NULL;
 
231
   } else {
 
232
      next->prev = p->prev;
 
233
      p->prev->next = next;
 
234
      if (*headp == p) {
 
235
         *headp = next;
 
236
      }
 
237
   }
 
238
}
 
239
 
 
240
 
 
241
/*
 
242
 *----------------------------------------------------------------------
 
243
 *
 
244
 * QueueListItem --
 
245
 *
 
246
 *      Adds a new member to the back of a doubly linked list (queue)
 
247
 *      Assumes neither p nor headp is null and p is not a member of *headp.
 
248
 *
 
249
 * Result
 
250
 *      None
 
251
 *
 
252
 * Side effects:
 
253
 *      Modifies *headp.
 
254
 *
 
255
 *----------------------------------------------------------------------
 
256
 */
 
257
 
 
258
static INLINE void
 
259
QueueListItem(ListItem *p,              // IN
 
260
              ListItem **headp)         // IN/OUT
 
261
{
 
262
   ListItem *head;
 
263
 
 
264
   head = *headp;
 
265
   if (LIST_EMPTY(head)) {
 
266
      INIT_LIST_ITEM(p);
 
267
      *headp = p;
 
268
   } else {
 
269
      p->prev = head->prev;
 
270
      p->next = head;
 
271
      p->prev->next = p;
 
272
      head->prev = p;
 
273
   }
 
274
}
 
275
                                                                                
 
276
 
 
277
/*
 
278
 *----------------------------------------------------------------------
 
279
 *
 
280
 * PushListItem --
 
281
 *
 
282
 *      Adds a new member to the front of a doubly linked list (stack)
 
283
 *      Assumes neither p nor headp is null and p is not a member of *headp.
 
284
 *
 
285
 * Result
 
286
 *      None
 
287
 *
 
288
 * Side effects:
 
289
 *      Modifies *headp.
 
290
 *
 
291
 *----------------------------------------------------------------------
 
292
 */
 
293
 
 
294
static INLINE void
 
295
PushListItem(ListItem *p,               // IN
 
296
             ListItem **headp)          // IN/OUT
 
297
{
 
298
   QueueListItem(p, headp);
 
299
   *headp = p;
 
300
}
 
301
 
 
302
 
 
303
/*
 
304
 *----------------------------------------------------------------------
 
305
 *
 
306
 * SpliceLists --
 
307
 *
 
308
 *      Make a single list {l1 l2} from {l1} and {l2} and return it.
 
309
 *      It is okay for one or both lists to be NULL.
 
310
 *      No checking is done. It is assumed that l1 and l2 are two
 
311
 *      distinct lists.
 
312
 *
 
313
 * Result
 
314
 *      A list { l1 l2 }.
 
315
 *
 
316
 * Side effects:
 
317
 *      Modifies l1 and l2 list pointers.
 
318
 *
 
319
 *----------------------------------------------------------------------
 
320
 */
 
321
 
 
322
static INLINE ListItem *
 
323
SpliceLists(ListItem *l1,      // IN
 
324
            ListItem *l2)      // IN
 
325
{
 
326
   ListItem *l1Last, *l2Last;
 
327
 
 
328
   if (LIST_EMPTY(l1)) {
 
329
      return l2;
 
330
   }
 
331
 
 
332
   if (LIST_EMPTY(l2)) {
 
333
      return l1;
 
334
   }
 
335
 
 
336
   l1Last = l1->prev;   /* last elem of l1 */
 
337
   l2Last = l2->prev;   /* last elem of l2 */
 
338
 
 
339
   /*
 
340
    *    l1 -> ... -> l1Last    l2 -> ... l2Last
 
341
    */
 
342
   l1Last->next = l2;
 
343
   l2->prev = l1Last;
 
344
 
 
345
   l1->prev = l2Last;
 
346
   l2Last->next = l1;
 
347
 
 
348
   return l1;
 
349
}
 
350
 
 
351
 
 
352
/*
 
353
 *----------------------------------------------------------------------
 
354
 *
 
355
 * SplitLists --
 
356
 *
 
357
 *      Make a list l = {l1 l2} into two separate lists {l1} and {l2}, where:
 
358
 *      l = { ... x -> p -> ... } split into:
 
359
 *      l1 = { ... -> x }
 
360
 *      l2 = { p -> ... } 
 
361
 *      Assumes neither p nor l is null and p is a member of l.
 
362
 *      If p is the first element of l, then l1 will be NULL.
 
363
 *
 
364
 * Result
 
365
 *      None.
 
366
 *
 
367
 * Side effects:
 
368
 *      Sets *l1p and *l2p to the resulting two lists.
 
369
 *      Modifies l's pointers.
 
370
 *
 
371
 *----------------------------------------------------------------------
 
372
 */
 
373
 
 
374
static INLINE void
 
375
SplitLists(ListItem *p,         // IN
 
376
           ListItem *l,         // IN
 
377
           ListItem **l1p,      // OUT
 
378
           ListItem **l2p)      // OUT
 
379
{
 
380
   ListItem *last;
 
381
 
 
382
   if (p == LIST_FIRST(l)) {   /* first element */
 
383
      *l1p = NULL;
 
384
      *l2p = l;
 
385
      return;
 
386
   }
 
387
 
 
388
   last = l->prev;
 
389
 
 
390
   *l1p = l;
 
391
   p->prev->next = l;
 
392
   l->prev = p->prev;
 
393
 
 
394
   *l2p = p;
 
395
   p->prev = last;
 
396
   last->next = p;
 
397
}
 
398
 
 
399
 
 
400
/*
 
401
 *----------------------------------------------------------------------
 
402
 *
 
403
 * GetListSize --
 
404
 *
 
405
 *      Return the number of items in the list.
 
406
 *
 
407
 * Result:
 
408
 *      The number of items in the list.
 
409
 *
 
410
 * Side effects:
 
411
 *      None.
 
412
 *
 
413
 *----------------------------------------------------------------------
 
414
 */
 
415
 
 
416
static INLINE int
 
417
GetListSize(ListItem *head)     // IN
 
418
{
 
419
   ListItem *li;
 
420
   int ret = 0;
 
421
 
 
422
   LIST_SCAN(li, head) {
 
423
      ret++;
 
424
   }
 
425
   return ret;
 
426
}
 
427
 
 
428
#endif /* _CIRCLIST_H_ */