// Note stored anywhere because we're woken using other means
SHORTREL( &glThreadListLock );
SHORTREL( &us->IsLocked );
- while(us->Status == THREAD_STAT_EVENTSLEEP) Threads_Yield();
+ Threads_int_WaitForStatusEnd(THREAD_STAT_EVENTSLEEP);
// Woken when lock is acquired
SHORTLOCK( &us->IsLocked );
}
"THREAD_STAT_ACTIVE",
"THREAD_STAT_SLEEPING",
"THREAD_STAT_MUTEXSLEEP",
+ "THREAD_STAT_RWLOCKSLEEP",
"THREAD_STAT_SEMAPHORESLEEP",
"THREAD_STAT_QUEUESLEEP",
"THREAD_STAT_EVENTSLEEP",
extern tThread *Threads_CloneTCB(Uint Flags);
extern tThread *Threads_CloneThreadZero(void);
+extern void Threads_int_WaitForStatusEnd(enum eThreadStatus Status);
extern void Semaphore_ForceWake(tThread *Thread);
#endif
SHORTREL( &glThreadListLock );
SHORTREL( &Mutex->Protector );
- while(us->Status == THREAD_STAT_MUTEXSLEEP) Threads_Yield();
+ Threads_int_WaitForStatusEnd(THREAD_STAT_MUTEXSLEEP);
// We're only woken when we get the lock
us->WaitPointer = NULL;
}
SHORTREL( &glThreadListLock );
SHORTREL( &Lock->Protector );
- while(us->Status == THREAD_STAT_RWLOCKSLEEP) Threads_Yield();
+ Threads_int_WaitForStatusEnd(THREAD_STAT_RWLOCKSLEEP);
// We're only woken when we get the lock
// TODO: Handle when this isn't the case
us->WaitPointer = NULL;
SHORTREL( &glThreadListLock );
SHORTREL( &Lock->Protector );
- while(us->Status == THREAD_STAT_RWLOCKSLEEP) Threads_Yield();
+ Threads_int_WaitForStatusEnd(THREAD_STAT_RWLOCKSLEEP);
us->WaitPointer = NULL;
}
else
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(us->Status == THREAD_STAT_SEMAPHORESLEEP)
- Log_Warning("Threads", "Semaphore %p %s:%s re-schedulued while asleep",
- Sem, Sem->ModName, Sem->Name);
- }
+ Threads_int_WaitForStatusEnd( THREAD_STAT_SEMAPHORESLEEP );
+ // We're only woken when there's something avaliable (or a signal arrives)
#if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
Log("Semaphore %p %s:%s woken", Sem, Sem->ModName, Sem->Name);
#endif
- // We're only woken when there's something avaliable (or a signal arrives)
us->WaitPointer = NULL;
taken = us->RetStatus;
SHORTREL( &glThreadListLock );
SHORTREL( &Sem->Protector );
- while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield();
+ Threads_int_WaitForStatusEnd(THREAD_STAT_SEMAPHORESLEEP);
// We're only woken when there's something avaliable
us->WaitPointer = NULL;
Proc_Reschedule();
}
+/**
+ * \breif Wait for the thread status to not be a specified value
+ */
+void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
+{
+ tThread *us = Proc_GetCurThread();
+ ASSERT(Status != THREAD_STAT_ACTIVE);
+ ASSERT(Status != THREAD_STAT_DEAD);
+ while( us->Status == Status )
+ {
+ Proc_Reschedule();
+ if( us->Status == Status )
+ Debug("Thread %p(%i %s) rescheduled while in %s state", casTHREAD_STAT[Status]);
+ }
+}
+
/**
* \fn void Threads_Sleep(void)
* \brief Take the current process off the run queue
// Release Spinlock
SHORTREL( &glThreadListLock );
-
- while(cur->Status != THREAD_STAT_ACTIVE) {
- Proc_Reschedule();
- if( cur->Status != THREAD_STAT_ACTIVE )
- Log("%i - Huh? why am I up? zzzz...", cur->TID);
- }
+ Threads_int_WaitForStatusEnd(THREAD_STAT_SLEEPING);
}
SHORTREL(&glThreadListLock);
// Yield and sleep
- Threads_Yield();
- if(us->Status == THREAD_STAT_QUEUESLEEP) {
- // Why are we awake?!
- }
+ Threads_int_WaitForStatusEnd(THREAD_STAT_QUEUESLEEP);
us->WaitPointer = NULL;
}
{
LOG("Why does this route not have a node? trying to find an iface for the next hop");
- rt = _Route_FindInterfaceRoute(type, rt->NextHop);
- if(!rt) {
+ void *nextrt = _Route_FindInterfaceRoute(type, rt->NextHop);
+ if(!nextrt) {
Log_Notice("Cannot find route to next hop '%s'",
IPStack_PrintAddress(type, rt->NextHop));
return NULL;
}
+ rt = nextrt;
}
if( !rt->Interface ) {
Log_Notice("Routes", "No interface for route %p, what the?", rt);
srv->NewConnections = conn;
VFS_MarkAvaliable( &srv->Node, 1 );
SHORTREL(&srv->lConnections);
+ Semaphore_Signal(&srv->WaitingConnections, 1);
// Send the SYN ACK
hdr->Flags |= TCP_FLAG_ACK;
{
Log_Log("TCP", "ACKing SYN-ACK");
Connection->State = TCP_ST_OPEN;
+ VFS_MarkFull(&Connection->Node, 0);
}
else
{
if( Header->Flags & TCP_FLAG_ACK )
{
// TODO: Handle max half-open limit
- Connection->State = TCP_ST_OPEN;
Log_Log("TCP", "Connection fully opened");
+ Connection->State = TCP_ST_OPEN;
+ VFS_MarkFull(&Connection->Node, 0);
}
break;
ENTER("pNode iPos", Node, Pos);
Log_Log("TCP", "Thread %i waiting for a connection", Threads_GetTID());
- for(;;)
- {
- SHORTLOCK( &srv->lConnections );
- if( srv->NewConnections != NULL ) break;
- SHORTREL( &srv->lConnections );
- Threads_Yield(); // TODO: Sleep until poked
- }
+ Semaphore_Wait( &srv->WaitingConnections, 1 );
-
+ SHORTLOCK(&srv->lConnections);
// Increment the new list (the current connection is still on the
// normal list)
conn = srv->NewConnections;
conn->Node.NumACLs = 1;
conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
conn->Node.Type = &gTCP_ClientNodeType;
+ conn->Node.BufferFull = 1; // Cleared when connection opens
conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE );
#if 0
ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
LOG("conn = %p {State:%i}", conn, conn->State);
- // Check if connection is estabilishing
- // - TODO: Sleep instead (maybe using VFS_SelectNode to wait for the
- // data to be availiable
- while( conn->State == TCP_ST_SYN_RCVD || conn->State == TCP_ST_SYN_SENT )
- Threads_Yield();
-
- // If the conneciton is not open, then clean out the recieved buffer
- if( conn->State != TCP_ST_OPEN )
+ // If the connection has been closed (state > ST_OPEN) then clear
+ // any stale data in the buffer (until it is empty (until it is empty))
+ if( conn->State > TCP_ST_OPEN )
{
Mutex_Acquire( &conn->lRecievedPackets );
len = RingBuffer_Read( Buffer, conn->RecievedBuffer, Length );
// Buffer, Length);
// #endif
- // Check if connection is open
- while( conn->State == TCP_ST_SYN_RCVD || conn->State == TCP_ST_SYN_SENT )
- Threads_Yield();
-
- if( conn->State != TCP_ST_OPEN ) {
+ // Don't allow a write to a closed connection
+ if( conn->State > TCP_ST_OPEN ) {
VFS_MarkError(Node, 1);
LEAVE('i', -1);
return -1;
}
+ // Wait
+ VFS_SelectNode(Node, VFS_SELECT_WRITE|VFS_SELECT_ERROR, NULL, "TCP_Client_Write");
+
do
{
int len = (rem < TCP_MAX_PACKET_SIZE) ? rem : TCP_MAX_PACKET_SIZE;
LEAVE_RET('i', 0);
{
- tTime timeout_end = now() + conn->Interface->TimeoutDelay;
+ tTime timeout = conn->Interface->TimeoutDelay;
TCP_StartConnection(conn);
- // TODO: Wait for connection to open
- while( conn->State == TCP_ST_SYN_SENT && timeout_end > now() ) {
- Threads_Yield();
- }
+ VFS_SelectNode(&conn->Node, VFS_SELECT_WRITE, &timeout, "TCP Connection");
if( conn->State == TCP_ST_SYN_SENT )
LEAVE_RET('i', 0);
}
while( conn->State == TCP_ST_FIN_WAIT1 ) Threads_Yield();
break;
default:
- Log_Warning("TCP", "Unhandled connection state in TCP_Client_Close");
+ Log_Warning("TCP", "Unhandled connection state %i in TCP_Client_Close",
+ conn->State);
break;
}
#include "ipstack.h"
#include <adt.h> // tRingBuffer
#include <timers.h> // tTimer
+#include <semaphore.h> // tSemaphore
typedef struct sTCPHeader tTCPHeader;
typedef struct sTCPListener tTCPListener;
tInterface *Interface; //!< Listening Interface
tVFS_Node Node; //!< Server Directory node
int NextID; //!< Name of the next connection
+ tSemaphore WaitingConnections;
tShortSpinlock lConnections; //!< Spinlock for connections
tTCPConnection *Connections; //!< Connections (linked list)
tTCPConnection *volatile NewConnections;
-.PHONY: all clean nativelib DiskTool NetTest
+.PHONY: all clean
+.PHONY: nativelib DiskTool NetTest
+#.PHONY: nativelib-clean DiskTool-clean NetTest-clean
-all: DiskTool NetTest
+all clean: DiskTool NetTest
img2sif: img2sif.c
$(CC) -o $@ $< `sdl-config --libs --cflags` -lSDL_image -Wall
nativelib:
- $(MAKE) -C $@
+ $(MAKE) -C $@ $(MAKECMDGOALS)
DiskTool NetTest: nativelib
- $(MAKE) -C $@
+ $(MAKE) -C $@ $(MAKECMDGOALS)
if( argc-i != 3 ) {
Log_Error("NetTest", "'netcat' <addr> <port>");
PrintUsage(argv[0]);
+ return -1;
}
NetTest_Suite_Netcat(argv[i+1], strtol(argv[i+2], NULL, 0));
// === CODE ===
int VFS_SelectNode(tVFS_Node *Node, int Type, tTime *Timeout, const char *Name)
{
+ tThread *us = Proc_GetCurThread();
+
+ int ret = 0;
+
+ Threads_ClearEvent(THREAD_EVENT_VFS);
+
+ if( Type & VFS_SELECT_READ ) {
+ Node->ReadThreads = (void*)us;
+ if(Node->DataAvaliable) ret |= VFS_SELECT_READ;
+ }
+ if( Type & VFS_SELECT_WRITE ) {
+ Node->WriteThreads = (void*)us;
+ if(!Node->BufferFull) ret |= VFS_SELECT_WRITE;
+ }
+ if( Type & VFS_SELECT_ERROR ) {
+ Node->ErrorThreads = (void*)us;
+ if(Node->ErrorOccurred) ret |= VFS_SELECT_ERROR;
+ }
- return 0;
+ if( !ret )
+ {
+ // TODO: Timeout
+ Threads_WaitEvents(THREAD_EVENT_VFS);
+ }
+
+ if( Type & VFS_SELECT_READ ) {
+ Node->ReadThreads = NULL;
+ if(Node->DataAvaliable) ret |= VFS_SELECT_READ;
+ }
+ if( Type & VFS_SELECT_WRITE ) {
+ Node->WriteThreads = NULL;
+ if(!Node->BufferFull) ret |= VFS_SELECT_WRITE;
+ }
+ if( Type & VFS_SELECT_ERROR ) {
+ Node->ErrorThreads = NULL;
+ if(Node->ErrorOccurred) ret |= VFS_SELECT_ERROR;
+ }
+ return ret;
}
int VFS_MarkAvaliable(tVFS_Node *Node, BOOL bAvail)
return 0;
}
+int VFS_MarkFull(tVFS_Node *Node, BOOL bError)
+{
+ Node->BufferFull = bError;
+ if( !Node->BufferFull && Node->WriteThreads )
+ Threads_PostEvent( (void*)Node->WriteThreads, THREAD_EVENT_VFS );
+ return 0;
+}
+
+
#if 0
int VFS_Open(const char *Path, Uint Flags)
{
NOBJ := logging.o misc.o threads_int.o
-LOBJ := threads.o time.o mutex.o rwlock.o semaphore.o
+LOBJ := threads.o time.o
+# mutex.o rwlock.o semaphore.o
KOBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/io.o vfs/dir.o
KOBJ += vfs/nodecache.o vfs/mount.o vfs/memfile.o # vfs/select.o
KOBJ += vfs/fs/root.o vfs/fs/devfs.o
KOBJ += drv/proc.o
+KOBJ += mutex.o rwlock.o semaphore.o
NOBJ := $(NOBJ:%.o=obj/%.o)
LOBJ := $(LOBJ:%.o=obj/%.o)
$(RM) $(BIN) $(OBJ)
$(BIN): $(OBJ)
- ar cru $(BIN) $(OBJ)
+ ar cr $(BIN) $(OBJ)
-$(NOBJ): obj/%.o: %.c
+$(NOBJ): obj/%.o: %.c Makefile
@echo [CC Native] $@
@mkdir -p $(dir $@)
- @$(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS)
-$(LOBJ): obj/%.o: %.c
+$(LOBJ): obj/%.o: %.c Makefile
@echo [CC Local] $@
@mkdir -p $(dir $@)
- @$(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS) -I $(KERNEL_DIR)/include
+ @$(CC) -o $@ -c $<
-MMD -MF [email protected] -MT $@ -MP $(CFLAGS) $(CPPFLAGS) -I $(KERNEL_DIR)/include
-$(KOBJ): obj/_Kernel/%.o: $(KERNEL_DIR)/%.c
+$(KOBJ): obj/_Kernel/%.o: $(KERNEL_DIR)/%.c Makefile
@echo [CC Kernel] $@
@mkdir -p $(dir $@)
- @$(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS) -I $(KERNEL_DIR)/include
+ @$(CC) -o $@ -c $< -MMD -MF
[email protected] -MT $@ -MP $(CFLAGS) $(CPPFLAGS) -I $(KERNEL_DIR)/include
+
+-include $(OBJ:%=%.dep)
typedef uint32_t tGID;
typedef uint32_t tTID;
-// NOTE: Since this is single-threaded (for now) mutexes can be implimented as simple locks
-typedef char tShortSpinlock;
-
typedef int64_t tTime;
extern tTime now(void);
extern int64_t timestamp(int sec, int min, int hr, int day, int month, int year);
static inline int MIN(int a, int b) { return a < b ? a : b; }
static inline int MAX(int a, int b) { return a > b ? a : b; }
-#if USE_MULTITHREADING
-#error "TODO: Impliment multithreaded SHORTLOCK"
-#else
-static inline void SHORTLOCK(tShortSpinlock *Lock) {
- if(*Lock) Log_KernelPanic("---", "Double short lock");
- *Lock = 1;
-}
-static inline void SHORTREL(tShortSpinlock *m) { *m = 0; }
-static inline int CPU_HAS_LOCK(tShortSpinlock *m) { return *m; }
-#endif
+#include <shortlock.h>
static inline intptr_t MM_GetPhysAddr(void *Ptr) { return 1; }
static inline int MM_IsUser(const void *Ptr) { return 1; }
--- /dev/null
+/*
+ * Acess2 native library
+ * - By John Hodge (thePowersGang)
+ *
+ * shortlock.h
+ * - Short locks :)
+ */
+#ifndef _SHORTLOCK_H_
+#define _SHORTLOCK_H_
+
+typedef void *tShortSpinlock;
+
+extern void SHORTLOCK(tShortSpinlock *Lock);
+extern void SHORTREL(tShortSpinlock *m);
+extern int CPU_HAS_LOCK(tShortSpinlock *m);
+
+#endif
#ifndef _THREADS_INT_H_
#define _THREADS_INT_H_
+#include <shortlock.h>
+
+typedef struct sThread tThread;
+
#define THREAD_EVENT_RWLOCK (1 << 8)
typedef struct sThreadIntMutex tThreadIntMutex; // actually pthreads
void *ThreadHandle;
int TID;
- tThreadIntMutex *Protector;
+ int Status;
+
+ tShortSpinlock IsLocked;
uint32_t PendingEvents;
uint32_t WaitingEvents;
tThreadIntSem *WaitSemaphore; // pthreads
- char *Name;
+ char *ThreadName;
+
+ int bInstrTrace; // Used for semaphore tracing
+
+ int RetStatus;
+ void *WaitPointer;
// Init Only
void (*SpawnFcn)(void*);
void *SpawnData;
};
+enum eThreadStatus {
+ THREAD_STAT_NULL, // Invalid process
+ THREAD_STAT_ACTIVE, // Running and schedulable process
+ THREAD_STAT_SLEEPING, // Message Sleep
+ THREAD_STAT_MUTEXSLEEP, // Mutex Sleep
+ THREAD_STAT_RWLOCKSLEEP, // Read-Writer lock Sleep
+ THREAD_STAT_SEMAPHORESLEEP, // Semaphore Sleep
+ THREAD_STAT_QUEUESLEEP, // Queue
+ THREAD_STAT_EVENTSLEEP, // Event sleep
+ THREAD_STAT_WAITING, // ??? (Waiting for a thread)
+ THREAD_STAT_PREINIT, // Being created
+ THREAD_STAT_ZOMBIE, // Died/Killed, but parent not informed
+ THREAD_STAT_DEAD, // Awaiting burial (free)
+ THREAD_STAT_BURIED // If it's still on the list here, something's wrong
+};
+static const char * const casTHREAD_STAT[] = {
+ "THREAD_STAT_NULL",
+ "THREAD_STAT_ACTIVE",
+ "THREAD_STAT_SLEEPING",
+ "THREAD_STAT_MUTEXSLEEP",
+ "THREAD_STAT_RWLOCKSLEEP",
+ "THREAD_STAT_SEMAPHORESLEEP",
+ "THREAD_STAT_QUEUESLEEP",
+ "THREAD_STAT_EVENTSLEEP",
+ "THREAD_STAT_WAITING",
+ "THREAD_STAT_PREINIT",
+ "THREAD_STAT_ZOMBIE",
+ "THREAD_STAT_DEAD",
+ "THREAD_STAT_BURIED"
+};
+
extern struct sThread __thread *lpThreads_This;
+extern tShortSpinlock glThreadListLock;
extern int Threads_int_CreateThread(struct sThread *Thread);
extern int Threads_int_ThreadingEnabled(void);
+extern tThread *Proc_GetCurThread(void);
+extern tThread *Threads_RemActive(void);
+extern void Threads_AddActive(tThread *Thread);
+extern void Threads_int_WaitForStatusEnd(enum eThreadStatus Status);
+
extern tThreadIntMutex *Threads_int_MutexCreate(void);
extern void Threads_int_MutexDestroy(tThreadIntMutex *Mutex);
extern void Threads_int_MutexLock(tThreadIntMutex *Mutex);
/*
- *
+ * Acess2 libnative (Kernel Simulation Library)
+ * - By John Hodge (thePowersGang)
+ *
+ * logging.c
+ * - Logging functions
*/
#include <stdio.h>
#include <stdarg.h>
#include <acess_logging.h>
#include <ctype.h>
#include <inttypes.h>
+#include <shortlock.h>
-#define LOGHDR(col,type) fprintf(stderr, "\e["col"m[%-8.8s]"type" ", Ident)
+extern int Threads_GetTID();
+
+#define LOGHDR(col,type) fprintf(stderr, "\e["col"m[%-8.8s]"type"%2i ", Ident, Threads_GetTID())
#define LOGTAIL() fprintf(stderr, "\e[0m\n")
#define PUTERR(col,type) {\
+ if(!gbThreadInLog) SHORTLOCK(&glDebugLock); \
+ gbThreadInLog ++; \
LOGHDR(col,type);\
va_list args; va_start(args, Message);\
vfprintf(stderr, Message, args);\
va_end(args);\
LOGTAIL();\
+ gbThreadInLog --; \
+ if(!gbThreadInLog) SHORTREL(&glDebugLock); \
}
+// === GLOBALS ===
+int __thread gbThreadInLog;
+tShortSpinlock glDebugLock;
+
// === CODE ===
void Log_KernelPanic(const char *Ident, const char *Message, ...) {
PUTERR("35", "k")
- abort();
+ exit(-1);
}
void Log_Panic(const char *Ident, const char *Message, ...)
PUTERR("34", "p")
#include <acess.h>
#include <semaphore.h>
+#if 0
+TODO:: Rework kernel-land semaphore code to use events
+- Allows it to be used here and be tested easier
+#endif
+
// === CODE ===
void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)
{
// === GLOBALS ===
tThread *gThreads_List;
tThread __thread *lpThreads_This;
+ int giThreads_NextTID = 1;
+tShortSpinlock glThreadListLock;
// === CODE ===
void Threads_int_Init(void)
// nope.avi
return ;
}
- Threads_int_MutexLock(Thread->Protector);
+ SHORTLOCK( &Thread->IsLocked );
Thread->PendingEvents |= Events;
if( Thread->WaitingEvents & Events )
Threads_int_SemSignal(Thread->WaitSemaphore);
- Threads_int_MutexRelease(Thread->Protector);
+ SHORTREL( &Thread->IsLocked );
}
Uint32 Threads_WaitEvents(Uint32 Events)
{
- if( Threads_int_ThreadingEnabled() ) {
+ if( !Threads_int_ThreadingEnabled() ) {
Log_Notice("Threads", "_WaitEvents: Threading disabled");
return 0;
}
void Threads_ClearEvent(Uint32 Mask)
{
- if( Threads_int_ThreadingEnabled() ) {
+ if( !Threads_int_ThreadingEnabled() ) {
Log_Notice("Threads", "_ClearEvent: Threading disabled");
return ;
}
- Threads_int_MutexLock(lpThreads_This->Protector);
+ SHORTLOCK(&lpThreads_This->IsLocked);
lpThreads_This->PendingEvents &= ~Mask;
- Threads_int_MutexRelease(lpThreads_This->Protector);
+ SHORTREL(&lpThreads_This->IsLocked);
}
tUID Threads_GetUID(void) { return 0; }
tGID Threads_GetGID(void) { return 0; }
-tTID Threads_GetTID(void) { return 0; }
+tTID Threads_GetTID(void) { return lpThreads_This->TID; }
int *Threads_GetMaxFD(void) { return &lpThreads_This->Process->MaxFDs; }
char **Threads_GetCWD(void) { return &lpThreads_This->Process->CWD; }
Log_Warning("Threads", "Threads_Sleep shouldn't be used");
}
+void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
+{
+ while( lpThreads_This->Status != Status )
+ Threads_int_SemWaitAll(lpThreads_This->WaitSemaphore);
+}
+
int Threads_SetName(const char *Name)
{
if( !lpThreads_This )
return 0;
- if( lpThreads_This->Name )
- free(lpThreads_This->Name);
- lpThreads_This->Name = strdup(Name);
+ if( lpThreads_This->ThreadName )
+ free(lpThreads_This->ThreadName);
+ lpThreads_This->ThreadName = strdup(Name);
return 0;
}
return &a_errno;
}
+tThread *Threads_RemActive(void)
+{
+ return lpThreads_This;
+}
+
+void Threads_AddActive(tThread *Thread)
+{
+ Thread->Status = THREAD_STAT_ACTIVE;
+ // Increment state-change semaphore
+ Threads_int_SemSignal(Thread->WaitSemaphore);
+}
+
struct sProcess *Threads_int_CreateProcess(void)
{
struct sProcess *ret = calloc(sizeof(struct sProcess), 1);
tThread *Threads_int_CreateTCB(tThread *Parent)
{
tThread *ret = calloc( sizeof(tThread), 1 );
+ ret->TID = giThreads_NextTID ++;
ret->WaitSemaphore = Threads_int_SemCreate();
- ret->Protector = Threads_int_MutexCreate();
+ //ret->Protector = Threads_int_MutexCreate();
if( !Parent )
{
#include <acess_logging.h>
#include <threads_int.h>
#include <pthread_weak.h>
+#include <shortlock.h>
// === TYPES ===
typedef struct sThread tThread;
// === CODE ===
int Threads_int_ThreadingEnabled(void)
{
- Log_Debug("Threads", "pthread_create = %p", pthread_create);
return !!pthread_create;
}
}
}
+void SHORTLOCK(tShortSpinlock *Lock)
+{
+ if( !pthread_mutex_init )
+ {
+ if(*Lock) Log_KernelPanic("---", "Double short lock");
+ *Lock = (void*)1;
+ }
+ else
+ {
+ if( !*Lock ) {
+ *Lock = malloc(sizeof(pthread_mutex_t));
+ pthread_mutex_init(*Lock, NULL);
+ }
+ pthread_mutex_lock(*Lock);
+ }
+}
+
+void SHORTREL(tShortSpinlock *Lock)
+{
+ if( !pthread_mutex_init )
+ {
+ if(!*Lock) Log_Notice("---", "Short release when not held");
+ *Lock = NULL;
+ }
+ else
+ {
+ pthread_mutex_unlock(*Lock);
+ }
+}
+
+int CPU_HAS_LOCK(tShortSpinlock *Lock)
+{
+ return 0;
+}
+
Message_Append(Server, MSG_TYPE_SERVER, user, user, message);\r
break;\r
case 372: // MOTD Data\r
+ case 375: // MOTD Start\r
case 376: // MOTD End\r
\r
default:\r