In the structure of my program I’ve divided “where it gets called from” and “what gets done” into separate source files. As a matter of practicality, this allows me to compile the program as standalone or include it in a DLL. The code below is not the actual code but a simplified example that makes the same point.
There are 3 interacting components here: kernel mode program that loads my DLL, the DLL and its source files and the utility program with it’s source, that is maintained separately.
In the DLL form, the program is loaded as a thread. According to the kernel mode application vendor’s documentation, I loose the ability to call Win32 API functions after the initialization of the kernel program so I load the thread as an active thread (as opposed to using CREATE_SUSPENDED since I can’t wake it).
I have it monitor a flag variable so that it knows when to do something useful through an inelegant but functional:
while ( pauseThreadFlag ) Sleep(1000);
The up to 1 second lag is acceptable (the overall process is lengthy, and infrequently called) and doesn’t seem to impact the system.
In the thread source file I declare the variable as
volatile bool pauseThreadFlag = true;
Within the DLL source file I’ve declared
extern volatile bool pauseThreadFlag;
and when I am ready to have the thread execute, in the DLL I set
pauseThreadFlag = false;
I’ve had some difficulty in declaring std::string objects as volatile, so instead I have declared my parameters as global variables within the thread’s source file and have the DLL call setters which reside in the thread’s source. These strings would have been parameters if I could instantiate the thread at will.
(Missing from all of this is locking the variable for thread safety, which is my next “to do”)
This strikes me as a bad design … it’s functional but convoluted. Given the constraints that I’ve mentioned is there a better way to go about this?
I was thinking that a possible revision would be to use the LPVOID lpParams variable given at thread creation to hold pointers to the string objects, even though the strings will be empty when the thread is created, and access them directly from the thread, that way erasing the declarations, setters, etc in the thread program altogether? If this works then the pause flag could also be referenced there, and the extern declarations eliminated (but I think it still needs to be declared volatile to hint the optimizer).
If it makes any difference, the environment is Visual Studio 2010, C++, target platform Win32 (XP).
Thanks!
I ended up removing the struct and replacing it with an object that encapsulates all the data. It’s a little hideous, being filled with getters and setters, but in this particular case I’m using the access methods to make sure that locks are properly set/unset.
Using a void cast pointer to this object passed the object correctly and it seems quite stable.