From fdc4ab5da0f72de5368e32bf9679da52a114fbea Mon Sep 17 00:00:00 2001 From: Graham Fagg Date: Fri, 13 Aug 2004 02:26:12 +0000 Subject: [PATCH] Added prealloced buffer init call (ompi_buffer_init_preallocated()) and updated the unit test for this. - This call is for use by the OOB device so it can pass the pack/buffer system memory. This removes the peek-recv race condition. This commit was SVN r2105. --- src/util/pack.c | 69 +++++++++++++++++++++++++++++++++++++++++++ src/util/pack.h | 23 +++++++++++++++ test/util/ompi_pack.c | 62 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 152 insertions(+), 2 deletions(-) diff --git a/src/util/pack.c b/src/util/pack.c index a2740d4f06..38745b6a2e 100644 --- a/src/util/pack.c +++ b/src/util/pack.c @@ -133,6 +133,75 @@ size_t isize = 0; return (OMPI_SUCCESS); } + +/** + * This function creates a buffer using USER allocated memory + * + * users can then pack MORE into this buffer if needed + * as the buffer is managed, we grow it as needed + * + * the user should not free the memory handed to the buffer + * this will be done by buffer_free + * + * This routine is really only used by the OOB + * + * @param pointer to new buffer handle (OUT) + * @param pointer to USER allocated memory (IN) + * @param to initial USER memory allocated length (IN) + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + * + */ + + int ompi_buffer_init_preallocated (ompi_buffer_t *buffer, void *usermemory, +size_t usermemorylen) +{ +ompi_buffer_internal_t* bptr; + + /* check that we can return a buffer atall.. */ + if (!buffer) { return (OMPI_ERROR); } + + /* check that we have a valid user memory buffer atall.. */ + if (!usermemory) { return (OMPI_ERROR); } + + /* check the requested initial size */ + if (usermemorylen<0) { return (OMPI_ERROR); } + + /* create new buffer object */ + bptr = (ompi_buffer_internal_t *) OBJ_NEW (ompi_buffer_internal_t); + + if (!bptr) { return (OMPI_ERROR); } + + ompi_buffer_cnts++; + + + /* we have a buffer now, so lets populate it */ + + /* allocate initial buffer space */ + + bptr->base_ptr = usermemory; /* set the start of the buffer */ + + /* set data pointer to END of the buffer */ + bptr->data_ptr = ((char*)bptr->base_ptr) + usermemorylen; + + bptr->from_ptr = bptr->base_ptr; /* set the unpack start at start */ + + /* set counts for size and space */ + bptr->size = usermemorylen; + bptr->len = usermemorylen; /* users buffer is expected 2 be full */ + bptr->space = 0; /* ditto */ + bptr->toend = usermemorylen; /* ditto */ + bptr->cnt = ompi_buffer_cnts; + + /* ok, all is well, return the buffer back to the user */ + *buffer = bptr; + + return (OMPI_SUCCESS); +} + + + /** * This function gets the size of packed data in an ompi_buffer * diff --git a/src/util/pack.h b/src/util/pack.h index 5c97a659dd..4ebefdaff9 100644 --- a/src/util/pack.h +++ b/src/util/pack.h @@ -62,6 +62,29 @@ extern "C" { int ompi_buffer_init (ompi_buffer_t *buffer, size_t reqinitsize); + +/** + * This function creates a buffer using USER allocated memory + * + * users can then pack MORE into this buffer if needed + * as the buffer is managed, we grow it as needed + * + * the user should not free the memory handed to the buffer + * this will be done by buffer_free + * + * This routine is really only used by the OOB + * + * @param pointer to new buffer handle (OUT) + * @param pointer to USER allocated memory (IN) + * @param to initial USER memory allocated length (IN) + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + * + */ + + int ompi_buffer_init_preallocated (ompi_buffer_t *buffer, void *usermemory, size_t usermemorylen); + /** * This function gets the size of packed data in a ompi_buffer * diff --git a/test/util/ompi_pack.c b/test/util/ompi_pack.c index 6654de1d58..ca80f7b969 100644 --- a/test/util/ompi_pack.c +++ b/test/util/ompi_pack.c @@ -6,6 +6,8 @@ #include #include #include +#include + #include "ompi_config.h" #include "util/sys_info.h" @@ -26,7 +28,8 @@ static bool test2(void); /* verify we can pack ok */ static bool test3(void); /* verify we can pack expanding buf */ static bool test4(void); /* verify pack a packed buffer */ static bool test5(void); /* verify unpack */ -static bool test6(void); /* verity free */ +static bool test6(void); /* verify free */ +static bool test7(void); /* verify preallocated buffer init, pack and unpack */ int main () { @@ -75,6 +78,14 @@ int main () test_failure("ompi_pack test6 failed"); } + if (test7()) { + test_success(); + } + else { + test_failure("ompi_pack test7 failed"); + } + + /* if (testN()) { */ /* test_success(); */ /* } */ @@ -192,7 +203,7 @@ static bool test5(void) /* verify unpack */ return (true); } -static bool test6(void) /* verity free */ +static bool test6(void) /* verify free */ { int rc; @@ -206,6 +217,53 @@ static bool test6(void) /* verity free */ return (true); } +static bool test7(void) /* verify preallocated buffer init, pack and unpack */ +{ + + int rc; + int results[6]; + int i, j, out; + char *mybuf; + int *p; + + + /* we cannot use heap/static memory for a buffer as it cannot be realloced as needed for this test */ + mybuf = (char*) malloc (sizeof(int)*5); + p = (int*) mybuf; + for(i=0;i<5;i++) { + *p++ = htonl (i); /* the data must be in network byte order for this test to be valid */ + /* as the test is emulating prepacked data recvd from the network (OOB) */ + } + + + rc = ompi_buffer_init_preallocated (&bufA, mybuf, sizeof(int)*5); + if (OMPI_ERROR==rc) { test_comment ("ompi_buffer_init_preallocated failed"); return(false);} + + i = 5; + rc = ompi_pack (bufA, &i, 1, OMPI_INT32); + if (OMPI_ERROR==rc) { test_comment ("ompi_pack failed"); return(false);} + + /* ok, now check its contents */ + for (i=0;i<6;i++) { + j = i; /* for bufA */ + rc = ompi_unpack (bufA, &out, 1, OMPI_INT32); + if (OMPI_ERROR==rc) { test_comment ("ompi_unpack failed"); return(false);} + + if (out!=j) { + test_comment ("bufA packed != unpacked data"); + printf("iteration %d expected %d have %d\n", i, j, out); + return(false); + } + } + + + /* I do not free mybuf as ompi_buffer_free() will */ + + rc = ompi_buffer_free (bufA); + if (OMPI_ERROR==rc) { test_comment ("ompi_buffer_free failed"); return(false);} + + return (true); +} /* int dump_buf (ompi_buffer_t buf) */ /* { */