Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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]?

like image 629
Gravis Avatar asked Mar 31 '26 18:03

Gravis


1 Answers

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);
}
like image 199
Maister Avatar answered Apr 02 '26 11:04

Maister



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!