Пример #1
0
// The parent will wait for the child pid to exit() before continuing execution
// wait(): on success, returns the process ID of the terminated child; on error, -1 is returned.
uint64_t wait_p()
{
  printf("In waitp() process pid=%p", running->pid);

  // Bring parent from the waitlist because in waitpid the parent might be waiting for the child to finish
  struct taskList * temp;
  int flag=0;
  temp = deadTaskQ;
  if(temp==NULL)
    printf("There are no processes in the WaitQ strange ???\n");
  while(temp->next)
  {
    // search for a child in the runnableQ 
    // if a child exists move parent to the waitQ until at least one child exits 
    if(temp->task->ppid == running->pid) 
    {
      flag=1;
      waitTaskQ = addToTailTaskList(waitTaskQ, running);
      runnableTaskQ = removeFromTaskList(runnableTaskQ, running);
      schedule_process();
      break;
    }
    temp=temp->next;
  }
  if(flag==0)
    return -1;
  return 0;

}
Пример #2
0
void exit_process(int status)
{
  printf("Exit() called for process pid=%p", running->pid);

  // Bring parent from the waitlist because in waitpid the parent might be waiting for the child to finish
  struct taskList * temp;
  PCB *parent=NULL;
  temp = waitTaskQ;
  if(temp==NULL)
    printf("There are no processes in the WaitQ strange ???\n");
  while(temp)
  {
    if(temp->task->pid == running->ppid) // parent found in the waitQ --- move it to the runnableQ 
    {
      parent = temp->task;
      waitTaskQ = removeFromTaskList(waitTaskQ, parent);
      runnableTaskQ = addToTailTaskList(runnableTaskQ, parent);
      break;
    }
    temp=temp->next;
  }

  // REmove the process from the Queue
  runnableTaskQ = removeFromTaskList(runnableTaskQ, running);
  deadTaskQ = addToHeadTaskList(deadTaskQ, running);

  // Set the status value to the parent ??? Where I dont know it yet !! :P

  // Free the memory used by the process
  deletePageTables();

  // call schedule() to start other process
  schedule_process();
}
Пример #3
0
// Sleeps for a specified number of seconds (time in secs)
// sec is a global variable which has count of number of seconds elapsed 
void sleep_t(uint64_t time)
{
  running->sleep_start = sec;
  running->sleep_duration = time;
  runnableTaskQ = removeFromTaskList(runnableTaskQ, running);
  waitTaskQ = addToTailTaskList(waitTaskQ, running);
  // if(sec - sleep_start > time) 
  //     do the following !! 

  // call schedule here to schedule another process
  // Make sure to check for the waiting processes to move them from waitQ to the runnableQ
  schedule_process();

}
Пример #4
0
//waitpid(): on success, returns the process ID of the child whose state has changed; if WNOHANG was specified  and  one  or  more  child(ren)
//specified by pid exist, but have not yet changed state, then 0 is returned.  On error, -1 is returned.
// The parent will wait for the child pid to exit() before continuing execution
// The waitpid() system call suspends execution of the calling process until a child specified by pid argument has changed state.  By  default,
// waitpid() waits only for terminated children, but this behavior is modifiable via the options argument, as described below.
uint64_t wait_pid(uint64_t pid)
{
  // just remove current running parent process to waitQ from runnableQ
  // cheack if PID exits ??
  if( searchPCB(runnableTaskQ, pid)==NULL )
    return -1;

  runnableTaskQ = removeFromTaskList(runnableTaskQ, running);
  waitTaskQ = addToTailTaskList(waitTaskQ, running);

  // should i call schedule ??
  // parent will pause executing and call yield/schedule
  schedule_process();
  return 0;
}
/*===========================================================================*
 *				do_lottery				     *
 *===========================================================================*/
int do_lottery() {
	struct schedproc *rmp;
	int proc_nr;
	int lucky;
	int old_priority;
	int flag = -1;
	int nTickets = 0;//Number of tickets hold by all processes in USER_Q

	/*calculates nTickets by adding tickets held by each process in USER_Q*/
	for (proc_nr=0, rmp=schedproc; proc_nr < NR_PROCS; proc_nr++, rmp++) {
		if ((rmp->flags & IN_USE) && PROCESS_IN_USER_Q(rmp)) {
			if(USER_Q == rmp->priority) {
				nTickets += rmp->ticketsNum;
			}
		}
	}

	//lucky no. is generated between 0 to nTickets
	lucky = nTickets ? random() % nTickets : 0;

	/*
        Selects process to schedule based  on lucky no.
        For each process in ready queue we use lucky = lucky - rmp->ticktsNum and if
        lucky < 0 we select that process to run by increasing the priority to 12.
	*/
	for (proc_nr=0, rmp=schedproc; proc_nr < NR_PROCS; proc_nr++, rmp++) {
		if ((rmp->flags & IN_USE) && PROCESS_IN_USER_Q(rmp) && USER_Q == rmp->priority) {//if process is in USER_Q
			old_priority = rmp->priority;												 //saving process priority to check whether process is elligible to run or not
			if (lucky >= 0) {															 //if lucky is greater than 0
				lucky -= rmp->ticketsNum;												 //subtract tickets held by the process from lucky
				if (lucky < 0) {														 //if lucky is less than 0
					rmp->priority = MAX_USER_Q;											 //change default priority of process to MAX_USER_Q
					flag = OK;															 //set flag to be OK
				}
			}
			if (old_priority != rmp->priority) {                                         //if priority of process changed
				schedule_process(rmp, flag);											 //schedule the process
			}
		}
	}
	return nTickets ? flag : OK;														 //return -1 if no process in USER_Q else OK
 }
Пример #6
0
/*===========================================================================*
 *				do_start_scheduling			     *
 *===========================================================================*/
int do_start_scheduling(message *m_ptr)
{
	register struct schedproc *rmp;
	int rv, proc_nr_n, parent_nr_n;

	/* we can handle two kinds of messages here */
	assert(m_ptr->m_type == SCHEDULING_START ||
		m_ptr->m_type == SCHEDULING_INHERIT);

	/* check who can send you requests */
	if (!accept_message(m_ptr))
		return EPERM;

	/* Resolve endpoint to proc slot. */
	if ((rv = sched_isemtyendpt(m_ptr->SCHEDULING_ENDPOINT, &proc_nr_n))
			!= OK) {
		return rv;
	}
	rmp = &schedproc[proc_nr_n];

	/* Populate process slot */
	rmp->endpoint     = m_ptr->SCHEDULING_ENDPOINT;
	rmp->parent       = m_ptr->SCHEDULING_PARENT;
	rmp->max_priority = (unsigned) m_ptr->SCHEDULING_MAXPRIO;
	rmp->YOLO = sys_times(rmp->endpoint, NULL, rmp->YOLO, NULL, NULL);
	if (rmp->max_priority >= NR_SCHED_QUEUES) {
		return EINVAL;
	}

	/* Inherit current priority and time slice from parent. Since there
	 * is currently only one scheduler scheduling the whole system, this
	 * value is local and we assert that the parent endpoint is valid */
	if (rmp->endpoint == rmp->parent) {
		/* We have a special case here for init, which is the first
		   process scheduled, and the parent of itself. */
		rmp->priority   = USER_Q;
		rmp->time_slice = DEFAULT_USER_TIME_SLICE;

		/*
		 * Since kernel never changes the cpu of a process, all are
		 * started on the BSP and the userspace scheduling hasn't
		 * changed that yet either, we can be sure that BSP is the
		 * processor where the processes run now.
		 */
#ifdef CONFIG_SMP
		rmp->cpu = machine.bsp_id;
		/* FIXME set the cpu mask */
#endif
	}

	switch (m_ptr->m_type) {

	case SCHEDULING_START:
		/* We have a special case here for system processes, for which
		 * quantum and priority are set explicitly rather than inherited
		 * from the parent */
		rmp->priority   = rmp->max_priority;
		rmp->time_slice = (unsigned) m_ptr->SCHEDULING_QUANTUM;
		break;

	case SCHEDULING_INHERIT:
		/* Inherit current priority and time slice from parent. Since there
		 * is currently only one scheduler scheduling the whole system, this
		 * value is local and we assert that the parent endpoint is valid */
		if ((rv = sched_isokendpt(m_ptr->SCHEDULING_PARENT,
				&parent_nr_n)) != OK)
			return rv;

		rmp->priority = schedproc[parent_nr_n].priority;
		rmp->time_slice = schedproc[parent_nr_n].time_slice;
		break;

	default:
		/* not reachable */
		assert(0);
	}

	/* Take over scheduling the process. The kernel reply message populates
	 * the processes current priority and its time slice */
	if ((rv = sys_schedctl(0, rmp->endpoint, 0, 0, 0)) != OK) {
		printf("Sched: Error taking over scheduling for %d, kernel said %d\n",
			rmp->endpoint, rv);
		return rv;
	}
	rmp->flags = IN_USE;

	/* Schedule the process, giving it some quantum */
	pick_cpu(rmp);
	while ((rv = schedule_process(rmp, SCHEDULE_CHANGE_ALL)) == EBADCPU) {
		/* don't try this CPU ever again */
		cpu_proc[rmp->cpu] = CPU_DEAD;
		pick_cpu(rmp);
	}

	if (rv != OK) {
		printf("Sched: Error while scheduling process, kernel replied %d\n",
			rv);
		return rv;
	}

	/* Mark ourselves as the new scheduler.
	 * By default, processes are scheduled by the parents scheduler. In case
	 * this scheduler would want to delegate scheduling to another
	 * scheduler, it could do so and then write the endpoint of that
	 * scheduler into SCHEDULING_SCHEDULER
	 */

	m_ptr->SCHEDULING_SCHEDULER = SCHED_PROC_NR;

	return OK;
}
Пример #7
0
/*===========================================================================*
 *				do_start_scheduling			     *
 *===========================================================================*/
int do_start_scheduling(message *m_ptr)
{
	register struct schedproc *rmp;
	int rv, proc_nr_n, parent_nr_n;
	
	/* we can handle two kinds of messages here */
	assert(m_ptr->m_type == SCHEDULING_START || 
		m_ptr->m_type == SCHEDULING_INHERIT);

	/* check who can send you requests */
	if (!accept_message(m_ptr))
		return EPERM;

	/* Resolve endpoint to proc slot. */
	if ((rv = sched_isemtyendpt(m_ptr->SCHEDULING_ENDPOINT, &proc_nr_n))
			!= OK) {
		return rv;
	}
	rmp = &schedproc[proc_nr_n];

	/* Populate process slot */
	rmp->endpoint     = m_ptr->SCHEDULING_ENDPOINT;
	rmp->parent       = m_ptr->SCHEDULING_PARENT;
	rmp->max_priority = (unsigned) m_ptr->SCHEDULING_MAXPRIO;
	if (rmp->max_priority >= NR_SCHED_QUEUES) {
		return EINVAL;
	}

	/* Inherit current priority and time slice from parent. Since there
	 * is currently only one scheduler scheduling the whole system, this
	 * value is local and we assert that the parent endpoint is valid */
	if (rmp->endpoint == rmp->parent) {
		/* We have a special case here for init, which is the first
		   process scheduled, and the parent of itself. */
		rmp->priority   = USER_Q;
		rmp->time_slice = DEFAULT_USER_TIME_SLICE;

		/*
		 * Since kernel never changes the cpu of a process, all are
		 * started on the BSP and the userspace scheduling hasn't
		 * changed that yet either, we can be sure that BSP is the
		 * processor where the processes run now.
		 */
#ifdef CONFIG_SMP
		rmp->cpu = machine.bsp_id;
		/* FIXME set the cpu mask */
#endif
	}
	
	switch (m_ptr->m_type) {

	case SCHEDULING_START:
		/* We have a special case here for system processes, for which
		 * quanum and priority are set explicitly rather than inherited 
		 * from the parent */
		rmp->priority   = rmp->max_priority;
		rmp->time_slice = (unsigned) m_ptr->SCHEDULING_QUANTUM;
		break;
		
	case SCHEDULING_INHERIT:
		/* Inherit current priority and time slice from parent. Since there
		 * is currently only one scheduler scheduling the whole system, this
		 * value is local and we assert that the parent endpoint is valid */
		if ((rv = sched_isokendpt(m_ptr->SCHEDULING_PARENT,
				&parent_nr_n)) != OK)
			return rv;

		rmp->priority = schedproc[parent_nr_n].priority;
		rmp->time_slice = schedproc[parent_nr_n].time_slice;
		
		// sys_getproctab((struct proc *) &tempProc);
		
		// const char* currentName = tempProc[_ENDPOINT_P(rmp->endpoint) + 5].p_name;
		// unsigned realRuntime = tempProc[_ENDPOINT_P(rmp->endpoint) + 5].p_cycles;

		// int fake_proc_flag = 0;
		// for (int i = 0; i < PROCNUM; i++) {
		// 	if (!strcmp(sjf[i].p_name, currentName)) {
		// 		sjf[i].p_endpoint = rmp->endpoint;
		// 		sjf[i].predBurst = ALPHA * realRuntime + (1 - ALPHA) * sjf[i].predBurst;
		// 		fake_proc_flag = 1;
		// 	}
		// }
		// printf("Before flag \n");
		// if (fake_proc_flag == 1) {
		// 	printf("In flag statement \n");
		// 	int c, d, i;
		// 	struct sjf swap;
		
		// 	for (c = 0; c < (PROCNUM - 1); c++) {
		// 		for (d = 0; d < (PROCNUM - c - 1); d++) {
		// 			if (sjf[d].predBurst > sjf[d+1].predBurst) {
		// 				swap = sjf[d];
		// 				sjf[d] = sjf[d+1];
		// 				sjf[d+1] = swap;
		// 			}
		// 		}
		// 	}
			
		// 	for (i = 0; i < PROCNUM; i++) {
		// 		printf("Process name: %s - Predicted Runtime: %ld", sjf[i].p_name, sjf[i].predBurst);
		// 	}
		
		// 	for (i = PROCNUM - 1; i >= 0; i--) {
		// 		sys_qptab(sjf[i].p_endpoint);
		// 	}
		// } else {
		// 	rmp->priority = schedproc[parent_nr_n].priority;
		// 	rmp->time_slice = schedproc[parent_nr_n].time_slice;
		// }
		// printf("After flag, before break \n");
		break;
		
	default: 
		/* not reachable */
		assert(0);
	}

	/* Take over scheduling the process. The kernel reply message populates
	 * the processes current priority and its time slice */
	if ((rv = sys_schedctl(0, rmp->endpoint, 0, 0, 0)) != OK) {
		printf("Sched: Error taking over scheduling for %d, kernel said %d\n",
			rmp->endpoint, rv);
		return rv;
	}
	rmp->flags = IN_USE;

	/* Schedule the process, giving it some quantum */
	pick_cpu(rmp);
	while ((rv = schedule_process(rmp, SCHEDULE_CHANGE_ALL)) == EBADCPU) {
		/* don't try this CPU ever again */
		cpu_proc[rmp->cpu] = CPU_DEAD;
		pick_cpu(rmp);
	}

	if (rv != OK) {
		printf("Sched: Error while scheduling process, kernel replied %d\n",
			rv);
		return rv;
	}

	/* Mark ourselves as the new scheduler.
	 * By default, processes are scheduled by the parents scheduler. In case
	 * this scheduler would want to delegate scheduling to another
	 * scheduler, it could do so and then write the endpoint of that
	 * scheduler into SCHEDULING_SCHEDULER
	 */

	m_ptr->SCHEDULING_SCHEDULER = SCHED_PROC_NR;

	return OK;
}