From abe6c6cf7fac39102e20cd28687b24c67f4952f8 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 16 Jun 2011 19:01:51 +0800 Subject: [PATCH] Kernel - Implemented waking from semaphores - Threads waiting on semaphores can now be woken by other threads - Changed ping to not base its timestamp on after the packet is sent > Fixes extra-long timeouts --- Kernel/debug.c | 9 ++--- Kernel/drv/vterm.c | 52 +++++++++++++++++++++++++++++ Kernel/include/semaphore.h | 2 +- Kernel/messages.c | 11 ++++--- Kernel/threads.c | 55 ++++++++++++++++++++++++++++++- Kernel/vfs/select.c | 6 ++-- Modules/IPStack/icmp.c | 4 ++- Modules/IPStack/link.c | 5 +-- Modules/Network/NE2000/ne2000.c | 17 ++++++---- Modules/Network/RTL8139/rtl8139.c | 11 +++++-- Modules/Storage/ATA/io.c | 2 -- 11 files changed, 147 insertions(+), 27 deletions(-) diff --git a/Kernel/debug.c b/Kernel/debug.c index 76525bf3..7915b869 100644 --- a/Kernel/debug.c +++ b/Kernel/debug.c @@ -250,7 +250,7 @@ void Debug_Enter(const char *FuncName, const char *ArgTypes, ...) va_start(args, ArgTypes); - LogF("%012lli ", now()); + LogF("%014lli ", now()); while(i--) Debug_Putchar(' '); Debug_Puts(1, FuncName); @@ -308,7 +308,7 @@ void Debug_Log(const char *FuncName, const char *Fmt, ...) va_start(args, Fmt); - LogF("%012lli ", now()); + LogF("%014lli ", now()); while(i--) Debug_Putchar(' '); Debug_Puts(1, FuncName); @@ -343,7 +343,7 @@ void Debug_Leave(const char *FuncName, char RetType, ...) gDebug_Level = 0; i = 0; } - LogF("%012lli ", now()); + LogF("%014lli ", now()); // Indenting while(i--) Debug_Putchar(' '); @@ -387,6 +387,7 @@ void Debug_HexDump(const char *Header, const void *Data, Uint Length) { const Uint8 *cdat = Data; Uint pos = 0; + LogF("%014lli ", now()); Debug_Puts(1, Header); LogF(" (Hexdump of %p)\r\n", Data); @@ -410,7 +411,7 @@ void Debug_HexDump(const char *Header, const void *Data, Uint Length) { int i ; - LogF("Log: %04x: ", pos); + LogF("%014lli Log: %04x: ", now(), pos); for(i = 0; i < Length; i ++) { LogF("%02x ", cdat[i]); diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index bead23cf..2b9f6562 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -1047,6 +1047,57 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) break; } break; + + // Erase in line + case 'K': + switch(args[0]) + { + case 0: // Erase to right + if( Term->Flags & VT_FLAG_ALTBUF ) + { + int i, max; + max = Term->Width - Term->AltWritePos % Term->Width; + for( i = 0; i < max; i ++ ) + Term->AltBuf[Term->AltWritePos+i].Ch = 0; + } + else + { + int i, max; + max = Term->Width - Term->WritePos % Term->Width; + for( i = 0; i < max; i ++ ) + Term->Text[Term->WritePos+i].Ch = 0; + } + VT_int_UpdateScreen(Term, 0); + break; + case 1: // Erase to left + if( Term->Flags & VT_FLAG_ALTBUF ) + { + int i = Term->AltWritePos % Term->Width; + while( i -- ) + Term->AltBuf[Term->AltWritePos++].Ch = 0; + } + else + { + int i = Term->WritePos % Term->Width; + while( i -- ) + Term->Text[Term->WritePos++].Ch = 0; + } + VT_int_UpdateScreen(Term, 0); + break; + case 2: // Erase all + if( Term->Flags & VT_FLAG_ALTBUF ) + { + VT_int_ClearLine(Term, Term->AltWritePos / Term->Width); + } + else + { + VT_int_ClearLine(Term, Term->WritePos / Term->Width); + } + VT_int_UpdateScreen(Term, 0); + break; + } + break; + // Set cursor position case 'H': if( Term->Flags & VT_FLAG_ALTBUF ) @@ -1582,6 +1633,7 @@ void VT_int_ToggleAltBuffer(tVTerm *Term, int Enabled) Term->Flags |= VT_FLAG_ALTBUF; else Term->Flags &= ~VT_FLAG_ALTBUF; + VT_int_UpdateScreen(Term, 1); } // --- diff --git a/Kernel/include/semaphore.h b/Kernel/include/semaphore.h index 0cf4b211..f42da042 100644 --- a/Kernel/include/semaphore.h +++ b/Kernel/include/semaphore.h @@ -46,7 +46,7 @@ extern void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const c * \param Semaphore Semaphore structure to use * \param MaxToTake Maximum number of items to take off the list (if zero, as much as possible is taken) * \return Number of items fetched - * \retval 0 Semaphore interrupted + * \retval 0 Semaphore interrupted (signal/message) * \retval -1 Unspecified error */ extern int Semaphore_Wait(tSemaphore *Sem, int MaxToTake); diff --git a/Kernel/messages.c b/Kernel/messages.c index 45b5dfa8..ce23d6b1 100644 --- a/Kernel/messages.c +++ b/Kernel/messages.c @@ -2,6 +2,7 @@ * AcessOS Microkernel Version * messages.c */ +#define DEBUG 1 #include #include #include @@ -24,18 +25,18 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data) tThread *thread; tMsg *msg; - Log("Proc_SendMessage: (Err=%p, Dest=%i, Length=%i, Data=%p)", Err, Dest, Length, Data); + ENTER("pErr iDest iLength pData", Err, Dest, Length, Data); if(Length <= 0 || !Data) { *Err = -EINVAL; - return -1; + LEAVE_RET('i', -1); } // Get thread thread = Threads_GetThread( Dest ); // Error check - if(!thread) { return -1; } + if(!thread) LEAVE_RET('i', -1); // Get Spinlock SHORTLOCK( &thread->IsLocked ); @@ -43,7 +44,7 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data) // Check if thread is still alive if(thread->Status == THREAD_STAT_DEAD) { SHORTREL( &thread->IsLocked ); - return -1; + LEAVE_RET('i', -1); } // Create message @@ -68,7 +69,7 @@ int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data) Threads_Wake( thread ); SHORTREL(&glThreadListLock); - return 0; + LEAVE_RET('i', 0); } /** diff --git a/Kernel/threads.c b/Kernel/threads.c index 40e1729b..bee332b5 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -755,6 +755,56 @@ int Threads_Wake(tThread *Thread) SHORTREL( &glThreadListLock ); return -EOK; + case THREAD_STAT_SEMAPHORESLEEP: { + tSemaphore *sem; + tThread *th, *prev=NULL; + + sem = Thread->WaitPointer; + + SHORTLOCK( &sem->Protector ); + + // Remove from sleeping queue + for( th = sem->Waiting; th; prev = th, th = th->Next ) + if( th == Thread ) break; + if( th ) + { + if(prev) + prev->Next = Thread->Next; + else + sem->Waiting = Thread->Next; + if(sem->LastWaiting == Thread) + sem->LastWaiting = prev; + } + else + { + prev = NULL; + for( th = sem->Signaling; th; prev = th, th = th->Next ) + if( th == Thread ) break; + if( !th ) { + Log_Warning("Threads", "Thread %p(%i %s) is not on semaphore %p(%s:%s)", + Thread, Thread->TID, Thread->ThreadName, + sem, sem->ModName, sem->Name); + return -EINTERNAL; + } + + if(prev) + prev->Next = Thread->Next; + else + sem->Signaling = Thread->Next; + if(sem->LastSignaling == Thread) + sem->LastSignaling = prev; + } + + SHORTLOCK( &glThreadListLock ); + Threads_AddActive( Thread ); + SHORTREL( &glThreadListLock ); + + #if DEBUG_TRACE_STATE + Log("Threads_Sleep: %p(%i %s) woken from semaphore", Thread, Thread->TID, Thread->ThreadName); + #endif + SHORTREL( &sem->Protector ); + } return -EOK; + case THREAD_STAT_WAITING: Warning("Threads_Wake - Waiting threads are not currently supported"); return -ENOTIMPL; @@ -863,6 +913,9 @@ tThread *Threads_RemActive(void) #endif { SHORTREL( &glThreadListLock ); + Log_Warning("Threads", "Current thread %p(%i %s) is not on active queue", + ret, ret->TID, ret->ThreadName + ); return NULL; } @@ -1456,7 +1509,7 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) SHORTREL( &Sem->Protector ); // Release first to make sure it is released SHORTREL( &glThreadListLock ); while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield(); - // We're only woken when there's something avaliable + // We're only woken when there's something avaliable (or a signal arrives) us->WaitPointer = NULL; taken = us->RetStatus; diff --git a/Kernel/vfs/select.c b/Kernel/vfs/select.c index 22417c88..a092b07c 100644 --- a/Kernel/vfs/select.c +++ b/Kernel/vfs/select.c @@ -68,7 +68,7 @@ int VFS_SelectNode(tVFS_Node *Node, enum eVFS_SelectTypes Type, tTime *Timeout, } thread_info = malloc(sizeof(tVFS_SelectThread)); - if(!thread_info) return -1; + if(!thread_info) LEAVE_RET('i', -1); Semaphore_Init(&thread_info->SleepHandle, 0, 0, "VFS_SelectNode()", Name); @@ -148,7 +148,7 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set if( !Timeout || *Timeout > 0 ) { ret = Semaphore_Wait(&thread_info->SleepHandle, 1); - // TODO: Do something with ret + // TODO: Do something with ret? } // Fill output (modify *Handles) @@ -486,9 +486,9 @@ void VFS_int_Select_SignalAll(tVFS_SelectList *List) { for( i = 0; i < NUM_THREADS_PER_ALLOC; i ++ ) { - LOG("block->Threads[i] = %p", block->Threads[i]); if( block->Threads[i] ) { + LOG("block(%p)->Threads[%i] = %p", block, i, block->Threads[i]); Semaphore_Signal( &block->Threads[i]->SleepHandle, 1 ); } } diff --git a/Modules/IPStack/icmp.c b/Modules/IPStack/icmp.c index de3a9db5..969a1fa9 100644 --- a/Modules/IPStack/icmp.c +++ b/Modules/IPStack/icmp.c @@ -118,9 +118,11 @@ int ICMP_Ping(tInterface *Interface, tIPv4 Addr) hdr->ID = i; hdr->Sequence = ~i; hdr->Checksum = htons( IPv4_Checksum(hdr, sizeof(buf)) ); - IPv4_SendPacket(Interface, Addr, 1, i, sizeof(buf), buf); ts = now(); + + IPv4_SendPacket(Interface, Addr, 1, i, sizeof(buf), buf); + end = ts + Interface->TimeoutDelay; while( !gICMP_PingSlots[i].bArrived && now() < end) Threads_Yield(); diff --git a/Modules/IPStack/link.c b/Modules/IPStack/link.c index fe08b8d5..e5e789a9 100644 --- a/Modules/IPStack/link.c +++ b/Modules/IPStack/link.c @@ -129,8 +129,9 @@ void Link_WatchDevice(tAdapter *Adapter) ret = VFS_Read(Adapter->DeviceFD, MAX_PACKET_SIZE, buf); if(ret == -1) break; - if(ret <= (int)sizeof(tEthernetHeader)) { - Log_Log("Net Link", "Recieved an undersized packet"); + if(ret < sizeof(tEthernetHeader)) { + Log_Log("Net Link", "Recieved an undersized packet (%i < %i)", + ret, sizeof(tEthernetHeader)); continue; } diff --git a/Modules/Network/NE2000/ne2000.c b/Modules/Network/NE2000/ne2000.c index 53602e7b..3fa85f47 100644 --- a/Modules/Network/NE2000/ne2000.c +++ b/Modules/Network/NE2000/ne2000.c @@ -289,6 +289,8 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); + // TODO: Lock + // Sanity Check Length if(Length > TX_BUF_SIZE*256) { Log_Warning( @@ -360,7 +362,11 @@ Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); // Wait for packets - Semaphore_Wait( &Card->Semaphore, 1 ); + if( Semaphore_Wait( &Card->Semaphore, 1 ) != 1 ) + { + // Error or interrupted + LEAVE_RET('i', 0); + } outb(Card->IOBase, 0x22 | (1 << 6)); // Page 6 LOG("CURR : 0x%02x", inb(Card->IOBase + CURR)); @@ -392,10 +398,7 @@ Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) LOG("pktHdr->Length (%i) > 256 - 4, allocated buffer %p", pktHdr->Length, buf); - if(!buf) { - LEAVE('i', -1); - return -1; - } + if(!buf) LEAVE_RET('i', -1); // Copy the already read data memcpy(buf, data, 256); @@ -523,7 +526,9 @@ void Ne2k_IRQHandler(int IntNum) { //if( gpNe2k_Cards[i].NumWaitingPackets > MAX_PACKET_QUEUE ) // gpNe2k_Cards[i].NumWaitingPackets = MAX_PACKET_QUEUE; - Semaphore_Signal( &gpNe2k_Cards[i].Semaphore, 1 ); + if( Semaphore_Signal( &gpNe2k_Cards[i].Semaphore, 1 ) != 1 ) { + // Oops? + } } // 1: Packet sent (no error) // 2: Recieved with error diff --git a/Modules/Network/RTL8139/rtl8139.c b/Modules/Network/RTL8139/rtl8139.c index c63dfeed..d77fe273 100644 --- a/Modules/Network/RTL8139/rtl8139.c +++ b/Modules/Network/RTL8139/rtl8139.c @@ -255,7 +255,10 @@ Uint64 RTL8139_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer); retry: - Semaphore_Wait( &card->ReadSemaphore, 1 ); + if( Semaphore_Wait( &card->ReadSemaphore, 1 ) != 1 ) + { + LEAVE_RET('i', 0); + } Mutex_Acquire( &card->ReadMutex ); @@ -423,9 +426,13 @@ void RTL8139_IRQHandler(int Num) LOG("packet_count = %i, read_ofs = 0x%x", packet_count, read_ofs); - Semaphore_Signal( &card->ReadSemaphore, packet_count ); if( packet_count ) + { + if( Semaphore_Signal( &card->ReadSemaphore, packet_count ) != packet_count ) { + // Oops? + } VFS_MarkAvaliable( &card->Node, 1 ); + } outw(card->IOBase + ISR, FLAG_ISR_ROK); } diff --git a/Modules/Storage/ATA/io.c b/Modules/Storage/ATA/io.c index 6ed04096..73c33b28 100644 --- a/Modules/Storage/ATA/io.c +++ b/Modules/Storage/ATA/io.c @@ -368,7 +368,6 @@ int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) while( gaATA_IRQs[cont] == 0 && now() < timeoutTime) { HALT(); -// Threads_Yield(); } // Complete Transfer @@ -471,7 +470,6 @@ int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer) timeoutTime = now() + ATA_TIMEOUT; while( gaATA_IRQs[cont] == 0 && now() < timeoutTime) { -// Threads_Yield(); HALT(); } -- 2.20.1