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 );
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();
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
//
#include "link.h"
#include "ipv4.h" // For IPv4_Netmask
#include "include/adapters_int.h" // for MAC addr
+#include <semaphore.h>
+#include <timers.h>
#define ARPv6 0
-#define ARP_CACHE_SIZE 64
+#define ARP_CACHE_SIZE 128
#define ARP_MAX_AGE (60*60*1000) // 1Hr
// === IMPORTS ===
} *gaARP_Cache4;
int giARP_Cache4Space;
tMutex glARP_Cache4;
+tSemaphore gARP_Cache4Semaphore;
+ int giARP_WaitingThreads;
#if ARPv6
struct sARP_Cache6 {
tIPv6 IP;
int giARP_Cache6Space;
tMutex glARP_Cache6;
#endif
-volatile int giARP_LastUpdateID = 0;
// === CODE ===
/**
*/
tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address)
{
- int lastID;
int i;
struct sArpRequest4 req;
- Sint64 timeout;
ENTER("pInterface xAddress", Interface, 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]
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],
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);
}