From 2db551c69841b4fb5a70ae05e08d54b1a016364b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 28 Jan 2013 18:56:20 +0800 Subject: [PATCH] Kernel - (experimental) Allowing THREAD_EVENT_TIMER to wake a semaphore --- KernelLand/Kernel/events.c | 14 ++++++++-- KernelLand/Kernel/include/threads_int.h | 2 ++ KernelLand/Kernel/semaphore.c | 34 ++++++++++++++++++++++++- KernelLand/Modules/IPStack/arp.c | 34 ++++++++++++------------- 4 files changed, 63 insertions(+), 21 deletions(-) diff --git a/KernelLand/Kernel/events.c b/KernelLand/Kernel/events.c index da095e9e..c3ab282f 100644 --- a/KernelLand/Kernel/events.c +++ b/KernelLand/Kernel/events.c @@ -26,15 +26,25 @@ void Threads_PostEvent(tThread *Thread, Uint32 EventMask) LOG("Thread->EventState = 0x%x", Thread->EventState); // Currently sleeping on an event? - if( Thread->Status == THREAD_STAT_EVENTSLEEP ) + switch(Thread->Status) { - // Waiting on this event? + // Waiting on this event? + case THREAD_STAT_EVENTSLEEP: if( (Uint32)Thread->RetStatus & EventMask ) { // Wake up LOG("Waking thread %p(%i %s)", Thread, Thread->TID, Thread->ThreadName); Threads_AddActive(Thread); } + break; + case THREAD_STAT_SEMAPHORESLEEP: + if( EventMask & THREAD_EVENT_TIMER ) + { + LOG("Waking %p(%i %s) from semaphore on timer", + Thread, Thread->TID, Thread->ThreadName); + Semaphore_ForceWake(Thread); + } + break; } SHORTREL( &Thread->IsLocked ); diff --git a/KernelLand/Kernel/include/threads_int.h b/KernelLand/Kernel/include/threads_int.h index 48452649..642f6c32 100644 --- a/KernelLand/Kernel/include/threads_int.h +++ b/KernelLand/Kernel/include/threads_int.h @@ -152,4 +152,6 @@ extern tThread *Threads_GetNextToRun(int CPU, tThread *Last); extern tThread *Threads_CloneTCB(Uint Flags); extern tThread *Threads_CloneThreadZero(void); +extern void Semaphore_ForceWake(tThread *Thread); + #endif diff --git a/KernelLand/Kernel/semaphore.c b/KernelLand/Kernel/semaphore.c index 2c9fc94b..ce7d4ba0 100644 --- a/KernelLand/Kernel/semaphore.c +++ b/KernelLand/Kernel/semaphore.c @@ -78,6 +78,7 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) SHORTREL( &Sem->Protector ); // Release first to make sure it is released SHORTREL( &glThreadListLock ); + // Sleep until woken (either by getting what we need, or a timer event) while( us->Status == THREAD_STAT_SEMAPHORESLEEP ) { Threads_Yield(); @@ -244,13 +245,44 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) if( toWake->Status != THREAD_STAT_ACTIVE ) Threads_AddActive(toWake); else - Warning("Thread %p (%i %s) is already awake", toWake, toWake->TID, toWake->ThreadName); + Warning("Thread %p (%i %s) is already awake", + toWake, toWake->TID, toWake->ThreadName); } SHORTREL( &Sem->Protector ); return added; } +void Semaphore_ForceWake(tThread *Thread) +{ + if( !CPU_HAS_LOCK(&Thread->IsLocked) ) { + Log_Error("Semaphore", "Force wake should be called with the thread lock held"); + return ; + } + if( Thread->Status != THREAD_STAT_SEMAPHORESLEEP ) { + Log_Error("Semaphore", "_ForceWake called on non-semaphore thread"); + return ; + } + + tSemaphore *sem = Thread->WaitPointer; + SHORTLOCK( &sem->Protector ); + tThread *prev = NULL; + if( sem->Waiting == Thread ) + sem->Waiting = sem->Waiting->Next; + else + { + for( prev = sem->Waiting; prev && prev->Next != Thread; prev = prev->Next ) + ; + if( prev ) + prev->Next = Thread->Next; + } + if( sem->LastWaiting == Thread ) + sem->LastWaiting = prev; + SHORTREL( &sem->Protector ); + Thread->RetStatus = 0; + Threads_AddActive(Thread); +} + // // Get the current value of a semaphore // diff --git a/KernelLand/Modules/IPStack/arp.c b/KernelLand/Modules/IPStack/arp.c index e152e33d..43c34256 100644 --- a/KernelLand/Modules/IPStack/arp.c +++ b/KernelLand/Modules/IPStack/arp.c @@ -9,9 +9,11 @@ #include "link.h" #include "ipv4.h" // For IPv4_Netmask #include "include/adapters_int.h" // for MAC addr +#include +#include #define ARPv6 0 -#define ARP_CACHE_SIZE 64 +#define ARP_CACHE_SIZE 128 #define ARP_MAX_AGE (60*60*1000) // 1Hr // === IMPORTS === @@ -34,6 +36,8 @@ struct sARP_Cache4 { } *gaARP_Cache4; int giARP_Cache4Space; tMutex glARP_Cache4; +tSemaphore gARP_Cache4Semaphore; + int giARP_WaitingThreads; #if ARPv6 struct sARP_Cache6 { tIPv6 IP; @@ -44,7 +48,6 @@ struct sARP_Cache6 { int giARP_Cache6Space; tMutex glARP_Cache6; #endif -volatile int giARP_LastUpdateID = 0; // === CODE === /** @@ -72,10 +75,8 @@ int ARP_Initialise() */ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) { - int lastID; int i; struct sArpRequest4 req; - Sint64 timeout; ENTER("pInterface xAddress", Interface, Address); @@ -133,10 +134,9 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) LEAVE('-'); return gaARP_Cache4[i].MAC; } + giARP_WaitingThreads ++; Mutex_Release( &glARP_Cache4 ); - lastID = giARP_LastUpdateID; - // Create request Log_Log("ARP4", "Asking for address %i.%i.%i.%i", Address.B[0], Address.B[1], Address.B[2], Address.B[3] @@ -151,35 +151,33 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address) req.DestMac = cMAC_BROADCAST; req.DestIP = Address; - tIPStackBuffer *buffer = IPStack_Buffer_CreateBuffer(3); // Assumes only a header and footer at link layer + // Assumes only a header and footer at link layer + tIPStackBuffer *buffer = IPStack_Buffer_CreateBuffer(3); IPStack_Buffer_AppendSubBuffer(buffer, sizeof(struct sArpRequest4), 0, &req, NULL, NULL); // Send Request Link_SendPacket(Interface->Adapter, 0x0806, req.DestMac, buffer); + // Clean up IPStack_Buffer_DestroyBuffer(buffer); - timeout = now() + Interface->TimeoutDelay; - // Wait for a reply + Time_ScheduleTimer(NULL, Interface->TimeoutDelay); for(;;) { - while(lastID == giARP_LastUpdateID && now() < timeout) { - Threads_Yield(); - } - - if( now() >= timeout ) { + if( Semaphore_Wait(&gARP_Cache4Semaphore, 1) != 1 ) + { + giARP_WaitingThreads --; Log_Log("ARP4", "Timeout"); - break; // Timeout + break; } - lastID = giARP_LastUpdateID; - Mutex_Acquire( &glARP_Cache4 ); for( i = 0; i < giARP_Cache4Space; i++ ) { if(gaARP_Cache4[i].IP.L != Address.L) continue; + giARP_WaitingThreads --; Mutex_Release( &glARP_Cache4 ); Log_Debug("ARP4", "Return %02x:%02x:%02x:%02x:%02x:%02x", gaARP_Cache4[i].MAC.B[0], gaARP_Cache4[i].MAC.B[1], @@ -231,7 +229,7 @@ void ARP_UpdateCache4(tIPv4 SWAddr, tMacAddr HWAddr) gaARP_Cache4[i].IP = SWAddr; gaARP_Cache4[i].MAC = HWAddr; gaARP_Cache4[i].LastUpdate = now(); - giARP_LastUpdateID ++; + Semaphore_Signal(&gARP_Cache4Semaphore, giARP_WaitingThreads); Mutex_Release(&glARP_Cache4); } -- 2.20.1