Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / include / ipxe / refcnt.h
diff --git a/qemu/roms/ipxe/src/include/ipxe/refcnt.h b/qemu/roms/ipxe/src/include/ipxe/refcnt.h
new file mode 100644 (file)
index 0000000..0e8b865
--- /dev/null
@@ -0,0 +1,114 @@
+#ifndef _IPXE_REFCNT_H
+#define _IPXE_REFCNT_H
+
+/** @file
+ *
+ * Reference counting
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <assert.h>
+
+/**
+ * A reference counter
+ *
+ * This data structure is designed to be embedded within a
+ * reference-counted object.
+ *
+ * Reference-counted objects are freed when their reference count
+ * drops below zero.  This means that a freshly allocated-and-zeroed
+ * reference-counted object will be freed on the first call to
+ * ref_put().
+ */
+struct refcnt {
+       /** Current reference count
+        *
+        * When this count is decremented below zero, the free()
+        * method will be called.
+        */
+       int count;
+       /** Free containing object
+        *
+        * This method is called when the reference count is
+        * decremented below zero.
+        *
+        * If this method is left NULL, the standard library free()
+        * function will be called.  The upshot of this is that you
+        * may omit the free() method if the @c refcnt object is the
+        * first element of your reference-counted struct.
+        */
+       void ( * free ) ( struct refcnt *refcnt );
+};
+
+/**
+ * Initialise a reference counter
+ *
+ * @v refcnt           Reference counter
+ * @v free             Freeing function
+ */
+static inline __attribute__ (( always_inline )) void
+ref_init ( struct refcnt *refcnt,
+          void ( * free ) ( struct refcnt *refcnt ) ) {
+       refcnt->free = free;
+}
+
+/**
+ * Initialise a reference counter
+ *
+ * @v refcnt           Reference counter
+ * @v free             Free containing object
+ */
+#define ref_init( refcnt, free ) do {                                  \
+       if ( __builtin_constant_p ( (free) ) && ( (free) == NULL ) ) {  \
+               /* Skip common case of no initialisation required */    \
+       } else {                                                        \
+               ref_init ( (refcnt), (free) );                          \
+       }                                                               \
+       } while ( 0 )
+
+/**
+ * Initialise a static reference counter
+ *
+ * @v free_fn          Free containing object
+ */
+#define REF_INIT( free_fn ) {                                          \
+               .free = free_fn,                                        \
+       }
+
+extern void ref_increment ( struct refcnt *refcnt );
+extern void ref_decrement ( struct refcnt *refcnt );
+
+/**
+ * Get additional reference to object
+ *
+ * @v refcnt           Reference counter, or NULL
+ * @ret refcnt         Reference counter
+ *
+ * If @c refcnt is NULL, no action is taken.
+ */
+#define ref_get( refcnt ) ( {                                          \
+       if ( refcnt )                                                   \
+               assert ( (refcnt)->count >= 0 );                        \
+       ref_increment ( refcnt );                                       \
+       (refcnt); } )
+
+/**
+ * Drop reference to object
+ *
+ * @v refcnt           Reference counter, or NULL
+ * @ret refcnt         Reference counter
+ *
+ * If @c refcnt is NULL, no action is taken.
+ */
+#define ref_put( refcnt ) do {                                         \
+       if ( refcnt )                                                   \
+               assert ( (refcnt)->count >= 0 );                        \
+       ref_decrement ( refcnt );                                       \
+       } while ( 0 )
+
+extern void ref_no_free ( struct refcnt *refcnt );
+
+#endif /* _IPXE_REFCNT_H */