From: Ben Pfaff Date: Wed, 18 Apr 2012 04:55:27 +0000 (-0700) Subject: ofpbuf: New functions ofpbuf_use_stub() and ofpbuf_get_uninit_pointer(). X-Git-Tag: sliver-openvswitch-0.1-1~91 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=cca408daa5dba2465ebf1ba9cc7cc842617b0ab9;p=sliver-openvswitch.git ofpbuf: New functions ofpbuf_use_stub() and ofpbuf_get_uninit_pointer(). Signed-off-by: Ben Pfaff --- diff --git a/lib/ofpbuf.c b/lib/ofpbuf.c index 29698dcd8..a98242091 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 7f8338cd0..37f445328 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 /* Starts on stack, 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);