⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sharedpool.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
字号:
/***********************************************************************
 Copyright 2002 Ben Rudiak-Gould.

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any 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
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA,
 or visit <http://www.gnu.org/copyleft/gpl.html>.
***********************************************************************/


#include "SharedPool.h"
#include "miniport.h"

#include <stdio.h>

/*******************************************************************\
\*******************************************************************/


#define max(a,b) ((a)<(b)?(b):(a))


/*******************************************************************\
\*******************************************************************/


// values for page (PageReserve)
#define PR_PRIVATE 0x80000400
#define PR_SHARED  0x80060000
#define PR_SYSTEM  0x80080000

// values for flags (PageReserve)
#define PR_FIXED    0x00000008
#define PR_4MEG     0x00000001
#define PR_STATIC   0x00000010

// values for hpd (PageCommit)
#define PD_ZEROINIT  1
#define PD_NOINIT    2
#define PD_FIXEDZERO 3
#define PD_FIXED     4

// values for flags (PageCommit)
#define PC_FIXED      0x00000008
#define PC_LOCKED     0x00000080
#define PC_LOCKEDIFDP 0x00000100
#define PC_WRITEABLE  0x00020000
#define PC_USER       0x00040000
#define PC_INCR       0x40000000
#define PC_PRESENT    0x80000000
#define PC_STATIC     0x20000000
#define PC_DIRTY      0x08000000
#define PC_CACHEDIS   0x00100000
#define PC_CACHEWT    0x00080000
#define PC_PAGEFLUSH  0x00008000


void* _PageReserve(unsigned page, unsigned npages, unsigned flags) {
   return Miniport::DriverCall(miniport_handle, (char*)mpdfunc__PageReserve, "iii", page, npages, flags);
}

unsigned _PageCommit(unsigned page, unsigned npages, unsigned hpd, unsigned pagerdata, unsigned flags) {
   return (unsigned)Miniport::DriverCall(miniport_handle, (char*)mpdfunc__PageCommit, "iiiii", page, npages, hpd, pagerdata, flags);
}

unsigned _PageFree(void* p, unsigned flags=0) {
   return (unsigned)Miniport::DriverCall(miniport_handle, (char*)mpdfunc__PageFree, "ii", p, flags);
}


inline bool PageCommit(void* p, unsigned npages, int locked) {
   unsigned page = unsigned(p) >> 12;
   return !!_PageCommit(page, npages,
      locked ? PD_FIXEDZERO : PD_ZEROINIT, 0,
      locked ? PC_USER+PC_WRITEABLE+PC_FIXED : PC_USER+PC_WRITEABLE);
}


/*******************************************************************\
\*******************************************************************/


class SharedPool {
   char* latest_block_next_free_byte;
   char* latest_block_end;
   unsigned latest_block_index;
   int locked;
   char* blocks[18];

public:
   static void* Create(int _locked);
   void* Allocate(unsigned len);
   void Clear();
   void Delete();
};

inline void* SharedPool::Create(int _locked) {
   char* block = (char*)_PageReserve(PR_SHARED, 1, _locked ? PR_FIXED : 0);
   if (!block) {
      return 0;
   }
   if (!PageCommit(block, 1, _locked)) {
      _PageFree(block);
      return 0;
   }
   SharedPool* self = (SharedPool*)block;
   self->latest_block_next_free_byte = block + sizeof(SharedPool);
   self->latest_block_end = block + 4096;
   self->locked = _locked;
   self->blocks[0] = block;
   return self;
}

inline void* SharedPool::Allocate(unsigned len) {
   len = (len+3) & -4;

   char* alloc_end = latest_block_next_free_byte + len;
   if (alloc_end > latest_block_end) {
      // Current block isn't big enough; allocate a new one. The size of
      // block N is at least 4K * 2^N, to ensure that we'll run out of
      // virtual address space before we run out of array slots.
      unsigned pages_to_alloc = max((len + 4095U) >> 12, 2U << latest_block_index);
      char* new_block = (char*)_PageReserve(PR_SHARED, pages_to_alloc, locked ? PR_FIXED : 0);
      if (new_block == 0) {
         return 0;
      }
      latest_block_next_free_byte = new_block;
      latest_block_end = new_block + pages_to_alloc*4096;
      ++latest_block_index;
      blocks[latest_block_index] = new_block;
      alloc_end = new_block + len;
   }
   char* first_uncommitted_byte = (char*)(((unsigned)latest_block_next_free_byte + 4095) & -4096);
   if (alloc_end > first_uncommitted_byte) {
      unsigned pages_to_commit = (alloc_end - first_uncommitted_byte + 4095) >> 12;
      if (!PageCommit(first_uncommitted_byte, pages_to_commit, locked)) {
         return 0;
      }
   }
   void* rtn = latest_block_next_free_byte;
   latest_block_next_free_byte = alloc_end;
   return rtn;
}


inline void SharedPool::Clear() {
   for (unsigned i=1; i<=latest_block_index; ++i) {
      _PageFree(blocks[i]);
   }
   latest_block_next_free_byte = blocks[0] + sizeof(SharedPool);
   latest_block_end = blocks[0] + 4096;
   latest_block_index = 0;
}

inline void SharedPool::Delete() {
   for (unsigned i=1; i<=latest_block_index; ++i) {
      _PageFree(blocks[i]);
   }
   _PageFree(blocks[0]);
}


void* SharedPool_Create(int locked) {
   return SharedPool::Create(locked);
}
void* SharedPool_Alloc(void* self, unsigned len) {
   return ((SharedPool*)self)->Allocate(len);
}
void SharedPool_Clear(void* self) {
   ((SharedPool*)self)->Clear();
}
void SharedPool_Delete(void* self) {
   ((SharedPool*)self)->Delete();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -