Tools/nativelib - Many features implimented
authorJohn Hodge <[email protected]>
Mon, 28 Jan 2013 10:46:53 +0000 (18:46 +0800)
committerJohn Hodge <[email protected]>
Mon, 28 Jan 2013 10:46:53 +0000 (18:46 +0800)
17 files changed:
Tools/DiskTool/Makefile
Tools/Makefile [new file with mode: 0644]
Tools/NetTest/Makefile
Tools/NetTest/helpers.c [new file with mode: 0644]
Tools/NetTest/include/nettest.h
Tools/NetTest/main.c
Tools/NetTest/nic.c
Tools/NetTest/tcpclient.c
Tools/NetTest/vfs_shim.c
Tools/nativelib/Makefile
Tools/nativelib/include/acess.h
Tools/nativelib/include/threads_int.h
Tools/nativelib/rwlock.c [new file with mode: 0644]
Tools/nativelib/semaphore.c [new file with mode: 0644]
Tools/nativelib/threads.c
Tools/nativelib/threads_int.c
Tools/nativelib/time.c

index 9d68da3..4b0ef60 100644 (file)
@@ -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 (file)
index 0000000..e10b765
--- /dev/null
@@ -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 $@
index 45e76b2..4473e73 100644 (file)
@@ -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 (file)
index 0000000..f0c77a6
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * 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;
+}
+
index c8d16b8..090f5d4 100644 (file)
 
 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
 
index 4f3e9f5..9ce48a4 100644 (file)
@@ -9,7 +9,9 @@
 #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 ===
@@ -18,45 +20,87 @@ void PrintUsage(const char *ProgramName)
        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);
+}
index 1e736c2..4effc00 100644 (file)
@@ -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);
index e69de29..3ad9f6d 100644 (file)
@@ -0,0 +1,33 @@
+/*
+ * 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);
+}
index bc0c67c..1b0c686 100644 (file)
@@ -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];
+}
index e8ca923..e8e7f55 100644 (file)
@@ -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
index da1693f..7198865 100644 (file)
@@ -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 <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);
index 240f525..36e5aba 100644 (file)
@@ -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 (file)
index 0000000..6bef637
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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);
+}
+
diff --git a/Tools/nativelib/semaphore.c b/Tools/nativelib/semaphore.c
new file mode 100644 (file)
index 0000000..c1476f6
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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;
+}
index eafe87f..1231c43 100644 (file)
@@ -9,10 +9,20 @@
 #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;
@@ -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);
index 2274eea..f25ab95 100644 (file)
@@ -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
        {
index a091c0b..4eb7463 100644 (file)
@@ -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)

UCC git Repository :: git.ucc.asn.au