You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by hi...@apache.org on 2007/10/27 21:36:57 UTC

svn commit: r589195 - /harmony/enhanced/classlib/trunk/modules/portlib/src/main/native/port/unix/freebsd/hyvmem.c

Author: hindessm
Date: Sat Oct 27 12:36:56 2007
New Revision: 589195

URL: http://svn.apache.org/viewvc?rev=589195&view=rev
Log:
Add stubs for real implementation of hyvmem on FreeBSD.

Modified:
    harmony/enhanced/classlib/trunk/modules/portlib/src/main/native/port/unix/freebsd/hyvmem.c

Modified: harmony/enhanced/classlib/trunk/modules/portlib/src/main/native/port/unix/freebsd/hyvmem.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/portlib/src/main/native/port/unix/freebsd/hyvmem.c?rev=589195&r1=589194&r2=589195&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/portlib/src/main/native/port/unix/freebsd/hyvmem.c (original)
+++ harmony/enhanced/classlib/trunk/modules/portlib/src/main/native/port/unix/freebsd/hyvmem.c Sat Oct 27 12:36:56 2007
@@ -15,6 +15,443 @@
  *  limitations under the License.
  */
 
-/* Temporary placeholder so FreeBSD port still compiles. FreeBSD requires it's own
-   implementation of these functions, but for now just let it build against the Linux ones. */
-#include "../linux/hyvmem.c"
+#define CDEV_CURRENT_FUNCTION _comment_
+/**
+ * @file
+ * @ingroup Port
+ * @brief Virtual memory
+ */
+
+#undef CDEV_CURRENT_FUNCTION
+
+#include "hyport.h"
+#include "portpriv.h"
+#include "hyportpg.h"
+#include "ut_hyprt.h"
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <sys/shm.h>
+#include <unistd.h>
+
+#if !defined(MAP_FAILED)
+#define MAP_FAILED -1
+#endif
+
+#define VMEM_MEMINFO_SIZE_MAX	1024
+#define VMEM_PROC_MEMINFO_FNAME	"/proc/meminfo"
+
+typedef struct vmem_hugepage_info_t
+{
+  UDATA enabled;                /*!< boolean enabling hy large page support */
+  UDATA pages_total;            /*!< total number of pages maintained by the kernel */
+  UDATA pages_free;             /*!< number of free pages that may be allocated by us */
+  UDATA page_size;              /*!< page size in bytes */
+} vmem_hugepage_info_t;
+
+#define CDEV_CURRENT_FUNCTION _prototypes_private
+void *VMCALL default_pageSize_reserve_memory (struct HyPortLibrary
+                                              *portLibrary, void *address,
+                                              UDATA byteAmount,
+                                              struct HyPortVmemIdentifier
+                                              *identifier, UDATA mode,
+                                              UDATA pageSize);
+static UDATA get_hugepages_info (struct HyPortLibrary *portLibrary,
+                                 vmem_hugepage_info_t * page_info);
+void VMCALL update_vmemIdentifier (HyPortVmemIdentifier * identifier,
+                                   void *address, void *handle,
+                                   UDATA byteAmount, UDATA mode,
+                                   UDATA pageSize);
+int VMCALL get_protectionBits (UDATA mode);
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyvmem_shutdown
+/**
+ * PortLibrary shutdown.
+ *
+ * This function is called during shutdown of the portLibrary.  Any resources that were created by @ref hyvmem_startup
+ * should be destroyed here.
+ *
+ * @param[in] portLibrary The port library.
+ *
+ * @note Most implementations will be empty.
+ */
+void VMCALL
+hyvmem_shutdown (struct HyPortLibrary *portLibrary)
+{
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyvmem_startup
+/**
+ * PortLibrary startup.
+ *
+ * This function is called during startup of the portLibrary.  Any resources that are required for
+ * the virtual memory operations may be created here.  All resources created here should be destroyed
+ * in @ref hyvmem_shutdown.
+ *
+ * @param[in] portLibrary The port library.
+ *
+ * @return 0 on success, negative error code on failure.  Error code values returned are
+ * \arg HYPORT_ERROR_STARTUP_VMEM
+ *
+ * @note Most implementations will simply return success.
+ */
+I_32 VMCALL
+hyvmem_startup (struct HyPortLibrary *portLibrary)
+{
+  vmem_hugepage_info_t vmem_page_info;
+
+  /* clear page info data, this has the effect of starting off in a standard state */
+  memset (&vmem_page_info, 0x00, sizeof (vmem_hugepage_info_t));
+  get_hugepages_info (portLibrary, &vmem_page_info);
+
+  /* 0 terminate the table */
+  memset (PPG_vmem_pageSize, 0, HYPORT_VMEM_PAGESIZE_COUNT * sizeof (UDATA));
+
+  /* First the default page size */
+  PPG_vmem_pageSize[0] = (UDATA) getpagesize ();
+
+  /* Now the large pages */
+  if (vmem_page_info.enabled)
+    {
+      PPG_vmem_pageSize[1] = vmem_page_info.page_size;
+    }
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyvmem_commit_memory
+/**
+ * Commit memory in virtual address space.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] address The page aligned starting address of the memory to commit.
+ * @param[in] byteAmount The number of bytes to commit.
+ * @param[in] identifier Descriptor for virtual memory block.
+ *
+ * @return pointer to the allocated memory on success, NULL on failure.
+ */
+void *VMCALL
+hyvmem_commit_memory (struct HyPortLibrary *portLibrary, void *address,
+                      UDATA byteAmount,
+                      struct HyPortVmemIdentifier *identifier)
+{
+  Trc_PRT_vmem_hyvmem_commit_memory_Entry (address, byteAmount);
+
+  /* Default page size */
+  if (PPG_vmem_pageSize[0] == identifier->pageSize)
+    {
+      if (0 ==
+          mprotect (address, byteAmount,
+                    get_protectionBits (identifier->mode)))
+        {
+          Trc_PRT_vmem_hyvmem_commit_memory_Exit (address);
+          return address;
+        }
+    }
+  if (PPG_vmem_pageSize[1] == identifier->pageSize)
+    {
+      Trc_PRT_vmem_hyvmem_commit_memory_Exit (address);
+      return address;
+    }
+
+  Trc_PRT_vmem_hyvmem_commit_memory_Exit (NULL);
+  return NULL;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyvmem_decommit_memory
+/**
+ * Decommit memory in virtual address space.
+ *
+ * Decommits physical storage of the size specified starting at the address specified.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] address The starting address of the memory to be decommitted.
+ * @param[in] byteAmount The number of bytes to be decommitted.
+ * @param[in] identifier Descriptor for virtual memory block.
+ *
+ * @return 0 on success, non zero on failure.
+ */
+IDATA VMCALL
+hyvmem_decommit_memory (struct HyPortLibrary * portLibrary, void *address,
+                        UDATA byteAmount,
+                        struct HyPortVmemIdentifier * identifier)
+{
+  Trc_PRT_vmem_hyvmem_decommit_memory_Entry (address, byteAmount);
+  Trc_PRT_vmem_hyvmem_decommit_memory_Exit (0);
+  return (IDATA) 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyvmem_free_memory
+/**
+ * Free memory in virtual address space.
+ *
+ * Frees physical storage of the size specified starting at the address specified.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] address The starting address of the memory to be de-allocated.
+ * @param[in] byteAmount The number of bytes to be allocated.
+ * @param[in] identifier Descriptor for virtual memory block.
+ *
+ * @return 0 on success, non zero on failure.
+ */
+I_32 VMCALL
+hyvmem_free_memory (struct HyPortLibrary * portLibrary, void *address,
+                    UDATA byteAmount,
+                    struct HyPortVmemIdentifier * identifier)
+{
+  Trc_PRT_vmem_hyvmem_free_memory_Entry (address, byteAmount);
+
+  /* Default page Size */
+  if (PPG_vmem_pageSize[0] == identifier->pageSize)
+    {
+      I_32 ret = 0;
+
+      update_vmemIdentifier (identifier, NULL, NULL, 0, 0, 0);
+      ret = (I_32) munmap (address, (size_t) byteAmount);
+      Trc_PRT_vmem_hyvmem_free_memory_Exit (ret);
+      return ret;
+    }
+  if (PPG_vmem_pageSize[1] == identifier->pageSize)
+    {
+      shmdt (identifier->address);
+      update_vmemIdentifier (identifier, NULL, NULL, 0, 0, 0);
+      Trc_PRT_vmem_hyvmem_free_memory_Exit (0);
+      return 0;
+    }
+
+  Trc_PRT_vmem_hyvmem_free_memory_Exit (-1);
+  return -1;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyvmem_reserve_memory
+/**
+ * Reserve memory in virtual address space.
+ *
+ * Reserves a range of  virtual address space without allocating any actual physical storage.
+ * The memory is not available for use until committed @ref hyvmem_commit_memory.
+ * The memory may not be used by other memory allocation routines until it is explicitly released.
+ *
+ * @param[in] portLibrary The port library.
+ * @param[in] address The starting address of the memory to be reserved.
+ * @param[in] byteAmount The number of bytes to be reserved.
+ * @param[in] identifier Descriptor for virtual memory block.
+ * @param[in] mode Bitmap indicating how memory is to be reserved.  Expected values combination of:
+ * \arg HYPORT_VMEM_MEMORY_MODE_READ memory is readable
+ * \arg HYPORT_VMEM_MEMORY_MODE_WRITE memory is writable
+ * \arg HYPORT_VMEM_MEMORY_MODE_EXECUTE memory is executable
+ * \arg HYPORT_VMEM_MEMORY_MODE_COMMIT commits memory as part of the reserve
+ * @param[in] pageSize Size of the page requested, a value returned by @ref hyvmem_supported_page_sizes,
+ * or the constant HYPORT_VMEM_PAGE_SIZE_DEFAULT for the system default page size.
+ *
+ * @return pointer to the reserved memory on success, NULL on failure.
+ *
+ * @internal @warning Do not call error handling code @ref hyerror upon error as 
+ * the error handling code uses per thread buffers to store the last error.  If memory
+ * can not be allocated the result would be an infinite loop.
+ */
+void *VMCALL
+hyvmem_reserve_memory (struct HyPortLibrary *portLibrary, void *address,
+                       UDATA byteAmount,
+                       struct HyPortVmemIdentifier *identifier, UDATA mode,
+                       UDATA pageSize)
+{
+
+  Trc_PRT_vmem_hyvmem_reserve_memory_Entry (address, byteAmount);
+  /* Invalid input */
+  if (0 == pageSize)
+    {
+      update_vmemIdentifier (identifier, NULL, NULL, 0, 0, 0);
+      Trc_PRT_vmem_hyvmem_reserve_memory_Exit1 ();
+      return NULL;
+    }
+
+  /* Handle default page size differently, don't use shmget */
+  if ((HYPORT_VMEM_PAGE_SIZE_DEFAULT == pageSize)
+      || (PPG_vmem_pageSize[0] == pageSize))
+    {
+      void *defptr =
+        default_pageSize_reserve_memory (portLibrary, address, byteAmount,
+                                         identifier, mode,
+                                         PPG_vmem_pageSize[0]);
+      Trc_PRT_vmem_hyvmem_reserve_memory_Exit2 (defptr);
+      return defptr;
+    }
+
+  /* If the pageSize is not one of the large page sizes supported, error */
+  if (PPG_vmem_pageSize[1] != pageSize)
+    {
+      update_vmemIdentifier (identifier, NULL, NULL, 0, 0, 0);
+      Trc_PRT_vmem_hyvmem_reserve_memory_Exit3 (pageSize);
+      return NULL;
+    }
+
+  /* TODO: large page support */
+  update_vmemIdentifier (identifier, NULL, NULL, 0, 0, 0);
+  Trc_PRT_vmem_hyvmem_reserve_memory_Exit3 (pageSize);
+  return NULL;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hyvmem_supported_page_sizes
+/**
+ * Determine the page sizes supported.
+ *
+ * @param[in] portLibrary The port library.
+ *
+ * @return A 0 terminated array of supported page sizes.  The first entry is the default page size, other entries
+ * are the large page sizes supported.
+ */
+UDATA *VMCALL
+hyvmem_supported_page_sizes (struct HyPortLibrary * portLibrary)
+{
+  return PPG_vmem_pageSize;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION get_hugepages_info
+static UDATA
+get_hugepages_info (struct HyPortLibrary *portLibrary,
+                    vmem_hugepage_info_t * page_info)
+{
+  return 1;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION default_pageSize_reserve_memory
+void *VMCALL
+default_pageSize_reserve_memory (struct HyPortLibrary *portLibrary,
+                                 void *address, UDATA byteAmount,
+                                 struct HyPortVmemIdentifier *identifier,
+                                 UDATA mode, UDATA pageSize)
+{
+  /* This function is cloned in HySourceUnixHyVMem (hyvmem_reserve_memory).  
+   * Any changes made here may need to be reflected in that version .
+   */
+  int fd = -1;
+  int flags = MAP_PRIVATE;
+  void *result;
+  int protectionFlags = PROT_NONE;
+
+#if defined(MAP_ANONYMOUS)
+  flags |= MAP_ANONYMOUS;
+#elif defined(MAP_ANON)
+  flags |= MAP_ANON;
+#else
+  fd =
+    portLibrary->file_open (portLibrary, "/dev/zero",
+                            HyOpenRead | HyOpenWrite, 0);
+  if (fd == -1)
+    {
+      update_vmemIdentifier (identifier, NULL, NULL, 0, 0, 0);
+      return NULL;
+    }
+#endif
+
+  if (0 != (HYPORT_VMEM_MEMORY_MODE_COMMIT & mode))
+    {
+      protectionFlags = get_protectionBits (mode);
+    }
+  else
+    {
+      flags |= MAP_NORESERVE;
+    }
+  result = mmap (address, (size_t) byteAmount, protectionFlags, flags, fd, 0);
+
+#if !defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
+  portLibrary->file_close (portLibrary, fd);
+#endif
+
+  if (MAP_FAILED == result)
+    {
+      update_vmemIdentifier (identifier, NULL, NULL, 0, 0, 0);
+      return NULL;
+    }
+  else
+    {
+      /* Update identifier and commit memory if required, else return reserved memory */
+      update_vmemIdentifier (identifier, result, result, byteAmount, mode,
+                             pageSize);
+      if (0 != (HYPORT_VMEM_MEMORY_MODE_COMMIT & mode))
+        {
+          portLibrary->vmem_commit_memory (portLibrary, result, byteAmount,
+                                           identifier);
+        }
+      return result;
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION update_vmemIdentifier
+/**
+ * @internal
+ * Update HyPortVmIdentifier structure
+ *
+ * @param[in] identifier The structure to be updated
+ * @param[in] address Base address
+ * @param[in] handle Platform specific handle for reserved memory
+ * @param[in] byteAmount Size of allocated area
+ * @param[in] mode Access Mode
+ * @param[in] pageSize Constant describing pageSize
+ */
+void VMCALL
+update_vmemIdentifier (HyPortVmemIdentifier * identifier, void *address,
+                       void *handle, UDATA byteAmount, UDATA mode,
+                       UDATA pageSize)
+{
+  identifier->address = address;
+  identifier->handle = handle;
+  identifier->size = byteAmount;
+  identifier->pageSize = pageSize;
+  identifier->mode = mode;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION get_protectionBits
+int VMCALL
+get_protectionBits (UDATA mode)
+{
+  int protectionFlags = 0;
+
+  if (0 != (HYPORT_VMEM_MEMORY_MODE_EXECUTE & mode))
+    {
+      protectionFlags |= PROT_EXEC;
+    }
+  if (0 != (HYPORT_VMEM_MEMORY_MODE_READ & mode))
+    {
+      protectionFlags |= PROT_READ;
+    }
+  if (0 != (HYPORT_VMEM_MEMORY_MODE_WRITE & mode))
+    {
+      protectionFlags |= PROT_WRITE;
+    }
+  if (0 == protectionFlags)
+    {
+      protectionFlags = PROT_NONE;
+    }
+
+  return protectionFlags;
+}
+
+#undef CDEV_CURRENT_FUNCTION