the stack and vtable [re]location
NOTE: To understand my question, you might need to know about my project and the problem. If not, skip right to the "QUESTION" section at the bottom.
PROJECT I'm working on a writing a C++ class that enables its parent to act like synchronous/blocking threads by having Pause() and Resume(). Here's an example of how it would work.
class BlockingThread
: public BlockingThreadBase // all the Asm magic happens in BlockingThreadBase
{
void StartStopHere(void) // called upon the first Resume() call (pure virtual in base)
{
printf("1"); Pause();
printf("3"); Pause();
printf("5"); Pause();
}
};
int main(void)
{
BlockingThread obj;
obj.Resume(); printf("2");
obj.Resume(); printf("4");
obj.Resume(); printf("6");
return 0;
}
// OUTPUT: 123456
I've tried true threading and several novel ideas but they ended up too slow to transfer between code locations 21 million times per second.
My latest idea is use chunks of the stack (stack buffers) to create the illusion of multiple stacks. When obj1.Resume() is called, it would return to location of its personal stack, New #1 Stack
, execute until Pause() and then return to the previous stack location it was at.
ILLUSTRATIONS
How the stack would look without anyBlockingThread
objects in main().
_________________
| Normal | Stack |
| Stack | Buffer |
|________|________|
How aBlockingThread
object in main() would look like on the stack.
__开发者_开发知识库_________________________________
| Normal | Stack | New #1 | Stack |
| Stack | Buffer | Stack | Buffer |
|________|________|________|________|
How twoBlockingThread
objects in main() would look like on the stack.
_____________________________________________________
| Normal | Stack | New #1 | Stack | New #2 | Stack |
| Stack | Buffer | Stack | Buffer | Stack | Buffer |
|________|________|________|________|________|________|
PROBLEM
When moving to a "new" stack, and then calling obj.Resume() (from main) which in turn call StartStopHere() causes a segfault at the point of calling StartStopHere(). GDB says can't find linker symbol for virtual table for 'BlockingThreadBase' value
when I try to get the value of a member variable from BlockingThreadBase. This is why I suspect it has the same problem when trying to find the location of StartStopHere() when it's called.
QUESTION
(ignore the italics words if you didn't read the other sections)
How can I find [and move or copy] the vtable (or its location if that's what's stored) of the class in the [normal] stack [to a new stack]?
I think what you're looking for is cooperative threading. For a fast and simple implementation of it, check out libco. http://byuu.org/files/libco_v16.tar.bz2. The coswitching is implemented in raw assembly and works for x86, x86_64, PPC32 and PPC64. It also has implementation (ab)using setjmp/longjmp and posix ucontext (very slow). The overhead with this kind of stack swizzling is about 5x. 20 million swaps / sec should work fine. There are some test programs included to test speed.
Example:
#include "libco.h"
#include <stdio.h>
static cothread_t t1;
static cothread_t t2;
static void foo(void)
{
for (int i = 1; i < 10; i+=2)
{
printf("%d\n", i);
co_switch(t1); // Swap back to main cothread
}
}
int main(void)
{
// Get a handle to the current coinstance.
t1 = co_active();
t2 = co_create(10000, foo); // New cothread with stacksize 10000.
for (int i = 0; i < 10; i+=2)
{
printf("%d\n", i);
co_switch(t2); // Swap to cothread t2.
}
co_delete(t2);
}
I assume that magic of your project is happening via some assembly magic. This obviously implies that this will be architecture-specific. To check how to access vtable (or vpointer) to class from assembly, best would be simply to check how copiler does it when accessing virtual method - simply disassble your code and see. On x86 linux g++ copiled program i tested - first four bytes of object are pointer to a table (allocated statically i think) of virtual functions.
I don't think there is any method of doing it architecture independent, as different architectures might use different approaches to vtables. Therefore i wouldn't expect c++ to have any means for it.
So much about your question. I think however, that if simple memcpy(&BlockingThread, sizeof(BlockingThread)) does not work, then there is not much more you will be able to copy.
精彩评论