void fg_showmenu(int choice) { int i; DWORD cpuflags; fg_processinfo screens[FG_MAXCONSOLE]; dex32_stopints(&cpuflags); for (i=0; i < FG_MAXCONSOLE; i++) { if (fg_vconsoles[i]) memcpy(&screens[i], fg_vconsoles[i], sizeof(fg_processinfo)); else screens[i].id = -1; }; dex32_restoreints(cpuflags); for (i=0; i < FG_MAXCONSOLE; i++) { char pname[255]; if (choice == i) textbackground(BLUE); else textbackground(BLACK); if (screens[i].id!=-1) { PCB386 *process=ps_findprocess(screens[i].pid); if (process != -1) { PCB386 *subprocess = ps_findprocess(screens[i].keyboardfocus); strcpy(pname,process->name); if (screens[i].keyboardfocus != screens[i].pid && subprocess!=0) sprintf(pname,"%s (%s)",process->name,subprocess->name); if (screens[i].ignore) textcolor(RED); else textcolor(WHITE); printf("[%2d] %-73s\n",i, pname); textbackground(BLACK); } else printf("[%2d] unknown\n",i); } else printf("[%2d] unused\n", i+1); }; };
//sends a message to another process int sendmessageEX(DWORD source,DWORD pid,DWORD mes,DWORD data) { DWORD cpuflags; PCB386 *ptr=(PCB386*)ps_findprocess(pid); if (ptr!=-1) { int index=ptr->meshead; if (ptr->mestotal>=MAX_MESSAGE-1) return IPCSTAT_FULL; dex32_stopints(&cpuflags); ptr->mesq[index].message=mes; ptr->mesq[index].data=data; ptr->mesq[index].sender=source; ptr->mesq[index].receiver=pid; ptr->mestotal++; ptr->meshead++; if (ptr->meshead>=MAX_MESSAGE) ptr->meshead=0; dex32_restoreints(cpuflags); return IPCSTAT_OK; }; return IPCSTAT_ERROR; };
/*kills a process with the specified pid, leaves all files open*/ void ps_user_kill(int pid) { if (ps_findprocess(pid)!=-1) { sigterm = pid; taskswitch(); }; };
int ps_changename(const char *name,int pid) { PCB386 *ptr; sync_entercrit(&processmgr_busy); ptr=ps_findprocess(pid); if (ptr!=-1) strcpy(ptr->name,name); sync_entercrit(&processmgr_busy); };
//decrements the wait status of the parent //used for creating services DWORD dex32_setservice() { PCB386 *ptr; sync_entercrit(&processmgr_busy); ptr=ps_findprocess(current_process->owner); if (ptr!=-1) { ptr->childwait=0; }; sync_leavecrit(&processmgr_busy); };
DEX32_DDL_INFO *Dex32SetProcessDDL(DEX32_DDL_INFO *dev, int pid){ DEX32_DDL_INFO *ret = 0; PCB386 *pcb = ps_findprocess(pid); if(pcb != -1) { /*pid is valid*/ ret = pcb->outdev; pcb->outdev = dev; return ret; } return 0; }
DWORD getprocessinfo(DWORD processid,PCB386 *data) { PCB386 *ptr; sync_justwait(&processmgr_busy); ptr = ps_findprocess(processid); if (ptr!=-1) { memcpy(data,ptr,ptr->size); return 1; }; return 0; ; };
int dex32_getname(DWORD processid,int bufsize,char *s) { PCB386 *ptr; sync_justwait(&processmgr_busy); ptr = ps_findprocess(processid); if (ptr!=-1) { int i; //copy the name of the process to s for (i=0;i<bufsize&&ptr->name[i];i++) s[i]=ptr->name[i]; s[i]=0; return 1; }; return 0; };
int dex32_waitpid(int pid,int status) { while (ps_findprocess(pid) != -1); };
/*called when another process wants to kill another. Also performs garbage collection (reclaims memory used by the application).*/ DWORD kill_process(DWORD processid) { PCB386 *ptr,*parentptr=0; sync_entercrit(&processmgr_busy); ptr = bridges_ps_findprocess(processid); if (ptr!=-1) { if (! (ptr->status&PS_ATTB_UNLOADABLE) ) { PCB386 *parent; kill_children(processid); //kill child processes first if (ptr->accesslevel == ACCESS_SYS) //a kernel thread? { dex32_killkthread(ptr); sync_leavecrit(&processmgr_busy); return 1; }; if ( ptr->status&PS_ATTB_THREAD ) //a thread process? If yes then redirect to another procedure { kill_thread(ptr); sync_leavecrit(&processmgr_busy); return 1; }; while (closeallfiles(ptr->processid)==1); parent=ps_findprocess(ptr->owner); if (parent!=-1) { parent->childwait=0; }; //locate the parent process and decrement its waiting //status...important for the dex32_wait() function if (ptr->accesslevel == ACCESS_SYS) free(ptr->stackptr); /*Perform memory garbage collection if necessary*/ if (ptr->meminfo!=0) freeprocessmemory(ptr->meminfo,(DWORD*)ptr->pagedirloc); if (!(ptr->status&PS_ATTB_THREAD) && (ptr->accesslevel != ACCESS_SYS) ) { //free the page tables used by the application dex32_freeuserpagetable((DWORD*)ptr->pagedirloc); #ifdef MEM_LEAK_CHECK printf("1 page freed (page directory).\n"); #endif mempush(ptr->pagedirloc); }; if (ptr->parameters!=0) free(ptr->parameters); if (ptr->stdout!=0) { free(ptr->stdout); }; //Tell the scheduler to remove this process from the queue ps_dequeue(ptr); free(ptr); sync_leavecrit(&processmgr_busy); return 1; }; }; sync_leavecrit(&processmgr_busy); return 0; };
//displays the list of processes void show_process() { int total=0,i; DWORD totalsize=0 , grandtotalcputime = 0; PCB386* ptr; char levelstr[13]; textbackground(BLUE); printf("dex32_scheduler v1.00\n"); textbackground(BLACK); printf("Processes in memory:\n\n"); textcolor(MAGENTA); printf("%-5s %-17s %-10s %-17s %6s %5s %10s\n","ID","Name","User Level","Owner","Size","AT","CT"); textcolor(WHITE); /*Tell the scheduler to give us an array of PCBs which contain the PCBs of the processes running in the system*/ total = get_processlist(&ptr); qsort(ptr,total,sizeof(PCB386),process_pid_sorter); /*first we obtain the total cputime of all the processes, this is computed by the summation of the delta cputimes*/ for (i=0; i<total; i++) grandtotalcputime += ( ptr[i].totalcputime - ptr[i].lastcputime ); for (i=0; i<total; i++) { char temp[255]; PCB386 *ps; int percent_cpu_time; //obtain the size of the memory used by the process (no. of pages used) DWORD psize=getprocessmemory(ptr[i].meminfo,ptr[i].pagedirloc); //convert to Kilobytes psize=((psize*0x1000)/1024)+4; //update the global total totalsize+=psize; printf("[%-3s]",itoa(ptr[i].processid,temp,10)); if ( ptr[i].status & PS_ATTB_UNLOADABLE ) textcolor(RED); else if (ptr[i].accesslevel == ACCESS_SYS) textcolor(LIGHTBLUE); else textcolor(GREEN); printf(" %-17s",ptr[i].name); textcolor(WHITE); strcpy(levelstr,"?"); //determine the access level and then show it on the screen if (ptr[i].accesslevel == ACCESS_SYS) strcpy(levelstr,"supervisor"); else if (ptr[i].accesslevel == ACCESS_USER) strcpy(levelstr,"user"); //obtain the name of the parent process dex32_getname(ptr[i].owner,sizeof(temp),temp); /*compute for the percent CPU time*/ percent_cpu_time = (ptr[i].totalcputime - ptr[i].lastcputime) * 100 / grandtotalcputime; sync_entercrit(&processmgr_busy); ps = ps_findprocess(ptr[i].processid); if (ps!=-1) { ps->lastcputime = ptr[i].totalcputime; }; sync_leavecrit(&processmgr_busy); printf(" %-10s %-17s %5dK %5ds %5ds(%2d)%%\n",levelstr,temp,psize, ptr[i].arrivaltime/100, ptr[i].totalcputime/100, percent_cpu_time); }; printf("\nTotal : %d processes (%d KB)\n",total,totalsize); printf("Time Since Startup : %d\n", ticks / context_switch_rate); printf("Legend: AT = Arrival Time, CT = CPU Time, %%CT = Percent CPU Time\n"); free(ptr); };
//The taskswitcher is basically the program that runs all the time. //It is responsible for switching ro various processes and terminating them. void taskswitcher() { char temp[255]; DWORD cputime=0; PCB386 *readyprocess; do { stopints(); //fetch a ready process from the ready queue do { if (!sigwait) { //if the wait register is not set, switch to //another process, the wait is used to prevent //other processes from taking control during //a critical section, sigwait should be //returned to its original state after the critical //section is over //obtain next job from the scheduler //readyprocess=extension_current->ps_scheduler->scheduler(&kernelPCB); devmgr_scheduler_extension *cursched = (devmgr_scheduler_extension*)extension_table[CURRENT_SCHEDULER].iface; readyprocess = (PCB386*)bridges_link((devmgr_generic*)cursched,&cursched->scheduler, current_process,0,0,0,0,0); }; //readyprocess=bridges_ps_scheduler(current_process); current_process=readyprocess; //tell the cpu to give control to <readyprocess> ps_switchto(readyprocess); /*Make sure the taskwitcher was really called by the timer, since another way of calling the taskswithcer is through taskswitch(). In that case we must not call time_handler in order to make the time as accurate as possible*/ if (!ps_notimeincrement) { //Increment system time... etc. time_handler(); } else ps_notimeincrement = 0; //record the number of milleseconds the process used readyprocess->totalcputime++; //A process wants to get immediate control, usually set by //device drivers that are hooked to IRQs if (sigpriority) { PCB386 *priorityprocess = ps_findprocess(sigpriority); if (priorityprocess!=-1) { //give the process to the CPU ps_switchto(priorityprocess); }; sigpriority = 0; }; } while (sigwait); //check the registers, and act if necessary if (pfoccured) { setattb(PF_TSS,0x89); memcpy(&pfPCB.regs,&pfPCB_copy.regs,sizeof(pfPCB.regs)); pfoccured=0; }; if (sigterm&&!flushing) { flushok=0; kill_process(sigterm); flushok=1; sigterm=0; ; }; if (sched_sysmes[0]) { sendmessage(sched_sysmes[0],sched_sysmes[1],sched_sysmes[2]); sched_sysmes[0]=0; ; }; if (sigshutdown) { broadcastmessage(1,SIG_KILL,0); ; }; } while (1); ; };