📄 sharedpool.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 + -