]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c
BaseTools Lzma: Update LZMA SDK version to 18.05
[mirror_edk2.git] / BaseTools / Source / C / LzmaCompress / Sdk / C / Alloc.c
index 9f1d036afe9759640c0b481cc0654b64ca4efcc3..30b499e5ff7cce3433f1be9ee26b3582aa8c8ca8 100644 (file)
@@ -1,8 +1,10 @@
 /* Alloc.c -- Memory allocation functions\r
-2015-02-21 : Igor Pavlov : Public domain */\r
+2018-04-27 : Igor Pavlov : Public domain */\r
 \r
 #include "Precomp.h"\r
 \r
+#include <stdio.h>\r
+\r
 #ifdef _WIN32\r
 #include <windows.h>\r
 #endif\r
 \r
 /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */\r
 #ifdef _SZ_ALLOC_DEBUG\r
+\r
 #include <stdio.h>\r
 int g_allocCount = 0;\r
 int g_allocCountMid = 0;\r
 int g_allocCountBig = 0;\r
+\r
+\r
+#define CONVERT_INT_TO_STR(charType, tempSize) \\r
+  unsigned char temp[tempSize]; unsigned i = 0; \\r
+  while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \\r
+  *s++ = (charType)('0' + (unsigned)val); \\r
+  while (i != 0) { i--; *s++ = temp[i]; } \\r
+  *s = 0;\r
+\r
+static void ConvertUInt64ToString(UInt64 val, char *s)\r
+{\r
+  CONVERT_INT_TO_STR(char, 24);\r
+}\r
+\r
+#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))\r
+\r
+static void ConvertUInt64ToHex(UInt64 val, char *s)\r
+{\r
+  UInt64 v = val;\r
+  unsigned i;\r
+  for (i = 1;; i++)\r
+  {\r
+    v >>= 4;\r
+    if (v == 0)\r
+      break;\r
+  }\r
+  s[i] = 0;\r
+  do\r
+  {\r
+    unsigned t = (unsigned)(val & 0xF);\r
+    val >>= 4;\r
+    s[--i] = GET_HEX_CHAR(t);\r
+  }\r
+  while (i);\r
+}\r
+\r
+#define DEBUG_OUT_STREAM stderr\r
+\r
+static void Print(const char *s)\r
+{\r
+  fputs(s, DEBUG_OUT_STREAM);\r
+}\r
+\r
+static void PrintAligned(const char *s, size_t align)\r
+{\r
+  size_t len = strlen(s);\r
+  for(;;)\r
+  {\r
+    fputc(' ', DEBUG_OUT_STREAM);\r
+    if (len >= align)\r
+      break;\r
+    ++len;\r
+  }\r
+  Print(s);\r
+}\r
+\r
+static void PrintLn()\r
+{\r
+  Print("\n");\r
+}\r
+\r
+static void PrintHex(UInt64 v, size_t align)\r
+{\r
+  char s[32];\r
+  ConvertUInt64ToHex(v, s);\r
+  PrintAligned(s, align);\r
+}\r
+\r
+static void PrintDec(UInt64 v, size_t align)\r
+{\r
+  char s[32];\r
+  ConvertUInt64ToString(v, s);\r
+  PrintAligned(s, align);\r
+}\r
+\r
+static void PrintAddr(void *p)\r
+{\r
+  PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12);\r
+}\r
+\r
+\r
+#define PRINT_ALLOC(name, cnt, size, ptr) \\r
+    Print(name " "); \\r
+    PrintDec(cnt++, 10); \\r
+    PrintHex(size, 10); \\r
+    PrintAddr(ptr); \\r
+    PrintLn();\r
\r
+#define PRINT_FREE(name, cnt, ptr) if (ptr) { \\r
+    Print(name " "); \\r
+    PrintDec(--cnt, 10); \\r
+    PrintAddr(ptr); \\r
+    PrintLn(); }\r
\r
+#else\r
+\r
+#define PRINT_ALLOC(name, cnt, size, ptr)\r
+#define PRINT_FREE(name, cnt, ptr)\r
+#define Print(s)\r
+#define PrintLn()\r
+#define PrintHex(v, align)\r
+#define PrintDec(v, align)\r
+#define PrintAddr(p)\r
+\r
 #endif\r
 \r
+\r
+\r
 void *MyAlloc(size_t size)\r
 {\r
   if (size == 0)\r
-    return 0;\r
+    return NULL;\r
   #ifdef _SZ_ALLOC_DEBUG\r
   {\r
     void *p = malloc(size);\r
-    fprintf(stderr, "\nAlloc %10d bytes, count = %10d,  addr = %8X", size, g_allocCount++, (unsigned)p);\r
+    PRINT_ALLOC("Alloc    ", g_allocCount, size, p);\r
     return p;\r
   }\r
   #else\r
@@ -37,10 +146,8 @@ void *MyAlloc(size_t size)
 \r
 void MyFree(void *address)\r
 {\r
-  #ifdef _SZ_ALLOC_DEBUG\r
-  if (address != 0)\r
-    fprintf(stderr, "\nFree; count = %10d,  addr = %8X", --g_allocCount, (unsigned)address);\r
-  #endif\r
+  PRINT_FREE("Free    ", g_allocCount, address);\r
+  \r
   free(address);\r
 }\r
 \r
@@ -49,20 +156,18 @@ void MyFree(void *address)
 void *MidAlloc(size_t size)\r
 {\r
   if (size == 0)\r
-    return 0;\r
-  #ifdef _SZ_ALLOC_DEBUG\r
-  fprintf(stderr, "\nAlloc_Mid %10d bytes;  count = %10d", size, g_allocCountMid++);\r
-  #endif\r
-  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);\r
+    return NULL;\r
+  \r
+  PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL);\r
+  \r
+  return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);\r
 }\r
 \r
 void MidFree(void *address)\r
 {\r
-  #ifdef _SZ_ALLOC_DEBUG\r
-  if (address != 0)\r
-    fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);\r
-  #endif\r
-  if (address == 0)\r
+  PRINT_FREE("Free-Mid", g_allocCountMid, address);\r
+\r
+  if (!address)\r
     return;\r
   VirtualFree(address, 0, MEM_RELEASE);\r
 }\r
@@ -79,10 +184,10 @@ typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
 void SetLargePageSize()\r
 {\r
   #ifdef _7ZIP_LARGE_PAGES\r
-  SIZE_T size = 0;\r
+  SIZE_T size;\r
   GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)\r
         GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");\r
-  if (largePageMinimum == 0)\r
+  if (!largePageMinimum)\r
     return;\r
   size = largePageMinimum();\r
   if (size == 0 || (size & (size - 1)) != 0)\r
@@ -95,31 +200,36 @@ void SetLargePageSize()
 void *BigAlloc(size_t size)\r
 {\r
   if (size == 0)\r
-    return 0;\r
-  #ifdef _SZ_ALLOC_DEBUG\r
-  fprintf(stderr, "\nAlloc_Big %10d bytes;  count = %10d", size, g_allocCountBig++);\r
-  #endif\r
+    return NULL;\r
+\r
+  PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL);\r
   \r
   #ifdef _7ZIP_LARGE_PAGES\r
-  if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))\r
   {\r
-    void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),\r
-        MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);\r
-    if (res != 0)\r
-      return res;\r
+    SIZE_T ps = g_LargePageSize;\r
+    if (ps != 0 && ps <= (1 << 30) && size > (ps / 2))\r
+    {\r
+      size_t size2;\r
+      ps--;\r
+      size2 = (size + ps) & ~ps;\r
+      if (size2 >= size)\r
+      {\r
+        void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);\r
+        if (res)\r
+          return res;\r
+      }\r
+    }\r
   }\r
   #endif\r
-  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);\r
+\r
+  return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);\r
 }\r
 \r
 void BigFree(void *address)\r
 {\r
-  #ifdef _SZ_ALLOC_DEBUG\r
-  if (address != 0)\r
-    fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);\r
-  #endif\r
+  PRINT_FREE("Free-Big", g_allocCountBig, address);\r
   \r
-  if (address == 0)\r
+  if (!address)\r
     return;\r
   VirtualFree(address, 0, MEM_RELEASE);\r
 }\r
@@ -127,10 +237,219 @@ void BigFree(void *address)
 #endif\r
 \r
 \r
-static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }\r
-static void SzFree(void *p, void *address) { UNUSED_VAR(p); MyFree(address); }\r
-ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }\r
+static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); }\r
+const ISzAlloc g_Alloc = { SzAlloc, SzFree };\r
+\r
+static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); }\r
+static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); }\r
+const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };\r
+\r
+static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }\r
+static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); }\r
+const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+\r
+\r
+/*\r
+  uintptr_t : <stdint.h> C99 (optional)\r
+            : unsupported in VS6\r
+*/\r
+\r
+#ifdef _WIN32\r
+  typedef UINT_PTR UIntPtr;\r
+#else\r
+  /*\r
+  typedef uintptr_t UIntPtr;\r
+  */\r
+  typedef ptrdiff_t UIntPtr;\r
+#endif\r
+\r
+\r
+#define ADJUST_ALLOC_SIZE 0\r
+/*\r
+#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1)\r
+*/\r
+/*\r
+  Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if\r
+     MyAlloc() can return address that is NOT multiple of sizeof(void *).\r
+*/\r
+\r
+\r
+/*\r
+#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1))))\r
+*/\r
+#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1))))\r
+\r
+#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align)\r
+\r
+\r
+#if (_POSIX_C_SOURCE >= 200112L) && !defined(_WIN32)\r
+  #define USE_posix_memalign\r
+#endif\r
+\r
+/*\r
+  This posix_memalign() is for test purposes only.\r
+  We also need special Free() function instead of free(),\r
+  if this posix_memalign() is used.\r
+*/\r
+\r
+/*\r
+static int posix_memalign(void **ptr, size_t align, size_t size)\r
+{\r
+  size_t newSize = size + align;\r
+  void *p;\r
+  void *pAligned;\r
+  *ptr = NULL;\r
+  if (newSize < size)\r
+    return 12; // ENOMEM\r
+  p = MyAlloc(newSize);\r
+  if (!p)\r
+    return 12; // ENOMEM\r
+  pAligned = MY_ALIGN_PTR_UP_PLUS(p, align);\r
+  ((void **)pAligned)[-1] = p;\r
+  *ptr = pAligned;\r
+  return 0;\r
+}\r
+*/\r
+\r
+/*\r
+  ALLOC_ALIGN_SIZE >= sizeof(void *)\r
+  ALLOC_ALIGN_SIZE >= cache_line_size\r
+*/\r
+\r
+#define ALLOC_ALIGN_SIZE ((size_t)1 << 7)\r
+\r
+static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)\r
+{\r
+  #ifndef USE_posix_memalign\r
+  \r
+  void *p;\r
+  void *pAligned;\r
+  size_t newSize;\r
+  UNUSED_VAR(pp);\r
+\r
+  /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned\r
+     block to prevent cache line sharing with another allocated blocks */\r
+\r
+  newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE;\r
+  if (newSize < size)\r
+    return NULL;\r
+\r
+  p = MyAlloc(newSize);\r
+  \r
+  if (!p)\r
+    return NULL;\r
+  pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE);\r
+\r
+  Print(" size="); PrintHex(size, 8);\r
+  Print(" a_size="); PrintHex(newSize, 8);\r
+  Print(" ptr="); PrintAddr(p);\r
+  Print(" a_ptr="); PrintAddr(pAligned);\r
+  PrintLn();\r
+\r
+  ((void **)pAligned)[-1] = p;\r
+\r
+  return pAligned;\r
+\r
+  #else\r
+\r
+  void *p;\r
+  UNUSED_VAR(pp);\r
+  if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size))\r
+    return NULL;\r
+\r
+  Print(" posix_memalign="); PrintAddr(p);\r
+  PrintLn();\r
+\r
+  return p;\r
+\r
+  #endif\r
+}\r
+\r
+\r
+static void SzAlignedFree(ISzAllocPtr pp, void *address)\r
+{\r
+  UNUSED_VAR(pp);\r
+  #ifndef USE_posix_memalign\r
+  if (address)\r
+    MyFree(((void **)address)[-1]);\r
+  #else\r
+  free(address);\r
+  #endif\r
+}\r
+\r
+\r
+const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };\r
+\r
+\r
+\r
+#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *))\r
+\r
+/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */\r
+#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1]\r
+/*\r
+#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1]\r
+*/\r
+\r
+static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)\r
+{\r
+  CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);\r
+  void *adr;\r
+  void *pAligned;\r
+  size_t newSize;\r
+  size_t extra;\r
+  size_t alignSize = (size_t)1 << p->numAlignBits;\r
+\r
+  if (alignSize < sizeof(void *))\r
+    alignSize = sizeof(void *);\r
+  \r
+  if (p->offset >= alignSize)\r
+    return NULL;\r
+\r
+  /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned\r
+     block to prevent cache line sharing with another allocated blocks */\r
+  extra = p->offset & (sizeof(void *) - 1);\r
+  newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE;\r
+  if (newSize < size)\r
+    return NULL;\r
 \r
-static void *SzBigAlloc(void *p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }\r
-static void SzBigFree(void *p, void *address) { UNUSED_VAR(p); BigFree(address); }\r
-ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\r
+  adr = ISzAlloc_Alloc(p->baseAlloc, newSize);\r
+  \r
+  if (!adr)\r
+    return NULL;\r
+\r
+  pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr +\r
+      alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset;\r
+\r
+  PrintLn();\r
+  Print("- Aligned: ");\r
+  Print(" size="); PrintHex(size, 8);\r
+  Print(" a_size="); PrintHex(newSize, 8);\r
+  Print(" ptr="); PrintAddr(adr);\r
+  Print(" a_ptr="); PrintAddr(pAligned);\r
+  PrintLn();\r
+\r
+  REAL_BLOCK_PTR_VAR(pAligned) = adr;\r
+\r
+  return pAligned;\r
+}\r
+\r
+\r
+static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)\r
+{\r
+  if (address)\r
+  {\r
+    CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);\r
+    PrintLn();\r
+    Print("- Aligned Free: ");\r
+    PrintLn();\r
+    ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address));\r
+  }\r
+}\r
+\r
+\r
+void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p)\r
+{\r
+  p->vt.Alloc = AlignOffsetAlloc_Alloc;\r
+  p->vt.Free = AlignOffsetAlloc_Free;\r
+}\r