void Kernel(tf_t *tf_p) // kernel begins its control upon/after interrupt { int pid; pcbs[ cur_pid ].tf_p = tf_p; // save for cur_pid which may change switch( tf_p->intr_id ) { case TIMER_INTR: TimerISR(); break; case IRQ7_INTR: IRQ7ISR(); // service parallel printer port event break; case GETPID_INTR: tf_p->eax = cur_pid; break; case SLEEP_INTR: SleepISR(); break; case SPAWN_INTR: pid = DeQ( &avail_q ); // get pid and put in ebx can be in Kernel() pcbs[ cur_pid ].tf_p->ebx = pid; // child PID, could be -1 if( pid == -1 ) break; // no more process SpawnISR(pid, (func_ptr_t) pcbs[ cur_pid ].tf_p->eax); break; case SEMINIT_INTR: SemInitISR(); break; case SEMWAIT_INTR: SemWaitISR(tf_p->eax); break; case SEMPOST_INTR: SemPostISR(tf_p->eax); break; case MSGSND_INTR: MsgSndISR(); break; case MSGRCV_INTR: MsgRcvISR(); break; case IRQ3_INTR: case IRQ4_INTR: IRQ34ISR(); break; case FORK_INTR: pid = DeQ( &avail_q ); ForkISR(pid); pcbs[ cur_pid ].tf_p->ebx = pid; break; case WAIT_INTR: //cons_printf("Wait Intr\n"); WaitISR(); break; case EXIT_INTR: //cons_printf("Exit Intr\n"); ExitISR(); break; } Scheduler(); // find same/new process to run Loader(pcbs[ cur_pid ].tf_p); // load it to run } // Kernel()
// ********************************************************************** // ********************************************************************** // signal semaphore // // if task blocked by semaphore, then clear semaphore and wakeup task // else signal semaphore // void semSignal(Semaphore* s) { int i; // assert there is a semaphore and it is a legal type assert("semSignal Error" && s && ((s->type == 0) || (s->type == 1))); // check semaphore type if (s->type == 0) { // binary semaphore // look through tasks for one suspended on this semaphore for (i=0; i<MAX_TASKS; i++) // look for suspended task { if (tcb[i].event == s) { s->state = 0; // clear semaphore tcb[i].event = 0; // clear event pointer tcb[i].state = S_READY; // unblock task if(DeQ(s->q,i) >= 0) { enQ(rq,i,tcb[i].priority); } if (!superMode) swapTask(); return; } } // nothing waiting on semaphore, go ahead and just signal s->state = 1; // nothing waiting, signal if (!superMode) swapTask(); return; } else { // counting semaphore if (++s->state > 0) { return; } else { int nextTask = DeQ(s->q,-1); enQ(rq, nextTask, tcb[nextTask].priority); tcb[nextTask].state = S_READY; tcb[nextTask].event = 0; return; } } } // end semSignal
int main() { int pid; InitKernelData(); InitKernelControl(); pid = DeQ(&free_q); StartProcISR(pid,(unsigned int)IdleProc); pid = DeQ(&free_q); StartProcISR(pid,(unsigned int)InitProc); LoadRun(pcb[0].TF_ptr); return 0; // not reached, but compiler needs it for syntax }
void MsgSndISR() { int mid, pid; msg_t *src, *dest; mid = pcbs[cur_pid].tf_p->eax; src = (msg_t *)pcbs[cur_pid].tf_p->ebx; src->sender = cur_pid; // authenticate sender src->time_stamp = sys_tick; // authenticate time_stamp if(EmptyQ(&mboxes[mid].wait_q)) { MsgEnQ( src, &( mboxes[mid].msg_q ) ); } else { pid = DeQ(&mboxes[mid].wait_q); pcbs[pid].state = READY; EnQ(pid, &ready_q); dest = (msg_t *)pcbs[pid].tf_p->eax; // eax since MsgRcv changed *dest = *src; } }
static void exitTask(int taskId) { Semaphore* sem = semaphoreList; Semaphore** semLink = &semaphoreList; assert("exitTaskError" && tcb[taskId].name); // 1. find task in system queue // 2. if blocked, unblock (handle semaphore) // 3. set state to exit // ?? add code here while(sem = *semLink) { if (tcb[taskId].event == sem) { // printf("\nHello World"); DeQ(sem->q,taskId); enQ(rq,taskId,tcb[taskId].priority); // printQ(rq); } // move to next semaphore semLink = (Semaphore**)&sem->semLink; } // DeQ(rq,taskId); tcb[taskId].state = S_EXIT; // EXIT task state return; } // end exitTask
void MsgSndISR() { int mid,pid,head; msg_t *source, *destination; mid = pcbs[cur_pid].tf_p ->eax; source = (msg_t*)pcbs[cur_pid].tf_p -> ebx; if(!EmptyQ(&mboxes[mid].wait_q)) { pid = DeQ(&mboxes[mid].wait_q); EnQ(pid,&ready_q); pcbs[pid].state = READY; destination = (msg_t *)pcbs[pid].tf_p -> ebx; MyMemCpy((char*)destination,(char*)source,sizeof(msg_t)); } else { EnQMsg(source, &mboxes[mid].msg_q); head = mboxes[mid].msg_q.head; destination = &mboxes[mid].msg_q.msgs[head]; } destination->sender = cur_pid; destination->send_tick = sys_tick; }
void TimerISR() { outportb(0x20, 0x60); // dismiss timer interrupt // deal with sleep items sys_tick++; while(!EmptyQ(&sleep_q) && (pcbs[sleep_q.q[sleep_q.head]].wake_tick <= sys_tick)) { int tmpPID = DeQ(&sleep_q); pcbs[tmpPID].state=READY; EnQ(tmpPID, &ready_q); } if(cur_pid == 0) return; // if Idle process, no need to do this on it pcbs[cur_pid].tick_count++; if(pcbs[cur_pid].tick_count == TIME_SLICE) // running up time, preempt it? { pcbs[cur_pid].tick_count = 0; // reset (roll over) usage time pcbs[cur_pid].total_tick_count += TIME_SLICE; // sum to total pcbs[cur_pid].state = READY; // change its state EnQ(cur_pid, &ready_q); // move it to ready_q cur_pid = -1; // no longer running } }
////////////phase 4 void MsgSndISR(int msg_addr) { int msg_q_id; int freed_pid; msg_t *incoming_msg_ptr, *dst_msg_ptr; incoming_msg_ptr = (msg_t *) msg_addr; msg_q_id = incoming_msg_ptr->recipient; incoming_msg_ptr->OS_clock = OS_clock; incoming_msg_ptr->sender = running_pid; if(msg_q[msg_q_id].wait_q.len == 0) { MsgEnQ(incoming_msg_ptr, &msg_q[msg_q_id]); } else { freed_pid = DeQ(&(msg_q[msg_q_id].wait_q)); EnQ(freed_pid, &ready_q); pcb[freed_pid].state = READY; dst_msg_ptr = (msg_t *) pcb[freed_pid].TF_ptr->eax; *dst_msg_ptr = *incoming_msg_ptr; } }
int bfs(int source, int dest){ int u, v; int d[300+10] , visited[300+10]; for(int i=0;i<305;i++) {d[i] = 10000; visited[i] = 0;} d[source] = 0; parent[source] = -1; visited[source] = 1; EnQ(source); while(Q_Empty()==0){ u = DeQ(); for(v=1; v<=Total_Router; v++){ if(routing_table[u][v]==1&&visited[v]==0){ d[v] = d[u] + 1; visited[v] = 1; parent[v] = u; EnQ(v); } } } return d[dest]; }
int main() { int pid; InitKernelData(); //call InitKernelData() to set kernel data InitKernelControl(); //call InitKernelControl() (see below) pid = DeQ(&free_q); StartProcISR(pid, IdleProc); //phase 3 pid = DeQ(&free_q); StartProcISR(pid, InitProc); LoadRun(pcb[0].TF_ptr); //call LoadRun() to load/run IdleProc return 0; //this will never be executed }
int SemInitISR(int sem_count) { int sid; sid = DeQ(&avail_sem_q); if(sid == -1) return sid; sems[sid].count = sem_count; InitQ(&(sems[sid].wait)); return sid; }
void SleepISR(int sleep_secs){ q_t tmp_q; InitQ(&tmp_q); pcbs[cur_pid].wake_tick = (sys_tick + sleep_secs * 100); while( !(EmptyQ(&sleep_q)) && (pcbs[sleep_q.q[sleep_q.head]].wake_tick <= pcbs[cur_pid].wake_tick) ){ int tmpPID= DeQ(&sleep_q); EnQ(tmpPID, &tmp_q); } EnQ(cur_pid, &tmp_q); while (!EmptyQ(&sleep_q)){ EnQ(DeQ(&sleep_q), &tmp_q); } while(!EmptyQ(&tmp_q)){ EnQ(DeQ(&tmp_q), &sleep_q); } pcbs[cur_pid].state = SLEEP; cur_pid = -1; }
void SemPostISR(int sid){ if (!EmptyQ(&(sems[sid].wait_q))) { int free_pid = DeQ(&(sems[sid].wait_q)); pcbs[free_pid].state = READY; EnQ(free_pid, &ready_q); } else { sems[sid].sem_count += 1; } }
int SemInitISR(int sem_count) { int sid; sid = DeQ(&avail_sem_q); if(sid < 0) { return -1; } sems[sid].sem_count = sem_count; InitQ(&sems[sid].wait_q); return sid; }
void Scheduler() // this is kernel's process scheduler, simple round robin { if(cur_pid > 0) return; // when cur_pid is not 0 (IdleProc) or -1 (none) if(cur_pid == 0) pcbs[0].state = READY; // skip when cur_pid is -1 if(EmptyQ(&ready_q)) cur_pid = 0; // ready q empty, use IdleProc else cur_pid = DeQ(&ready_q); // or get 1st process from ready_q pcbs[cur_pid].state = RUN; // RUN state for newly selected process }
//void SemPostISR(int sid) { void SemPostISR() { int pid, sid = pcbs[cur_pid].tf_p->eax; if(!EmptyQ(&sems[sid].wait_q)) { pid = DeQ(&sems[sid].wait_q); EnQ(pid, &ready_q); pcbs[pid].state = READY; } else { sems[sid].sem_count++; } }
void SemGetISR(int limit){ int sem_id; sem_id = DeQ(&sem_q); if(sem_id == -1){ pcb[running_pid].TF_ptr->ebx= -1; return; } MyBzero((char*)&sem[sem_id].wait_q,sizeof(q_t)); sem[sem_id].limit = limit; pcb[running_pid].TF_ptr->ebx= sem_id; }
int SemInitISR(int sem_count){ int sid; if (!EmptyQ(&avail_sem_q)) { sid = DeQ(&avail_sem_q); sems[sid].sem_count = sem_count; InitQ(&(sems[sid].wait_q)); } else { sid = -1; } return sid; }
int main() { int pid; InitKernelData(); //call InitKernelData() to set kernel data InitKernelControl(); //call InitKernelControl() (see below) pid = DeQ(&free_q); StartProcISR((int) pid, (int) IdleProc); //phase 3 pid = DeQ(&free_q); StartProcISR((int) pid, (int) InitProc); //phase 7 pid = DeQ(&free_q); StartProcISR((int) pid, (int) FileService); //phase 6 pid = DeQ(&free_q); StartProcISR((int) pid, (int) ShellProc); pid = DeQ(&free_q); StartProcISR((int) pid, (int) StdinProc); pid = DeQ(&free_q); StartProcISR((int) pid, (int) StdoutProc); LoadRun(pcb[0].TF_ptr); //call LoadRun() to load/run IdleProc return 0; //this will never be executed }
// ********************************************************************** // ********************************************************************** // wait on semaphore // // if semaphore is signaled, return immediately // else block task // int semWait(Semaphore* s) { assert("semWait Error" && s); // assert semaphore assert("semWait Error" && ((s->type == 0) || (s->type == 1))); // assert legal type assert("semWait Error" && !superMode); // assert user mode // check semaphore type if (s->type == 0) { // binary semaphore // if state is zero, then block task if (s->state == 0) { tcb[curTask].event = s; // block task tcb[curTask].state = S_BLOCKED; DeQ(rq,curTask); enQ(s->q, curTask,tcb[curTask].priority); swapTask(); // reschedule the tasks return 1; } // state is non-zero (semaphore already signaled) s->state = 0; // reset state, and don't block return 0; } else { s->state--; if (s->state >= 0) return; tcb[curTask].event = s; // block task tcb[curTask].state = S_BLOCKED; DeQ(rq,curTask); enQ(s->q, curTask,tcb[curTask].priority); swapTask(); // reschedule the tasks return 1; } } // end semWait
void SemInitISR() { int sem_count = pcbs[ cur_pid ].tf_p->eax; int sid = DeQ( &avail_sem_q ); // get sid and put in ebx can be in Kernel() if(sid != -1) { MyBZero( (char *)&sems[ sid ], sizeof( sem_t ) ); sems[ sid ].sem_count = sem_count; } pcbs[ cur_pid ].tf_p->ebx = sid; }
void SemPostISR( int sid ) // passing arg as device driver phase uses this { if( EmptyQ( &sems[ sid ].wait_q ) ) { sems[ sid ].sem_count++; } else { int pid = DeQ( &sems[ sid ].wait_q ); pcbs[ pid ].state = READY; EnQ( pid, &ready_q ); } }
void SemPostISR(int sem_id){ if(sem[sem_id].wait_q.len > 0){ int pid = DeQ(&sem[sem_id].wait_q); pcb[pid].state = READY; EnQ(pid, &ready_q); } else{ sem[sem_id].limit++; } }
// ********************************************************************** // system kill task // int sysKillTask(int taskId) { Semaphore* sem = semaphoreList; Semaphore** semLink = &semaphoreList; // assert that you are not pulling the rug out from under yourself! assert("sysKillTask Error" && tcb[taskId].name && superMode); printf("\nKill Task %s", tcb[taskId].name); // signal task terminated semSignal(taskSems[taskId]); // look for any semaphores created by this task while(sem = *semLink) { DeQ(sem->q,taskId); if(sem->taskNum == taskId) { // semaphore found, delete from list, release memory deleteSemaphore(semLink); } else { // move to next semaphore semLink = (Semaphore**)&sem->semLink; } } // ?? delete task from system queues // printQ(rq); DeQ(rq,taskId); // printQ(rq); free_argv(tcb[taskId].argv,tcb[taskId].argc); free(tcb[taskId].name); free(tcb[taskId].stack); tcb[taskId].name = 0; // release tcb slot return 0; } // end sysKillTask
void Kernel(tf_t *tf_p) // kernel directly enters here when interrupt occurs { // Save "tf_p" to pcbs[cur_pid].tf_p for future resume of process runtime pcbs[cur_pid].tf_p = tf_p; // tf_p->intr_id tells what intr made CPU get here, pushed in entry.S switch(tf_p->intr_id) { case TIMER_INTR: TimerISR(); // this must include dismissal of timer interrupt break; case IRQ7_INTR: IRQ7ISR(); break; case SLEEP_INTR: SleepISR(tf_p->eax); break; case GETPID_INTR: tf_p->eax = cur_pid; break; case SPAWN_INTR: if (EmptyQ(&avail_q)) { cons_printf("No more available PIDs!\n"); tf_p->ebx = -1; } else { tf_p->ebx = DeQ(&avail_q); SpawnISR((int) tf_p->ebx, (func_ptr_t) tf_p->eax); } break; case SEMINIT_INTR: tf_p->ebx = SemInitISR(tf_p->eax); break; case SEMWAIT_INTR: SemWaitISR(tf_p->eax); break; case SEMPOST_INTR: SemPostISR(tf_p->eax); break; case MSGSND_INTR: MsgSndISR(); break; case MSGRCV_INTR: MsgRcvISR(); break; } Scheduler(); // select a process to run Loader(pcbs[cur_pid].tf_p); // run the process selected }
void Scheduler() { // to choose running PID if(running_pid >0) return; if(running_pid == 0) pcb[running_pid].state = READY; running_pid = DeQ(&ready_q); if(running_pid == -1) running_pid=0; pcb[running_pid].state = RUN; }
void SemPostISR(int sid) { int pid; if( EmptyQ( &(sems[sid].wait)) ) { sems[sid].count++; return; } pid = DeQ(&(sems[sid].wait)); pcbs[pid].state = READY; EnQ(pid, &ready_q); return; }
void SemPostISR(int sem_id) { int temp; if(sem[sem_id].wait_q.len == 0) //check if any awaits { sem[sem_id].limit++; } else { temp = DeQ(&(sem[sem_id].wait_q)); EnQ(temp, &ready_q); pcb[running_pid].state = READY; } }
void SleepISR() { q_t tmp_q; InitQ( &tmp_q ); // empty temp q // calc the future wake_tick of cur_pid pcbs[cur_pid].wake_tick = sys_tick + 100 * pcbs[cur_pid].tf_p->eax; // WHILE sleep_q not empty AND the 1st one in it has a wake_tick <= // wake_tick of cur_pid: move that 1st one from sleep_q to tmp_q while(!EmptyQ(&sleep_q) && pcbs[ sleep_q.q[ sleep_q.head ] ].wake_tick <= pcbs[ cur_pid ].wake_tick ) { EnQ(DeQ(&sleep_q), &tmp_q); // append it to tmp_q } // insertion point is reached as either sleep_q is now empty or the // wake_tick of cur_pid is smaller than the 1st one in the sleep_q EnQ( cur_pid, &tmp_q ); // append cur_pid to tmp_q // append the rest of sleep_q to tmp_q while( ! EmptyQ( &sleep_q ) ) { EnQ( DeQ( &sleep_q ), &tmp_q ); } // update sleep_q with the now ordered tmp_q sleep_q = tmp_q; // assignment allowed for struct type pcbs[cur_pid].state = SLEEP; cur_pid = -1; // need to get a different proc to run now }
// ********************************************************************** // ********************************************************************** // Delete semaphore and free its resources // bool deleteSemaphore(Semaphore** semaphore) { Semaphore* sem = semaphoreList; Semaphore** semLink = &semaphoreList; int i; // assert there is a semaphore assert("deleteSemaphore Error" && *semaphore); // look for semaphore while(sem) { if (sem == *semaphore) { // semaphore found, delete from list, release memory *semLink = (Semaphore*)sem->semLink; // free the name array before freeing semaphore printf("\ndeleteSemaphore(%s)", sem->name); // ?? free all semaphore memory // ?? What should you do if there are tasks in this // semaphore's blocked queue???? while(sem->q[0]) { DeQ(sem->q,-1); } deleteDeltaClock(dClock,sem); free(sem->q); sem->q = 0; free(sem->name); sem->name = 0; free(sem); return TRUE; } // move to next semaphore semLink = (Semaphore**)&sem->semLink; sem = (Semaphore*)sem->semLink; } // could not delete return FALSE; } // end deleteSemaphore