// Tests creation, yielding, destruction, and yielding to a nonexistent thread
// arg is the string to print within the method.
void funkyTown(char* arg)
{
	printf("%s",arg);
	Tid weave = ULT_CreateThread((void (*)(void *))doALittleDance, "Make a little love\n");
	Tid ret = ULT_Yield(weave);
	assert(ret == weave);
	Tid ret2 = ULT_DestroyThread(weave);
	assert(ret2 == weave);
	Tid ret3 = ULT_Yield(ret2);
	assert(ret3 = ULT_INVALID);
}
static void finale()
{
  int ret;
  printf("Finale running\n");
  ret = ULT_Yield(ULT_ANY);
  assert(ret == ULT_NONE);
  ret = ULT_Yield(ULT_ANY);
  assert(ret == ULT_NONE);
  printf("Done.\n");
  /* 
   * Stub should exit cleanly if there are no threads left to run.
   */
  return; 
}
Beispiel #3
0
static void
mbWorker0(Mailbox *mb)
{
  ULT_CreateThread((void (*)(void *))mbWorker1, mb);
  
  int myPart = MAXMAIL/2;
  int ii;
  for(ii = 0; ii < myPart; ii++){
    mb_increment(mb, 0);
    ULT_Yield(ULT_ANY);
    ULT_Yield(ULT_ANY);
  }
  return;
}
static void doPotato(int mySlot)//You will want to create data structures like a ready list (for TCBs that are 
{
  int ret;
  int moved;
  int passes = 0;

  printf("Made it to doPotato %d\n", mySlot);
  while(1){
    assert(alarmIsEnabled());
    moved = tryMovePotato(mySlot);
    if(moved){
      passes++;
      printf("%d passes potato for %d-st/nd/rd time \n", mySlot, passes);
    }

    /*
     * Add some yields by some threads to scramble the list
     */
     if(mySlot > 4){
      int ii;
      for(ii = 0; ii < mySlot - 4; ii++){
        ret = ULT_Yield(ULT_ANY);
        assert(ULT_isOKRet(ret));
      }
    }
  }
}
static void
doPotato(int mySlot)
{
  int ret;
  int moved;
  int passes = 0;

  printf("Made it to doPotato %d\n", mySlot);
  while(1){
    assert(alarmIsEnabled());
    moved = tryMovePotato(mySlot);
    if(moved){
      passes++;
      printf("%d passes potato for %d-st/nd/rd time \n", mySlot, passes);
    }

    /*
     * Add some yields by some threads to scramble the list
     */
    if(mySlot > 4){
      int ii;
      for(ii = 0; ii < mySlot - 4; ii++){
        ret = ULT_Yield(ULT_ANY);
        assert(tidValid(ret));
      }
    }
  }
}
// Tests that arg was passed correctly and yields to another thread on the readyQueue.
// arg is the string to compare.
void doALittleDance(char* arg)
{
	assert(strcmp(arg, "Make a little love\n") == 0);
	while(1)
	{
		ULT_Yield(ULT_ANY);
	}
}
static void hello(char *msg)
{
  Tid ret;

  printf("Made it to hello() in called thread\n");
  printf("Message: %s\n", msg);
  ret = ULT_Yield(ULT_SELF);
  assert(ULT_isOKRet(ret));
  printf("Thread returns from first yield\n");

  ret = ULT_Yield(ULT_SELF);
  assert(ULT_isOKRet(ret));
  printf("Thread returns from second yield\n");

  while(1){
    ULT_Yield(ULT_ANY);
  }
  
}
Beispiel #8
0
static void
mbWorker1(Mailbox *mb)
{
  int myPart = MAXMAIL - MAXMAIL/2;
  int ii;
  for(ii = 0; ii < myPart; ii++){
    mb_increment(mb, 1);
    ULT_Yield(ULT_ANY);
  }
  return;
}
int main(int argc, char **argv)
{
	printf("Starting our tests....\n");
	
	Tid IAmNotValid = 5;
	
	Tid linen;
	Tid cotton;
	Tid silk;
	// Get it? Because they are threads...
	
	printf("Testing destruction of a nonexistent thread.\n");
	IAmNotValid = ULT_DestroyThread(IAmNotValid);
	assert(IAmNotValid == ULT_INVALID);
	
	printf("Testing creation of a thread and yielding to it.\n");
	linen = ULT_CreateThread((void (*)(void *))doALittleDance, "Make a little love\n");
	cotton = ULT_Yield(linen);
	assert(cotton == linen);
	
	printf("Testing destruction of a thread.\n");
	Tid ret = ULT_DestroyThread(linen);
	assert(ret == linen);
	
	printf("Testing creation of a thread with a more complex root function, and then yielding to it.\n");
	silk = ULT_CreateThread((void (*)(void *))funkyTown, "In the funkyTown method and the arg was passed just fine. Woohoo.\n");
	Tid cloth = ULT_Yield(silk);
	assert(cloth == silk);
	
	printf("Testing destruction of a thread that has already terminated naturally.\n");
	Tid deleteAttempt = ULT_DestroyThread(silk);
	assert(deleteAttempt == ULT_INVALID);
	
	printf("You have passed all your tests! Nice dude!\n");

	return 1;
}
//destroys the thread whose identifier is tid
//caller continues to execute and receives the result
Tid ULT_DestroyThread(Tid tid)
{
	ULT_Maintainence();

	if(tid == ULT_ANY)
	{
		//destroy any thread except the caller
		//if there are no more other threads available to destroy, return ULT_NONE
		if (alive->head->next == NULL)	return ULT_NONE;
		if (alive->head == NULL)	return ULT_NONE;
		Thread* target;
		do
		{
			target = ThreadListRemoveEnd(alive);
			if (!target) return ULT_NONE;
			ThreadListAddToHead(alive, target);
		} while(target->id == runningThread->id);

		ThreadListRemove(alive, target->id);
		ThreadListAddToHead(zombie, target);
		numberOfThreads--;
		//printf("Thead[%d] zombified\n", target->id);
		return target->id;
	}
	else if(tid == ULT_SELF)
	{
		//destroy the caller, function does not return
		//schedule another to run
		ThreadListRemove(alive, runningThread->id);
		ThreadListAddToHead(zombie, runningThread);
		numberOfThreads--;
		//printf("Thead[%d] zombified\n", runningThread->id);
		ULT_Yield(ULT_ANY);
		return ULT_NONE;
		//return runningThread->id;
	}
	else if(tid > 0)
	{
		//destroy the thread with id tid
		Thread* target = ThreadListFind(alive, tid);
		if (!target) return ULT_INVALID;
		ThreadListRemove(alive, target->id);
		ThreadListAddToHead(zombie, target);
		numberOfThreads--;
		//printf("Thead[%d] zombified\n", target->id);
		return target->id;
	}
	else return ULT_FAILED;
}
Beispiel #11
0
static void
pcTestConsumer(PCTestArgs *args)
{
  int ii, jj;
  for(ii = 0; ii < args->count; ii++){
    if(vverbose){
      printf("consumer getting color %d\n", args->color);
    }
    PC_Get(args->pc, args->color);
    if(vverbose){
      printf("consumer done getting color %d\n", args->color);
    }
    for(jj = 0; jj < args->color + 1; jj++){
      ULT_Yield(ULT_ANY);
    }
  }
  mb_increment(args->mb, 0);
  free(args);
}
void basicThreadTests()
{
  Tid ret;
  Tid ret2;

  printf("Starting tests...\n");

  /*
   * Initial thread yields
   */
  ret = ULT_Yield(ULT_SELF);
  assert(ULT_isOKRet(ret));
  printf("Initial thread returns from Yield(SELF)\n");
  ret = ULT_Yield(0); /* See ULT.h -- initial thread must be Tid 0 */
  assert(ULT_isOKRet(ret));
  printf("Initial thread returns from Yield(0)\n");
  ret = ULT_Yield(ULT_ANY);
  assert(ret == ULT_NONE);
  printf("Initial thread returns from Yield(ANY)\n");
  ret = ULT_Yield(0xDEADBEEF);
  assert(ret == ULT_INVALID);
  printf("Initial thread returns from Yield(INVALID)\n");
  ret = ULT_Yield(16);
  assert(ret == ULT_INVALID);
  printf("Initial thread returns from Yield(INVALID2)\n");
  
  /*
   * Create a thread
   */
  ret = ULT_CreateThread((void (*)(void *))hello, "World");
  assert(ULT_isOKRet(ret));
  ret2 = ULT_Yield(ret);
  assert(ret2 == ret);

  /*
   * Create 10 threads
   */
  int ii;
  static const int NTHREAD = 10;
  Tid children[NTHREAD];
  char msg[NTHREAD][1024];
  for(ii = 0; ii < NTHREAD; ii++){
    ret = snprintf(msg[ii], 1023, "Hello from thread %d\n", ii);
    assert(ret > 0);
    children[ii] = ULT_CreateThread((void (*)(void *))hello, msg[ii]);
    assert(ULT_isOKRet(children[ii]));
  }
  for(ii = 0; ii < NTHREAD; ii++){
    ret = ULT_Yield(children[ii]);
    assert(ret == children[ii]);
  }


  /*
   * Destroy 11 threads we just created
   */
  ret = ULT_DestroyThread(ret2);
  assert(ret == ret2);
  for(ii = 0; ii < NTHREAD; ii++){
    ret = ULT_DestroyThread(children[ii]);
    assert(ret == children[ii]);
  }

  /*
   * Create maxthreads-1 threads
   */
  printf("Creating %d threads\n", ULT_MAX_THREADS-1);
  for(ii = 0; ii < ULT_MAX_THREADS-1; ii++){
    ret = ULT_CreateThread((void (*)(void *))fact, (void *)10);
    assert(ULT_isOKRet(ret));
  }
  /*
   * Now we're out of threads. Next create should fail.
   */
  ret = ULT_CreateThread((void (*)(void *))fact, (void *)10);
  assert(ret == ULT_NOMORE);
  /*
   * Now let them all run.
   */
  printf("Running %d threads\n", ULT_MAX_THREADS-1);
  for(ii = 0; ii < ULT_MAX_THREADS; ii++)
  {
    ret = ULT_Yield(ii);
    if(ii == 0){ 
      /* 
       * Guaranteed that first yield will find someone. 
       * Later ones may or may not depending on who
       * stub schedules  on exit.
       */
      assert(ULT_isOKRet(ret));
    }
  }
  /*
   * They should have cleaned themselves up when
   * they finished running. Create maxthreads-1 threads.
   */
  printf("Creating %d threads\n", ULT_MAX_THREADS-1);
  for(ii = 0; ii < ULT_MAX_THREADS-1; ii++){
    ret = ULT_CreateThread((void (*)(void *))fact, (void *)10);
    assert(ULT_isOKRet(ret));
  }
  /*
   * Now destroy some explicitly and let the others run
   */
  printf("Destorying %d threads, running the rest\n",
         ULT_MAX_THREADS/2);
  for(ii = 0; ii < ULT_MAX_THREADS; ii+=2){
    ret = ULT_DestroyThread(ULT_ANY);
    assert(ULT_isOKRet(ret));
  }
  for(ii = 0; ii < ULT_MAX_THREADS; ii++){
    ret = ULT_Yield(ii);
  }
  printf("Trying some destroys even though I'm the only thread\n");
  ret = ULT_DestroyThread(ULT_ANY);
  assert(ret == ULT_NONE);
  ret = ULT_DestroyThread(42);
  assert(ret == ULT_INVALID);
  ret = ULT_DestroyThread(-42);
  assert(ret == ULT_INVALID);
  ret = ULT_DestroyThread(ULT_MAX_THREADS + 1000);
  assert(ret == ULT_INVALID);

  /*
   * Create a thread that destroys itself. 
   * Control should come back here after
   * that thread runs.
   */
  printf("Testing destroy self\n");
  int flag = setFlag(0);
  ret = ULT_CreateThread((void (*)(void *))suicide, NULL);
  assert(ULT_isOKRet(ret));
  ret = ULT_Yield(ret);
  assert(ULT_isOKRet(ret));
  flag = setFlag(0);
  assert(flag == 1); /* Other thread ran */
  /* That thread is gone now */
  ret = ULT_Yield(ret);
  assert(ret == ULT_INVALID);
  

}   
Beispiel #13
0
void 
lockTests()
{

  ULT_Yield(ULT_ANY);
  startAlarmHelper();
  interruptsQuiet();

  /*
   * One mailbox
   */
  Mailbox *mb = (Mailbox *)malloc(sizeof(Mailbox));
  assert(mb);
  mb_init(mb, 2, MAXMAIL);

  ULT_CreateThread((void (*)(void *))mbWorker0, mb);

  while(!mb_checkDone(mb)){
    ULT_Yield(ULT_ANY);
  }
  int jj;
  for(jj = 0; jj < 1000; jj++){
    ULT_Yield(ULT_ANY);
  }
  assert(mb_checkDone(mb));
  free(mb);


  printf("One mailbox, two threads OK\n");

  /*
   * Two mailboxen
   */
  mb = (Mailbox *)malloc(sizeof(Mailbox));
  assert(mb);
  mb_init(mb, 2, MAXMAIL);
  Mailbox *mb2 = (Mailbox *)malloc(sizeof(Mailbox));
  assert(mb2);
  mb_init(mb2, 2, MAXMAIL);

  ULT_CreateThread((void (*)(void *))mbWorker0, mb);
  ULT_CreateThread((void (*)(void *))mbWorker0, mb2);

  while(!mb_checkDone(mb)){
    ULT_Yield(ULT_ANY);
  }
  for(jj = 0; jj < 1000; jj++){
    ULT_Yield(ULT_ANY);
  }
  assert(mb_checkDone(mb));
  while(!mb_checkDone(mb2)){
    ULT_Yield(ULT_ANY);
  }
  for(jj = 0; jj < 1000; jj++){
    ULT_Yield(ULT_ANY);
  }
  assert(mb_checkDone(mb2));

  free(mb);
  free(mb2);
  printf("Two mailboxen, four threads OK\n");

  
  printf("lockTests OK\n");
}