1/** 2 * \file imports.c 3 * Standard C library function wrappers. 4 * 5 * Imports are services which the device driver or window system or 6 * operating system provides to the core renderer. The core renderer (Mesa) 7 * will call these functions in order to do memory allocation, simple I/O, 8 * etc. 9 * 10 * Some drivers will want to override/replace this file with something 11 * specialized, but that'll be rare. 12 * 13 * Eventually, I want to move roll the glheader.h file into this. 14 * 15 * \todo Functions still needed: 16 * - scanf 17 * - qsort 18 * - rand and RAND_MAX 19 */ 20 21/* 22 * Mesa 3-D graphics library 23 * 24 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 25 * 26 * Permission is hereby granted, free of charge, to any person obtaining a 27 * copy of this software and associated documentation files (the "Software"), 28 * to deal in the Software without restriction, including without limitation 29 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 30 * and/or sell copies of the Software, and to permit persons to whom the 31 * Software is furnished to do so, subject to the following conditions: 32 * 33 * The above copyright notice and this permission notice shall be included 34 * in all copies or substantial portions of the Software. 35 * 36 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 37 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 39 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 40 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 41 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 42 * OTHER DEALINGS IN THE SOFTWARE. 43 */ 44 45#include <stdio.h> 46#include <stdarg.h> 47#include "c99_math.h" 48#include "util/rounding.h" /* for _mesa_roundeven */ 49#include "imports.h" 50#include "context.h" 51#include "mtypes.h" 52#include "version.h" 53 54#ifdef _GNU_SOURCE 55#include <locale.h> 56#ifdef __APPLE__ 57#include <xlocale.h> 58#endif 59#endif 60 61 62#ifdef _WIN32 63#define vsnprintf _vsnprintf 64#elif defined(__IBMC__) || defined(__IBMCPP__) 65extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg); 66#endif 67 68/**********************************************************************/ 69/** \name Memory */ 70/*@{*/ 71 72/** 73 * Allocate aligned memory. 74 * 75 * \param bytes number of bytes to allocate. 76 * \param alignment alignment (must be greater than zero). 77 * 78 * Allocates extra memory to accommodate rounding up the address for 79 * alignment and to record the real malloc address. 80 * 81 * \sa _mesa_align_free(). 82 */ 83void * 84_mesa_align_malloc(size_t bytes, unsigned long alignment) 85{ 86#if defined(HAVE_POSIX_MEMALIGN) 87 void *mem; 88 int err = posix_memalign(& mem, alignment, bytes); 89 if (err) 90 return NULL; 91 return mem; 92#elif defined(_WIN32) 93 return _aligned_malloc(bytes, alignment); 94#else 95 uintptr_t ptr, buf; 96 97 assert( alignment > 0 ); 98 99 ptr = (uintptr_t)malloc(bytes + alignment + sizeof(void *)); 100 if (!ptr) 101 return NULL; 102 103 buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1); 104 *(uintptr_t *)(buf - sizeof(void *)) = ptr; 105 106#ifdef DEBUG 107 /* mark the non-aligned area */ 108 while ( ptr < buf - sizeof(void *) ) { 109 *(unsigned long *)ptr = 0xcdcdcdcd; 110 ptr += sizeof(unsigned long); 111 } 112#endif 113 114 return (void *) buf; 115#endif /* defined(HAVE_POSIX_MEMALIGN) */ 116} 117 118/** 119 * Same as _mesa_align_malloc(), but using calloc(1, ) instead of 120 * malloc() 121 */ 122void * 123_mesa_align_calloc(size_t bytes, unsigned long alignment) 124{ 125#if defined(HAVE_POSIX_MEMALIGN) 126 void *mem; 127 128 mem = _mesa_align_malloc(bytes, alignment); 129 if (mem != NULL) { 130 (void) memset(mem, 0, bytes); 131 } 132 133 return mem; 134#elif defined(_WIN32) 135 void *mem; 136 137 mem = _aligned_malloc(bytes, alignment); 138 if (mem != NULL) { 139 (void) memset(mem, 0, bytes); 140 } 141 142 return mem; 143#else 144 uintptr_t ptr, buf; 145 146 assert( alignment > 0 ); 147 148 ptr = (uintptr_t)calloc(1, bytes + alignment + sizeof(void *)); 149 if (!ptr) 150 return NULL; 151 152 buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1); 153 *(uintptr_t *)(buf - sizeof(void *)) = ptr; 154 155#ifdef DEBUG 156 /* mark the non-aligned area */ 157 while ( ptr < buf - sizeof(void *) ) { 158 *(unsigned long *)ptr = 0xcdcdcdcd; 159 ptr += sizeof(unsigned long); 160 } 161#endif 162 163 return (void *)buf; 164#endif /* defined(HAVE_POSIX_MEMALIGN) */ 165} 166 167/** 168 * Free memory which was allocated with either _mesa_align_malloc() 169 * or _mesa_align_calloc(). 170 * \param ptr pointer to the memory to be freed. 171 * The actual address to free is stored in the word immediately before the 172 * address the client sees. 173 * Note that it is legal to pass NULL pointer to this function and will be 174 * handled accordingly. 175 */ 176void 177_mesa_align_free(void *ptr) 178{ 179#if defined(HAVE_POSIX_MEMALIGN) 180 free(ptr); 181#elif defined(_WIN32) 182 _aligned_free(ptr); 183#else 184 if (ptr) { 185 void **cubbyHole = (void **) ((char *) ptr - sizeof(void *)); 186 void *realAddr = *cubbyHole; 187 free(realAddr); 188 } 189#endif /* defined(HAVE_POSIX_MEMALIGN) */ 190} 191 192/** 193 * Reallocate memory, with alignment. 194 */ 195void * 196_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize, 197 unsigned long alignment) 198{ 199#if defined(_WIN32) 200 (void) oldSize; 201 return _aligned_realloc(oldBuffer, newSize, alignment); 202#else 203 const size_t copySize = (oldSize < newSize) ? oldSize : newSize; 204 void *newBuf = _mesa_align_malloc(newSize, alignment); 205 if (newBuf && oldBuffer && copySize > 0) { 206 memcpy(newBuf, oldBuffer, copySize); 207 } 208 209 _mesa_align_free(oldBuffer); 210 return newBuf; 211#endif 212} 213 214/*@}*/ 215 216 217/**********************************************************************/ 218/** \name Math */ 219/*@{*/ 220 221 222#ifndef HAVE___BUILTIN_POPCOUNT 223/** 224 * Return number of bits set in given GLuint. 225 */ 226unsigned int 227_mesa_bitcount(unsigned int n) 228{ 229 unsigned int bits; 230 for (bits = 0; n > 0; n = n >> 1) { 231 bits += (n & 1); 232 } 233 return bits; 234} 235#endif 236 237#ifndef HAVE___BUILTIN_POPCOUNTLL 238/** 239 * Return number of bits set in given 64-bit uint. 240 */ 241unsigned int 242_mesa_bitcount_64(uint64_t n) 243{ 244 unsigned int bits; 245 for (bits = 0; n > 0; n = n >> 1) { 246 bits += (n & 1); 247 } 248 return bits; 249} 250#endif 251 252/*@}*/ 253 254 255/** Needed due to #ifdef's, above. */ 256int 257_mesa_vsnprintf(char *str, size_t size, const char *fmt, va_list args) 258{ 259 return vsnprintf( str, size, fmt, args); 260} 261 262/** Wrapper around vsnprintf() */ 263int 264_mesa_snprintf( char *str, size_t size, const char *fmt, ... ) 265{ 266 int r; 267 va_list args; 268 va_start( args, fmt ); 269 r = vsnprintf( str, size, fmt, args ); 270 va_end( args ); 271 return r; 272} 273 274 275