Example #1
0
// Finds and deletes node with given pid
// Return 0 on success, else -1
int destroy_pid(int pid) {

  found_node = jrb_find_int(pid_tree, pid);
  
  if (found_node != NULL) {
    jrb_delete_node(found_node);
    return 0;
  } else {
    return -1;
  }
}
Example #2
0
void jrb_free_tree(JRB n)
{
  if (!ishead(n)) {
    fprintf(stderr, "ERROR: Rb_free_tree called on a non-head node\n");
    exit(1);
  }

  while(jrb_first(n) != jrb_nil(n)) {
    jrb_delete_node(jrb_first(n));
  }
  free(n);
}
Example #3
0
void kt_exit()
{
        JRB tmp;

	InitKThreadSystem();
	/*
	 * unroll stack and escape
	 */
	if(Debug & KT_DEBUG)
	{
		printf("longjmping to 0x%x exitbuf\n",ktRunning->func);
	}
 
        /* Now, do one of two things.  If this is the main (original)
           thread, you simply want to set its state to dead, and 
           reschedule.  You don't want to clean up its stack, because
           its stack is the main stack.  

           If this is any other thread, then longjmp to its exitbuf.
           This jumps you down to the bottom of the thread's stack, and
           the thread will put itself on the ktFree_me list, so that it
           can be cleaned up */
    
        if (ktRunning == ktOriginal) {
          ktRunning->state = DEAD;

          /* Nuke it from ktActive */
          tmp = jrb_find_int(ktActive, ktRunning->tid);
          if (tmp == NULL) {
            fprintf(stderr, "Panic: Original thread not in ktActive\n");
            exit(1);
          }
          jrb_delete_node(tmp);

          /* If there is a thread waiting on me, wake it up */

          tmp = jrb_find_int(ktBlocked, ktRunning->tid);
          if (tmp != NULL) {
            WakeKThread((K_t)tmp->val.v);
          }

          KtSched();

          /* This should never return, because this thread will never
             be rescheduled */
          fprintf(stderr, 
                  "Error: main thread returned after calling kt_exit()\n");
          exit(1);
        } else {
	  longjmp(ktRunning->exitbuf,1);
        }
}
Example #4
0
void
WakeKThread(K_t kt)
{
	/*
	 * look through the various blocked lists and try to wake the
	 * specified thread
	 */

        if (kt->state == RUNNING || kt->state == RUNNABLE 
                                 || kt->state == DEAD) return;

        jrb_delete_node(kt->blocked_list_ptr);
	kt->state = RUNNABLE;
	kt->blocked_list = NULL;
	kt->blocked_list_ptr = NULL;
	dll_append(ktRunnable,new_jval_v(kt));
	return;
}
Example #5
0
void finesleep_sleep(void *a, double t)
{
  Finesleep *fs;
  fd_set r;
  struct timeval tv;
  double newtime;
  JRB ptr;
  double diff;

  fs = (Finesleep *) a;
  if (fs->cheat) {
    newtime = fs->stime + t;
    pthread_mutex_lock(fs->lock);
    ptr = jrb_insert_dbl(fs->tree, newtime, new_jval_i(0));
    diff = newtime - fs->stime;
    pthread_mutex_unlock(fs->lock);
  } else {
    diff = t;
  }
  while (1) {
    tv.tv_sec = diff;
    diff -= tv.tv_sec;
    diff *= 1000000.0;
    tv.tv_usec = diff;
    FD_ZERO(&r);
    FD_SET(fs->fd[0], &r);
    select(fs->fd[0]+1, &r, NULL, NULL, &tv);
    if (fs->cheat) {
      pthread_mutex_lock(fs->lock);
      if (fs->tree->flink->key.d == newtime) {
        jrb_delete_node(ptr);
        fs->stime = newtime;
        pthread_mutex_unlock(fs->lock);
        return;
      } else {
        diff = newtime - fs->tree->flink->key.d;
        pthread_mutex_unlock(fs->lock);
      }
    } else {
      return;
    }
  }
}
Example #6
0
void
KtSched()
{
	K_t kt;
	JRB jb;
	unsigned int sp;
	unsigned int now;
        JRB tmp;
        Dllist dtmp;

	/*
	 * start by recording the current stack contents in case
	 * I'm descheduled
	 *
	 * this is where I return to when I'm rescheduled
	 */
	if(setjmp(ktRunning->jmpbuf) != 0)
	{
		FreeFinishedThreads();
		/*
		 * if we are being killed by another thread, jump through
		 * the exitbuf
		 */
		if(ktRunning->die_now)
		{
                        /* Jim: This used to longjmp to the exitbuf,
                                but I changed it for two reasons:  
                                1. It wasn't being removed from ktActive
                                2. Hell will be paid if it is ktOriginal.
                                I believe kt_exit() is cleaner.  I
                                have not tested it.  I should.  */
			kt_exit();
			/* not reached */
		}
		return;
	}


start:

        if (!jrb_empty(ktSleeping)) {
  	  now = time(0);
	  while(!jrb_empty(ktSleeping))
	  {
	  	kt = (K_t) jval_v(jrb_val(jrb_first(ktSleeping)));
		if(kt->wake_time > now)
		{
			break;
		}
		WakeKThread(kt);
          }
	}
			


	/*
	 * if there is nothing left to run, exit.  However, if there 
         * are sleepers or a joinall, deal with them appropriately
	 */
	if(dll_empty(ktRunnable))
	{

		/*
		 * first, check for sleepers and deal with them
		 */
		if(!jrb_empty(ktSleeping))
		{
			kt = jval_v(jrb_val(jrb_first(ktSleeping)));
			sleep(kt->wake_time - now);
			goto start;
		}

		/*
		 * next, see if there is a joinall thread waiting
		 */
		jb = jrb_find_int(ktBlocked,0);
		if(jb != NULL)
		{
			WakeKThread((K_t)jval_v(jrb_val(jb)));
			goto start;
		}

		if(!jrb_empty(ktBlocked)) 
		{
			if(Debug & KT_DEBUG)
			{
				fprintf(stderr,
					"All processes blocked, exiting\n");
				fflush(stderr);
			}
			exit(1);
		} else {
			if(Debug & KT_DEBUG)
			{
				fprintf(stderr,
					"No runnable threads, exiting\n");
				fflush(stderr);
			}
			exit(0);
                }

                fprintf(stderr, "We shouldn't get here\n");
                exit(1);
	}

        /* Grab the first job of the ready queue */

        dtmp = dll_first(ktRunnable);
        kt = (K_t) dtmp->val.v;
	dll_delete_node(dtmp);

        /* If it is runnable, run it */

	if(kt->state == RUNNABLE) {

		ktRunning = kt;
		ktRunning->state = RUNNING;
		longjmp(ktRunning->jmpbuf,1);
                /* This doesn't return */
	}

	/*
	 * if we have never run before, set up initial stack and go
	 */
	if(kt->state == STARTING) {
		if(setjmp(kt->jmpbuf) == 0)
		{
			/*
			 * get double word aligned SP -- stacks grow from high
			 * to low
			 */
			sp = (unsigned int)&((kt->stack[kt->stack_size-1]));
			while((sp % 8) != 0)
				sp--;
#ifdef LINUX
			/*
			 * keep double word aligned but put in enough
			 * space to handle local variables for KtSched
			 */
			kt->jmpbuf->__jmpbuf[JB_BP] = (int)sp;
			kt->jmpbuf->__jmpbuf[JB_SP] = (int)sp-1024;
			PTR_MANGLE(kt->jmpbuf->__jmpbuf[JB_SP]);
#endif

#ifdef SOLARIS
			/*
			 * keep double word aligned but put in enough
			 * space to handle local variables for KtSched
			 */
			kt->jmpbuf[JB_FP] = (int)sp;
			kt->jmpbuf[JB_SP] = (int)sp-1024;
#endif
			/*
			 * set ktRunning while we still have local variables
			 */
			kt->state = RUNNING;
			ktRunning = kt;
			/*
			 * now jump onto the new stack
			 */
			longjmp(kt->jmpbuf,1);
		}
		else
		{
			/*
			 * here we are on a new, clean stack -- touch nothing,
			 * set the state, and call
			 *
			 * ktRunning is global so there is no local variable
			 * problem
			 *
			 * borrow this stack to try and free the last thread
			 * if there was one
			 */

			FreeFinishedThreads();

			if(setjmp(ktRunning->exitbuf) == 0)
			{
				/*
				 * if we were killed before we ran, skip the
				 * function call
				 */
				if(ktRunning->die_now == 0)
				{
					ktRunning->func(ktRunning->arg);
				}
			}


			/*
			 * we are back and this thread is done
			 *
			 * make it inactive
			 */

			jb = jrb_find_int(ktActive,ktRunning->tid);
			if(jb == NULL)
			{
				if(Debug & KT_DEBUG)
				{
					fprintf(stderr,
				"KtSched: panic -- inactive return\n");
					fflush(stderr);
				}
				exit(1);
			}
			jrb_delete_node(jb);

			/*
			 * look to see if there is a thread waiting for this
			 * one to exit -- careful with locals
			 */
			jb = jrb_find_int(ktBlocked,ktRunning->tid);
			if(jb != NULL)
			{
				WakeKThread((K_t)jval_v(jrb_val(jb)));
			}


			/*
			 * all we can do now is to commit suicide
			 *
			 * don't touch the locals;
			 *
			 * and don't free the stack we are running on
			 */
			FreeFinishedThreads();
                        ktRunning->state = DEAD;
			dll_append(ktFree_me,new_jval_v(ktRunning));
			ktRunning = NULL;
			goto start;
		}
	}

        /* The only way we get here is if there was a thread on the
           runnable queue whose state was not RUNNABLE or STARTING.
           Flag that as an error */

        fprintf(stderr, 
                "Error: non-STARTING or RUNNABLE thread on the ready queue\n");
        exit(1);
}
Example #7
0
main(int argc, char **argv)
{
  IS is;
  JRB people, tmp;
  JRB elevators;
  double t;
  Elevator *e;
  char name[100];
  Person *p;

  elevators = make_jrb();
  people = make_jrb();
  is = new_inputstruct(NULL);

  while (get_line(is) > 0) {
    sscanf(is->fields[0], "%lf", &t);
    if (strcmp(is->fields[1], "Elevator") == 0) {
      e = get_elevator(atoi(is->fields[2]), elevators);
      if (strcmp(is->fields[3], "opening") == 0) {
        if (e->door != 0) {
          printf("Line %d: Elevator %d opening a door that's already open\n", is->line, e->id);
          exit(1);
        }
        if (e->state == 'O') {
          printf("Line %d: Elevator %d opening a door twice\n", is->line, e->id);
          exit(1);
        }
        if (e->state == 'C') {
          printf("Line %d: Elevator %d opening a door that is closing\n", is->line, e->id);
          exit(1);
        }
        e->state = 'O';
        e->time = t;
      } else if (strcmp(is->fields[3], "closing") == 0) {
        if (e->door != 1) {
          printf("Line %d: Elevator %d closing a door that's already closed\n", is->line, e->id);
          exit(1);
        }
        if (e->state == 'C') {
          printf("Line %d: Elevator %d closing a door twice\n", is->line, e->id);
          exit(1);
        }
        if (e->state == 'O') {
          printf("Line %d: Elevator %d closing a door that is opening\n", is->line, e->id);
          exit(1);
        }
        e->state = 'C';
        e->time = t;
      } else if (strcmp(is->fields[5], "closed.") == 0) {
        if (e->state != 'C') {
          printf("Line %d: Elevator %d closed a door that was not closing.\n", is->line, e->id);
          exit(1);
        }
        e->state = 'R';
        e->door = 0;
        e->time = t;
      } else if (strcmp(is->fields[5], "open.") == 0) {
        if (e->state != 'O') {
          printf("Line %d: Elevator %d opened a door that was not opening.\n", is->line, e->id);
          exit(1);
        }
        e->state = 'R';
        e->door = 1;
        e->time = t;
      } else if (strcmp(is->fields[3], "moving") == 0) {
        if (e->state != 'R') {
          printf("Line %d: Elevator %d moving from a non-rest state.\n", is->line, e->id);
          exit(1);
        }
        if (e->door != 0) {
          printf("Line %d: Elevator %d moving when the door is open.\n", is->line, e->id);
          exit(1);
        }
        if (atoi(is->fields[6]) != e->floor) {
          printf("Line %d: Elevator %d moving from a bad floor.\n", is->line, e->id);
          exit(1);
        }
        e->floor = atoi(is->fields[9]);
        e->state = 'M';
        e->time = t;
      } else if (strcmp(is->fields[3], "arrives") == 0) {
        if (e->state != 'M') {
          printf("Line %d: Elevator %d arriving from a non-moving state.\n", is->line, e->id);
          exit(1);
        }
        if (e->door != 0) {
          printf("Line %d: Elevator %d arriving when the door is open.\n", is->line, e->id);
          exit(1);
        }
        if (atoi(is->fields[6]) != e->floor) {
          printf("Line %d: Elevator %d arriving at the wrong floor (%d).\n", is->line, e->id, e->floor);
          exit(1);
        }
        e->state = 'R';
        e->time = t;
      }
    } else if (strcmp(is->fields[1], "Simulation") == 0) {
      exit(0);
    } else {
      sprintf(name, "%s %s", is->fields[1], is->fields[2]);
      if (strcmp(is->fields[3], "arrives") == 0) {
        if (jrb_find_str(people, name) != NULL) {
          printf("%d: Duplicate person %s\n", is->line, name);
          exit(1);
        }
        p = talloc(Person, 1);
        p->name = strdup(name);
        jrb_insert_str(people, p->name, new_jval_v((void *) p));
        p->from = atoi(is->fields[6]);
        p->to = atoi(is->fields[12]);
        p->state = 'A';
      } else {
        tmp = jrb_find_str(people, name);
        if (tmp == NULL) {
          printf("Line %d: Person %s doesn't exist\n", is->line, name);
          exit(1);
        }
        p = (Person *) tmp->val.v;
        if (strcmp(is->fields[4], "on") == 0) {
          if (p->state != 'A') {
            printf("Line %d: Person %s not in arriving state when getting on an elevator\n", is->line, p->name);
            exit(1);
          }
          if (atoi(is->fields[9]) != p->from) {
            printf("Line %d: Person %s not getting on the proper floor\n", is->line, p->name);
            exit(1);
          }
          e = get_elevator(atoi(is->fields[6]), elevators);
          if (e->floor != p->from) {
            printf("Line %d: Person %s getting on an elevator not on the right floor\n", is->line, p->name);
            exit(1);
          }
          if (e->door != 1) {
            printf("Line %d: Person %s getting on an elevator whose door isn't open.\n", is->line, p->name);
            exit(1);
          }
          if (e->state != 'R') {
            printf("Line %d: Person %s getting on an elevator who is not at rest.\n", is->line, p->name);
            exit(1);
          }
          p->state = 'O';
          p->e = e;
        } else if (strcmp(is->fields[4], "off") == 0) {
          if (p->state != 'O') {
            printf("Line %d: Person %s not on the elevator when getting off\n", is->line, p->name);
            exit(1);
          }
          if (atoi(is->fields[9]) != p->to) {
            printf("Line %d: Person %s not getting off on the proper floor\n", is->line, p->name);
            exit(1);
          }
          e = get_elevator(atoi(is->fields[6]), elevators);
          if (e != p->e) {
            printf("Line %d: Person %s getting off the wrong elevator\n", is->line, p->name);
            exit(1);
          }
          if (e->floor != p->to) {
            printf("Line %d: Person %s getting off an elevator not on the right floor\n", is->line, p->name);
            exit(1);
          }
          if (e->door != 1) {
            printf("Line %d: Person %s getting off an elevator whose door isn't open.\n", is->line, p->name);
            exit(1);
          }
          if (e->state != 'R') {
            printf("Line %d: Person %s getting off an elevator who is not at rest.\n", is->line, p->name);
            exit(1);
          }
          p->state = 'F';
        } else if (strcmp(is->fields[4], "done.") == 0) {
          if (p->state != 'F') {
            printf("Line %d: Person %s done before getting off the elevator\n", is->line, p->name);
            exit(1);
          }
          jrb_delete_node(tmp);
          free(p->name);          
          free(p);
        }
      }
    }
  }
  exit(0);
}