BIN = ../disktool
# Kernel Sources (compiled with -ffreestanding)
K_OBJ := lib.o
-K_OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/io.o vfs/dir.o
-K_OBJ += vfs/nodecache.o vfs/mount.o vfs/memfile.o # vfs/select.o
-K_OBJ += vfs/fs/root.o vfs/fs/devfs.o
K_OBJ += drvutil_disk.o drv/proc.o
# Modules
MODULES := Storage/LVM Filesystems/FAT Filesystems/Ext2 Filesystems/NTFS
clean:
$(RM) -f $(OBJ) $(DEPFILES) $(BIN)
-$(BIN): $(OBJ)
+$(BIN): $(OBJ) ../libnativelib.a
@echo [CC Link] -o $(BIN)
@$(CC) -o $(BIN) $(OBJ) $(LDFLAGS)
@echo BUILD_NUM = $$(( $(BUILD_NUM) + 1 )) > Makefile.BuildNum
--- /dev/null
+
+.PHONY: all clean nativelib DiskTool NetTest
+
+all: DiskTool NetTest
+
+img2sif: img2sif.c
+ $(CC) -o $@ $< `sdl-config --libs --cflags` -lSDL_image -Wall
+
+nativelib:
+ $(MAKE) -C $@
+
+DiskTool NetTest: nativelib
+ $(MAKE) -C $@
# Kernel Sources (compiled with -ffreestanding)
K_OBJ := lib.o adt.o
K_OBJ += vfs/acls.o vfs/io.o vfs/fs/devfs.o
-#K_OBJ += vfs/main.o vfs/open.o vfs/io.o vfs/dir.o
-#K_OBJ += vfs/nodecache.o vfs/mount.o vfs/memfile.o # vfs/select.o
-#K_OBJ += vfs/fs/root.o vfs/fs/devfs.o
-#K_OBJ += drvutil_disk.o drv/proc.o
# Modules
MODULES := IPStack
# Local kernel soruces (same as above, but located in same directory as Makefile)
-L_OBJ = vfs_shim.o nic.o tcpclient.o tcpserver.o
+L_OBJ = vfs_shim.o nic.o tcpclient.o tcpserver.o helpers.o
# Native Sources (compiled as usual)
N_OBJ = main.o tap.o
# Compilation Options
-CFLAGS := -Wall -std=gnu99 -g -Werror
+CFLAGS := -Wall -std=gnu99 -g -Werror -O0 -pthread
CPPFLAGS := -I include/ -I ../nativelib/include
K_CPPFLAGS := -I $(KERNEL_SRC)include -I $(MODULE_SRC)
-LDFLAGS += -Wl,--defsym,__buildnum=$(BUILD_NUM) -g -L .. -lnativelib
+LDFLAGS += -Wl,--defsym,__buildnum=$(BUILD_NUM) -g -L .. -lpthread -lnativelib
BUILDINFO_OBJ := obj/$(TARGET)/buildinfo.o
BUILDINFO_SRC := $(BUILDINFO_OBJ:%.o=%.c)
clean:
$(RM) -f $(OBJ) $(DEPFILES) $(BIN)
-$(BIN): $(OBJ)
+$(BIN): $(OBJ) ../libnativelib.a
@echo [CC Link] -o $(BIN)
@$(CC) -o $(BIN) $(OBJ) $(LDFLAGS)
@echo BUILD_NUM = $$(( $(BUILD_NUM) + 1 )) > Makefile.BuildNum
+ @objdump -S $(BIN) > $(BIN).dsm
$(M_OBJ): $(M_OBJ_PREFIX)%.o: $(MODULE_SRC)%.c
@mkdir -p $(dir $@)
--- /dev/null
+/*
+ * Acess2 Networking Test Suite (NetTest)
+ * - By John Hodge (thePowersGang)
+ *
+ * helpers.c
+ * - General purpose helper functions
+ */
+#include <acess.h>
+#include <vfs.h>
+#include <IPStack/ipstack.h>
+#include <IPStack/interface.h>
+
+// === IMPORTS ===
+//extern tInterface *IPStack_AddInterface(const char *Device, int Type, const char *Name);
+extern tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
+
+// === PROTOTYES ===
+ int Net_ParseAddress(const char *String, void *Addr);
+
+// === CODE ===
+int NetTest_AddAddress(char *SetAddrString)
+{
+ uint8_t addr[16];
+ int addrtype, netmask;
+ char *ifend, *addrend, *end;
+
+ // SetAddrString:
+ // <interface>,<ip>/<netmask>
+ ifend = strchr(SetAddrString, ',');
+ *ifend = '\0';
+ addrend = strchr(ifend+1, '/');
+ *addrend = '\0';
+
+ addrtype = Net_ParseAddress(ifend+1, addr);
+ netmask = strtol(addrend+1, &end, 10);
+
+ *ifend = ',';
+ *addrend = '/';
+
+ if( *end != '\0' || addrtype == 0 )
+ return 1;
+
+ // Create interface
+ *ifend = '\0';
+ tInterface *iface = IPStack_AddInterface(SetAddrString, addrtype, "");
+ *ifend = ',';
+ if( !iface ) {
+ return 1;
+ }
+
+ // Set interface address
+ iface->Node.Type->IOCtl(&iface->Node, 6, addr);
+ iface->Node.Type->IOCtl(&iface->Node, 7, &netmask);
+// iface->Node.Type->Close(&iface->Node);
+
+ return 0;
+}
+
+// ----------------------------------
+// Copy-pasta'd from userland libnet
+// ----------------------------------
+/**
+ * \brief Read an IPv4 Address
+ * \param String IPv4 dotted decimal address
+ * \param Addr Output 32-bit representation of IP address
+ * \return Boolean success
+ */
+static int Net_ParseIPv4Addr(const char *String, uint8_t *Addr)
+{
+ int i = 0;
+ int j;
+ int val;
+
+ for( j = 0; String[i] && j < 4; j ++ )
+ {
+ val = 0;
+ for( ; String[i] && String[i] != '.'; i++ )
+ {
+ if('0' > String[i] || String[i] > '9') {
+ return 0;
+ }
+ val = val*10 + String[i] - '0';
+ }
+ if(val > 255) {
+ return 0;
+ }
+ Addr[j] = val;
+
+ if(String[i] == '.')
+ i ++;
+ }
+ if( j != 4 ) {
+ return 0;
+ }
+ if(String[i] != '\0') {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * \brief Read an IPv6 Address
+ * \param String IPv6 colon-hex representation
+ * \param Addr Output 128-bit representation of IP address
+ * \return Boolean success
+ */
+static int Net_ParseIPv6Addr(const char *String, uint8_t *Addr)
+{
+ int i = 0;
+ int j, k;
+ int val, split = -1, end;
+ uint16_t hi[8], low[8];
+
+ for( j = 0; String[i] && j < 8; j ++ )
+ {
+ if(String[i] == ':') {
+ if(split != -1) {
+ return 0;
+ }
+ split = j;
+ i ++;
+ continue;
+ }
+
+ val = 0;
+ for( k = 0; String[i] && String[i] != ':'; i++, k++ )
+ {
+ val *= 16;
+ if('0' <= String[i] && String[i] <= '9')
+ val += String[i] - '0';
+ else if('A' <= String[i] && String[i] <= 'F')
+ val += String[i] - 'A' + 10;
+ else if('a' <= String[i] && String[i] <= 'f')
+ val += String[i] - 'a' + 10;
+ else {
+ return 0;
+ }
+ }
+
+ if(val > 0xFFFF) {
+ return 0;
+ }
+
+ if(split == -1)
+ hi[j] = val;
+ else
+ low[j-split] = val;
+
+ if( String[i] == ':' ) {
+ i ++;
+ }
+ }
+ end = j;
+
+ // Create final address
+ // - First section
+ for( j = 0; j < split; j ++ )
+ {
+ Addr[j*2] = hi[j]>>8;
+ Addr[j*2+1] = hi[j]&0xFF;
+ }
+ // - Zero region
+ for( ; j < 8 - (end - split); j++ )
+ {
+ Addr[j*2] = 0;
+ Addr[j*2+1] = 0;
+ }
+ // - Tail section
+ k = 0;
+ for( ; j < 8; j ++, k++)
+ {
+ Addr[j*2] = low[k]>>8;
+ Addr[j*2+1] = low[k]&0xFF;
+ }
+
+ return 1;
+}
+
+/**
+ * \brief Parse an address from a string
+ * \param String String containing an IPv4/IPv6 address
+ * \param Addr Buffer for the address (must be >= 16 bytes)
+ * \return Address type
+ * \retval 0 Unknown address type
+ * \retval 4 IPv4 Address
+ * \retval 6 IPv6 Address
+ */
+int Net_ParseAddress(const char *String, void *Addr)
+{
+ if( Net_ParseIPv4Addr(String, Addr) )
+ return 4;
+
+ if( Net_ParseIPv6Addr(String, Addr) )
+ return 6;
+
+ return 0;
+}
+
+int Net_OpenSocket(int AddrType, void *Addr, const char *Filename)
+{
+ int addrLen = IPStack_GetAddressSize(AddrType);
+ int i;
+ uint8_t *addrBuffer = Addr;
+ char hexAddr[addrLen*2+1];
+
+ for( i = 0; i < addrLen; i ++ )
+ sprintf(hexAddr+i*2, "%02x", addrBuffer[i]);
+
+ if(Filename)
+ {
+ int len = snprintf(NULL, 0, "/Devices/ip/routes/@%i:%s/%s", AddrType, hexAddr, Filename);
+ char path[len+1];
+ snprintf(path, 100, "/Devices/ip/routes/@%i:%s/%s", AddrType, hexAddr, Filename);
+ return VFS_Open(path, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);
+ }
+ else
+ {
+ int len = snprintf(NULL, 0, "/Devices/ip/routes/@%i:%s", AddrType, hexAddr);
+ char path[len+1];
+ snprintf(path, 100, "/Devices/ip/routes/@%i:%s", AddrType, hexAddr);
+ return VFS_Open(path, VFS_OPENFLAG_READ);
+ }
+}
+
+int Net_OpenSocket_TCPC(int AddrType, void *Addr, int Port)
+{
+ int fd = Net_OpenSocket(AddrType, Addr, "tcpc");
+ if( fd == -1 ) return -1;
+
+ VFS_IOCtl(fd, 5, &Port); // Remote Port
+ VFS_IOCtl(fd, 6, Addr); // Remote address
+ VFS_IOCtl(fd, 7, NULL); // connect
+ return fd;
+}
+
extern int NativeNic_AddDev(char *Desc);
+extern int NetTest_AddAddress(const char *SetAddrString);
+
extern void *NetTest_OpenTap(const char *Name);
extern size_t NetTest_WritePacket(void *Handle, size_t Size, const void *Data);
extern size_t NetTest_ReadPacket(void *Handle, size_t MaxSize, void *Data);
+extern size_t NetTest_WriteStdout(const void *Data, size_t Size);
+
+extern void NetTest_Suite_Netcat(const char *Addr, int Port);
+
+extern int Net_ParseAddress(const char *String, void *Addr);
+extern int Net_OpenSocket_TCPC(int AddrType, void *Addr, int Port);
+
#endif
#include <acess_logging.h>
#include <nettest.h>
#include <string.h>
+#include <stdlib.h>
+extern int VFS_Init(void);
extern int IPStack_Install(char **Args);
// === CODE ===
fprintf(stderr, "Usage: %s <commands...>\n", ProgramName);
fprintf(stderr, "\n");
fprintf(stderr,
- "-dev <tapdev>:<mac>\n"
- "-ip <dev>,<addr>,<mask>\n"
+ "Options:\n"
+ "-dev <mac>:<tapdev>\n"
+ "-ip <dev>,<addr>/<mask>\n"
"-route <net>,<mask>,<nexthop>\n"
+ "\n"
+ "Suites:\n"
+ "netcat <addr> <port>\n"
);
}
int main(int argc, char *argv[])
{
+ int rv;
+
if( argc <= 1 ) {
PrintUsage(argv[0]);
return 1;
}
// Startup
+ VFS_Init();
{
char *ipstack_args[] = {NULL};
IPStack_Install( ipstack_args );
}
- for( int i = 0; i < argc; i ++ )
+ for( int i = 1; i < argc; i ++ )
{
- if( argv[i][0] != '-' ) {
- }
- else if( strcmp(argv[i], "-dev") == 0 )
+ if( argv[i][0] != '-' )
{
- if( ++i == argc ) { PrintUsage(argv[0]); return 1; }
- NativeNic_AddDev(argv[i]);
+ if( strcmp(argv[i], "netcat") == 0 )
+ {
+ if( argc-i != 3 ) {
+ Log_Error("NetTest", "'netcat' <addr> <port>");
+ PrintUsage(argv[0]);
+ }
+
+ NetTest_Suite_Netcat(argv[i+1], strtol(argv[i+2], NULL, 0));
+ i += 2;
+ }
+ else
+ {
+ Log_Error("NetTest", "Unknown suite name '%s'", argv[i]);
+ PrintUsage(argv[0]);
+ }
}
- else if( strcmp(argv[i], "-ip") == 0 )
+ else
{
- if( ++i == argc ) { PrintUsage(argv[0]); return 1; }
- // TODO: parse argument and poke ipstack
+ if( strcmp(argv[i], "-dev") == 0 )
+ {
+ if( ++i == argc ) { PrintUsage(argv[0]); return 1; }
+ rv = NativeNic_AddDev(argv[i]);
+ if( rv ) {
+ Log_Error("NetTest", "Failed to add device %s", argv[i]);
+ return -1;
+ }
+ }
+ else if( strcmp(argv[i], "-ip") == 0 )
+ {
+ if( ++i == argc ) { PrintUsage(argv[0]); return 1; }
+ // TODO: parse argument and poke ipstack
+ if( NetTest_AddAddress(argv[i]) ) {
+ return -1;
+ }
+ }
+ else
+ {
+ Log_Error("NetTest", "Unknown argument '%s'", argv[i]);
+ PrintUsage(argv[0]);
+ return -1;
+ }
}
}
- // Run suite
-
-
// Teardown
-
+ Log_Log("NetTest", "Shutting down");
+ fflush(stdout);
return 0;
}
+
+size_t NetTest_WriteStdout(const void *Data, size_t Size)
+{
+ return fwrite(Data, 1, Size, stdout);
+}
char *colonpos = strchr(DevDesc, ':');
if( !colonpos )
return -1;
- *colonpos = 0;
if( UnHex(macaddr, 6, DevDesc) != 6 )
return -1;
void *ptr = NetTest_OpenTap(colonpos+1);
+/*
+ * Acess2 Networking Test Suite (NetTest)
+ * - By John Hodge (thePowersGang)
+ *
+ * tcpclient.c
+ * - TCP Client tester
+ */
+#include <vfs.h>
+#include <vfs_ext.h>
+#include <nettest.h>
+
+void NetTest_Suite_Netcat(const char *Address, int Port)
+{
+ Uint8 addr[16];
+ int type = Net_ParseAddress(Address, addr);
+ if( type == 0 )
+ return;
+
+ int fd = Net_OpenSocket_TCPC(type, addr, Port);
+ if( fd == -1 ) {
+ Log_Error("Netcat", "herpaderp tcpc");
+ return ;
+ }
+
+ char buffer[1024];
+ size_t len;
+ while( (len = VFS_Read(fd, sizeof(buffer), buffer)) )
+ {
+ NetTest_WriteStdout(buffer, len);
+ }
+
+ VFS_Close(fd);
+}
return 0;
}
+#if 0
int VFS_Open(const char *Path, Uint Flags)
{
return -1;
void VFS_Close(int FD)
{
}
+#endif
-tVFS_Handle *VFS_GetHandle(int FD)
+int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
{
- return NULL;
+ const int maxfd = *Threads_GetMaxFD();
+ tVFS_Handle *handles = *Threads_GetHandlesPtr();
+ if( !handles ) {
+ handles = calloc( maxfd, sizeof(tVFS_Handle) );
+ *Threads_GetHandlesPtr() = handles;
+ }
+
+ // TODO: Global handles
+
+ for( int i = 0; i < maxfd; i ++ )
+ {
+ if( handles[i].Node == NULL ) {
+ handles[i].Node = Node;
+ handles[i].Mode = Mode;
+ return i;
+ }
+ }
+ return -1;
}
+tVFS_Handle *VFS_GetHandle(int FD)
+{
+ const int maxfd = *Threads_GetMaxFD();
+ tVFS_Handle *handles = *Threads_GetHandlesPtr();
+ if( !handles )
+ return NULL;
+
+ if( FD < 0 || FD >= maxfd )
+ return NULL;
+
+ return &handles[FD];
+}
KERNEL_DIR := ../../KernelLand/Kernel
NOBJ := logging.o misc.o threads_int.o
-KOBJ := threads.o time.o mutex.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
NOBJ := $(NOBJ:%.o=obj/%.o)
-KOBJ := $(KOBJ:%.o=obj/%.o)
-OBJ := $(NOBJ) $(KOBJ)
+LOBJ := $(LOBJ:%.o=obj/%.o)
+KOBJ := $(KOBJ:%.o=obj/_Kernel/%.o)
+OBJ := $(NOBJ) $(LOBJ) $(KOBJ)
BIN := ../libnativelib.a
CFLAGS := -Wall -std=c99 -Werror
@echo [CC Native] $@
@mkdir -p $(dir $@)
@$(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS)
-$(KOBJ): obj/%.o: %.c
- @echo [CC Kernel] $@
+$(LOBJ): obj/%.o: %.c
+ @echo [CC Local] $@
@mkdir -p $(dir $@)
@$(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS) -I $(KERNEL_DIR)/include
+$(KOBJ): obj/_Kernel/%.o: $(KERNEL_DIR)/%.c
+ @echo [CC Kernel] $@
+ @mkdir -p $(dir $@)
+ @$(CC) -o $@ -c $< $(CFLAGS) $(CPPFLAGS) -I $(KERNEL_DIR)/include
extern void *calloc(size_t nmemb, size_t size);
extern void *realloc(void *oldptr, size_t bytes);
extern void free(void *buffer);
+extern char *strdup(const char *str);
#include <errno.h>
#include <acess_logging.h>
// Threads
+extern void **Threads_GetHandlesPtr(void);
extern int *Threads_GetErrno(void);
//extern tPGID Threads_GetPGID(void);
//extern tPID Threads_GetPID(void);
#ifndef _THREADS_INT_H_
#define _THREADS_INT_H_
+#define THREAD_EVENT_RWLOCK (1 << 8)
+
typedef struct sThreadIntMutex tThreadIntMutex; // actually pthreads
typedef struct sThreadIntSem tThreadIntSem;
struct sProcess
{
struct sProcess *Next;
+ struct sThread *Threads;
int PID;
int UID, GID;
char *CWD;
char *Chroot;
+
int MaxFDs;
+ void *Handles;
};
struct sThread
{
struct sThread *Next;
+ struct sThread *ListNext;
+
+ struct sProcess *Process;
+ struct sThread *ProcNext;
+
void *ThreadHandle;
int TID;
uint32_t PendingEvents;
uint32_t WaitingEvents;
tThreadIntSem *WaitSemaphore; // pthreads
-
+
+ char *Name;
+
// Init Only
void (*SpawnFcn)(void*);
void *SpawnData;
};
+extern struct sThread __thread *lpThreads_This;
+
extern int Threads_int_CreateThread(struct sThread *Thread);
+extern int Threads_int_ThreadingEnabled(void);
extern tThreadIntMutex *Threads_int_MutexCreate(void);
extern void Threads_int_MutexDestroy(tThreadIntMutex *Mutex);
--- /dev/null
+/*
+ * Acess2 libnative (Kernel Simulation Library)
+ * - By John Hodge (thePowersGang)
+ *
+ * rwlock.c
+ * - Read/Write locks
+ */
+#include <acess.h>
+#include <rwlock.h>
+#include <events.h>
+#include <threads_int.h>
+
+// === CODE ===
+int RWLock_AcquireRead(tRWLock *Lock)
+{
+ SHORTLOCK(&Lock->Protector);
+ while( Lock->Level < 0 || Lock->WriterWaiting )
+ {
+ // Wait
+ tThread *me = Proc_GetCurThread();
+ me->ListNext = NULL;
+ if( Lock->ReaderWaiting )
+ Lock->ReaderWaitingLast->Next = me;
+ else
+ Lock->ReaderWaiting = me;
+ Lock->ReaderWaitingLast = me;
+ SHORTREL(&Lock->Protector);
+ Threads_WaitEvents(THREAD_EVENT_RWLOCK);
+ SHORTLOCK(&Lock->Protector);
+ }
+ Lock->Level ++;
+ SHORTREL(&Lock->Protector);
+ return 0;
+}
+
+int RWLock_AcquireWrite(tRWLock *Lock)
+{
+ SHORTLOCK(&Lock->Protector);
+
+ while( Lock->Level != 0 )
+ {
+ tThread *me = Proc_GetCurThread();
+ me->ListNext = NULL;
+ if( Lock->WriterWaiting )
+ Lock->WriterWaitingLast->Next = me;
+ else
+ Lock->WriterWaiting = me;
+
+ SHORTREL(&Lock->Protector);
+ Threads_WaitEvents(THREAD_EVENT_RWLOCK);
+ SHORTLOCK(&Lock->Protector);
+ }
+ Lock->Level = -1;
+ SHORTREL(&Lock->Protector);
+ return 0;
+}
+
+void RWLock_Release(tRWLock *Lock)
+{
+ SHORTLOCK(&Lock->Protector);
+ if( Lock->Level == -1 || Lock->Level == 1 )
+ {
+ // Last reader or a writer yeilding
+ // - Yields to writers first, then readers
+ if( Lock->WriterWaiting )
+ {
+ Threads_PostEvent(Lock->WriterWaiting, THREAD_EVENT_RWLOCK);
+ Lock->WriterWaiting = Lock->WriterWaiting->ListNext;
+ }
+ else
+ {
+ while(Lock->ReaderWaiting)
+ {
+ Threads_PostEvent(Lock->ReaderWaiting, THREAD_EVENT_RWLOCK);
+ Lock->ReaderWaiting = Lock->ReaderWaiting->ListNext;
+ }
+ }
+ // Nobody to wake, oh well
+ Lock->Level = 0;
+ }
+ else if( Lock->Level == 0 )
+ {
+ // ... oops?
+ }
+ else
+ {
+ Lock->Level --;
+ }
+ SHORTREL(&Lock->Protector);
+}
+
--- /dev/null
+/*
+ * Acess2 libnative (Kernel Simulation Library)
+ * - By John Hodge (thePowersGang)
+ *
+ * semaphore.c
+ * - Acess semaphores
+ */
+#include <acess.h>
+#include <semaphore.h>
+
+// === CODE ===
+void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)
+{
+
+}
+
+int Semaphore_Wait(tSemaphore *Sem, int MaxToTake)
+{
+ return 0;
+}
+
+int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd)
+{
+ return 0;
+}
+
+int Semaphore_GetValue(tSemaphore *Sem)
+{
+ return 0;
+}
#include <threads.h>
#include <threads_int.h>
+// === PROTOTYPES ===
+void Threads_int_Init(void) __attribute__((constructor(101)));
+tThread *Threads_int_CreateTCB(tThread *Parent);
+
// === GLOBALS ===
+tThread *gThreads_List;
tThread __thread *lpThreads_This;
// === CODE ===
+void Threads_int_Init(void)
+{
+ lpThreads_This = Threads_int_CreateTCB(NULL);
+}
+
tThread *Proc_GetCurThread(void)
{
return lpThreads_This;
Uint32 Threads_WaitEvents(Uint32 Events)
{
- if( !lpThreads_This ) {
+ if( Threads_int_ThreadingEnabled() ) {
Log_Notice("Threads", "_WaitEvents: Threading disabled");
return 0;
}
void Threads_ClearEvent(Uint32 Mask)
{
- if( !lpThreads_This ) {
+ if( Threads_int_ThreadingEnabled() ) {
Log_Notice("Threads", "_ClearEvent: Threading disabled");
return ;
}
tTID Threads_GetTID(void) { return 0; }
-int *Threads_GetMaxFD(void) { static int max_fd=32; return &max_fd; }
-char **Threads_GetCWD(void) { static char *cwd; return &cwd; }
-char **Threads_GetChroot(void) { static char *chroot; return &chroot; }
+int *Threads_GetMaxFD(void) { return &lpThreads_This->Process->MaxFDs; }
+char **Threads_GetCWD(void) { return &lpThreads_This->Process->CWD; }
+char **Threads_GetChroot(void) { return &lpThreads_This->Process->Chroot; }
+void **Threads_GetHandlesPtr(void) { return &lpThreads_This->Process->Handles; }
void Threads_Yield(void)
{
- Log_Warning("Threads", "Threads_Yield DEFINITELY shouldn't be used");
+ Log_KernelPanic("Threads", "Threads_Yield DEFINITELY shouldn't be used (%p)",
+ __builtin_return_address(0));
}
void Threads_Sleep(void)
int Threads_SetName(const char *Name)
{
- Log_Notice("Threads", "TODO: Threads_SetName('%s')", Name);
+ if( !lpThreads_This )
+ return 0;
+
+ if( lpThreads_This->Name )
+ free(lpThreads_This->Name);
+ lpThreads_This->Name = strdup(Name);
+
return 0;
}
int *Threads_GetErrno(void) __attribute__ ((weak));
-int *Threads_GetErrno(void)// __attribute__ ((weak))
+int *Threads_GetErrno(void)
{
static int a_errno;
return &a_errno;
}
+struct sProcess *Threads_int_CreateProcess(void)
+{
+ struct sProcess *ret = calloc(sizeof(struct sProcess), 1);
+
+ ret->MaxFDs = 32;
+
+ return ret;
+}
+
+tThread *Threads_int_CreateTCB(tThread *Parent)
+{
+ tThread *ret = calloc( sizeof(tThread), 1 );
+ ret->WaitSemaphore = Threads_int_SemCreate();
+ ret->Protector = Threads_int_MutexCreate();
+
+ if( !Parent )
+ {
+ ret->Process = Threads_int_CreateProcess();
+ }
+ else
+ ret->Process = Parent->Process;
+
+ ret->ProcNext = ret->Process->Threads;
+ ret->Process->Threads = ret;
+
+ ret->Next = gThreads_List;
+ gThreads_List = ret;
+
+ return ret;
+}
+
struct sThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
{
- if( !lpThreads_This )
+ if( !Threads_int_ThreadingEnabled() )
{
Log_Error("Threads", "Multithreading is disabled in this build");
return NULL;
}
else
{
- tThread *ret = malloc( sizeof(tThread) );
+ tThread *ret = Threads_int_CreateTCB(lpThreads_This);
ret->SpawnFcn = Fcn;
ret->SpawnData = Data;
Threads_int_CreateThread(ret);
struct sThreadIntMutex { int lock; };
struct sThreadIntSem { int val; };
+// === PROTOTYPES ===
+
// === CODE ===
+int Threads_int_ThreadingEnabled(void)
+{
+ Log_Debug("Threads", "pthread_create = %p", pthread_create);
+ return !!pthread_create;
+}
+
+tThreadIntMutex *Threads_int_MutexCreate(void)
+{
+ if( pthread_mutex_init )
+ {
+ tThreadIntMutex *ret = malloc(sizeof(pthread_mutex_t));
+ pthread_mutex_init( (void*)ret, NULL );
+ return ret;
+ }
+ else
+ {
+ return calloc(sizeof(tThreadIntMutex), 1);
+ }
+}
+
void Threads_int_MutexLock(tThreadIntMutex *Mutex)
{
if( !Mutex ) {
}
}
+tThreadIntSem *Threads_int_SemCreate(void)
+{
+ if( sem_init )
+ {
+ tThreadIntSem *ret = malloc(sizeof(sem_t));
+ sem_init( (void*)ret, 0, 0 );
+ return ret;
+ }
+ else
+ {
+ return calloc(sizeof(tThreadIntSem), 1);
+ }
+}
+
void Threads_int_SemSignal(tThreadIntSem *Sem)
{
if( sem_wait )
void *Threads_int_ThreadRoot(void *ThreadPtr)
{
tThread *thread = ThreadPtr;
+ lpThreads_This = thread;
+ Log_Debug("Threads", "SpawnFcn: %p, SpawnData: %p", thread->SpawnFcn, thread->SpawnData);
thread->SpawnFcn(thread->SpawnData);
return NULL;
}
{
pthread_t *pthread = malloc(sizeof(pthread_t));
Thread->ThreadHandle = pthread;
- return pthread_create(pthread, NULL, Threads_int_ThreadRoot, Thread);
+ return pthread_create(pthread, NULL, &Threads_int_ThreadRoot, Thread);
}
else
{
void Time_ScheduleTimer(tTimer *Timer, int Delta)
{
-
+ if( !Timer )
+ {
+ // SIGALRM
+ }
+ else
+ {
+
+ }
}
void Time_RemoveTimer(tTimer *Timer)