417 lines
9.7 KiB
C
417 lines
9.7 KiB
C
/*********************************************************
|
|
* Copyright (C) 2009-2015 VMware, Inc. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation version 2.1 and no later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
|
|
* License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
*********************************************************/
|
|
|
|
/*
|
|
* utilMem.c --
|
|
*
|
|
* misc util functions
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "vm_assert.h"
|
|
#include "util.h"
|
|
|
|
#ifdef __APPLE__
|
|
#include <TargetConditionals.h>
|
|
#if !defined TARGET_OS_IPHONE
|
|
#define TARGET_OS_IPHONE 0
|
|
#endif
|
|
#endif
|
|
|
|
static NORETURN void UtilAllocationFailure0(void);
|
|
static NORETURN void UtilAllocationFailure1(int bugNumber,
|
|
const char *file, int lineno);
|
|
|
|
|
|
static void
|
|
UtilAllocationFailure0(void)
|
|
{
|
|
Panic("Unrecoverable memory allocation failure\n");
|
|
}
|
|
|
|
|
|
static void
|
|
UtilAllocationFailure1(int bugNumber, const char *file, int lineno)
|
|
{
|
|
if (bugNumber == -1) {
|
|
Panic("Unrecoverable memory allocation failure at %s:%d\n",
|
|
file, lineno);
|
|
} else {
|
|
Panic("Unrecoverable memory allocation failure at %s:%d. Bug "
|
|
"number: %d\n", file, lineno, bugNumber);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* UtilSafeMalloc0 --
|
|
* UtilSafeMalloc1 --
|
|
* Helper function for malloc
|
|
*
|
|
* Results:
|
|
* Pointer to the dynamically allocated memory.
|
|
*
|
|
* Side effects:
|
|
* May Panic if ran out of memory.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void *
|
|
UtilSafeMalloc0(size_t size) // IN:
|
|
{
|
|
void *result = malloc(size);
|
|
if (result == NULL && size != 0) {
|
|
UtilAllocationFailure0();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
void *
|
|
UtilSafeMalloc1(size_t size, // IN:
|
|
int bugNumber, // IN:
|
|
const char *file, // IN:
|
|
int lineno) // IN:
|
|
{
|
|
void *result = malloc(size);
|
|
if (result == NULL && size != 0) {
|
|
UtilAllocationFailure1(bugNumber, file, lineno);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* UtilSafeRealloc0 --
|
|
* UtilSafeRealloc1 --
|
|
* Helper function for realloc
|
|
*
|
|
* Results:
|
|
* Pointer to the dynamically allocated memory.
|
|
*
|
|
* Side effects:
|
|
* May Panic if ran out of memory.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void *
|
|
UtilSafeRealloc0(void *ptr, // IN:
|
|
size_t size) // IN:
|
|
{
|
|
void *result = realloc(ptr, size);
|
|
if (result == NULL && size != 0) {
|
|
UtilAllocationFailure0();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
void *
|
|
UtilSafeRealloc1(void *ptr, // IN:
|
|
size_t size, // IN:
|
|
int bugNumber, // IN:
|
|
const char *file, // IN:
|
|
int lineno) // IN:
|
|
{
|
|
void *result = realloc(ptr, size);
|
|
if (result == NULL && size != 0) {
|
|
UtilAllocationFailure1(bugNumber, file, lineno);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* UtilSafeCalloc0 --
|
|
* UtilSafeCalloc1 --
|
|
* Helper function for calloc
|
|
*
|
|
* Results:
|
|
* Pointer to the dynamically allocated memory.
|
|
*
|
|
* Side effects:
|
|
* May Panic if ran out of memory.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void *
|
|
UtilSafeCalloc0(size_t nmemb, // IN:
|
|
size_t size) // IN:
|
|
{
|
|
void *result = calloc(nmemb, size);
|
|
if (result == NULL && nmemb != 0 && size != 0) {
|
|
UtilAllocationFailure0();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
void *
|
|
UtilSafeCalloc1(size_t nmemb, // IN:
|
|
size_t size, // IN:
|
|
int bugNumber, // IN:
|
|
const char *file, // IN:
|
|
int lineno) // IN:
|
|
{
|
|
void *result = calloc(nmemb, size);
|
|
if (result == NULL && nmemb != 0 && size != 0) {
|
|
UtilAllocationFailure1(bugNumber, file, lineno);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* Util_SafeStrdup --
|
|
* Helper function for strdup
|
|
*
|
|
* Results:
|
|
* Pointer to the dynamically allocated, duplicate string
|
|
*
|
|
* Side effects:
|
|
* May Panic if ran out of memory.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
char *
|
|
UtilSafeStrdup0(const char *s) // IN:
|
|
{
|
|
char *result;
|
|
if (s == NULL) {
|
|
return NULL;
|
|
}
|
|
#if defined(_WIN32)
|
|
if ((result = _strdup(s)) == NULL) {
|
|
#else
|
|
if ((result = strdup(s)) == NULL) {
|
|
#endif
|
|
UtilAllocationFailure0();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
char *
|
|
UtilSafeStrdup1(const char *s, // IN:
|
|
int bugNumber, // IN:
|
|
const char *file, // IN:
|
|
int lineno) // IN:
|
|
{
|
|
char *result;
|
|
if (s == NULL) {
|
|
return NULL;
|
|
}
|
|
#if defined(_WIN32)
|
|
if ((result = _strdup(s)) == NULL) {
|
|
#else
|
|
if ((result = strdup(s)) == NULL) {
|
|
#endif
|
|
UtilAllocationFailure1(bugNumber, file, lineno);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* Util_SafeStrndup --
|
|
*
|
|
* Returns a string consisting of first n characters of 's' if 's' has
|
|
* length >= 'n', otherwise returns a string duplicate of 's'.
|
|
*
|
|
* Results:
|
|
* Pointer to the duplicated string.
|
|
*
|
|
* Side effects:
|
|
* May Panic if ran out of memory.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
char *
|
|
UtilSafeStrndup0(const char *s, // IN:
|
|
size_t n) // IN:
|
|
{
|
|
size_t size;
|
|
char *copy;
|
|
const char *null;
|
|
size_t newSize;
|
|
|
|
if (s == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
null = memchr(s, '\0', n);
|
|
size = null ? (size_t)(null - s) : n;
|
|
newSize = size + 1;
|
|
if (newSize < size) { // Prevent integer overflow
|
|
copy = NULL;
|
|
} else {
|
|
copy = malloc(newSize);
|
|
}
|
|
|
|
if (copy == NULL) {
|
|
UtilAllocationFailure0();
|
|
}
|
|
|
|
copy[size] = '\0';
|
|
|
|
return (char *) memcpy(copy, s, size);
|
|
}
|
|
|
|
|
|
char *
|
|
UtilSafeStrndup1(const char *s, // IN:
|
|
size_t n, // IN:
|
|
int bugNumber, // IN:
|
|
const char *file, // IN:
|
|
int lineno) // IN:
|
|
{
|
|
size_t size;
|
|
char *copy;
|
|
const char *null;
|
|
size_t newSize;
|
|
|
|
if (s == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
null = memchr(s, '\0', n);
|
|
size = null ? (size_t)(null - s) : n;
|
|
newSize = size + 1;
|
|
if (newSize < size) { // Prevent integer overflow
|
|
copy = NULL;
|
|
} else {
|
|
copy = malloc(newSize);
|
|
}
|
|
|
|
if (copy == NULL) {
|
|
UtilAllocationFailure1(bugNumber, file, lineno);
|
|
}
|
|
|
|
copy[size] = '\0';
|
|
|
|
return (char *) memcpy(copy, s, size);
|
|
}
|
|
|
|
|
|
void *
|
|
Util_Memcpy(void *dest,
|
|
const void *src,
|
|
size_t count)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__)
|
|
uintptr_t align = ((uintptr_t)dest | (uintptr_t)src | count);
|
|
|
|
#if defined __GNUC__
|
|
|
|
#if defined(__x86_64__)
|
|
|
|
size_t dummy0;
|
|
void *dummy1;
|
|
void *dummy2;
|
|
|
|
if ((align & 7) == 0) {
|
|
__asm__ __volatile__("\t"
|
|
"cld" "\n\t"
|
|
"rep ; movsq" "\n"
|
|
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
|
|
: "0" (count >> 3), "1" (dest), "2" (src)
|
|
: "memory", "cc"
|
|
);
|
|
return dest;
|
|
} else if ((align & 3) == 0) {
|
|
__asm__ __volatile__("\t"
|
|
"cld" "\n\t"
|
|
"rep ; movsd" "\n"
|
|
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
|
|
: "0" (count >> 2), "1" (dest), "2" (src)
|
|
: "memory", "cc"
|
|
);
|
|
return dest;
|
|
}
|
|
|
|
#elif defined(__i386__)
|
|
|
|
size_t dummy0;
|
|
void *dummy1;
|
|
void *dummy2;
|
|
|
|
if ((align & 3) == 0) {
|
|
__asm__ __volatile__("\t"
|
|
"cld" "\n\t"
|
|
"rep ; movsd" "\n"
|
|
: "=c" (dummy0), "=D" (dummy1), "=S" (dummy2)
|
|
: "0" (count >> 2), "1" (dest), "2" (src)
|
|
: "memory", "cc"
|
|
);
|
|
return dest;
|
|
}
|
|
|
|
#endif
|
|
|
|
#elif defined _MSC_VER
|
|
|
|
#if defined(__x86_64__)
|
|
|
|
if ((align & 7) == 0) {
|
|
__movsq((uint64 *)dest, (uint64 *)src, count >> 3);
|
|
return dest;
|
|
} else if ((align & 3) == 0) {
|
|
__movsd((unsigned long *)dest, (unsigned long *)src, count >> 2);
|
|
return dest;
|
|
}
|
|
|
|
#elif defined(__i386__)
|
|
|
|
if ((((uintptr_t)dest | (uintptr_t)src | count) & 3) == 0) {
|
|
__movsd((unsigned long *)dest, (unsigned long *)src, count >> 2);
|
|
return dest;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#endif
|
|
#endif
|
|
|
|
memcpy(dest, src, count);
|
|
return dest;
|
|
}
|
|
|
|
|