typedef Sint64 tTimestamp;
typedef struct sShortSpinlock tShortSpinlock;
typedef struct sMutex tMutex;
+typedef struct sSemaphore tSemaphore;
struct sMutex {
tShortSpinlock Protector; //!< Protector for the lock strucure
+ const char *Name; //!< Human-readable name
struct sThread *volatile Owner; //!< Owner of the lock (set upon getting the lock)
struct sThread *Waiting; //!< Waiting threads
struct sThread *LastWaiting; //!< Waiting threads
};
+struct sSemaphore {
+ tShortSpinlock Protector; //!< Protector for the lock strucure
+ const char *Name; //!< Human-readable name
+ volatile int Value; //!< Current mutex value
+ struct sThread *Waiting; //!< Waiting threads
+ struct sThread *LastWaiting; //!< Waiting threads
+};
+
// --- Helper Macros ---
/**
* \name Helper Macros
THREAD_STAT_ACTIVE, // Running and schedulable process
THREAD_STAT_SLEEPING, // Message Sleep
THREAD_STAT_MUTEXSLEEP, // Mutex Sleep
+ THREAD_STAT_SEMAPHORESLEEP, // Semaphore Sleep
THREAD_STAT_WAITING, // ??? (Waiting for a thread)
THREAD_STAT_PREINIT, // Being created
THREAD_STAT_ZOMBIE, // Died/Killed, but parent not informed
int Threads_SetGID(Uint *Errno, tUID ID);
void Threads_Dump(void);
void Threads_DumpActive(void);
+
void Mutex_Acquire(tMutex *Mutex);
void Mutex_Release(tMutex *Mutex);
int Mutex_IsLocked(tMutex *Mutex);
return Mutex->Owner != NULL;
}
+/**
+ * \brief Initialise the semaphore
+ * \param Value Initial value of the semaphore
+ * \param Label Symbolic name
+ */
+void Semaphore_Init(tSemaphore *Sem, int Value, const char *Label)
+{
+ Sem->Value = Value;
+ Sem->Name = Label;
+}
+
+/**
+ * \brief Acquire a "item" from the semaphore
+ */
+void Semaphore_Wait(tSemaphore *Sem)
+{
+ tThread *us;
+
+ SHORTLOCK( &Sem->Protector );
+ if( Sem->Value > 0 ) {
+ Sem->Value --;
+ SHORTREL( &Sem->Protector );
+ return ;
+ }
+
+ SHORTLOCK( &glThreadListLock );
+
+ // - Remove from active list
+ us = Threads_RemActive();
+ us->Next = NULL;
+ // - Mark as sleeping
+ us->Status = THREAD_STAT_SEMAPHORESLEEP;
+ us->WaitPointer = Sem;
+
+ // - Add to waiting
+ if(Sem->LastWaiting) {
+ Sem->LastWaiting->Next = us;
+ Sem->LastWaiting = us;
+ }
+ else {
+ Sem->Waiting = us;
+ Sem->LastWaiting = us;
+ }
+
+ SHORTREL( &glThreadListLock );
+ SHORTREL( &Sem->Protector );
+ while(us->Status == THREAD_STAT_MUTEXSLEEP) Threads_Yield();
+ // We're only woken when there's something avaliable
+ us->WaitPointer = NULL;
+}
+
+/**
+ * \brief Add an "item" to the semaphore
+ */
+void Semaphore_Signal(tSemaphore *Sem)
+{
+ SHORTLOCK( &Sem->Protector );
+ Sem->Value ++;
+
+ if( Sem->Waiting )
+ {
+ tThread *toWake = Sem->Waiting;
+
+ Sem->Waiting = Sem->Waiting->Next; // Next!
+ // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
+ if( Sem->Waiting == NULL )
+ Sem->LastWaiting = NULL;
+
+ // Wake new owner
+ SHORTLOCK( &glThreadListLock );
+ if( toWake->Status != THREAD_STAT_ACTIVE )
+ Threads_AddActive(toWake);
+ SHORTREL( &glThreadListLock );
+
+ // Decrement (the value is now "owned" by `toWake`)
+ Sem->Value --;
+ }
+ SHORTREL( &Sem->Protector );
+}
+
// === EXPORTS ===
EXPORT(Threads_GetUID);
EXPORT(Threads_GetGID);
* AcessOS 1\r
* Video BIOS Extensions (Vesa) Driver\r
*/\r
-#define DEBUG 0\r
+#define DEBUG 1\r
#define VERSION 0x100\r
\r
#include <acess.h>\r
return MODULE_ERR_NOTNEEDED;\r
}\r
\r
- Log_Debug("VESA", "info->VideoModes = %04x:%04x", info->VideoModes.seg, info->VideoModes.ofs);\r
+ //Log_Debug("VESA", "info->VideoModes = %04x:%04x", info->VideoModes.seg, info->VideoModes.ofs);\r
modes = (Uint16 *) VM8086_GetPointer(gpVesa_BiosState, info->VideoModes.seg, info->VideoModes.ofs);\r
\r
// Read Modes\r
for( giVesaModeCount = 0; modes[giVesaModeCount] != 0xFFFF; giVesaModeCount++ );\r
gVesa_Modes = (tVesa_Mode *)malloc( giVesaModeCount * sizeof(tVesa_Mode) );\r
\r
+ Log_Debug("VESA", "%i Modes", giVesaModeCount);\r
+ \r
// Insert Text Mode\r
gVesa_Modes[0].width = 80;\r
gVesa_Modes[0].height = 25;\r
*/
int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
{
- int tmp;
ENTER("pNode iID pData", Node, ID, Data);
switch( ID )
{