// 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; }
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(); }
// 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(); }
//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 }
/*===========================================================================* * 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; }
/*===========================================================================* * 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; }