1
0
forked from 0ad/0ad

- fix incorrect use of block vs. sector aligned (both offset and length must be block-aligned to allow proper caching)

- use helper functions to reduce occurrences of BLOCK_SIZE and
SECTOR_SIZE
- wmi: provide for shutting it down (gets rid of its two threads); only
initialize if actually needed (costs 200ms)
- ogl_tex: don't complain if there's no gfx_card info (due to not having
used wmi)

This was SVN commit r5572.
This commit is contained in:
janwas 2008-01-20 21:52:54 +00:00
parent aebf8cbf68
commit 58360a629c
14 changed files with 109 additions and 60 deletions

View File

@ -26,6 +26,7 @@
#include "lib/file/file.h"
#include "lib/file/file_system_posix.h"
#include "lib/file/io/io.h"
#include "lib/file/io/io_align.h" // BLOCK_SIZE
#include "lib/file/io/write_buffer.h"
static FileSystem_Posix s_fileSystemPosix;
@ -243,7 +244,7 @@ public:
return 'A';
}
virtual LibError Load(const std::string& UNUSED(name), shared_ptr<u8> buf, size_t size) const
virtual LibError Load(const std::string& name, shared_ptr<u8> buf, size_t size) const
{
AdjustOffset();
@ -456,7 +457,7 @@ private:
static LibError LocateCentralDirectory(PIFile file, off_t fileSize, off_t& cd_ofs, uint& cd_numEntries, off_t& cd_size)
{
const off_t maxScanSize = 66000u; // see below
shared_ptr<u8> buf = io_Allocate(maxScanSize, ~0); // assume worst-case for alignment
shared_ptr<u8> buf = io_Allocate(maxScanSize, BLOCK_SIZE-1); // assume worst-case for alignment
// expected case: ECDR at EOF; no file comment
LibError ret = ScanForEcdr(file, fileSize, const_cast<u8*>(buf.get()), sizeof(ECDR), cd_numEntries, cd_ofs, cd_size);

View File

@ -16,7 +16,7 @@
#include "lib/lockfree.h"
#include "lib/allocators/pool.h"
#include "lib/fnv_hash.h"
#include "io_internal.h"
#include "io_align.h"
//-----------------------------------------------------------------------------

View File

@ -12,12 +12,13 @@
#include "io.h"
#include "lib/allocators/allocators.h" // AllocatorChecker
#include "lib/bits.h" // IsAligned, round_up
#include "lib/sysdep/cpu.h" // cpu_memcpy
#include "lib/file/file.h"
#include "lib/file/common/file_stats.h"
#include "block_cache.h"
#include "io_internal.h"
#include "io_align.h"
static const unsigned ioDepth = 8;
// the underlying aio implementation likes buffer and offset to be
@ -93,9 +94,7 @@ shared_ptr<u8> io_Allocate(size_t size, off_t ofs)
{
debug_assert(size != 0);
const size_t misalignment = ofs % SECTOR_SIZE;
const size_t paddedSize = (size_t)round_up(size+misalignment, BLOCK_SIZE);
const size_t paddedSize = PaddedSize((off_t)size, ofs);
u8* mem = (u8*)page_aligned_alloc(paddedSize);
if(!mem)
throw std::bad_alloc();
@ -119,7 +118,7 @@ public:
{
m_file = file;
m_blockId = BlockId(file->Pathname(), alignedOfs);
if(false && file->Mode() == 'r' && s_blockCache.Retrieve(m_blockId, m_cachedBlock))
if(file->Mode() == 'r' && s_blockCache.Retrieve(m_blockId, m_cachedBlock))
{
stats_block_cache(CR_HIT);
@ -206,9 +205,9 @@ public:
: m_ofs(ofs), m_alignedBuf(alignedBuf), m_size(size)
, m_totalIssued(0), m_totalTransferred(0)
{
m_misalignment = ofs % SECTOR_SIZE;
m_alignedOfs = ofs - (off_t)m_misalignment;
m_alignedSize = round_up(m_misalignment+size, BLOCK_SIZE);
m_alignedOfs = AlignedOffset(ofs);
m_alignedSize = PaddedSize(size, ofs);
m_misalignment = ofs - m_alignedOfs;
}
LibError Run(PIFile file, IoCallback cb = 0, uintptr_t cbData = 0)
@ -241,9 +240,9 @@ public:
return INFO::OK;
}
size_t Misalignment() const
off_t AlignedOfs() const
{
return m_misalignment;
return m_alignedOfs;
}
private:
@ -302,15 +301,15 @@ LibError io_Read(PIFile file, off_t ofs, u8* alignedBuf, size_t size, u8*& data)
{
IoSplitter splitter(ofs, alignedBuf, (off_t)size);
RETURN_ERR(splitter.Run(file));
data = alignedBuf + splitter.Misalignment();
data = alignedBuf + ofs - splitter.AlignedOfs();
return INFO::OK;
}
LibError io_WriteAligned(PIFile file, off_t alignedOfs, const u8* alignedData, size_t size)
{
debug_assert(IsAligned(alignedOfs, SECTOR_SIZE));
debug_assert(IsAligned(alignedData, SECTOR_SIZE));
debug_assert(IsAligned_Offset(alignedOfs));
debug_assert(IsAligned_Data(alignedData));
IoSplitter splitter(alignedOfs, const_cast<u8*>(alignedData), (off_t)size);
return splitter.Run(file);
@ -319,8 +318,8 @@ LibError io_WriteAligned(PIFile file, off_t alignedOfs, const u8* alignedData, s
LibError io_ReadAligned(PIFile file, off_t alignedOfs, u8* alignedBuf, size_t size)
{
debug_assert(IsAligned(alignedOfs, SECTOR_SIZE));
debug_assert(IsAligned(alignedBuf, SECTOR_SIZE));
debug_assert(IsAligned_Offset(alignedOfs));
debug_assert(IsAligned_Data(alignedBuf));
IoSplitter splitter(alignedOfs, alignedBuf, (off_t)size);
return splitter.Run(file);

View File

@ -0,0 +1,23 @@
#include "precompiled.h"
#include "io_align.h"
bool IsAligned_Offset(off_t ofs)
{
return IsAligned(ofs, BLOCK_SIZE);
}
off_t AlignedOffset(off_t ofs)
{
return round_down(ofs, BLOCK_SIZE);
}
off_t AlignedSize(off_t size)
{
return round_up(size, BLOCK_SIZE);
}
off_t PaddedSize(off_t size, off_t ofs)
{
return round_up(size + ofs - AlignedOffset(ofs), BLOCK_SIZE);
}

View File

@ -0,0 +1,35 @@
#ifndef INCLUDED_IO_ALIGN
#define INCLUDED_IO_ALIGN
#include "lib/bits.h" // IsAligned, round_up
/**
* block := power-of-two sized chunk of a file.
* all transfers are expanded to naturally aligned, whole blocks.
* (this makes caching parts of files feasible; it is also much faster
* for some aio implementations, e.g. wposix.)
* (blocks are also thereby page-aligned, which allows write-protecting
* file buffers without worrying about their boundaries.)
**/
static const size_t BLOCK_SIZE = 256*KiB;
// note: *sizes* and *offsets* are aligned to blocks to allow zero-copy block cache.
// that the *buffer* need only be sector-aligned (we assume 4kb for simplicity)
// (this is a requirement of the underlying Windows OS)
static const size_t SECTOR_SIZE = 4*KiB;
template<class T>
bool IsAligned_Data(T* address)
{
return IsAligned((uintptr_t)address, SECTOR_SIZE);
}
extern bool IsAligned_Offset(off_t ofs);
extern off_t AlignedOffset(off_t ofs);
extern off_t AlignedSize(off_t size);
extern off_t PaddedSize(off_t size, off_t ofs);
#endif // #ifndef INCLUDED_IO_ALIGN

View File

@ -1,16 +0,0 @@
/**
* block := power-of-two sized chunk of a file.
* all transfers are expanded to naturally aligned, whole blocks.
* (this makes caching parts of files feasible; it is also much faster
* for some aio implementations, e.g. wposix.)
* (blocks are also thereby page-aligned, which allows write-protecting
* file buffers without worrying about their boundaries.)
**/
static const size_t BLOCK_SIZE = 256*KiB;
// note: *sizes* are aligned to blocks to allow zero-copy block cache.
// that the *buffer* and *offset* must be sector aligned (we assume 4kb for simplicity)
// is a requirement of the OS.
static const size_t SECTOR_SIZE = 4*KiB;
static const unsigned ioDepth = 8;

View File

@ -4,7 +4,7 @@
#include "lib/bits.h" // IsAligned
#include "lib/sysdep/cpu.h"
#include "io.h"
#include "io_internal.h"
#include "io_align.h"
WriteBuffer::WriteBuffer()
@ -40,8 +40,8 @@ void WriteBuffer::Overwrite(const void* data, size_t size, size_t offset)
UnalignedWriter::UnalignedWriter(PIFile file, off_t ofs)
: m_file(file), m_alignedBuf(io_Allocate(BLOCK_SIZE))
{
const size_t misalignment = (size_t)ofs % SECTOR_SIZE;
m_alignedOfs = ofs - (off_t)misalignment;
m_alignedOfs = AlignedOffset(ofs);
const size_t misalignment = (size_t)(ofs - m_alignedOfs);
if(misalignment)
io_ReadAligned(m_file, m_alignedOfs, m_alignedBuf.get(), BLOCK_SIZE);
m_bytesUsed = misalignment;

View File

@ -12,13 +12,13 @@
#include "file_cache.h"
#include "lib/file/common/file_stats.h"
#include "lib/file/io/io_internal.h" // sectorSize
#include "lib/cache_adt.h" // Cache
#include "lib/bits.h" // round_up
#include "lib/file/io/io_align.h" // BLOCK_SIZE
#include "lib/cache_adt.h" // Cache
#include "lib/bits.h" // round_up
#include "lib/allocators/allocators.h"
#include "lib/allocators/shared_ptr.h"
#include "lib/allocators/headerless.h"
#include "lib/allocators/mem_util.h" // mem_PageSize
#include "lib/allocators/mem_util.h" // mem_PageSize
//-----------------------------------------------------------------------------

View File

@ -647,8 +647,8 @@ void ogl_tex_override(OglTexOverrides what, OglTexAllow allow)
// called once from the first ogl_tex_upload.
static void detect_gl_upload_caps()
{
// make sure us and the app hook have graphics card info available
debug_assert(gfx_card[0] != '\0'); // gfx_detect must be called before ogl_tex_upload
// note: gfx_card will be empty if running in quickstart mode;
// in that case, we won't be able to check for known faulty cards.
// detect features, but only change the variables if they were at
// "undecided" (if overrides were set before this, they must remain).

View File

@ -13,13 +13,10 @@
#include <wbemidl.h>
#include "winit.h"
#include "lib/module_init.h"
#pragma comment(lib, "wbemuuid.lib")
WINIT_REGISTER_EARLY_INIT(wmi_Init);
WINIT_REGISTER_EARLY_SHUTDOWN(wmi_Shutdown);
static IWbemServices* pSvc;
@ -27,9 +24,13 @@ _COM_SMARTPTR_TYPEDEF(IWbemLocator, __uuidof(IWbemLocator));
_COM_SMARTPTR_TYPEDEF(IWbemClassObject, __uuidof(IWbemClassObject));
_COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, __uuidof(IEnumWbemClassObject));
static ModuleInitState initState;
static LibError wmi_Init()
static LibError Init()
{
if(!ModuleShouldInitialize(&initState))
return INFO::SKIPPED;
HRESULT hr;
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
@ -59,24 +60,26 @@ static LibError wmi_Init()
}
static LibError wmi_Shutdown()
void wmi_Shutdown()
{
// the memory pointed to by pSvc is already invalidated at this point;
// maybe some other module has already wiped out COM?
//pSvc->Release();
if(!ModuleShouldShutdown(&initState))
return;
pSvc->Release();
// note: don't shut down COM because other modules may still be using it.
//CoUninitialize();
return INFO::OK;
}
LibError wmi_GetClass(const char* className, WmiMap& wmiMap)
{
HRESULT hr;
Init();
IEnumWbemClassObjectPtr pEnum = 0;
char query[200];
sprintf_s(query, ARRAY_SIZE(query), "SELECT * FROM %s", className);
hr = pSvc->ExecQuery(L"WQL", _bstr_t(query), WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY, 0, &pEnum);
HRESULT hr = pSvc->ExecQuery(L"WQL", _bstr_t(query), WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY, 0, &pEnum);
if(FAILED(hr))
WARN_RETURN(ERR::FAIL);
debug_assert(pEnum);

View File

@ -26,4 +26,6 @@ typedef std::map<std::wstring, VARIANT> WmiMap;
**/
extern LibError wmi_GetClass(const char* className, WmiMap& wmiMap);
extern void wmi_Shutdown();
#endif // #ifndef INCLUDED_WMI

View File

@ -278,7 +278,7 @@ public:
if(isWrite)
ok = WriteFile(hFile, buf, u64_lo(size), &bytesTransferred, &m_overlapped);
else
ok = ReadFile(hFile, buf, u64_lo(size), &bytesTransferred, &m_overlapped);
ok = ReadFile(hFile, buf, u64_lo(size), &bytesTransferred, &m_overlapped);
if(!ok && GetLastError() == ERROR_IO_PENDING) // "pending" isn't an error
{
ok = TRUE;

View File

@ -978,8 +978,10 @@ void Init(const CmdLineArgs& args, uint flags)
uint quality = SANE_TEX_QUALITY_DEFAULT; // TODO: set value from config file
SetTextureQuality(quality);
// required by ogl_tex to detect broken gfx card/driver combos
gfx_detect();
// needed by ogl_tex to detect broken gfx card/driver combos,
// but takes a while due to WMI startup, so make it optional.
if(!g_Quickstart)
gfx_detect();
ogl_WarnIfError();

View File

@ -10,7 +10,7 @@
#include "lib/sysdep/snd.h"
#include "lib/sysdep/cpu.h"
#include "lib/tex/tex.h"
#include "lib/file/io/io_internal.h" // BLOCK_SIZE
#include "lib/file/io/io_align.h" // BLOCK_SIZE
#include "ps/GameSetup/Config.h"
#include "ps/GameSetup/GameSetup.h"