1/** Implementation of page-related functions for GNUstep 2 Copyright (C) 1996, 1997 Free Software Foundation, Inc. 3 4 Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu> 5 Created: May 1996 6 7 This file is part of the GNUstep Base Library. 8 9 This library is free software; you can redistribute it and/or 10 modify it under the terms of the GNU Lesser General Public 11 License as published by the Free Software Foundation; either 12 version 2 of the License, or (at your option) any later version. 13 14 This library is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 Lesser General Public License for more details. 18 19 You should have received a copy of the GNU Lesser General Public 20 License along with this library; if not, write to the Free 21 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 Boston, MA 02110 USA. 23 24 <title>NSPage class reference</title> 25 $Date$ $Revision$ 26 */ 27 28#import "common.h" 29#include <stdio.h> 30#if __mach__ 31#include <mach.h> 32#endif 33 34#ifdef __CYGWIN__ 35#include <malloc.h> 36#endif 37 38#ifdef _WIN32 39#include <malloc.h> 40static size_t 41getpagesize(void) 42{ 43 SYSTEM_INFO info; 44 GetSystemInfo(&info); 45 return info.dwPageSize; 46} 47#endif 48 49#ifdef __SOLARIS__ 50#define getpagesize() sysconf(_SC_PAGESIZE) 51#endif 52 53#ifdef __svr4__ 54#define getpagesize() sysconf(_SC_PAGESIZE) 55#endif 56 57#if __mach__ 58#define getpagesize vm_page_size 59#endif 60 61#ifdef __BEOS__ 62#include <kernel/OS.h> 63#define getpagesize() B_PAGE_SIZE 64#endif 65 66/* Cache the size of a memory page here, so we don't have to make the 67 getpagesize() system call repeatedly. */ 68static NSUInteger ns_page_size = 0; 69 70/** 71 * Return the number of bytes in a memory page. 72 */ 73NSUInteger 74NSPageSize (void) 75{ 76 if (!ns_page_size) 77 ns_page_size = getpagesize (); 78 return ns_page_size; 79} 80 81/** 82 * Return log base 2 of the number of bytes in a memory page. 83 */ 84NSUInteger 85NSLogPageSize (void) 86{ 87 NSUInteger tmp_page_size = NSPageSize(); 88 NSUInteger log = 0; 89 90 while (tmp_page_size >>= 1) 91 log++; 92 return log; 93} 94 95/** 96 * Round bytes down to the nearest multiple of the memory page size, 97 * and return it. 98 */ 99NSUInteger 100NSRoundDownToMultipleOfPageSize (NSUInteger bytes) 101{ 102 NSUInteger a = NSPageSize(); 103 104 return (bytes / a) * a; 105} 106 107/** 108 * Round bytes up to the nearest multiple of the memory page size, 109 * and return it. 110 */ 111NSUInteger 112NSRoundUpToMultipleOfPageSize (NSUInteger bytes) 113{ 114 NSUInteger a = NSPageSize(); 115 116 return ((bytes % a) ? ((bytes / a + 1) * a) : bytes); 117} 118 119#if __linux__ 120#include <sys/sysinfo.h> 121#endif 122 123/** 124 * Return the number of bytes of real (physical) memory available. 125 */ 126NSUInteger 127NSRealMemoryAvailable () 128{ 129#if __linux__ 130 struct sysinfo info; 131 132 if ((sysinfo(&info)) != 0) 133 return 0; 134 return info.freeram; 135#elif defined(_WIN32) 136 MEMORYSTATUSEX memory; 137 138 memory.dwLength = sizeof(memory); 139 GlobalMemoryStatusEx(&memory); 140 return memory.ullAvailPhys; 141#elif defined(__BEOS__) 142 system_info info; 143 144 if (get_system_info(&info) != B_OK) 145 return 0; 146 return (info.max_pages - info.used_pages) * B_PAGE_SIZE; 147#else 148 fprintf (stderr, "NSRealMemoryAvailable() not implemented.\n"); 149 return 0; 150#endif 151} 152 153/** 154 * Allocate memory for this process and return a pointer to it (or a null 155 * pointer on failure). The allocated memory is page aligned and the 156 * actual size of memory allocated is a multiple of the page size. 157 */ 158void * 159NSAllocateMemoryPages (NSUInteger bytes) 160{ 161 NSUInteger size = NSRoundUpToMultipleOfPageSize (bytes); 162 void *where; 163#if defined(_WIN32) 164 where = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 165#elif __mach__ 166 kern_return_t r; 167 r = vm_allocate (mach_task_self(), &where, (vm_size_t) size, 1); 168 if (r != KERN_SUCCESS) 169 return NULL; 170 return where; 171#elif HAVE_POSIX_MEMALIGN 172 if (posix_memalign(&where, NSPageSize(), size) != 0) 173 return NULL; 174#else 175 where = valloc (size); 176 if (where == NULL) 177 return NULL; 178#endif 179 memset (where, 0, bytes); 180 return where; 181} 182 183/** 184 * Deallocate memory which was previously allocated using the 185 * NSAllocateMemoryPages() function.<br /> 186 * The bytes argument should be the same as the value passed 187 * to the NSAllocateMemoryPages() function. 188 */ 189void 190NSDeallocateMemoryPages (void *ptr, NSUInteger bytes) 191{ 192#if defined(_WIN32) 193 VirtualFree(ptr, 0, MEM_RELEASE); 194#elif __mach__ 195 vm_deallocate (mach_task_self (), ptr, NSRoundUpToMultipleOfPageSize (bytes)); 196#else 197 free (ptr); 198#endif 199} 200 201/** 202 * Perform an efficient large scale copy of data from src to dest. 203 * The value bytes specifies the length of the data copied. 204 */ 205void 206NSCopyMemoryPages (const void *src, void *dest, NSUInteger bytes) 207{ 208#if __mach__ 209 kern_return_t r; 210 r = vm_copy (mach_task_self(), src, bytes, dest); 211 NSParameterAssert (r == KERN_SUCCESS); 212#else 213 memcpy (dest, src, bytes); 214#endif 215} 216 217