Suppose I have a class
class Apple
{
bool flag =false;
Apple()
{
}
};
Apple apple=Apple();
Then a thread is created.
CreateThread(...
The instance apple is somehow passed to the thread.
Now int main program later make changes
apple.flag = true;
The problem is the thread is not detecting it.
In thread function,
if(apple.flag==true)
printf("Value changed");
It will not print anything.
I hope the situation is clear. Thanks in advance.
Edit: Minimal working example:
#include <windows.h>
#include <stdio.h>
class Apple
{
public:
bool flag = false;
Apple()
{
}
};
Apple all[1];
DWORD WINAPI myFunc(LPVOID lpParameter)
{
Apple t = *((Apple*)lpParameter);
for (int i = 0; i < 10; i++)
{
printf("flag = %d\n", t.flag);
Sleep(1000);
}
return 55;
}
int main()
{
int n = 0;
printf("flag is %d", all[n].flag);
DWORD myThreadID;
HANDLE myHandle = CreateThread(0, 0, myFunc, &(all[n]), 0, &myThreadID);
for(int i=0;i<10;i++)
{
if (i == 5)
{
all[n].flag = true;
printf("Value of flag set to %d by main\n", all[n].flag);
}
Sleep(1000);
}
return true;
}
Output
flag is 0flag = 0
flag = 0
flag = 0
flag = 0
flag = 0
Value of flag set to 1 by main
flag = 0
flag = 0
flag = 0
flag = 0
flag = 0
Related
I'm trying to get the size of allocated are for a process, descriminated by image, private and mapped. I'm using QueryWorkingSet to get the Working Set Information and then the Working Set Block.
When i called it for the first time, the GetLastError method return 24 which is to be expected so the next time I call QueryWorkingSet I set a diferent size for the block but then im getting an error code of 998.
Am I using QueryWorkingSet wrong or Im getting the handle for the process with the wrong access rights or Im the resize is not enough?
#include "pch.h"
#include <Windows.h>
#include<WinDef.h>
#include <psapi.h>
#include <iostream>
typedef struct {
DWORD img;
DWORD map;
DWORD prv;
} CommitCounters, *PCommitCounters;
BOOL GetCommitCountersFromProcess(_In_ int pid, _Out_ PCommitCounters committedCounter ) {
int numberOfTries = 3;
SYSTEM_INFO si;
GetSystemInfo(&si);
DWORD pageSz = si.dwPageSize;
PSAPI_WORKING_SET_INFORMATION wsi, *pwsi;
pwsi = &wsi;
DWORD ws_size;
MEMORY_BASIC_INFORMATION mbi, *pmbi;
pmbi = &mbi;
HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
wsi.NumberOfEntries = 0;
QueryWorkingSet(processHandle, &wsi, sizeof(pwsi));
BOOL res = false;
committedCounter->img = 0;
committedCounter->map = 0;
committedCounter->prv = 0;
while (numberOfTries > 0) {
DWORD lastError = GetLastError();
//ERROR_BAD_LENGTH
if (lastError == 24) {
ws_size = sizeof(wsi) + sizeof(PSAPI_WORKING_SET_INFORMATION) + sizeof(PSAPI_WORKING_SET_BLOCK) * wsi.NumberOfEntries;
pwsi = (PSAPI_WORKING_SET_INFORMATION*) malloc(ws_size);
pwsi->NumberOfEntries = wsi.NumberOfEntries;
BOOL resQws = QueryWorkingSet(processHandle, &wsi, ws_size);
DWORD teste = sizeof(wsi);
if (resQws) {
for (int i = 0; i < pwsi->NumberOfEntries; i++) {
PSAPI_WORKING_SET_BLOCK ws_block = pwsi->WorkingSetInfo[1];
//Access page information.
SIZE_T size = VirtualQuery((LPCVOID*)ws_block.VirtualPage, &mbi, 1);
if (size != 0 && pmbi ->State == 0x1000) {
switch (pmbi->Type)
{
case 0x1000000: // MEM_IMAGE
committedCounter->img += pageSz;
break;
case 0x40000: //MEM_MAPPED
committedCounter->map += pageSz;
break;
case 0x20000: //MEM_PRIVATE
committedCounter->prv += pageSz;
break;
}
}
else if (size == 0) {
return res;
}
}
CloseHandle(processHandle);
res = true;
return res;
}
free(pwsi);
}
numberOfTries--;
}
CloseHandle(processHandle);
return false;
}
You have a typo in your code. Just change:
BOOL resQws = QueryWorkingSet(processHandle, &wsi, ws_size);
to:
BOOL resQws = QueryWorkingSet(processHandle, pwsi, ws_size);
And then the call succeeds.
There may be further errors but I did not investigate those.
I wrote a simple test application to prove that the threads work:
// Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
class clsTest {
private:
uintptr_t muintHandle;
static unsigned int __stdcall fnThread(void* pData) {
while( 1 ) {
_sleep(1000);
printf("In fnThread, handle = %d\n", *(uintptr_t*)pData);
}
return 0;
}
public:
clsTest() {
muintHandle = _beginthreadex(0, 0, &clsTest::fnThread, (void*)&muintHandle, 0, 0);
printf("clsTest(), after beginthreadex, handle = %u\n", muintHandle);
}
};
int _tmain(int argc, _TCHAR* argv[]) {
clsTest* pT = NULL;
while(1) {
printf("From _tmain\n");
if ( pT == NULL ) {
pT = new clsTest();
}
_sleep(1000);
}
return 0;
}
The output from this application is:
From _tmain
clsTest(), after beginthreadex, handle = 112
In fnThread, handle = 112
From _tmain
In fnThread, handle = 112
From _tmain
In fnThread, handle = 112
From _tmain
In fnThread, handle = 112
From _tmain
In fnThread, handle = 112
From _tmain
In fnThread, handle = 112
...
Continuously which is exactly what I would expect to see...Now in a much larger project I have a base class:
typedef enum {
eIdle = 0, //Thread is not working at all
eStarted, //Thread has been started but is not fully operational yet
eRunning, //Thread is working normally
ePausing, //Thread is requested to enter the paused state
ePaused, //Thread is paused
eTerminating //Termination has been requested but not completed yet
} eThreadStates;
class clsOpenLDVthread {
protected:
volatile eThreadStates meState;
CRITICAL_SECTION mCritControl; // critical section for thread control
char mszName[80];
HANDLE mhEvent, mhThread;
virtual bool blnStart() = 0;
public:
clsOpenLDVthread(LPCSTR pszName);
~clsOpenLDVthread();
bool inline blnIsRunning();
bool inline blnIsStopped();
bool inline blnIsStopping();
bool inline blnIsStarting();
bool inline blnIsPausing();
bool inline blnIsPaused();
bool blnPause(bool blnState);
virtual bool blnStop();
};
clsOpenLDVthread::clsOpenLDVthread(LPCSTR pszName) : meState(eIdle)
, mhThread(NULL) {
::InitializeCriticalSection(&mCritControl); //Get a critical section
//Get a unique name for signaling event
sprintf(mszName, "%s%d", pszName, ::GetCurrentProcessId());
//Get the event object
mhEvent = ::CreateEvent(NULL, FALSE, FALSE, mszName);
}
clsOpenLDVthread::~clsOpenLDVthread() {
if ( blnIsPaused() ) {
blnPause(false);
}
if ( blnIsRunning() ) {
blnStop();
}
if ( mhEvent ) {
::CloseHandle(mhEvent);
mhEvent = NULL;
}
::DeleteCriticalSection(&mCritControl);
}
bool clsOpenLDVthread::blnIsPaused() {
return meState == ePaused;
}
bool clsOpenLDVthread::blnIsPausing() {
return meState == ePausing;
}
bool clsOpenLDVthread::blnIsRunning() {
return meState == eRunning;
}
bool clsOpenLDVthread::blnIsStarting() {
return meState == eStarted;
}
bool clsOpenLDVthread::blnIsStopped() {
return meState == eIdle;
}
bool clsOpenLDVthread::blnIsStopping() {
return meState == eTerminating;
}
bool clsOpenLDVthread::blnPause(bool blnState) {
bool blnResult = mhThread != NULL;
if ( blnResult ) {
if ( blnState ) {
unsigned uintCountDown = 10u;
if ( blnIsRunning() || blnIsPausing() ) {
meState = ePausing;
while( blnIsPausing() && -- uintCountDown ) {
::SetEvent(mhEvent);
//Give thread chance to run and pause
_sleep(751);
}
blnResult = blnIsPaused();
}
} else {
if ( blnIsPaused() ) {
meState = eRunning;
//this will need replacing...mhThread->ResumeThread();
}
blnResult = true;
}
}
return blnResult;
}
bool clsOpenLDVthread::blnStop() {
bool blnResult = meState == eIdle;
unsigned uintCountDown = 100u;
if ( blnIsPaused() ) {
blnPause(false);
}
if ( blnIsRunning() ) {
meState = eTerminating;
while( !blnIsStopped() && --uintCountDown ) {
if ( mhEvent ) {
::SetEvent(mhEvent);
}
//Give thread a change to run and terminate
_sleep(501);
}
blnResult = blnIsStopped();
mhThread = NULL;
}
return blnResult;
}
Finally a derived class that implements the thread class and provides the blnStart method:
class clsOpenLDVrdr : public clsOpenLDVthread {
public:
//Maximum size of uplink data per single transfer
static const unsigned mscuBuffersize;
private:
//The thread's main routine
static void msgReaderThread(LPVOID lpParam);
public:
clsOpenLDVrdr();
virtual ~clsOpenLDVrdr();
//Call this to start the thread, see clsOpenLDVthread for more operations
virtual bool blnStart();
};
const unsigned clsOpenLDVrdr::mscuBuffersize = MAX_OPENLDV_DATA;
clsOpenLDVrdr::clsOpenLDVrdr() : clsOpenLDVthread(_T("EvOpenLDVrdr")) {
}
clsOpenLDVrdr::~clsOpenLDVrdr() {
}
bool clsOpenLDVrdr::blnStart() {
bool blnResult = false;
if ( blnIsStopped() ) {
meState = eStarted;
//Create the thread
mhThread = (HANDLE)_beginthread(&clsOpenLDVrdr::msgReaderThread
,0, NULL);
blnResult = mhThread != NULL;
while( blnResult && (meState == eStarted) ) {
//Give the thread chance to start and initialize
_sleep(501);
}
}
return blnResult && (meState == eRunning);
}
void clsOpenLDVrdr::msgReaderThread(LPVOID lpParam) {
OutputDebugString("msgReaderThread\n");
}
An instance of the class clsOpenLDVrdr is created and the blnStart method called:
clsOpenLDVrdr* pobjReader = new clsOpenLDVrdr();
pobjReader->blnStart();
I can see in the debugger that "blnStart" is being called and stepping into it everything is executed...but the thread never runs.
Also tried using _beginthreadex instead of _beginthread:
mhThread = (HANDLE)_beginthreadex(0, 0, pfnThread, pobParam, 0, 0);
No difference. There is some kind of incompatibility problem here as the simple example I created at the start of this post works and there isn't much difference between the two versions. Except maybe the way its used...the first simple example was created as a Windows console application. The project I'm having difficulty with is in a DLL.
I'm attaching to the DLL with the debugger and stepping through the code which works until it gets to the loop after the beginthread call then it just loops forever and never gets into the thread.
I just tried the following, adding a standalone thread with a standard C function:
unsigned __stdcall threadTest(void* pobjData) {
OutputDebugString("threadTest\n");
return 0;
}
I then modify the "_beginthread" call as follows:
mhThread = (HANDLE)_beginthreadex(0, 0, threadTest, pobjParam, 0, 0);
Sadly the result is the same, the threadTest function is not called. But a valid handle is returned.
Found this:
unable to call a thread in dll file
Looks interesting and may explain the strange behaviour I'm experiencing.
Solved...I didn't realise at first but for some reason the existing DLL had a call to:
DisableThreadLibraryCalls(hInstance);
This prevents the threads from running. Having commented this out everything now works.
I simply implement Peterson Lock Algorithm, but it doesn't work rightly.
Here is the code:
#include <pthread.h>
typedef struct {
volatile bool flag[2];
volatile bool victim;
} peterson_lock_t;
void peterson_lock_init(peterson_lock_t &lock) {
lock.flag[0] = lock.flag[1] = false;
lock.victim = 0;
}
void peterson_lock(peterson_lock_t &lock, int id) {
lock.victim = id;
lock.flag[id] = true;
__asm__ __volatile__("" : : : "memory");
while (lock.flag[1 - id] == false && lock.victim != id);
}
void peterson_unlock(peterson_lock_t &lock, int id) {
lock.flag[id] = false;
}
What's wrong with this code?
main.cpp:
#include <stdio.h>
#include "peterson_lock.h"
peterson_lock_t lock;
int count = 0;
void *routine0(void *arg) {
int *cnt = (int *)arg;
for (int i = 0; i < *cnt; ++i) {
peterson_lock(lock, 0);
++count;
peterson_unlock(lock, 0);
}
return NULL;
}
void *routine1(void *arg) {
int *cnt = (int *)arg;
for (int i = 0; i < *cnt; ++i) {
peterson_lock(lock, 1);
++count;
peterson_unlock(lock, 1);
}
}
int main(int argc, char **argv) {
peterson_lock_init(lock);
pthread_t thread0, thread1;
int count0 = 10000;
int count1 = 20000;
pthread_create(&thread0, NULL, routine0, (void *)&count0);
pthread_create(&thread1, NULL, routine1, (void *)&count1);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
printf("Expected: %d\n", (count0 + count1));
printf("Reality : %d\n", count);
return 0;
}
And the result is not right:
Expected: 30000
Reality : 24304
Expected: 30000
Reality : 24316
OS:
Linux ip-172-31-43-244 3.14.35-28.38.amzn1.x86_64 #1 SMP Wed Mar 11 22:50:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
While condition also needs to be improved :
while (lock.flag[1 - id] == true && lock.victim == id)
continue;
Be in busy wait until the other thread has lock and you are the victim.
Peterson Lock
Code:
[peterson_lock.h]
#include <pthread.h>
typedef struct {
volatile bool flag[2];
volatile int victim;
} peterson_lock_t;
void peterson_lock_init(peterson_lock_t &lock) {
lock.flag[0] = lock.flag[1] = false;
lock.victim = 0;
}
void peterson_lock(peterson_lock_t &lock, int id) {
lock.victim = id; // Mark as A
lock.flag[id] = true; // Mark as B
asm volatile ("mfence" : : : "memory");
while (lock.flag[1 - id] && lock.victim == id);
}
void peterson_unlock(peterson_lock_t &lock, int id) {
lock.flag[id] = false;
lock.victim = id;
}
[main.cpp]
#include <stdio.h>
#include "peterson_lock.h"
peterson_lock_t lock;
int count = 0;
void *routine0(void *arg) {
int *cnt = (int *)arg;
for (int i = 0; i < *cnt; ++i) {
peterson_lock(lock, 0);
++count;
peterson_unlock(lock, 0);
}
return NULL;
}
void *routine1(void *arg) {
int *cnt = (int *)arg;
for (int i = 0; i < *cnt; ++i) {
peterson_lock(lock, 1);
++count;
peterson_unlock(lock, 1);
}
}
int main(int argc, char **argv) {
peterson_lock_init(lock);
pthread_t thread0, thread1;
int count0 = 10000;
int count1 = 20000;
pthread_create(&thread0, NULL, routine0, (void *)&count0);
pthread_create(&thread1, NULL, routine1, (void *)&count1);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
printf("Expected: %d\n", (count0 + count1));
printf("Reality : %d\n", count);
return 0;
}
Run this program 1000 times, sometimes the result is not 30000. But is I switch A and B, the result is always 30000. But how could this happend?
[please ignore this line, only to make this question could be submitted.please ignore this line, only to make this question could be submitted.please ignore this line, only to make this question could be submitted.]
The algorithm requires that you do swap your A and B. In other words your posted code isn't a correct implementation of Peterson's algorithm.
Let us see what goes wrong.
First take this code:
void peterson_lock(peterson_lock_t &lock, int id) {
lock.victim = id; // Mark as A
lock.flag[id] = true; // Mark as B
asm volatile ("mfence" : : : "memory");
while (lock.flag[1 - id] && lock.victim == id);
}
and write it as a function per process:
void peterson_lock_0(peterson_lock_t &lock) {
lock.victim = 0;
lock.flag[0] = true;
asm volatile ("mfence" : : : "memory");
while (lock.flag[1] && lock.victim == 0);
}
void peterson_lock_1(peterson_lock_t &lock) {
lock.victim = 1;
lock.flag[1] = true;
asm volatile ("mfence" : : : "memory");
while (lock.flag[0] && lock.victim == 1);
}
Then let process 0 execute the first line, then switch to process 1 (executing the whole function) and then back to process 0.
peterson_lock_0: peterson_lock_1:
-------------------------------------------------------
lock.victim = 0;
lock.victim = 1;
lock.flag[1] = true;
asm volatile ("mfence" : : : "memory");
while (lock.flag[0] && lock.victim == 1);
// lock.flag[0] is false so
// the process enters critical
// section
lock.flag[0] = true;
asm volatile ("mfence" : : : "memory");
while (lock.flag[1] && lock.victim == 0);
// lock.victim is 1 so
// the process enters critical
// section
Now both processes are in the critical section. That's bad.
See https://en.wikipedia.org/wiki/Peterson%27s_algorithm for more information
I want to search a file which may be present in any drives such as C:\, D:\ etc. Using GetLogicalDriveStrings I can able to get the list of drives but when I add anything extra for the output, I am getting a null in the output prompt. Here is my code:
#include "StdAfx.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
// Buffer length
DWORD mydrives = 100;
// Buffer for drive string storage
char lpBuffer[100];
const char *extFile = "text.ext";
// You may want to try the wmain() version
int main(void)
{
DWORD test;
int i;
test = GetLogicalDriveStrings(mydrives, (LPWSTR)lpBuffer);
if(test != 0)
{
printf("GetLogicalDriveStrings() return value: %d, Error (if any): %d \n", test, GetLastError());
printf("The logical drives of this machine are:\n");
// Check up to 100 drives...
for(i = 0; i<100; i++)
printf("%c%s", lpBuffer[i],extFile);
printf("\n");
}
else
printf("GetLogicalDriveStrings() is failed lor!!! Error code: %d\n", GetLastError());
_getch();
return 0;
}
I want above output as C:\text.ext D:\text.ext ... rather I am getting text.ext only. I am using Microsoft Visual C++ 2010 Express
GetLogicalDriveStrings() returns a double-null terminated list of null-terminated strings. E.g., say you had drives A, B and C in your machine. The returned string would look like this:
A:\<nul>B:\<nul>C:\<nul><nul>
You can use the following code to iterate through the strings in the returned buffer and print each one in turn:
DWORD dwSize = MAX_PATH;
char szLogicalDrives[MAX_PATH] = {0};
DWORD dwResult = GetLogicalDriveStrings(dwSize,szLogicalDrives);
if (dwResult > 0 && dwResult <= MAX_PATH)
{
char* szSingleDrive = szLogicalDrives;
while(*szSingleDrive)
{
printf("Drive: %s\n", szSingleDrive);
// get the next drive
szSingleDrive += strlen(szSingleDrive) + 1;
}
}
Note that the details of how the function works, including the example code that I shamelessly copied and pasted, can be found by reading the docs.
Did you mean to put the printf in the loop?
Currently, you set extFile 100 times (just to be sure?!)
for(i = 0; i<100; i++)
extFile = "text.ext";
You meant to show all the drive letters in a loop:
for(i = 0; i<100; i++)
{
extFile = "text.ext";
printf("%c%s", lpBuffer[i], extFile); //I guess you mean extFile here?
}
DWORD dwSize = MAX_PATH;
WCHAR szLogicalDrives[MAX_PATH] = { 0 };
DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives);
CStringArray m_Drives;
m_Drives.RemoveAll();
if (dwResult > 0 && dwResult <= MAX_PATH)
{
WCHAR* szSingleDrive = szLogicalDrives;
while (*szSingleDrive)
{
UINT nDriveType = GetDriveType(szSingleDrive);
m_Drives.Add(CString(szSingleDrive, 2));
// get the next drive
szSingleDrive += wcslen(szSingleDrive) + 1;
}
}
return m_Drives;
class DriveList {
protected:
LPTSTR m_driveList;
DWORD m_driveCount;
DWORD m_bufSize = 32 * sizeof(TCHAR);
public:
virtual ~DriveList() {
free(m_driveList);
}
DriveList() {
m_driveList = (LPTSTR)malloc(m_bufSize);
}
int getDriveCount() const {
return m_driveCount;
}
TCHAR operator[] (const int index) const {
return m_driveList[index];
}
void loadDriveList() {
DWORD mask;
if((mask = GetLogicalDrives()) == 0) {
throw;
}
m_driveCount = 0;
for(int x = 0; x <= 25; x++ ) {
if(mask & 1) {
m_driveList[m_driveCount] = TCHAR(65 + x);
m_driveCount += 1;
}
mask >>= 1;
}
}
};