Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / include / ipxe / refcnt.h
1 #ifndef _IPXE_REFCNT_H
2 #define _IPXE_REFCNT_H
3
4 /** @file
5  *
6  * Reference counting
7  *
8  */
9
10 FILE_LICENCE ( GPL2_OR_LATER );
11
12 #include <stddef.h>
13 #include <assert.h>
14
15 /**
16  * A reference counter
17  *
18  * This data structure is designed to be embedded within a
19  * reference-counted object.
20  *
21  * Reference-counted objects are freed when their reference count
22  * drops below zero.  This means that a freshly allocated-and-zeroed
23  * reference-counted object will be freed on the first call to
24  * ref_put().
25  */
26 struct refcnt {
27         /** Current reference count
28          *
29          * When this count is decremented below zero, the free()
30          * method will be called.
31          */
32         int count;
33         /** Free containing object
34          *
35          * This method is called when the reference count is
36          * decremented below zero.
37          *
38          * If this method is left NULL, the standard library free()
39          * function will be called.  The upshot of this is that you
40          * may omit the free() method if the @c refcnt object is the
41          * first element of your reference-counted struct.
42          */
43         void ( * free ) ( struct refcnt *refcnt );
44 };
45
46 /**
47  * Initialise a reference counter
48  *
49  * @v refcnt            Reference counter
50  * @v free              Freeing function
51  */
52 static inline __attribute__ (( always_inline )) void
53 ref_init ( struct refcnt *refcnt,
54            void ( * free ) ( struct refcnt *refcnt ) ) {
55         refcnt->free = free;
56 }
57
58 /**
59  * Initialise a reference counter
60  *
61  * @v refcnt            Reference counter
62  * @v free              Free containing object
63  */
64 #define ref_init( refcnt, free ) do {                                   \
65         if ( __builtin_constant_p ( (free) ) && ( (free) == NULL ) ) {  \
66                 /* Skip common case of no initialisation required */    \
67         } else {                                                        \
68                 ref_init ( (refcnt), (free) );                          \
69         }                                                               \
70         } while ( 0 )
71
72 /**
73  * Initialise a static reference counter
74  *
75  * @v free_fn           Free containing object
76  */
77 #define REF_INIT( free_fn ) {                                           \
78                 .free = free_fn,                                        \
79         }
80
81 extern void ref_increment ( struct refcnt *refcnt );
82 extern void ref_decrement ( struct refcnt *refcnt );
83
84 /**
85  * Get additional reference to object
86  *
87  * @v refcnt            Reference counter, or NULL
88  * @ret refcnt          Reference counter
89  *
90  * If @c refcnt is NULL, no action is taken.
91  */
92 #define ref_get( refcnt ) ( {                                           \
93         if ( refcnt )                                                   \
94                 assert ( (refcnt)->count >= 0 );                        \
95         ref_increment ( refcnt );                                       \
96         (refcnt); } )
97
98 /**
99  * Drop reference to object
100  *
101  * @v refcnt            Reference counter, or NULL
102  * @ret refcnt          Reference counter
103  *
104  * If @c refcnt is NULL, no action is taken.
105  */
106 #define ref_put( refcnt ) do {                                          \
107         if ( refcnt )                                                   \
108                 assert ( (refcnt)->count >= 0 );                        \
109         ref_decrement ( refcnt );                                       \
110         } while ( 0 )
111
112 extern void ref_no_free ( struct refcnt *refcnt );
113
114 #endif /* _IPXE_REFCNT_H */