[ovs-dev] [optimize 07/26] ofpbuf: New functions ofpbuf_use_stub() and ofpbuf_get_uninit_pointer().

Ben Pfaff blp at nicira.com
Tue Apr 17 00:18:47 UTC 2012


From: Ben Pfaff <blp at hardrock.nicira.com>

Signed-off-by: Ben Pfaff <blp at hardrock.nicira.com>
---
 lib/ofpbuf.c |   52 ++++++++++++++++++++++++++++++++++++++++++++--------
 lib/ofpbuf.h |    7 +++++--
 2 files changed, 49 insertions(+), 10 deletions(-)

diff --git a/lib/ofpbuf.c b/lib/ofpbuf.c
index 29698dc..a982420 100644
--- a/lib/ofpbuf.c
+++ b/lib/ofpbuf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -47,23 +47,44 @@ ofpbuf_use(struct ofpbuf *b, void *base, size_t allocated)
 
 /* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of
  * memory starting at 'base'.  'base' should point to a buffer on the stack.
- *
- * An ofpbuf operation that requires reallocating data will assert-fail if this
- * function was used to initialize it.
+ * (Nothing actually relies on 'base' being allocated on the stack.  It could
+ * be static or malloc()'d memory.  But stack space is the most common use
+ * case.)
  *
  * 'base' should be appropriately aligned.  Using an array of uint32_t or
  * uint64_t for the buffer is a reasonable way to ensure appropriate alignment
- * for 32- or 64-bit data.
+ * for 32- or 64-bit data.  OFPBUF_STACK_BUFFER is a convenient way to do so.
  *
- * (Nothing actually relies on 'base' being allocated on the stack.  It could
- * be static or malloc()'d memory.  But stack space is the most common use
- * case.) */
+ * An ofpbuf operation that requires reallocating data will assert-fail if this
+ * function was used to initialize it.  Thus, one need not call ofpbuf_uninit()
+ * on an ofpbuf initialized by this function (though doing so is harmless),
+ * because it is guaranteed that 'b' does not own any heap-allocated memory. */
 void
 ofpbuf_use_stack(struct ofpbuf *b, void *base, size_t allocated)
 {
     ofpbuf_use__(b, base, allocated, OFPBUF_STACK);
 }
 
+/* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of
+ * memory starting at 'base'.  'base' should point to a buffer on the stack.
+ * (Nothing actually relies on 'base' being allocated on the stack.  It could
+ * be static or malloc()'d memory.  But stack space is the most common usen
+ * case.)
+ *
+ * 'base' should be appropriately aligned.  Using an array of uint32_t or
+ * uint64_t for the buffer is a reasonable way to ensure appropriate alignment
+ * for 32- or 64-bit data.  OFPBUF_STACK_BUFFER is a convenient way to do so.
+ *
+ * An ofpbuf operation that requires reallocating data will copy the provided
+ * buffer into a malloc()'d buffer.  Thus, it is wise to call ofpbuf_uninit()
+ * on an ofpbuf initialized by this function, so that if it expanded into the
+ * heap, that memory is freed. */
+void
+ofpbuf_use_stub(struct ofpbuf *b, void *base, size_t allocated)
+{
+    ofpbuf_use__(b, base, allocated, OFPBUF_STUB);
+}
+
 /* Initializes 'b' as an ofpbuf whose data starts at 'data' and continues for
  * 'size' bytes.  This is appropriate for an ofpbuf that will be used to
  * inspect existing data, without moving it around or reallocating it, and
@@ -95,6 +116,15 @@ ofpbuf_uninit(struct ofpbuf *b)
     }
 }
 
+/* Returns a pointer that may be passed to free() to accomplish the same thing
+ * as ofpbuf_uninit(b).  The return value is a null pointer if ofpbuf_uninit()
+ * would not free any memory. */
+void *
+ofpbuf_get_uninit_pointer(struct ofpbuf *b)
+{
+    return b && b->source == OFPBUF_MALLOC ? b->base : NULL;
+}
+
 /* Frees memory that 'b' points to and allocates a new ofpbuf */
 void
 ofpbuf_reinit(struct ofpbuf *b, size_t size)
@@ -246,6 +276,12 @@ ofpbuf_resize__(struct ofpbuf *b, size_t new_headroom, size_t new_tailroom)
     case OFPBUF_STACK:
         NOT_REACHED();
 
+    case OFPBUF_STUB:
+        b->source = OFPBUF_MALLOC;
+        new_base = xmalloc(new_allocated);
+        ofpbuf_copy__(b, new_base, new_headroom, new_tailroom);
+        break;
+
     default:
         NOT_REACHED();
     }
diff --git a/lib/ofpbuf.h b/lib/ofpbuf.h
index 7f8338c..bfd12a4 100644
--- a/lib/ofpbuf.h
+++ b/lib/ofpbuf.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,7 +28,8 @@ extern "C" {
 
 enum ofpbuf_source {
     OFPBUF_MALLOC,              /* Obtained via malloc(). */
-    OFPBUF_STACK                /* Stack space or static buffer. */
+    OFPBUF_STACK,               /* Un-movable stack space or static buffer. */
+    OFPBUF_STUB                 /* As OFPBUF_STACK but may expand into heap. */
 };
 
 /* Buffer for holding arbitrary data.  An ofpbuf is automatically reallocated
@@ -56,10 +57,12 @@ struct ofpbuf {
 
 void ofpbuf_use(struct ofpbuf *, void *, size_t);
 void ofpbuf_use_stack(struct ofpbuf *, void *, size_t);
+void ofpbuf_use_stub(struct ofpbuf *, void *, size_t);
 void ofpbuf_use_const(struct ofpbuf *, const void *, size_t);
 
 void ofpbuf_init(struct ofpbuf *, size_t);
 void ofpbuf_uninit(struct ofpbuf *);
+void *ofpbuf_get_uninit_pointer(struct ofpbuf *);
 void ofpbuf_reinit(struct ofpbuf *, size_t);
 
 struct ofpbuf *ofpbuf_new(size_t);
-- 
1.7.9




More information about the dev mailing list