/* * Wait for a keycode to arrive. * Uses the keyboard wait queue to sleep until * a keycode arrives. */ Keycode Wait_For_Key(void) { bool gotKey, iflag; Keycode keycode = KEY_UNKNOWN; // see if we still have input from the qemu command line to hand off keycode = Get_Test_Input(); if (keycode != KEY_UNKNOWN) { return keycode; } iflag = Begin_Int_Atomic(); do { gotKey = !Is_Queue_Empty(); if (gotKey) keycode = Dequeue_Keycode(); else Wait(&s_waitQueue); } while (!gotKey); End_Int_Atomic(iflag); return keycode; }
/* * Look up a thread by its process id. * The caller must be the thread's owner. */ struct Kernel_Thread* Lookup_Thread(int pid) { struct Kernel_Thread *result = 0; bool iflag = Begin_Int_Atomic(); /* * TODO: we could remove the requirement that the caller * needs to be the thread's owner by specifying that another * reference is added to the thread before it is returned. */ result = Get_Front_Of_All_Thread_List(&s_allThreadList); while (result != 0) { if (result->pid == pid) { if (g_currentThread != result->owner) result = 0; break; } result = Get_Next_In_All_Thread_List(result); } End_Int_Atomic(iflag); return result; }
/* * Write a string of characters to the screen at current cursor * position using current attribute. */ void Put_String(const char *s) { bool iflag = Begin_Int_Atomic(); while (*s != '\0') Put_Char_Imp(*s++); Update_Cursor(); End_Int_Atomic(iflag); }
/* * Write a single character to the screen at current position * using current attribute, handling scrolling, special characters, etc. */ void Put_Char(int c) { bool iflag = Begin_Int_Atomic(); Put_Char_Imp(c); Update_Cursor(); End_Int_Atomic(iflag); }
/* * Get current cursor position. */ void Get_Cursor(int* row, int* col) { bool iflag = Begin_Int_Atomic(); *row = s_cons.row; *col = s_cons.col; End_Int_Atomic(iflag); //Print("cursor : %d, %d\n", *row, *col); }
/* * Initialize the screen module. */ void Init_Screen(void) { bool iflag = Begin_Int_Atomic(); s_cons.row = s_cons.col = 0; s_cons.currentAttr = DEFAULT_ATTRIBUTE; Clear_Screen(); End_Int_Atomic(iflag); }
/* * Write a buffer of characters at current cursor position * using current attribute. */ void Put_Buf(const char *buf, ulong_t length) { bool iflag = Begin_Int_Atomic(); while (length > 0) { Put_Char_Imp(*buf++); --length; } Update_Cursor(); End_Int_Atomic(iflag); }
/* * Print to console using printf()-style formatting. * Calls into Format_Output in common library. */ void Print(const char *fmt, ...) { va_list args; bool iflag = Begin_Int_Atomic(); va_start(args, fmt); Format_Output(&s_outputSink, fmt, args); va_end(args); End_Int_Atomic(iflag); }
/* * Clear the screen using the current attribute. */ void Clear_Screen(void) { uint_t *v = (uint_t *) VIDMEM; int i; uint_t fill = FILL_DWORD; bool iflag = Begin_Int_Atomic(); for(i = 0; i < NUM_SCREEN_DWORDS; ++i) *v++ = fill; End_Int_Atomic(iflag); }
/* * Set the current cursor position. * Return true if successful, or false if the specified * cursor position is invalid. */ bool Put_Cursor(int row, int col) { bool iflag; if(row < 0 || row >= NUMROWS || col < 0 || col >= NUMCOLS) return false; iflag = Begin_Int_Atomic(); s_cons.row = row; s_cons.col = col; Update_Cursor(); End_Int_Atomic(iflag); return true; }
/* * Allocate a key for accessing thread-local data. */ int Tlocal_Create(tlocal_key_t *key, tlocal_destructor_t destructor) { KASSERT(key); bool iflag = Begin_Int_Atomic(); if (s_tlocalKeyCounter == MAX_TLOCAL_KEYS) return -1; s_tlocalDestructors[s_tlocalKeyCounter] = destructor; *key = s_tlocalKeyCounter++; End_Int_Atomic(iflag); return 0; }
/* * Poll for a key event. * Returns true if a key is available, * false if not. If a key event is available, * it will be stored in the location pointed to * by keycode. */ bool Read_Key(Keycode * keycode) { bool result, iflag; iflag = Begin_Int_Atomic(); result = !Is_Queue_Empty(); if (result) { *keycode = Dequeue_Keycode(); } End_Int_Atomic(iflag); return result; }
/* Verhogen */ int V(int sid) { if (!validateSID(sid)) { return EINVALID; } bool atomic = Begin_Int_Atomic(); g_Semaphores[sid].resources++; if (g_Semaphores[sid].resources == 1) { /* from 0 to 1 we might wake up one */ Wake_Up_One(&g_Semaphores[sid].waitingThreads); } End_Int_Atomic(atomic); return 0; }
/* Probeer te verlagen */ int P(int sid) { if (!validateSID(sid)) { return EINVALID; } bool atomic = Begin_Int_Atomic(); if (g_Semaphores[sid].resources == 0) { Wait(&g_Semaphores[sid].waitingThreads); KASSERT(g_Semaphores[sid].resources == 1); } KASSERT(0 < g_Semaphores[sid].resources); g_Semaphores[sid].resources--; End_Int_Atomic(atomic); return 0; }
/* * If the given thread has a user context, detach it * and destroy it. This is called when a thread is * being destroyed. * Called with kthreadLock held */ void Detach_User_Context(struct Kernel_Thread *kthread) { struct User_Context *old = kthread->userContext; kthread->userContext = NULL; if (old != 0) { bool iflag; iflag = Begin_Int_Atomic(); int refCount; --old->refCount; if (old->refCount == 0) { Destroy_User_Context(old); } End_Int_Atomic(iflag); } }
/* * Wait for a keycode to arrive. * Uses the keyboard wait queue to sleep until * a keycode arrives. */ Keycode Wait_For_Key(void) { bool gotKey, iflag; Keycode keycode = KEY_UNKNOWN; iflag = Begin_Int_Atomic(); do { gotKey = !Is_Queue_Empty(); if (gotKey) keycode = Dequeue_Keycode(); else Wait(&s_waitQueue); } while (!gotKey); End_Int_Atomic(iflag); return keycode; }
int Destroy_Semaphore(int sid) { if (!validateSID(sid)) { return EINVALID; } bool atomic = Begin_Int_Atomic(); KASSERT(0 < g_Semaphores[sid].references); g_Semaphores[sid].references--; Clear_Bit(g_currentThread->semaphores, sid); if (g_Semaphores[sid].references == 0) { g_Semaphores[sid].available = true; /* mark it available */ Wake_Up(&g_Semaphores[sid].waitingThreads); /* wake all threads */ } End_Int_Atomic(atomic); return 0; }
/** * Reserve given DMA channel. * @param chan the channel to reserve * @return true if successful, false if not */ bool Reserve_DMA(int chan) { bool iflag = Begin_Int_Atomic(); bool result = false; KASSERT(VALID_CHANNEL(chan)); if (!IS_RESERVED(chan)) { /* Channel is available; unmask it. */ Out_Byte(DMA_MASK_ONE_REG(chan), chan & 3); /* Mask channel as allocated */ s_allocated |= (1 << chan); result = true; } End_Int_Atomic(iflag); return result; }
int Create_Semaphore(char *name, int nameLength, int initCount) { int sid = 0; int ret = -1; /* Syscall contract */ KASSERT(name != NULL); KASSERT(0 < nameLength && nameLength <= MAX_SEMAPHORE_NAME); KASSERT(0 <= initCount); KASSERT(strnlen(name, MAX_SEMAPHORE_NAME) == nameLength); bool atomic = Begin_Int_Atomic(); sid = isSemaphoreCreated(name, nameLength); KASSERT(sid < 0 || sid < MAX_NUM_SEMAPHORES); KASSERT(g_currentThread->semaphores != NULL); /* Negative sid for non existing, otherwise sid is Semaphore ID */ if (0 <= sid) { /* Already created semaphore */ g_Semaphores[sid].references++; Set_Bit(g_currentThread->semaphores, sid); ret = sid; } else { /* Semaphore not created. Create. */ sid = getFreeSemaphore(); if (sid < 0) { /* No semaphores available */ ret = EUNSPECIFIED; } else { strncpy(g_Semaphores[sid].name, name, MAX_SEMAPHORE_NAME); g_Semaphores[sid].resources = initCount; g_Semaphores[sid].available = false; g_Semaphores[sid].references = 1; Clear_Thread_Queue(&g_Semaphores[sid].waitingThreads); Set_Bit(g_currentThread->semaphores, sid); ret = sid; } } End_Int_Atomic(atomic); return ret; }
/* * Print list of all threads in system. * For debugging. */ void Dump_All_Thread_List(void) { struct Kernel_Thread *kthread; int count = 0; bool iflag = Begin_Int_Atomic(); kthread = Get_Front_Of_All_Thread_List(&s_allThreadList); Print("["); while (kthread != 0) { ++count; Print("<%lx,%lx,%lx>", (ulong_t) Get_Prev_In_All_Thread_List(kthread), (ulong_t) kthread, (ulong_t) Get_Next_In_All_Thread_List(kthread)); KASSERT(kthread != Get_Next_In_All_Thread_List(kthread)); kthread = Get_Next_In_All_Thread_List(kthread); } Print("]\n"); Print("%d threads are running\n", count); End_Int_Atomic(iflag); }
/* * Write a block at the logical block number indicated. */ static int IDE_Write(int driveNum, int blockNum, char *buffer) { int i; int head; int sector; int cylinder; short *bufferW; int reEnable = 0; if(driveNum < 0 || driveNum > (numDrives - 1)) { return IDE_ERROR_BAD_DRIVE; } if(blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) { return IDE_ERROR_INVALID_BLOCK; } /* now compute the head, cylinder, and sector */ sector = blockNum % drives[driveNum].num_SectorsPerTrack + 1; cylinder = blockNum / (drives[driveNum].num_Heads * drives[driveNum].num_SectorsPerTrack); head = (blockNum / drives[driveNum].num_SectorsPerTrack) % drives[driveNum].num_Heads; if(ideDebug) { Print("request to write block %d\n", blockNum); Print(" head %d\n", head); Print(" cylinder %d\n", cylinder); Print(" sector %d\n", sector); } #ifndef NS_INTERRUPTABLE_NO_GLOBAL_LOCK reEnable = Begin_Int_Atomic(); #endif Out_Byte(IDE_SECTOR_COUNT_REGISTER, 1); Out_Byte(IDE_SECTOR_NUMBER_REGISTER, sector); Out_Byte(IDE_CYLINDER_LOW_REGISTER, LOW_BYTE(cylinder)); Out_Byte(IDE_CYLINDER_HIGH_REGISTER, HIGH_BYTE(cylinder)); Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE(driveNum) | head); Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_WRITE_SECTORS); /* wait for the drive */ while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY) ; bufferW = (short *)buffer; for(i = 0; i < 256; i++) { Out_Word(IDE_DATA_REGISTER, bufferW[i]); } if(ideDebug) Print("About to wait for Write \n"); /* wait for the drive */ while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY) ; if(In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_ERROR) { Print("ERROR: Got Read %d\n", In_Byte(IDE_STATUS_REGISTER)); #ifndef NS_INTERRUPTABLE_NO_GLOBAL_LOCK End_Int_Atomic(reEnable); #endif return IDE_ERROR_DRIVE_ERROR; } if(ideDebug) Print("write completed \n"); #ifndef NS_INTERRUPTABLE_NO_GLOBAL_LOCK End_Int_Atomic(reEnable); #endif return IDE_ERROR_NO_ERROR; }
/* * Set the current character attribute. */ void Set_Current_Attr(uchar_t attrib) { bool iflag = Begin_Int_Atomic(); s_cons.currentAttr = attrib; End_Int_Atomic(iflag); }
/* * Get current cursor position. */ void Get_Cursor(int *row, int *col) { bool iflag = Begin_Int_Atomic(); *row = s_cons.row; *col = s_cons.col; End_Int_Atomic(iflag); }