P>>На любое не получится, если память общая для всех потоков.
А>Вот, оптимизированный вариант. Быстро обнуляет все DWORDы в указанном процессе. Масштабируется на любое количество процессоров.
Еще и отрефакторил
#include <windows.h>
#include <queue>
#include <vector>
#include <algorithm>
class IThread
{
public:
virtual void ThreadRoutine() = 0;
};
class ThreadsPool
{
typedef std::vector<HANDLE> Handles;
IThread *_ithread;
Handles _handles;
static DWORD CALLBACK StaticThreadRoutine(void *p)
{
((ThreadsPool*)p)->_ithread->ThreadRoutine();
return 0;
}
public:
ThreadsPool(IThread *ithread) throw (std::runtime_error)
:
_ithread(ithread)
{
DWORD_PTR max_affinity = 0x01, sys_affinity;
if (!::GetProcessAffinityMask(::GetCurrentProcess(), &max_affinity, &sys_affinity))
max_affinity = 0x01;
for(DWORD_PTR i = 1; i; i<<=1)
{
if (max_affinity&i)
{
DWORD tid;
HANDLE trd = ::CreateThread(NULL, 0, StaticThreadRoutine, this, CREATE_SUSPENDED, &tid);
if (trd)
{
::SetThreadAffinityMask(trd, i);
_handles.push_back(trd);
}
}
}
if (_handles.empty())
throw std::runtime_error("failed to create threads");
printf("%u threads initialized\n", _handles.size());
}
void Complete()
{
if (_handles.empty())
throw std::runtime_error("already complete");
std::for_each(_handles.begin(), _handles.end(), ::ResumeThread);
for(size_t i=0; i<_handles.size(); i+=MAXIMUM_WAIT_OBJECTS)
{
::WaitForMultipleObjects(min(_handles.size()-i, MAXIMUM_WAIT_OBJECTS), &_handles[i], TRUE, INFINITE);
}
std::for_each(_handles.begin(), _handles.end(), ::CloseHandle);
_handles.clear();
}
};
class AbsoluteZero : private IThread
{
HANDLE _process;
typedef std::queue<MEMORY_BASIC_INFORMATION> MemoryRanges;
MemoryRanges _mem_ranges;
CRITICAL_SECTION _cs;
void ZeroThatDwords(PDWORD ptr, SIZE_T count)
{
for(;count;--count,++ptr)
{
DWORD etalon = 0, written;
::WriteProcessMemory(_process, ptr, &etalon, sizeof(etalon), &written);
}
}
virtual void ThreadRoutine()
{
for(;;)
{
MEMORY_BASIC_INFORMATION mbi;
::EnterCriticalSection(&_cs);
bool exit = _mem_ranges.empty();
if (!exit)
{
mbi = _mem_ranges.front();
_mem_ranges.pop();
}
::LeaveCriticalSection(&_cs);
if (exit) break;
ZeroThatDwords((PDWORD)mbi.BaseAddress, mbi.RegionSize/sizeof(DWORD));
}
}
void QueryMemory()
{
for(PCHAR ptr = NULL;ptr<(PCHAR)MAXLONG_PTR;)
{
MEMORY_BASIC_INFORMATION mbi = {0};
if (::VirtualQueryEx(_process, ptr, &mbi, sizeof(mbi)) && ((PCHAR)mbi.BaseAddress+mbi.RegionSize)>ptr)
{
if ( mbi.State!=MEM_FREE && mbi.State!=MEM_RESERVE &&
(mbi.Protect==PAGE_READWRITE || mbi.Protect==PAGE_WRITECOPY ||
mbi.Protect==PAGE_EXECUTE_READWRITE || mbi.Protect==PAGE_EXECUTE_WRITECOPY))
{
_mem_ranges.push(mbi);
}
ptr = (PCHAR)mbi.BaseAddress + mbi.RegionSize;
}
else
ptr+= 0x1000;
}
}
public:
AbsoluteZero(DWORD pid) throw (std::runtime_error)
{
_process = ::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE, FALSE, pid);
if (!_process)
{
throw std::runtime_error("failed to capture process handle");
}
::InitializeCriticalSection(&_cs);
}
virtual ~AbsoluteZero()
{
::DeleteCriticalSection(&_cs);
::CloseHandle(_process);
}
void ZeroAllDwords()
{
QueryMemory();
printf("%u memory regions found\n", _mem_ranges.size());
try
{
ThreadsPool(this).Complete();
}
catch (std::runtime_error &e)
{
printf("Threads error: %s [%u] will use single-thread model\n", e.what(), ::GetLastError());
ThreadRoutine();
}
}
};
int main(int argc, const char *argv[])
{
try
{
if (argc!=2)
throw std::runtime_error("You should specify one additional parameter - process wich DWORDs must be zeroed\n");
DWORD ticks = ::GetTickCount();
AbsoluteZero(atoi(argv[1])).ZeroAllDwords();
printf("Zeroing complete in %u msec\n", ::GetTickCount()-ticks);
}
catch(std::runtime_error &e)
{
printf("Error: %s [%u]\n", e.what(), ::GetLastError());
}
return 0;
}