home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / system / source / memory.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  9.8 KB  |  453 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #include "stdafx.h"
  27. #include <malloc.h>
  28. #include <windows.h>
  29. #include <vd2/system/atomic.h>
  30. #include <vd2/system/memory.h>
  31. #include <vd2/system/cpuaccel.h>
  32.  
  33. void *VDAlignedMalloc(size_t n, unsigned alignment) {
  34.     return _aligned_malloc(n, alignment);
  35. }
  36.  
  37. void VDAlignedFree(void *p) {
  38.     _aligned_free(p);
  39. }
  40.  
  41. void *VDAlignedVirtualAlloc(size_t n) {
  42.     return VirtualAlloc(NULL, n, MEM_COMMIT, PAGE_READWRITE);
  43. }
  44.  
  45. void VDAlignedVirtualFree(void *p) {
  46.     VirtualFree(p, 0, MEM_RELEASE);
  47. }
  48.  
  49. void VDSwapMemoryScalar(void *p0, void *p1, size_t bytes) {
  50.     uint32 *dst0 = (uint32 *)p0;
  51.     uint32 *dst1 = (uint32 *)p1;
  52.  
  53.     while(bytes >= 4) {
  54.         uint32 a = *dst0;
  55.         uint32 b = *dst1;
  56.  
  57.         *dst0++ = b;
  58.         *dst1++ = a;
  59.  
  60.         bytes -= 4;
  61.     }
  62.  
  63.     char *dstb0 = (char *)dst0;
  64.     char *dstb1 = (char *)dst1;
  65.  
  66.     while(bytes--) {
  67.         char a = *dstb0;
  68.         char b = *dstb1;
  69.  
  70.         *dstb0++ = b;
  71.         *dstb1++ = a;
  72.     }
  73. }
  74.  
  75. #if defined(VD_CPU_AMD64) || defined(VD_CPU_X86)
  76.     void VDSwapMemorySSE(void *p0, void *p1, size_t bytes) {
  77.         if (((uint32)(size_t)p0 | (uint32)(size_t)p1) & 15)
  78.             return VDSwapMemoryScalar(p0, p1, bytes);
  79.  
  80.         __m128 *pv0 = (__m128 *)p0;
  81.         __m128 *pv1 = (__m128 *)p1;
  82.  
  83.         size_t veccount = bytes >> 4;
  84.         if (veccount) {
  85.             do {
  86.                 __m128 v0 = *pv0;
  87.                 __m128 v1 = *pv1;
  88.  
  89.                 *pv0++ = v1;
  90.                 *pv1++ = v0;
  91.             } while(--veccount);
  92.         }
  93.  
  94.         uint32 left = bytes & 15;
  95.         if (left) {
  96.             uint8 *pb0 = (uint8 *)pv0;
  97.             uint8 *pb1 = (uint8 *)pv1;
  98.             do {
  99.                 uint8 b0 = *pb0;
  100.                 uint8 b1 = *pb1;
  101.  
  102.                 *pb0++ = b1;
  103.                 *pb1++ = b0;
  104.             } while(--left);
  105.         }
  106.     }
  107. #endif
  108.  
  109. void (__cdecl *VDSwapMemory)(void *p0, void *p1, size_t bytes) = VDSwapMemoryScalar;
  110.  
  111. void VDInvertMemory(void *p, unsigned bytes) {
  112.     char *dst = (char *)p;
  113.  
  114.     if (!bytes)
  115.         return;
  116.  
  117.     while((int)dst & 3) {
  118.         *dst = ~*dst;
  119.         ++dst;
  120.  
  121.         if (!--bytes)
  122.             return;
  123.     }
  124.  
  125.     unsigned lcount = bytes >> 2;
  126.  
  127.     if (lcount)
  128.         do {
  129.             *(long *)dst = ~*(long *)dst;
  130.             dst += 4;
  131.         } while(--lcount);
  132.  
  133.     bytes &= 3;
  134.  
  135.     while(bytes--) {
  136.         *dst = ~*dst;
  137.         ++dst;
  138.     }
  139. }
  140.  
  141. namespace {
  142.     uintptr VDGetSystemPageSizeW32() {
  143.         SYSTEM_INFO sysInfo;
  144.         GetSystemInfo(&sysInfo);
  145.  
  146.         return sysInfo.dwPageSize;
  147.     }
  148.  
  149.     uintptr VDGetSystemPageSize() {
  150.         static uintptr pageSize = VDGetSystemPageSizeW32();
  151.  
  152.         return pageSize;
  153.     }
  154. }
  155.  
  156. bool VDIsValidReadRegion(const void *p0, size_t bytes) {
  157.     if (!bytes)
  158.         return true;
  159.  
  160.     if (!p0)
  161.         return false;
  162.  
  163.     uintptr pageSize = VDGetSystemPageSize();
  164.     uintptr p = (uintptr)p0;
  165.     uintptr pLimit = p + (bytes-1);
  166.  
  167.     __try {
  168.         for(;;) {
  169.             *(volatile char *)p;
  170.  
  171.             if (pLimit - p < pageSize)
  172.                 break;
  173.  
  174.             p += pageSize;
  175.         }
  176.     } __except(1) {
  177.         return false;
  178.     }
  179.  
  180.     return true;
  181. }
  182.  
  183. bool VDIsValidWriteRegion(void *p0, size_t bytes) {
  184.     if (!bytes)
  185.         return true;
  186.  
  187.     if (!p0)
  188.         return false;
  189.  
  190.     // Note: Unlike IsValidWritePtr(), this is threadsafe.
  191.  
  192.     uintptr pageSize = VDGetSystemPageSize();
  193.     uintptr p = (uintptr)p0;
  194.     uintptr pLimit = p + (bytes-1);
  195.     p &= ~(uintptr)3;
  196.  
  197.     __try {
  198.         for(;;) {
  199.             VDAtomicInt::staticCompareExchange((volatile int *)p, 0xa5, 0xa5);
  200.  
  201.             if (pLimit - p < pageSize)
  202.                 break;
  203.  
  204.             p += pageSize;
  205.         }
  206.     } __except(1) {
  207.         return false;
  208.     }
  209.  
  210.     return true;
  211. }
  212.  
  213. bool VDCompareRect(void *dst, ptrdiff_t dstpitch, const void *src, ptrdiff_t srcpitch, size_t w, size_t h) {
  214.     if (!w || !h)
  215.         return false;
  216.  
  217.     do {
  218.         if (memcmp(dst, src, w))
  219.             return true;
  220.  
  221.         dst = (char *)dst + dstpitch;
  222.         src = (const char *)src + srcpitch;
  223.     } while(--h);
  224.  
  225.     return false;
  226. }
  227.  
  228. const void *VDMemCheck8(const void *src, uint8 value, size_t count) {
  229.     if (count) {
  230.         const uint8 *src8 = (const uint8 *)src;
  231.  
  232.         do {
  233.             if (*src8 != value)
  234.                 return src8;
  235.  
  236.             ++src8;
  237.         } while(--count);
  238.     }
  239.  
  240.     return NULL;
  241. }
  242.  
  243. void VDMemset8(void *dst, uint8 value, size_t count) {
  244.     if (count) {
  245.         uint8 *dst2 = (uint8 *)dst;
  246.  
  247.         do {
  248.             *dst2++ = value;
  249.         } while(--count);
  250.     }
  251. }
  252.  
  253. void VDMemset16(void *dst, uint16 value, size_t count) {
  254.     if (count) {
  255.         uint16 *dst2 = (uint16 *)dst;
  256.  
  257.         do {
  258.             *dst2++ = value;
  259.         } while(--count);
  260.     }
  261. }
  262.  
  263. void VDMemset24(void *dst, uint32 value, size_t count) {
  264.     if (count) {
  265.         uint8 *dst2 = (uint8 *)dst;
  266.         uint8 c0 = (uint8)value;
  267.         uint8 c1 = (uint8)(value >> 8);
  268.         uint8 c2 = (uint8)(value >> 16);
  269.  
  270.         do {
  271.             *dst2++ = c0;
  272.             *dst2++ = c1;
  273.             *dst2++ = c2;
  274.         } while(--count);
  275.     }
  276. }
  277.  
  278. void VDMemset32(void *dst, uint32 value, size_t count) {
  279.     if (count) {
  280.         uint32 *dst2 = (uint32 *)dst;
  281.  
  282.         do {
  283.             *dst2++ = value;
  284.         } while(--count);
  285.     }
  286. }
  287.  
  288. void VDMemset64(void *dst, uint64 value, size_t count) {
  289.     if (count) {
  290.         uint64 *dst2 = (uint64 *)dst;
  291.  
  292.         do {
  293.             *dst2++ = value;
  294.         } while(--count);
  295.     }
  296. }
  297.  
  298. void VDMemset128(void *dst, const void *src0, size_t count) {
  299.     if (count) {
  300.         const uint32 *src = (const uint32 *)src0;
  301.         uint32 a0 = src[0];
  302.         uint32 a1 = src[1];
  303.         uint32 a2 = src[2];
  304.         uint32 a3 = src[3];
  305.  
  306.         uint32 *dst2 = (uint32 *)dst;
  307.  
  308.         do {
  309.             dst2[0] = a0;
  310.             dst2[1] = a1;
  311.             dst2[2] = a2;
  312.             dst2[3] = a3;
  313.             dst2 += 4;
  314.         } while(--count);
  315.     }
  316. }
  317.  
  318. void VDMemsetPointer(void *dst, const void *value, size_t count) {
  319. #if defined(_M_IX86)
  320.     VDMemset32(dst, (uint32)(size_t)value, count);
  321. #elif defined(_M_AMD64)
  322.     VDMemset64(dst, (uint64)(size_t)value, count);
  323. #else
  324.     #error Unknown pointer size
  325. #endif
  326. }
  327.  
  328. void VDMemset8Rect(void *dst, ptrdiff_t pitch, uint8 value, size_t w, size_t h) {
  329.     if (w>0 && h>0) {
  330.         do {
  331.             memset(dst, value, w);
  332.             dst = (char *)dst + pitch;
  333.         } while(--h);
  334.     }
  335. }
  336.  
  337. void VDMemset16Rect(void *dst, ptrdiff_t pitch, uint16 value, size_t w, size_t h) {
  338.     if (w>0 && h>0) {
  339.         do {
  340.             VDMemset16(dst, value, w);
  341.             dst = (char *)dst + pitch;
  342.         } while(--h);
  343.     }
  344. }
  345.  
  346. void VDMemset24Rect(void *dst, ptrdiff_t pitch, uint32 value, size_t w, size_t h) {
  347.     if (w>0 && h>0) {
  348.         do {
  349.             VDMemset24(dst, value, w);
  350.             dst = (char *)dst + pitch;
  351.         } while(--h);
  352.     }
  353. }
  354.  
  355. void VDMemset32Rect(void *dst, ptrdiff_t pitch, uint32 value, size_t w, size_t h) {
  356.     if (w>0 && h>0) {
  357.         do {
  358.             VDMemset32(dst, value, w);
  359.             dst = (char *)dst + pitch;
  360.         } while(--h);
  361.     }
  362. }
  363.  
  364. #if defined(_WIN32) && defined(_M_IX86)
  365.     extern "C" void __cdecl VDFastMemcpyPartialScalarAligned8(void *dst, const void *src, size_t bytes);
  366.     extern "C" void __cdecl VDFastMemcpyPartialMMX(void *dst, const void *src, size_t bytes);
  367.     extern "C" void __cdecl VDFastMemcpyPartialMMX2(void *dst, const void *src, size_t bytes);
  368.  
  369.     void VDFastMemcpyPartialScalar(void *dst, const void *src, size_t bytes) {
  370.         if (!(((int)dst | (int)src | bytes) & 7))
  371.             VDFastMemcpyPartialScalarAligned8(dst, src, bytes);
  372.         else
  373.             memcpy(dst, src, bytes);
  374.     }
  375.  
  376.     void VDFastMemcpyFinishScalar() {
  377.     }
  378.  
  379.     void __cdecl VDFastMemcpyFinishMMX() {
  380.         __asm emms
  381.     }
  382.  
  383.     void __cdecl VDFastMemcpyFinishMMX2() {
  384.         __asm emms
  385.         __asm sfence
  386.     }
  387.  
  388.     void (__cdecl *VDFastMemcpyPartial)(void *dst, const void *src, size_t bytes) = VDFastMemcpyPartialScalar;
  389.     void (__cdecl *VDFastMemcpyFinish)() = VDFastMemcpyFinishScalar;
  390.  
  391.     void VDFastMemcpyAutodetect() {
  392.         long exts = CPUGetEnabledExtensions();
  393.  
  394.         if (exts & CPUF_SUPPORTS_SSE) {
  395.             VDFastMemcpyPartial = VDFastMemcpyPartialMMX2;
  396.             VDFastMemcpyFinish    = VDFastMemcpyFinishMMX2;
  397.             VDSwapMemory        = VDSwapMemorySSE;
  398.         } else if (exts & CPUF_SUPPORTS_INTEGER_SSE) {
  399.             VDFastMemcpyPartial = VDFastMemcpyPartialMMX2;
  400.             VDFastMemcpyFinish    = VDFastMemcpyFinishMMX2;
  401.             VDSwapMemory        = VDSwapMemoryScalar;
  402.         } else if (exts & CPUF_SUPPORTS_MMX) {
  403.             VDFastMemcpyPartial = VDFastMemcpyPartialMMX;
  404.             VDFastMemcpyFinish    = VDFastMemcpyFinishMMX;
  405.             VDSwapMemory        = VDSwapMemoryScalar;
  406.         } else {
  407.             VDFastMemcpyPartial = VDFastMemcpyPartialScalar;
  408.             VDFastMemcpyFinish    = VDFastMemcpyFinishScalar;
  409.             VDSwapMemory        = VDSwapMemoryScalar;
  410.         }
  411.     }
  412.  
  413. #else
  414.     void VDFastMemcpyPartial(void *dst, const void *src, size_t bytes) {
  415.         memcpy(dst, src, bytes);
  416.     }
  417.  
  418.     void VDFastMemcpyFinish() {
  419.     }
  420.  
  421.     void VDFastMemcpyAutodetect() {
  422.     }
  423. #endif
  424.  
  425. void VDMemcpyRect(void *dst, ptrdiff_t dststride, const void *src, ptrdiff_t srcstride, size_t w, size_t h) {
  426.     if (w <= 0 || h <= 0)
  427.         return;
  428.  
  429.     if (w == srcstride && w == dststride)
  430.         VDFastMemcpyPartial(dst, src, w*h);
  431.     else {
  432.         char *dst2 = (char *)dst;
  433.         const char *src2 = (const char *)src;
  434.  
  435.         do {
  436.             VDFastMemcpyPartial(dst2, src2, w);
  437.             dst2 += dststride;
  438.             src2 += srcstride;
  439.         } while(--h);
  440.     }
  441.     VDFastMemcpyFinish();
  442. }
  443.  
  444. bool VDMemcpyGuarded(void *dst, const void *src, size_t bytes) {
  445.     __try {
  446.         memcpy(dst, src, bytes);
  447.     } __except(GetExceptionCode() == STATUS_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  448.         return false;
  449.     }
  450.  
  451.     return true;
  452. }
  453.