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