|
Hi,
I am sure this is right but I am having a hell of time debugging a multithreading application
When executing the same code/functions each thread has its own set of registers and local
Variables
Thanks
|
|
|
|
|
Yes, each thread has its own stack (local variables), registers, and "thread-local-storage". Static and global variables are common to all threads.
This is what makes multithreaded programming such a joy...
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack.
--Winston Churchill
|
|
|
|
|
This is, despite the title, not really a question.
Clearly there will be multiple threads yes, that's the point.
What do you want to know?
|
|
|
|
|
Yes, just the same as MVS and VM programs.
|
|
|
|
|
The problem is the breaking the debugger doesn't stop the system clocks on the PC which means you get a backlog and out of sequence queue of things to happen when you release the debug. So often your debugging does not look like the system when running which can be more than a little frustrating
There is an extension that helps
GitHub - mayerwin/vs-debug-single-thread: Debug Single Thread - Visual Studio Extension[^]
But at times it still gets frustrating.
In vino veritas
|
|
|
|
|
If you're familiar with Visual Studio debugging options they include a Task window, Thread window, and a window to view Parallel stacks. All these windows support various flags and the Parallel stacks shows a nice visual diagram of the execution environment. There's also the Tracepoint option if you want a breakpoint that outputs state information but doesn't halt execution.
I don't really see the issue with out of order execution. That should be something addressed in your code with barriers/fences, locks, semaphores, mutexes, or whatever else you use.
|
|
|
|
|
Thanks
The visual studio thread window I know has the ability to freeze a thread
Regardless I'll down load the
Extension
Let me explain the nature of the problem
I'm writting a debugger for another platform
The way I Interrupt the program and show the user the code is by overlaying the instruction which causes a interrupt and allows me to get control
I quickly put back the instruction that was overlayed
However the interrupt gives me control
This all fine when the "Debugged" program is single thread
However in a multi thread program in which other programs use he same code
I get a operation exception
The way I coded this was the as soon as I overlay the instruction I do a Restevent which cause an event to be non- signaled this will cause the other programs to Wait or WaitForSingleEvent until I have chance to put the instruction back and then I do a SetEvent to let execution of the program to the other threads trying to execute it
Something is obviously not working out right in this timing
In Visual Sudio I can observe how QUICKLY the windows dispatcher switches from thread to thread
Thanks
|
|
|
|
|
Lets see if I have got this right
The other threads won't stop until they hit a lock point. So let me imagine they are in the section of code you overlayed. They will see your overlay (which is an interrupt opcode I guess .. you transposed the real opcode out to a hold memory somewhere). However interrupts will be disabled because you are in the IRQ routine already so it then continues thru to next opcode.
I can imagine if that is the scheme you end up with two equally bad situations
1.) the other threads pull an illegal opcode if your transpose isn't the same length as the replaced opcode
2.) they pass thru the overlay missing the held opcode (they saw the interrupt request which was ignored). So anything could happen the thread missed an entire opcode.
If that is what you are doing there is no fix, you either can't have the threads going thru the same code or you need to stop the threads immediately the other threads even advancing one opcode can be fatal much less allowing them to run to next lock point.
This goes back to what I was getting at originally you need to stop the system totally in some schemes. Some processors like Arm and many microcontrollers can do that under system control for hardware debugging. The Raspberry PI which uses an ARM6/7/8 could do that for example. I fear your current schema needs a full hardware debugging setup if I understand it correctly.
Edit: Assuming above is correct I gave this a bit of thought and there is possibly a way to do this on a normal non stepable processor. You have the stacks of the threads and that contains the Program Counter for each thread. So overlay the other threads as well this time with a relative branch instruction to there current position ... get it ... will deadloop them to exactly where they are ... meeting the requirement they don't move even one opcode forward You don't need the event stuff at all it's just a repeat of what you do to the active thread in the interrupt overlaying a different instruction into non active threads. Just make sure you put back the opcodes in reverse order (incase two threads are in the exact same place) from within an interrupt when you want to release it back.
In vino veritas
modified 10-Jan-17 0:55am.
|
|
|
|
|
I am a MainFrame Assembler programmer by trade
this is the emulator
The Hercules System/370, ESA/390, and z/Architecture Emulator[^]
I overlay two bytes of code (causing it to pause) right before I overlay the code I do a ResetEvent which will cause a manual Event to be NON-signaled the threads right behind this will stop on the WaitForSingleObject
I have code to determine the Work unit executing code in CSA (common storage) it is only for that code that I do a ResetEvent and then memcpy
Once the emulated code that I overlayed (cuasing it to interrupt and pause)
I put back the legal opcode via memcpy right after I do a SetEvent for the other workunits executing the common storage to proceed (as it is now okay) and bypass the overlaying logic
I will paste the relevant code shortly as it is late (have to get to sleep)
I wanted to give you a feel (of what I doing) as you have been so verrrrrry helpful
|
|
|
|
|
Make sure you are using manual reset events there is a trap for young players with Auto-Reset Events
Read the documentation
SetEvent function (Windows)[^]
Quote => The state of an auto-reset event object remains signaled until a single waiting thread is released, at which time the system automatically sets the state to nonsignaled. If no threads are waiting, the event object's state remains signaled.
In vino veritas
|
|
|
|
|
Hi
before pasting the code let me Clarify NON-signaled would mean a thread executing WaitForSingleObject is suspended
I am still running into problems where other threads are executing the overlayed code
here is the code Initiallly the event is created signaled
sysblk.single_thread = CreateEvent(NULL,TRUE,FALSE,"WaitThread");
/* this block of code checks if the address where the code is executing is within the address looking to be traced and is the address space correct the GET_WU function checks the the task or thread within the address space so GET_WU returns a 64 bit value 32 bits for a address space 32 for the task this is UNIQUE */
if(sysblk.debug_init == 0)
{
if (sysblk.asid != 0)
{
if((shouldstep == 1) && (regs->CR_LHL(4) == sysblk.asid))
{
sysblk.debug_init = 1;
regs->should_step = 1;
sysblk.hercgui_break = 1;
sysblk.hercgui_initbreak = 0; sysblk.debug_wu.D = ARCH_DEP(GET_WU)(regs);
if(IsDebuggerPresent())
{
sprintf(buf,"CPU%4.4X: WU Being Debugged ASCB=%4X,TCB/SRB=%4X \n",regs->cpuad,sysblk.debug_wu.F.H.F,sysblk.debug_wu.F.L.F);
OutputDebugString(buf);
}
}
else
shouldstep = 0;
}
/* the next piece of code checks after the user has examined the code and I have restored the correct instruction I want to let it execute and not over lay stop ia is the instruction address */
// Hercmd is a from end Windows MFC/C++ I have written to display the information
if(regs->psw.ia.D == sysblk.debug_ia.D)
{
wu_ptr.D = ARCH_DEP(GET_WU)(regs);
if(wu_ptr.D == sysblk.debug_wu.D)
{
sysblk.debug_ia.D =0;
if(IsDebuggerPresent())
{
ARCH_DEP(vfetchc)(buf1,5,regs->psw.ia.D,0X00,regs);
sprintf(buf,"CPU%4.4X: inst being executed=%s At address %8X\n",buf1,regs->psw.ia.D);
OutputDebugString(buf);
}
return;
}
}
/* this is the code where I check if other threads are execting the same code and the address or instruction has been overlayed to genarate a pause so I WaitForSingleObject */
if(regs->psw.ia.D == sysblk.debug_ia.D)
{
wu_ptr.D = ARCH_DEP(GET_WU)(regs);
if (wu_ptr.D != sysblk.debug_wu.D)
{
regs->cpustate = CPUSTATE_STOPPED;
dwWaitResult = WaitForSingleObject(sysblk.single_thread,INFINITE);
if(dwWaitResult == -1)
errcd = GetLastError();
if(IsDebuggerPresent())
{
ARCH_DEP(vfetchc)(buf1,4,regs->psw.ia.D,0X00,regs);
FETCH_FW(INST,buf1);
sprintf(buf,"CPU%4.4X: WU Was Held ASCB=%4X TCB/SRB=%4X, AT instruction address %8X inst=%04X\n",regs->cpuad,wu_ptr.F.H.F,wu_ptr.F.L.F,regs->psw.ia.D,INST);
OutputDebugString(buf);
}
return;
}
else
return;
}
// this where I overlay the insruction to stop the CORRECT task
if ((wu_ptr.D = ARCH_DEP(GET_WU)(regs)) == sysblk.debug_wu.D && shouldstep == 1)
{
ResetEvent(sysblk.single_thread); ip = regs->ip < regs->aip ? regs->inst : regs->ip;
ARCH_DEP(display_inst) (regs, ip);
sysblk.debug_inst_count++;
sysblk.stop_ip = regs->ip < regs->aip ? regs->inst : regs->ip;
if(sysblk.debug_overlay[0] == 0x00)
{
ip = regs->ip < regs->aip ? regs->inst : regs->ip;
sysblk.debug_ip = ip;
memcpy((void *)&sysblk.debug_overlay[0],(void *)ip,2);
memcpy((char *)&sysblk.savereg15,(char *)®s->gr[15],8);
memcpy((char *)&sysblk.savereg14,(char *)®s->gr[14],8);
sysblk.debug_ia.D = regs->psw.ia.D;
memcpy((void *)®s->gr[15].F.L.F,(void *)&sysblk.pause_rtn,4);
memcpy((void *)ip,(void *)&BASSM,2);
sysblk.hercgui_debug = 1;
}
regs->is_debugging = 1;
if(IsDebuggerPresent())
{
sprintf(buf,"CPU%4.4X: Inst Modified For ASCB=%4X TCB/SRB=%4X \n",regs->cpuad,wu_ptr.F.H.F,wu_ptr.F.L.F);
OutputDebugString(buf);
}
}
// This the code after the emulated instruction that I overlayed has executed I put back the 1st two bytes of the instruction and do a SetEvent as now other threads can proceed
if((regs->gr[15].F.L.F == sysblk.pause_rtn) && ((void *)sysblk.pause_rtn != NULL))
{
memcpy(sysblk.stop_ip,&sysblk.debug_overlay[0],2);
memcpy((char *)®s->gr[15],(char *)&sysblk.savereg15,8);
memcpy((char *)®s->gr[14],(char *)&sysblk.savereg14,8);
sysblk.debug_overlay[0] = 0x00;
sysblk.debug_overlay[1] = 0x00;
sysblk.hercgui_is_debugging = 0;
regs->bypass_debug = 1;
regs->is_debugging = 0;
regs->should_step = 0;
SetEvent(sysblk.single_thread);
wu_ptr.D = ARCH_DEP(GET_WU)(regs);
if(IsDebuggerPresent())
{
sprintf(buf,"CPU%4.4X: SetEvent for ASCB=%4X TBC/SRB=%4X\n",regs->cpuad,wu_ptr.F.H.F,wu_ptr.F.L.F);
OutputDebugString(buf);
}
}
|
|
|
|
|
I will need time to look at this and see if I can spot it.
This is one of those situations it would be nice to have a .NET managed thread so you can pull a threadstate enumeration on all the threads, something we can't do on raw win32 threads
In vino veritas
|
|
|
|
|
Do you have an-email address I can e-mail you offline
Thanks
|
|
|
|
|
It's on my bio
In vino veritas
|
|
|
|
|
thanks
The Visual Studio Thread windows I know has the ability to freeze threads
Regardless I'll download the extension
Let me explain the nature of the problem
I'll writing an a debugger for another platform (working with an emulator )
I am modifying the emulated "C" code
the way interrupt the "debugged" code/program
is by overlaying the instruction which gives me control and shows the user the code
I quickly put back the over laid instruction
this works well when the user is debugging a Single Threaded program
however in a multiThreaded programs other threads or tasks executing the same code
get a operation exception before I put the code back
The way I coded this was as soon as I overlay the instruction I do a
ResetEvent which cause a Event to be non-signaled and stop the other threads/tasks
from executing this code until I have a chance
to put back the instruction I then do a SetEvent
to let the other threads/tasks execute the code
Something is obviously not working out right in this timing
In Visual Studio I can observe how QUICKLY The Windows dispatcher
Switches from thread to thread
Thanks for your help
|
|
|
|
|
If you get this then you need to use thread synchronisaiton so that WHATEVER happens, and it will, one day, your threads process data and events in a coordinated fashion.
|
|
|
|
|
(I still must be in the spirit of Christmas)
Q: How do I add gallery buttons items to a gallery button with the resource editor ?
I created a default application with the ribbon UI.
In the resource editor, I added a "Gallery Button" and into that I added a few button items in the collection
I manually added event handlers for each item.
When I start the application, the gallery button just looks like a button and when I click on it, no "menu" is displayed.
I looked at the samples projects ( RibbonGadgets and RibbonMDI) and they just code the ribbon manually.
Q: Am I missing something? The properties for the gallery button does not show anything useful.
Q: Should I just give up on the ribbon designer and code everything manually ?
Thanks.
Max.
I'd rather be phishing!
|
|
|
|
|
Did you ever find an answer here? I have the same issue.
|
|
|
|
|
A semi-popular IDE compiles my C++ code without declaring function prototype.
Did I missed the newsflash or just an compiler option?
Seems odd.
|
|
|
|
|
You only need prototypes for forward declarations. And IDEs do not do the compiling, that's the compiler's job.
|
|
|
|
|
True, but I have been using IDE whose authors are very fond of their "beginners feature " which actually builds prototypes "for you". So they claim.
I am now test driving another IDE, still based on GCC and the first test function I used compiled without prototype, that is why I made this post.
Next function failed without prototype, so I am not sure what is going on.
So what is the difference between prototype and forward declaration?
Or is there a difference?
|
|
|
|
|
When the compiler comes across a function call it checks its tables for a declared prototype. If it cannot find one then it will infer a definition from the parameters of the function call. When it then finds the actual function it will check that the definition matches the stored declaration. If it does, then all well and good. If it does not then it will throw out an error message.
As to your last question, a prototype is a forward declaration. It just tells the compiler the type of the parameters and return value of the function, so it can check on any calls made to the function before it is found in the source. The same applies to external functions whose prototypes are in .h files.
|
|
|
|
|
A declaration (prototype) describes an object (function, class, variable).
int some_function(int some_arg);
A definition (implementation) implements an object.
int some_function(int some_arg)
{
int result = 0;
return result;
}
If there is no declaration for an object, the definition implies the declaration.
The compiler needs a declaration when an object is used the first time (accessing a variable, calling a function). So there is no need for a declaration if the first usage is located after the definition in the source code.
While strictly speaking all declarations are forward declarations, the term is mainly used with function declarations in header files where a pointer or reference to another class is passed as function argument. An example:
class OtherClass;
class MyClass
{
MyClass();
SomeFunction(OtherClass &otherClass);
}; The implementation file of MyClass must still include the header file containing the OtherClass declaration. But the above header file must not do so which reduces the compile time. More important, this must be used when both classes use the other which would normally require that both header files include each other which would lock the compiler (recursive inclusion).
See also this SO thread: c++ - What is the difference between a definition and a declaration? - Stack Overflow[^]
|
|
|
|
|
The compiler needs a declaration when an object is used the first time (accessing a variable, calling a function). So there is no need for a declaration if the first usage is located after the definition in the source code.
Perfect answer - that is exactly why my test function - first one in header file - did not need declaration.
Jochen,
I really appreciate your help - always right to the point. Thanks
PS
Are you by any chance teacher / instructor ? You sure know how to explain stuff.
Cheers
Vaclav
|
|
|
|
|
Thank you.
I'm not a teacher. I'm an R&D engineer (hardware and software).
|
|
|
|
|