Demo entry 2843049

asgn2

   

Submitted by anonymous on Oct 16, 2015 at 22:28
Language: C. Code size: 6.6 kB.

/*
 * Luke Gnos
 * 10/11/15
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define _x86_64
#include "lwp.h"

/* Global Variables */
thread lwpHead;        /* Start of the linked list, hold current thread info */
thread lwpEnd;         /* End of the linked list, last thread to go */
int lwpIDCount = 1;    /* Counter for creating unique thread ID's */
thread lwpCurrThread;  /* Set to a thread's ID before entering it,
                                    otherwise is NO_THREAD */
scheduler lwpSched;
rfile lwpOrigContext;  

/* Default Scheduler function prototypes */
void rrAdmit(thread);
void rrRemove(thread);
thread rrNext(void);

//malloc thread's stack
//create stacke frame for the thread (needs RA and old bp at top of stack)
//malloc thread info
//initialize thread info and add to LL
//create/add to scheduler
tid_t lwp_create(lwpfun function, void *argument, size_t stacksize) {
  thread new;
  unsigned long *stackBase, *temp, *temp2;
  rfile old, regs = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //initialize to all 0's
    
  //allocate stack
  stackBase = malloc(4 * stacksize);  //4 * to get size in words not bytes
  if (stackBase == NULL) {
    fputs("Malloc failed to allocate a LWP's stack\n", stderr);
    return -1;
  }

  /* Go to top of stack in order to place ra */
  temp = ((void *)stackBase + (4 * stacksize));
  //temp2 = stackBase + stacksize;

  temp--;
  *temp = (unsigned long)lwp_exit;
  temp--;
  *temp = (unsigned long)function;
  temp--;
  regs.rbp = (unsigned long)temp;
  
  regs.rax = (unsigned long)lwp_exit;
  regs.rdi = (unsigned long)argument;
  regs.rsp = (unsigned long)temp;
  
  /* Malloc the new thread's info and check for malloc error */
  new = malloc(sizeof(thread));
  if (new == NULL) {
    fputs("Malloc failed to allocate thread structure\n", stderr);
    return -1;
  }
  
  /* Set the fields of the new thread's info structure */
  new->tid = lwpIDCount++;   /* Get a unique id and increment the counter */
  new->stack = stackBase;
  new->stacksize = stacksize;
  new->state = regs;
  new->next = NULL;
  new->lib_two = NULL;
  new->sched_one = NULL;
  new->sched_two = NULL;

  if (!lwpHead) {
    lwpHead = lwpEnd = new;
  } else {
    lwpEnd->next = new;
    lwpEnd = new;
  }

  if (!lwpSched) {
    lwp_set_scheduler(NULL);
  }

  lwpSched->admit(new); //add to the scheduler
  
  printf("end of create\n");
  
  return new->tid;
}

void lwp_exit(void) {
  printf("in exit\n");
  
  thread curr = lwpCurrThread, next;

  lwpSched->remove(curr);
  
  free(curr->stack);
  free(curr);

  next = lwpSched->next();
  
  load_context(&(next->state));
}

/* 
 * Function that returns the tid of the current LWP or
 *   returns NO_THREAD if not called by a LWP.
 */
tid_t lwp_gettid(void) {
  if (!lwpCurrThread)
    return NO_THREAD;
  
  return lwpCurrThread->tid;
}

void lwp_yield(void) {

  //printf ("in yield\n");
  
  thread next, old;

  old = lwpCurrThread;
  printf("in yield before sched->next\n");

  next = lwpSched->next(); //this fucker seg faults

  printf("after sched in yield\n");
  lwpCurrThread = next;

  printf("in yield before swap\n");

  swap_rfiles(&(old->state), &(next->state));  
}

/*
 *
 */
void lwp_start(void) {
  thread curr;
  rfile context, old;

  if (!lwpHead) {
    fputs("No LWPs detected, create a LWP with"
	  "lwp_create(3) before calling lwp_start(0)\n", stderr);
    return;
  }

  //call next to get the first thread to go
  curr = lwpSched->next();
  
  //set curThread global for gettid function
  lwpCurrThread = curr;

  printf("end of start b4 load\n");

  //set registers for the next thread (effectively calling it)
  
  swap_rfiles(&lwpOrigContext, &(curr->state));

  printf("end of start, never should be printed\n");
}

void lwp_stop(void) {

  printf("in stop\n");
    //any number of current other threads
  //restore original context (effectively returning from start)
  load_context(&lwpOrigContext);

 
}

/*
 * Function that allows the user to designate their own scheduler.
 * If no scheduler is provided before a call to lwp_start(0), the 
    default round robin scheduler is selected.
 * Function calls the shutdown function on the old scheduler if it exists
 * Function sets the lwpSched global variable
 */
void lwp_set_scheduler(scheduler new) {
  scheduler old = lwpSched, sch;
  thread curr = lwpHead;

  /* If function called with null, set up the default scheduler */
  if (!new) { 

    //might need to shutdown old here as well
    sch = malloc(sizeof(scheduler));
    sch->init = NULL;
    sch->shutdown = NULL;
    sch->admit = rrAdmit;
    sch->remove = rrRemove;
    sch->next = rrNext;

    lwpSched = sch;

    /* Otherwise, initialize new scheduler if necessary, admit all the threads
       and shutdown the old scheduler if necessary */
  } else {
    if (new->init)
      new->init();

     while (curr) {
      new->admit(curr);
      curr = curr->next;
     }

     if (old->shutdown)
       old->shutdown();
  
     lwpSched = new;
  }
}

/*
 * Function that returns the current scheduler.
 * If no scheduler has been set, and lwp_create(3) has not been called,
     then function returns NULL.
*/
scheduler lwp_get_scheduler(void) {
  if (!lwpSched)
    return NULL;
  return lwpSched;
}

/*
 *  Returns the thread corresponding to the tid parameter, or
      returns NULL if the id is invalid.
 */
thread tid2thread(tid_t tid) {
  thread temp = lwpHead, result;
  int found = 0;
  
  while (temp) {
    if (temp->tid == tid)
      result = temp;

    temp = temp->next;
  }

  if (!result)
    return NULL;

  return result;
}

void rrAdmit(thread new) {

  lwpCurrThread = new;

  // printf("in admit\n");
  //does nothing
}

void rrRemove (thread victim) {
  //does it need to be remove entirely by calling lwp_exit?
  //when does this even get called??
}

/*
 * Default round robin scheduler next function
 * Returns NULL if function called with no threads
 */
thread rrNext (void) {
  printf("start of admit\n");

  thread newHead, temp;

  if (!lwpHead) {
    //fputs("Attempted to get next thread on an empty pool\n" stderr);
    return NULL;
  }

  if (lwpHead == lwpEnd)
    return lwpHead;

  printf("halfway thru admit\n");

  //at least two left
  temp = lwpCurrThread;

  if (temp->next == NULL) { //at end of LL
    return lwpHead;
  } else
    return temp->next;
}

This snippet took 0.01 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).