summaryrefslogtreecommitdiff
path: root/lib/util/util.c
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2011-08-14 18:10:53 -0400
committerSimo Sorce <idra@samba.org>2011-08-14 20:19:02 -0400
commit039ddef20900322760093a04881007dbb0897b50 (patch)
treeca79b916a5d2c459bd4e5ff4db664be4024bd55d /lib/util/util.c
parenta171938408adde0d787b9ff40a4cebeee66d747a (diff)
downloadsamba-039ddef20900322760093a04881007dbb0897b50.tar.gz
samba-039ddef20900322760093a04881007dbb0897b50.tar.bz2
samba-039ddef20900322760093a04881007dbb0897b50.zip
util: add function to extend anonymous shared memory
Diffstat (limited to 'lib/util/util.c')
-rw-r--r--lib/util/util.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/lib/util/util.c b/lib/util/util.c
index 2d1d83036d..b700f372c7 100644
--- a/lib/util/util.c
+++ b/lib/util/util.c
@@ -1073,6 +1073,70 @@ void *anonymous_shared_allocate(size_t orig_bufsz)
return ptr;
}
+void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove)
+{
+#ifdef HAVE_MREMAP
+ void *buf;
+ size_t pagesz = getpagesize();
+ size_t pagecnt;
+ size_t bufsz;
+ struct anonymous_shared_header *hdr;
+ int flags = 0;
+
+ if (ptr == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ hdr = (struct anonymous_shared_header *)ptr;
+ hdr--;
+ if (hdr->u.length > (new_size + sizeof(*hdr))) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ bufsz = new_size + sizeof(*hdr);
+
+ /* round up to full pages */
+ pagecnt = bufsz / pagesz;
+ if (bufsz % pagesz) {
+ pagecnt += 1;
+ }
+ bufsz = pagesz * pagecnt;
+
+ if (new_size >= bufsz) {
+ /* integer wrap */
+ errno = ENOSPC;
+ return NULL;
+ }
+
+ if (bufsz <= hdr->u.length) {
+ return ptr;
+ }
+
+ if (maymove) {
+ flags = MREMAP_MAYMOVE;
+ }
+
+ buf = mremap(hdr, hdr->u.length, bufsz, flags);
+
+ if (buf == MAP_FAILED) {
+ errno = ENOSPC;
+ return NULL;
+ }
+
+ hdr = (struct anonymous_shared_header *)buf;
+ hdr->u.length = bufsz;
+
+ ptr = (void *)(&hdr[1]);
+
+ return ptr;
+#else
+ errno = ENOSPC;
+ return NULL;
+#endif
+}
+
void anonymous_shared_free(void *ptr)
{
struct anonymous_shared_header *hdr;