Locke
Locke

Reputation: 544

My threads never finish after context switching

So I am working on context switching to make my own thread library. I'm running into a lot of difficulty though. I have a queue created which I store contexts in so that when a process is yielded it may later continue. However it seems that the context I am popping is incorrect. I suspect that it may be due to my global currentContext variable not being properly assigned?

         ucontext_t* currentContext;

         void system_init() {
           createQueue();
           isRunning = 0;
         }

    int uthread_create(void (* func)()) {
       ucontext_t *context;
       context = (ucontext_t*)malloc(sizeof(ucontext_t));
       getcontext(context);
       context->uc_stack.ss_sp = malloc(16384);
       context->uc_stack.ss_size = 16384;

       makecontext(context, func, 0);
       if(isRunning == 0) {
           isRunning = 1;
           currentContext = context;
           setcontext(context);
           return 0;
       }
       else {
           push(context);
           return 0;
       }
       return -1;

}


   int uthread_yield() {
        push(currentContext);
        currentContext = pop();
        setcontext(currentContext);
   }

Here is how my code needs to be implemented:

int n threads=0;
int myid=0;
void do something()
{
     int id;
     id=myid;
     myid++;
     printf (”This is ult %d\n”, id); //just for demo purpose
     if(n threads<5){
          uthread create(do something);
          n threads++;
          printf (”ult %d yields \n”,id );
          uthread yield ();
          printf (”ult %d resumes \n”,id);
          uthread create(do something);
          n threads++;
     }
     printf (”ult %d starts I/O \n”,id);
     uthread startIO();
     sleep (2); //simulate some long−time I/O operation
     uthread endIO();
     printf (”ult %d returns from I/O \n”,id);
     uthread exit ();
     }

main()
{
     int i ;
     system init ();
     uthread create(do something);
     uthread exit ();
}

It has an expected output of:

This is ult 0
ult 0 yields
This is ult 1
ult 1 yields
ult 0 resumes
ult 0 starts I/O
This is ult 2
ult 2 yields
ult 1 resumes
ult 1 starts I/O
This is ult 3
ult 3 starts I/O
This is ult 4
ult 4 starts I/O
ult 2 resumes
ult 2 starts I/O
This is ult 5
ult 5 starts I/O
ult 0 returns from I/O
ult 1 returns from I/O
ult 3 returns from I/O
ult 4 returns from I/O
ult 2 returns from I/O
ult 5 returns from I/O

However my output is only:

This is ult 0
ult 0 yields
This is ult 1
ult 1 yields
This is ult 2
ult 2 yields
This is ult 3
ult 3 yields
This is ult 4
ult 4 yields
This is ult 5
ult 5 starts I/O
ult 5 returns from I/O

Which demonstrates that my threads are not resuming and instead just being skipped.

Upvotes: 1

Views: 513

Answers (1)

CLL
CLL

Reputation: 331

It looks like you are pushing data type ucontext_t into your queue. This is going to create copies of the context that you are putting into your queue, which is going to cause issues because you are stranding memory in the heap (not to mention abandoning the original ucontext_t you created).

Try having your queue store pointers of type ucontext_t * instead of ucontext_t's. That way you don't strand memory and can access the process you originally created when you pop a context off of your queue.

Upvotes: 1

Related Questions