[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH v4 4/4] lib/ukmmap: mmap trick for Go



Signed-off-by: Charalampos Mainas <Charalampos.Mainas@xxxxxxxxx>
---
 lib/ukmmap/Makefile.uk   |   2 +
 lib/ukmmap/exportsyms.uk |   3 +-
 lib/ukmmap/mmap.c        | 166 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 170 insertions(+), 1 deletion(-)
 create mode 100644 lib/ukmmap/mmap.c

diff --git a/lib/ukmmap/Makefile.uk b/lib/ukmmap/Makefile.uk
index 8ac3ab3c..71ff432f 100644
--- a/lib/ukmmap/Makefile.uk
+++ b/lib/ukmmap/Makefile.uk
@@ -1 +1,3 @@
 $(eval $(call addlib_s,libukmmap,$(CONFIG_LIBUKMMAP)))
+
+LIBUKMMAP_SRCS-y += $(LIBUKMMAP_BASE)/mmap.c
diff --git a/lib/ukmmap/exportsyms.uk b/lib/ukmmap/exportsyms.uk
index 621e94f0..a31c636b 100644
--- a/lib/ukmmap/exportsyms.uk
+++ b/lib/ukmmap/exportsyms.uk
@@ -1 +1,2 @@
-none
+mmap
+munmap
diff --git a/lib/ukmmap/mmap.c b/lib/ukmmap/mmap.c
new file mode 100644
index 00000000..4e24f379
--- /dev/null
+++ b/lib/ukmmap/mmap.c
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ *
+ * Authors: Charalampos Mainas <charalampos.mainas@xxxxxxxxx>
+ *
+ *
+ * Copyright (c) 2019, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#include <sys/mman.h>
+#include <uk/alloc.h>
+#include <string.h>
+
+struct mmap_addr {
+       void *begin;
+       void *end;
+       struct mmap_addr *next;
+};
+
+static struct mmap_addr *mmap_addr;
+
+/**
+ * This is not a correct implementation of mmap. It is just a trick that works
+ * for Go but it needs to be revisited. Instead of mapping, it allocates len
+ * bytes of memory and stores the beginninig and the end of that memory chunk
+ * in struct mmap_addr. At first it checks if addr belongs to one of the memory
+ * chunks that have been allocated in a previous call of mmap. If that is the
+ * case addr is the return value. Otherwise a new memory block is allocated and
+ * the return value is a pointer to the beginninig of that block.
+ *
+ * Go uses mmap always with:
+ * @prot   =   either PROT_NONE or PROT_READ|PROT_WRITE,
+ * @flags  =   as MAP_ANON|MAP_PRIVATE, or MAP_FIXED|MAP_ANON|MAP_PRIVATE
+ *             or MAP_NORESERVE|MAP_ANON|MAP_PRIVATE
+ * @fildes =   -1
+ * @off    =   0
+ *
+ */
+
+void *mmap(void *addr, size_t len, int prot,
+               int flags, int fildes, off_t off)
+{
+       struct mmap_addr *tmp = mmap_addr, *last = NULL, *new = NULL;
+
+       if (!len) {
+               errno = EINVAL;
+               return (void *) -1;
+       }
+
+       /* Check if parameters match the ones that go use
+        * Otherwise return 0 (unimplemented mmap)
+        */
+       if (fildes != -1 || off)
+               return 0;
+       if (!(prot & (PROT_READ|PROT_WRITE)) && (prot != 0))
+               return 0;
+       if (!(flags & (MAP_ANON|MAP_PRIVATE)) &&
+                       !(flags & (MAP_FIXED|MAP_ANON|MAP_PRIVATE)) &&
+                       !(flags & (MAP_NORESERVE|MAP_ANON|MAP_PRIVATE)))
+               return 0;
+
+       while (tmp) {
+               if (addr) {
+                       if (addr >= tmp->begin && addr < tmp->end)
+                               return addr;
+               }
+               last = tmp;
+               tmp = tmp->next;
+       }
+       void *mem = uk_malloc(uk_alloc_get_default(), len);
+
+       if (!mem) {
+               errno = ENOMEM;
+               return (void *) -1;
+       }
+       new = uk_malloc(uk_alloc_get_default(), sizeof(struct mmap_addr));
+       new->begin = mem;
+       new->end = mem + len;
+       new->next = NULL;
+       if (!mmap_addr)
+               mmap_addr = new;
+       else
+               last->next = new;
+       return mem;
+}
+
+/*
+ * munmap frees len bytes os memory starting from addr.
+ * addr needs to be a pointer to a memory block that has been allocated from
+ * mmap. If len has the same value with the size of the memory block that has
+ * been allocated from mmap the struct mmap_addr counterpart is destroyed.
+ * Otherwise the initial memory block is replaced by a smaller one.
+ */
+
+int munmap(void *addr, size_t len)
+{
+       struct mmap_addr *tmp = mmap_addr, *prev = NULL;
+       size_t remain_mem;
+
+       if (!len) {
+               errno = EINVAL;
+               return -1;
+       }
+       if (!addr)
+               return 0;
+       while (tmp) {
+               if (addr != tmp->begin) {
+                       if (tmp->end > addr + len) {
+                               errno = EINVAL;
+                               return -1;
+                       }
+                       remain_mem = tmp->end - addr - len;
+                       if (remain_mem) {
+
+                               void *mem = uk_malloc(uk_alloc_get_default(),
+                                               remain_mem);
+                               if (!mem) {
+                                       errno = ENOMEM;
+                                       return -1;
+                               }
+                               memcpy(mem, addr+len, remain_mem);
+                               tmp->begin = mem;
+                       } else {
+
+                               if (!prev)
+                                       mmap_addr = tmp->next;
+                               else
+                                       prev->next = tmp->next;
+                               uk_free(uk_alloc_get_default(), tmp);
+                       }
+                       uk_free(uk_alloc_get_default(), addr);
+                       return 0;
+               }
+               prev = tmp;
+               tmp = tmp->next;
+       }
+       /* unimplemented munmap */
+       return 0;
+}
-- 
2.17.1


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.