From 3241c317ee9f714eba6a0fa82de79cfe5f104993 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 28 Jan 2013 18:46:53 +0800 Subject: [PATCH] Tools/nativelib - Many features implimented --- Tools/DiskTool/Makefile | 5 +- Tools/Makefile | 13 ++ Tools/NetTest/Makefile | 13 +- Tools/NetTest/helpers.c | 235 ++++++++++++++++++++++++++ Tools/NetTest/include/nettest.h | 9 + Tools/NetTest/main.c | 74 ++++++-- Tools/NetTest/nic.c | 1 - Tools/NetTest/tcpclient.c | 33 ++++ Tools/NetTest/vfs_shim.c | 35 +++- Tools/nativelib/Makefile | 21 ++- Tools/nativelib/include/acess.h | 2 + Tools/nativelib/include/threads_int.h | 17 +- Tools/nativelib/rwlock.c | 91 ++++++++++ Tools/nativelib/semaphore.c | 30 ++++ Tools/nativelib/threads.c | 69 ++++++-- Tools/nativelib/threads_int.c | 40 ++++- Tools/nativelib/time.c | 9 +- 17 files changed, 649 insertions(+), 48 deletions(-) create mode 100644 Tools/Makefile create mode 100644 Tools/NetTest/helpers.c create mode 100644 Tools/nativelib/rwlock.c create mode 100644 Tools/nativelib/semaphore.c diff --git a/Tools/DiskTool/Makefile b/Tools/DiskTool/Makefile index 9d68da35..4b0ef607 100644 --- a/Tools/DiskTool/Makefile +++ b/Tools/DiskTool/Makefile @@ -14,9 +14,6 @@ MODULE_SRC = ../../KernelLand/Modules/ 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 @@ -62,7 +59,7 @@ all: $(BIN) 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 diff --git a/Tools/Makefile b/Tools/Makefile new file mode 100644 index 00000000..e10b765f --- /dev/null +++ b/Tools/Makefile @@ -0,0 +1,13 @@ + +.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 $@ diff --git a/Tools/NetTest/Makefile b/Tools/NetTest/Makefile index 45e76b2f..4473e734 100644 --- a/Tools/NetTest/Makefile +++ b/Tools/NetTest/Makefile @@ -15,22 +15,18 @@ BIN = ../nettest # 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) @@ -63,10 +59,11 @@ all: $(BIN) 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 $@) diff --git a/Tools/NetTest/helpers.c b/Tools/NetTest/helpers.c new file mode 100644 index 00000000..f0c77a63 --- /dev/null +++ b/Tools/NetTest/helpers.c @@ -0,0 +1,235 @@ +/* + * Acess2 Networking Test Suite (NetTest) + * - By John Hodge (thePowersGang) + * + * helpers.c + * - General purpose helper functions + */ +#include +#include +#include +#include + +// === 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: + // ,/ + 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; +} + diff --git a/Tools/NetTest/include/nettest.h b/Tools/NetTest/include/nettest.h index c8d16b8f..090f5d4e 100644 --- a/Tools/NetTest/include/nettest.h +++ b/Tools/NetTest/include/nettest.h @@ -12,9 +12,18 @@ 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 diff --git a/Tools/NetTest/main.c b/Tools/NetTest/main.c index 4f3e9f58..9ce48a4a 100644 --- a/Tools/NetTest/main.c +++ b/Tools/NetTest/main.c @@ -9,7 +9,9 @@ #include #include #include +#include +extern int VFS_Init(void); extern int IPStack_Install(char **Args); // === CODE === @@ -18,45 +20,87 @@ void PrintUsage(const char *ProgramName) fprintf(stderr, "Usage: %s \n", ProgramName); fprintf(stderr, "\n"); fprintf(stderr, - "-dev :\n" - "-ip ,,\n" + "Options:\n" + "-dev :\n" + "-ip ,/\n" "-route ,,\n" + "\n" + "Suites:\n" + "netcat \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' "); + 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); +} diff --git a/Tools/NetTest/nic.c b/Tools/NetTest/nic.c index 1e736c2b..4effc007 100644 --- a/Tools/NetTest/nic.c +++ b/Tools/NetTest/nic.c @@ -33,7 +33,6 @@ int NativeNic_AddDev(char *DevDesc) char *colonpos = strchr(DevDesc, ':'); if( !colonpos ) return -1; - *colonpos = 0; if( UnHex(macaddr, 6, DevDesc) != 6 ) return -1; void *ptr = NetTest_OpenTap(colonpos+1); diff --git a/Tools/NetTest/tcpclient.c b/Tools/NetTest/tcpclient.c index e69de29b..3ad9f6da 100644 --- a/Tools/NetTest/tcpclient.c +++ b/Tools/NetTest/tcpclient.c @@ -0,0 +1,33 @@ +/* + * Acess2 Networking Test Suite (NetTest) + * - By John Hodge (thePowersGang) + * + * tcpclient.c + * - TCP Client tester + */ +#include +#include +#include + +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); +} diff --git a/Tools/NetTest/vfs_shim.c b/Tools/NetTest/vfs_shim.c index bc0c67c3..1b0c686a 100644 --- a/Tools/NetTest/vfs_shim.c +++ b/Tools/NetTest/vfs_shim.c @@ -32,6 +32,7 @@ int VFS_MarkError(tVFS_Node *Node, BOOL bError) return 0; } +#if 0 int VFS_Open(const char *Path, Uint Flags) { return -1; @@ -40,9 +41,39 @@ int VFS_Open(const char *Path, Uint Flags) 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]; +} diff --git a/Tools/nativelib/Makefile b/Tools/nativelib/Makefile index e8ca9236..e8e7f55a 100644 --- a/Tools/nativelib/Makefile +++ b/Tools/nativelib/Makefile @@ -2,11 +2,18 @@ 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 @@ -27,8 +34,12 @@ $(NOBJ): obj/%.o: %.c @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 diff --git a/Tools/nativelib/include/acess.h b/Tools/nativelib/include/acess.h index da1693fc..71988653 100644 --- a/Tools/nativelib/include/acess.h +++ b/Tools/nativelib/include/acess.h @@ -70,11 +70,13 @@ extern void *malloc(size_t bytes); 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 #include // Threads +extern void **Threads_GetHandlesPtr(void); extern int *Threads_GetErrno(void); //extern tPGID Threads_GetPGID(void); //extern tPID Threads_GetPID(void); diff --git a/Tools/nativelib/include/threads_int.h b/Tools/nativelib/include/threads_int.h index 240f5253..36e5aba3 100644 --- a/Tools/nativelib/include/threads_int.h +++ b/Tools/nativelib/include/threads_int.h @@ -8,24 +8,34 @@ #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; @@ -34,13 +44,18 @@ struct sThread 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); diff --git a/Tools/nativelib/rwlock.c b/Tools/nativelib/rwlock.c new file mode 100644 index 00000000..6bef637d --- /dev/null +++ b/Tools/nativelib/rwlock.c @@ -0,0 +1,91 @@ +/* + * Acess2 libnative (Kernel Simulation Library) + * - By John Hodge (thePowersGang) + * + * rwlock.c + * - Read/Write locks + */ +#include +#include +#include +#include + +// === 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); +} + diff --git a/Tools/nativelib/semaphore.c b/Tools/nativelib/semaphore.c new file mode 100644 index 00000000..c1476f62 --- /dev/null +++ b/Tools/nativelib/semaphore.c @@ -0,0 +1,30 @@ +/* + * Acess2 libnative (Kernel Simulation Library) + * - By John Hodge (thePowersGang) + * + * semaphore.c + * - Acess semaphores + */ +#include +#include + +// === 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; +} diff --git a/Tools/nativelib/threads.c b/Tools/nativelib/threads.c index eafe87f4..1231c439 100644 --- a/Tools/nativelib/threads.c +++ b/Tools/nativelib/threads.c @@ -9,10 +9,20 @@ #include #include +// === 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; @@ -33,7 +43,7 @@ void Threads_PostEvent(tThread *Thread, Uint32 Events) Uint32 Threads_WaitEvents(Uint32 Events) { - if( !lpThreads_This ) { + if( Threads_int_ThreadingEnabled() ) { Log_Notice("Threads", "_WaitEvents: Threading disabled"); return 0; } @@ -46,7 +56,7 @@ Uint32 Threads_WaitEvents(Uint32 Events) void Threads_ClearEvent(Uint32 Mask) { - if( !lpThreads_This ) { + if( Threads_int_ThreadingEnabled() ) { Log_Notice("Threads", "_ClearEvent: Threading disabled"); return ; } @@ -60,13 +70,15 @@ tGID Threads_GetGID(void) { return 0; } 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) @@ -76,28 +88,65 @@ 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); diff --git a/Tools/nativelib/threads_int.c b/Tools/nativelib/threads_int.c index 2274eeaa..f25ab95a 100644 --- a/Tools/nativelib/threads_int.c +++ b/Tools/nativelib/threads_int.c @@ -17,7 +17,29 @@ typedef struct sThread tThread; 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 ) { @@ -53,6 +75,20 @@ void Threads_int_MutexRelease(tThreadIntMutex *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 ) @@ -82,6 +118,8 @@ void Threads_int_SemWaitAll(tThreadIntSem *Sem) 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; } @@ -92,7 +130,7 @@ int Threads_int_CreateThread(tThread *Thread) { 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 { diff --git a/Tools/nativelib/time.c b/Tools/nativelib/time.c index a091c0bf..4eb74631 100644 --- a/Tools/nativelib/time.c +++ b/Tools/nativelib/time.c @@ -16,7 +16,14 @@ tTimer *Time_AllocateTimer(tTimerCallback *Callback, void *Argument) void Time_ScheduleTimer(tTimer *Timer, int Delta) { - + if( !Timer ) + { + // SIGALRM + } + else + { + + } } void Time_RemoveTimer(tTimer *Timer) -- 2.20.1