fg_processinfo *fg_register(DEX32_DDL_INFO *scr, int keyboard) { //first check if there is any slot for another virtual console int i, slot = -1; DWORD cpuflags; fg_processinfo *new_vconsole; for (i=0; i < FG_MAXCONSOLE; i++) { if (fg_vconsoles[i] == 0) {slot = i;break;}; }; //oops! no more slots left, return with error if (slot == -1) return -1; new_vconsole = (fg_processinfo*) malloc(sizeof(fg_processinfo)); memset(new_vconsole,0,sizeof(fg_processinfo)); /*Lock when entering a mutual exclusion section*/ dex32_stopints(&cpuflags); new_vconsole->id = slot; new_vconsole->size = sizeof(fg_processinfo); new_vconsole->screen = scr; new_vconsole->keyboardfocus = keyboard; new_vconsole->pid = getprocessid(); fg_vconsoles[slot] = new_vconsole; dex32_restoreints(cpuflags); return new_vconsole; };
void fg_setmykeyboard(int pid) { fg_processinfo *ptr = fg_getinfo(getprocessid()); if (ptr!=0) { ptr->keyboardfocus = pid; }; };
int kb_keypressed() { if ( getprocessid() != fg_getkeyboardowner()) return 0; return !empty(&_q); };
/*creates a USER thread (In DEX this is process which shares the same memory space as its parent process, but has its own stack pointer)*/ DWORD createthread(void *ptr,void *stack,DWORD stacksize) { int pages; DWORD flags; PCB386 *temp=(PCB386*)malloc(sizeof(PCB386)); memset(temp,0,sizeof(PCB386)); totalprocesses++; dex32_stopints(&flags); temp->size=sizeof(PCB386); temp->before=current_process; sprintf(temp->name,"%s.thread",current_process->name); temp->processid = nextprocessid++; temp->accesslevel = ACCESS_USER; temp->status |= PS_ATTB_THREAD; current_process->childwait++; temp->meminfo = current_process->meminfo; temp->owner = getprocessid(); temp->workdir = current_process->workdir; temp->stdout = current_process->stdout; temp->outdev = current_process->outdev; temp->knext = current_process->knext; temp->pagedirloc = current_process->pagedirloc; /*Set up initial contents of the CPU registers*/ memset(temp,0,sizeof(saveregs)); temp->regs.EIP = (DWORD)ptr; temp->regs.ESP = (DWORD)(stack+stacksize-4); temp->stackptr = (void*)temp->regs.ESP; temp->regs.CR3 = (DWORD)current_process->pagedirloc; temp->regs.ES = USER_DATA; temp->regs.SS = USER_DATA; temp->regs.CS = USER_CODE; temp->regs.DS = USER_DATA; temp->regs.FS = USER_DATA; temp->regs.GS = USER_DATA; temp->regs.SS0 = SYS_STACK_SEL; //set up the initial stack pointer for system calls temp->stackptr0 = malloc(SYSCALL_STACK); temp->regs.ESP0 = temp->stackptr0+SYSCALL_STACK-4; temp->regs.EFLAGS = current_process->regs.EFLAGS; //initialize the current FPU state memcpy(&temp->regs2,&ps_kernelfpustate,sizeof(ps_kernelfpustate)); //Tell the scheduler to add it to the process queue ps_enqueue(temp); dex32_restoreints(flags); return temp->processid; };
int kb_dequeue(int *val) { int retval; if (getprocessid()!=fg_getkeyboardowner()) retval= -1; else retval= deq(&_q,val); return retval; };
void keyboard_wait() { if (fg_current) while ( getprocessid() != fg_getkeyboardowner()) { //we may probably allow child threads to share the keyoard with its parent if ( (current_process->status & PS_ATTB_THREAD) && current_process->accesslevel!=ACCESS_SYS && current_process->owner == fg_getkeyboardowner()) break; taskswitch(); }; };
/*creates a kernel thread*/ DWORD createkthread(void *ptr,char *name,DWORD stacksize) { PCB386 *temp=(PCB386*)malloc(sizeof(PCB386)); DWORD cpuflags; memset(temp,0,sizeof(PCB386)); temp->before=current_process; strcpy(temp->name,name); totalprocesses++; temp->size = sizeof(PCB386); temp->processid = nextprocessid++; temp->accesslevel = ACCESS_SYS; temp->owner = getprocessid(); temp->status |= PS_ATTB_THREAD; temp->knext = knext; temp->pagedirloc = pagedir1; temp->workdir = current_process->workdir; //set up the initial values of the CPU registers for this process memset(temp,0,sizeof(saveregs)); temp->regs.EIP = (DWORD)ptr; temp->stackptr = malloc(stacksize); temp->regs.ESP = (DWORD)(temp->stackptr+stacksize-4); temp->stackptr = (void*)temp->regs.ESP; temp->regs.CR3 = (DWORD)pagedir1; temp->regs.ES = SYS_DATA_SEL; temp->regs.SS = SYS_STACK_SEL; temp->regs.CS = SYS_CODE_SEL; temp->regs.DS = SYS_DATA_SEL; temp->regs.FS = SYS_DATA_SEL; temp->regs.GS = SYS_DATA_SEL; temp->regs.EFLAGS = 0x200; temp->arrivaltime = getprecisetime(); temp->stdin = current_process->stdin; /*critical section...*/ sync_entercrit(&processmgr_busy); dex32_stopints(&cpuflags); //add to the process list ps_enqueue(temp); dex32_restoreints(cpuflags); //end of critical section sync_leavecrit(&processmgr_busy); return temp->processid; ; };
/*execute program finds an available process table entry and puts the program in the appropriate segment*/ void executeprogram(char* filebuffer, int length, int foreground) { char* programbuffer; int i,j; short seg; /*set the current data segment to the kernel so we can read the process list*/ setdatasegkernel(); /*find an empty space for a process*/ for (i=0; i<MAXPROCESSES; i++) if (process_table[i].active==0) break; /*if the memory is full, we can't execute*/ if (i==MAXPROCESSES) { restoredataseg(); return; } /*set the process entry to active, set the stack pointer*/ seg=process_table[i].segment; process_table[i].active=1; process_table[i].sp=0xff00; /*get the id of the process that called execute*/ procid=getprocessid(); /*if the new process is to occupy the foreground, make the caller sleep*/ if (foreground==1) { process_table[procid].active=2; process_table[procid].waiton=i; } /*set the data segment back to the caller's segment*/ restoredataseg(); /*load the new process into memory*/ loadprogram(seg,filebuffer,length); }
/*Deactivate the process and wait for a process change*/ void terminateprogram() { int i; /*set the data segment to the kernel so we can read the process table*/ setdatasegkernel(); /*get the id of the caller*/ procid=getprocessid(); /*set its entry in the table to empty*/ process_table[procid].active=0; /*check if anyone is waiting on the caller. if so, wake them up*/ for (i=0; i<MAXPROCESSES; i++) if (process_table[i].active==2 && process_table[i].waiton==procid) process_table[i].active=1; /*set the data segment back to the caller*/ restoredataseg(); /*just busy wait until the timer moves us along*/ terminate(); }
void fg_updateinfo() { int refreshrate=100; //determines how long in milliseconds until the task manager refreshes its display int loop; int choice = 0; //Create a screen buffer that we can use fg_out = Dex32CreateDDL(); //register myself fg_fginfo = fg_register(fg_out,getprocessid()); fg_myslot = fg_fginfo->id; //prevent F5 and F6 from setting this process as the foreground fg_fginfo->ignore = 1; Dex32SetProcessDDL(fg_out,getprocessid()); fg_started = 1; while(1) { sleep(50); if (fg_state) { dd_swaptomemory(fg_out); clrscr(); textbackground(BLUE); textcolor(WHITE); printf("%-79s\n","Dex32- Virtual Console Management"); textbackground(BLACK); //Display processes in memory fg_showmenu(choice); dd_swaptohardware(fg_out); if (kb_keypressed()) { unsigned char c = getch(); if (c-'0' >= 0 && c-'0' <= 9) { int choice = c - '0'; if (fg_vconsoles[choice]!=0) if (!fg_vconsoles[choice]->ignore) fg_setforeground(choice); } else if (c == KEY_UP) { if (choice>0) choice -- ; } else if (c == KEY_DOWN) { if (choice<FG_MAXCONSOLE -1) choice++; } else if (c== '\n') { if (fg_vconsoles[choice]!=0) if (!fg_vconsoles[choice]->ignore) fg_setforeground(choice); }; }; }; }; };
fg_processinfo *fg_getmyinfo() { return fg_getinfo(getprocessid()); };