Tools/*/Makefile.BuildNum
Tools/disktool
Tools/nettest
+Tools/nettest_runner
Tools/img2sif
+Tools/stdout.txt
+Tools/stderr.txt
*.udi
UDI/drivers/*/bin
# 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 helpers.o
+L_OBJ = vfs_shim.o nic.o tcpclient.o tcpserver.o helpers.o mode_cmdline.o
# Native Sources (compiled as usual)
N_OBJ = main.o tap.o
# Compilation Options
CFLAGS := -Wall -std=gnu99 -g -Werror -O0 -pthread
CPPFLAGS := -I include/ -I ../nativelib/include
-K_CPPFLAGS := -I $(KERNEL_SRC)include -I $(MODULE_SRC)
+K_CPPFLAGS := -I $(KERNEL_SRC)include -I $(MODULE_SRC) -I ../../Usermode/Libraries/ld-acess.so_src/include_exp/
LDFLAGS += -Wl,--defsym,__buildnum=$(BUILD_NUM) -g -L .. -lpthread -lnativelib
BUILDINFO_OBJ := obj/$(TARGET)/buildinfo.o
extern int NetTest_AddAddress(const char *SetAddrString);
extern void *NetTest_OpenTap(const char *Name);
+extern void *NetTest_OpenUnix(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 void NetTest_Suite_Cmdline(void);
extern int Net_ParseAddress(const char *String, void *Addr);
extern int Net_OpenSocket_TCPC(int AddrType, void *Addr, int Port);
fprintf(stderr, "\n");
fprintf(stderr,
"Options:\n"
- "-dev <mac>:<tapdev>\n"
+ "-dev <mac>:<type>:<arg>\n"
"-ip <dev>,<addr>/<mask>\n"
- "-route <net>,<mask>,<nexthop>\n"
+ "-route <net>/<mask>,<nexthop>\n"
"\n"
- "Suites:\n"
+ "Commands:\n"
"netcat <addr> <port>\n"
+ "\n"
+ "Device Types:\n"
+ "tun - Linux TUN/TAP device (takes an optional name)\n"
+ "unix - Unix named pipe (datagram)\n"
);
}
for( int i = 1; i < argc; i ++ )
{
- if( argv[i][0] != '-' )
+ char *arg = argv[i];;
+ if( arg[0] != '-' )
{
- if( strcmp(argv[i], "netcat") == 0 )
+ if( strcmp(arg, "netcat") == 0 )
{
if( argc-i != 3 ) {
Log_Error("NetTest", "'netcat' <addr> <port>");
NetTest_Suite_Netcat(argv[i+1], strtol(argv[i+2], NULL, 0));
i += 2;
}
+ else if( strcmp(arg, "cmdline") == 0 )
+ {
+ NetTest_Suite_Cmdline();
+ }
else
{
- Log_Error("NetTest", "Unknown suite name '%s'", argv[i]);
+ Log_Error("NetTest", "Unknown suite name '%s'", arg);
PrintUsage(argv[0]);
}
}
else
{
- if( strcmp(argv[i], "-dev") == 0 )
+ if( strcmp(arg, "--help") == 0 )
+ {
+ PrintUsage(0);
+ return 0;
+ }
+ else if( strcmp(arg, "-dev") == 0 )
{
- if( ++i == argc ) { PrintUsage(argv[0]); return 1; }
- rv = NativeNic_AddDev(argv[i]);
+ if( i+1 == argc ) { PrintUsage(argv[0]); return 1; }
+ rv = NativeNic_AddDev(argv[i+1]);
if( rv ) {
- Log_Error("NetTest", "Failed to add device %s", argv[i]);
+ Log_Error("NetTest", "Failed to add device %s", argv[i+1]);
return -1;
}
+ i ++;
}
- else if( strcmp(argv[i], "-ip") == 0 )
+ else if( strcmp(arg, "-ip") == 0 )
{
- if( ++i == argc ) { PrintUsage(argv[0]); return 1; }
- // TODO: parse argument and poke ipstack
- if( NetTest_AddAddress(argv[i]) ) {
+ if( i+1 == argc ) { PrintUsage(argv[0]); return 1; }
+ // Parse argument and poke ipstack
+ if( NetTest_AddAddress(argv[i+1]) ) {
return -1;
}
+ i ++;
}
else
{
- Log_Error("NetTest", "Unknown argument '%s'", argv[i]);
+ Log_Error("NetTest", "Unknown argument '%s'", arg);
PrintUsage(argv[0]);
return -1;
}
--- /dev/null
+/*
+ */
+#include <nettest.h>
+#include <stdio.h>
+#include <string.h>
+
+// === CODE ===
+void NetTest_Suite_Cmdline(void)
+{
+ char line[BUFSIZ];
+ while( fgets(line, sizeof(line)-1, stdin) )
+ {
+ const char *cmd = strtok(line, " ");
+ if(!cmd)
+ continue;
+ if( strcmp(cmd, "exit") == 0 ) {
+ return ;
+ }
+ else if( strcmp(cmd, "request") == 0 ) {
+ //const char *addr = strtok(NULL, " ");
+
+ }
+ else {
+ fprintf(stderr, "ERROR: Unknown command '%s'\n", cmd);
+ }
+ }
+}
// === GLOBALS ===
tIPStack_AdapterType gNativeNIC_AdapterType = {
.Name = "NativeNIC",
- .Type = 0, // TODO: Differentiate differnet wire protos and speeds
- .Flags = 0, // TODO: IP checksum offloading, MAC checksum offloading etc
+ .Type = 0,
+ .Flags = 0,
.SendPacket = NativeNic_SendPacket,
.WaitForPacket = NativeNic_WaitForPacket
};
int NativeNic_AddDev(char *DevDesc)
{
Uint8 macaddr[6];
+ // Parse descriptor into mac address and path
+ // 123456789ABC:tun:ifname
+ // 123456789ABC:unix:/path
+ // 123456789ABC:file:/path
+ // 123456789ABC:tcp:host_desc
char *colonpos = strchr(DevDesc, ':');
if( !colonpos )
return -1;
if( UnHex(macaddr, 6, DevDesc) != 6 )
return -1;
- void *ptr = NetTest_OpenTap(colonpos+1);
+
+ char *class = colonpos + 1;
+ colonpos = strchr(class, ':');
+ void *ptr;
+ if( strncmp(class, "tun:", 4) == 0 ) {
+ ptr = NetTest_OpenTap(colonpos+1);
+ }
+ else if( strncmp(class, "unix:", 5) == 0 ) {
+ ptr = NetTest_OpenUnix(colonpos+1);
+ }
+ else {
+ Log_Warning("NIC", "Unknown opener '%.*s'", colonpos-class, class);
+ ptr = NULL;
+ }
if( !ptr )
return 1;
IPStack_Adapter_Add(&gNativeNIC_AdapterType, ptr, macaddr);
tIPStackBuffer *ret = IPStack_Buffer_CreateBuffer(1);
IPStack_Buffer_AppendSubBuffer(ret, len, 0, buf, NativeNic_int_FreePacket, Ptr);
+
+ Debug_HexDump("NativeNic: RX", buf, len);
+
return ret;
}
// Serialise into stack
char buf[len];
IPStack_Buffer_GetData(Buffer, buf, len);
+
+ Debug_HexDump("NativeNic: TX", buf, len);
NetTest_WritePacket(Ptr, len, buf);
return 0;
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
// === CODE ===
void *NetTest_OpenTap(const char *Name)
return (void*)(intptr_t)fd;
}
+void *NetTest_OpenUnix(const char *Path)
+{
+ int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ struct sockaddr_un sa = {AF_UNIX, ""};
+ struct sockaddr_un sa_local = {AF_UNIX, ""};
+ strcpy(sa.sun_path, Path);
+ if( connect(fd, (struct sockaddr*)&sa, sizeof(sa)) ) {
+ perror("NetTest_OpenUnix - connect");
+ close(fd);
+ return NULL;
+ }
+ if( bind(fd, (struct sockaddr*)&sa_local, sizeof(sa)) ) {
+ perror("NetTest_OpenUnix - bind");
+ close(fd);
+ return NULL;
+ }
+
+ {
+ char somenulls[] = { 0,0,0,0,0,0, 0,0,0,0,0, 0,0};
+ write(fd, somenulls, sizeof(somenulls));
+ }
+
+ return (void*)(intptr_t)fd;
+}
+
size_t NetTest_WritePacket(void *Handle, size_t Size, const void *Data)
{
- return write( (intptr_t)Handle, Data, Size);
+ int ret = write( (intptr_t)Handle, Data, Size);
+ if( ret < 0 ) {
+ perror("NetTest_WritePacket - write");
+ return 0;
+ }
+ return ret;
}
size_t NetTest_ReadPacket(void *Handle, size_t MaxSize, void *Data)
#include <events.h>
// === 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;
- }
-
- 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)
-{
- Node->DataAvaliable = bAvail;
- if( Node->DataAvaliable && Node->ReadThreads )
- Threads_PostEvent( (void*)Node->ReadThreads, THREAD_EVENT_VFS );
- return 0;
-}
-
-int VFS_MarkError(tVFS_Node *Node, BOOL bError)
-{
- Node->ErrorOccurred = bError;
- if( Node->ErrorOccurred && Node->ErrorThreads )
- Threads_PostEvent( (void*)Node->ErrorThreads, THREAD_EVENT_VFS );
- 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)
-{
- return -1;
-}
-
-void VFS_Close(int FD)
-{
-}
-#endif
-
int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
{
const int maxfd = *Threads_GetMaxFD();
return &handles[FD];
}
+
+int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode)
+{
+ const int maxfd = *Threads_GetMaxFD();
+ tVFS_Handle *handles = *Threads_GetHandlesPtr();
+ if( !handles )
+ return -1;
+
+ if( FD < 0 || FD >= maxfd )
+ return -1;
+
+ handles[FD].Node = Node;
+ handles[FD].Mode = Mode;
+ return FD;
+}
--- /dev/null
+
+OBJ := main.o net.o stack.o
+OBJ += tcp.o
+OBJ += ip.o arp.o
+OBJ += link.o
+OBJ += test_arp.o test_tcp.o
+BIN := ../nettest_runner
+
+CFLAGS := -Wall -std=c99
+CPPFLAGS := -Iinclude
+LIBS :=
+
+OBJ := $(OBJ:%=obj/%)
+
+.PHONY: all clean
+
+all: $(BIN)
+
+clean:
+ $(RM) $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+ @echo [CC] -o $@
+ @$(CC) $(LINKFLAGS) -o $@ $(OBJ) $(LIBS)
+
+obj/%.o: %.c
+ @mkdir -p $(dir $@)
+ @echo [CC] -c -o $@
+ @$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< -MMD -MP
+
+-include $(OBJ:%.o=%.d)
+
--- /dev/null
+/*
+ */
+#include "arp.h"
+#include "net.h"
+#include <stdint.h>
+#include <string.h>
+#include "test.h"
+#include "tests.h"
+
+// === CODE ===
+void ARP_SendRequest(int IfNum, const void *IPv4Addr)
+{
+ const uint8_t *addr = IPv4Addr;
+ uint8_t pkt[] = {
+ // Ethernet
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ HOST_MAC,
+ 0x08,0x06,
+ // ARP
+ 0x00,0x01, 0x08,0x00,
+ 6,4, 0,1,
+ HOST_MAC,
+ HOST_IP,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ addr[0],addr[1],addr[2],addr[3],
+ };
+ Net_Send(IfNum, sizeof(pkt), pkt);
+}
+
+void ARP_SendResponse(int IfNum, const void *IPv4Addr, const void *MacAddr)
+{
+
+}
+
+bool ARP_Pkt_IsResponse(size_t Len, const void *Packet, const void *ExpectedIP, const void *ExpectedMac)
+{
+ const uint8_t *pkt8 = Packet;
+ if( Len < 2*6+2 ) {
+ TEST_WARN("Undersized");
+ return false;
+ }
+ // Ethernet ARP id
+ if( pkt8[12+0] != 0x08 || pkt8[12+1] != 0x06 ) {
+ TEST_WARN("Ethernet tag %02x %02x != 08 06", pkt8[12+0], pkt8[12+1]);
+ return false;
+ }
+
+ // ARP HWtype/ProtoType
+ if( pkt8[14+0] != 0x00 || pkt8[14+1] != 0x01 || pkt8[14+2] != 0x08 || pkt8[14+3] != 0x00 ) {
+ TEST_WARN("ARP Types %02x %02x %02x %02x != 00 01 08 00",
+ pkt8[14+0], pkt8[14+1], pkt8[14+2], pkt8[14+3]);
+ return false;
+ }
+ // ARP Sizes (HW/Proto) and operation (Response)
+ if( pkt8[14+4] != 6 || pkt8[14+5] != 4 || pkt8[14+6] != 0 || pkt8[14+7] != 2 ) {
+ TEST_WARN("Sizes+op %02x %02x %02x %02x != 06 04 00 02",
+ pkt8[14+4], pkt8[14+5], pkt8[14+6], pkt8[14+7]);
+ return false;
+ }
+
+ if( memcmp(pkt8+14+8, ExpectedMac, 6) != 0 )
+ return false;
+ if( memcmp(pkt8+14+14, ExpectedIP, 4) != 0 )
+ return false;
+ if( memcmp(pkt8+14+18, (char[]){HOST_MAC}, 6) != 0 )
+ return false;
+ if( memcmp(pkt8+14+24, (char[]){HOST_IP}, 4) != 0 )
+ return false;
+
+ return true;
+}
+
+bool ARP_Pkt_IsRequest(size_t Len, const void *Packet, const void *ExpectedIP)
+{
+ return false;
+}
+
--- /dev/null
+/*
+ */
+#ifndef _ARP_H_
+#define _ARP_H_
+
+#include <stddef.h>
+#include <stdbool.h>
+
+
+extern void ARP_SendRequest(int IfNum, const void *IPv4Addr);
+extern void ARP_SendResponse(int IfNum, const void *IPv4Addr, const void *MacAddr);
+extern bool ARP_Pkt_IsResponse(size_t Len, const void *Packet, const void *ExpectedIP, const void *ExpectedMac);
+extern bool ARP_Pkt_IsRequest(size_t Len, const void *Packet, const void *ExpectedIP);
+
+#endif
+
--- /dev/null
+/*
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <stdint.h>
+
+#define HOST_IP_STR "10.1.1.2"
+#define HOST_IP 0x0A,0x01,0x01,0x02
+#define HOST_MAC 0x54,0x56,0x00,0x12,0x34,0x11
+
+#define TEST_IP 0x0A,0x01,0x01,0x01
+#define TEST_MAC 0x54,0x56,0x00,0x12,0x34,0x56
+
+#define BLOB(bytes) (const char[]){bytes}
+
+#if BIG_ENDIAN
+# define htons(x) ((uint16_t)(x))
+# define htonl(x) ((uint32_t)(x))
+#else
+static inline uint16_t htons(uint16_t x) {
+ return (x >> 8) | (x << 8);
+}
+static inline uint32_t htonl(uint32_t x) {
+ return ((x >> 24) & 0xFF) << 0
+ |((x >> 16) & 0xFF) << 8
+ |((x >> 8) & 0xFF) << 16
+ |((x >> 0) & 0xFF) << 24;
+}
+#endif
+#define ntohs(x) htons(x)
+#define ntohl(x) htonl(x)
+
+
+#endif
+
--- /dev/null
+/*
+ * ip.h
+ * - IP-layer Test Wrapper (v5/v6)
+ */
+#ifndef _IP_H_
+#define _IP_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#define IPPROTO_TCP 6
+
+#define IP_CHECKSUM_START 0xFFFF
+
+extern uint16_t IP_Checksum(uint16_t Prev, size_t Length, const void *Data);
+
+extern void IP_Send(int IfNum, int AF, const void *Src, const void *Dst, uint8_t proto,
+ int BufCount, size_t BufLens[], const void *Bufs[]);
+
+extern bool IP_Pkt_Check(size_t len, const void *data, size_t *ofs, int AF, const void *Src, const void *Dst, uint8_t proto);
+
+#endif
+
--- /dev/null
+/*
+ */
+#ifndef _LINK_H_
+#define _LINK_H_
+
+#define ETHER_PROTO_IPV4 0x0800
+
+#include <stdint.h>
+#include <stdbool.h>
+
+extern void Link_Send(int IfNum, const void *Src, const void *Dst, uint16_t Proto, int BufCount, size_t BufLens[], const void *Bufs[]);
+
+extern bool Link_Pkt_Check(size_t len, const void *data, size_t *ofs, const void *Src, const void *Dst, uint16_t Proto);
+
+#endif
+
--- /dev/null
+/*
+ * net.h
+ * - Network interface IO
+ */
+#ifndef _NET_H_
+#define _NET_H_
+
+#include <stddef.h>
+#include <stdbool.h>
+
+#define MTU 1520
+
+extern int Net_Open(int IfNum, const char *Path);
+extern void Net_Close(int IfNum);
+
+
+extern size_t Net_Receive(int IfNum, size_t MaxLen, void *DestBuf, unsigned int Timeout);
+extern void Net_Send(int IfNum, size_t Length, const void *Buf);
+
+#endif
+
--- /dev/null
+/*
+ * stack.h
+ * - Functions for interacting with the IPStack program
+ */
+#ifndef _STACK_H_
+#define _STACK_H_
+
+#include <stdint.h>
+
+extern void Stack_AddDevice(const char *Ident, const void *MacAddr);
+extern void Stack_AddInterface(const char *Name, int AddrType, const void *Addr, int MaskBits);
+extern void Stack_AddRoute(int Type, const void *Network, int MaskBits, const void *NextHop);
+
+extern void Stack_AddArg(const char *Fmt, ...);
+extern int Stack_Start(const char *Subcommand);
+extern void Stack_Kill(void);
+
+extern int Stack_SendCommand(const char *CommandString);
+
+#endif
+
--- /dev/null
+/*
+ * tcp.h
+ * - TCP Test Wrapper
+ */
+#ifndef _TCP_H_
+#define _TCP_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#define TCP_FIN 0x01
+#define TCP_SYN 0x02
+#define TCP_RST 0x04
+
+extern void TCP_Send(int IF, int AF, const void *IP, short sport, short dport, uint32_t seq, uint32_t ack, uint8_t flags, uint16_t window, size_t data_len, const void *data);
+extern bool TCP_Pkt_Check(size_t len, const void *data, size_t *ofs, int AF, const void *IP, short sport, short dport, uint8_t flags);
+
+#endif
+
--- /dev/null
+/*
+ */
+#ifndef _TEST_H_
+#define _TEST_H_
+
+#define TEST_SETNAME(name) test_setname(name)
+#define TEST_ASSERT(cnd) do{if(!(cnd)) {test_assertion_fail(__FILE__,__LINE__,"%s",#cnd);return false;}}while(0)
+#define TEST_ASSERT_REL(a,r,b) do{long long a_val=(a),b_val=(b);if(!(a_val r b_val)) {test_assertion_fail(__FILE__,__LINE__,"%s(0x%llx)%s%s(%llx)",#a,a_val,#r,#b,b_val);return false;}}while(0)
+#define TEST_WARN(msg...) test_message(__FILE__,__LINE__,msg)
+
+extern void test_setname(const char *name);
+extern void test_message(const char *filename, int line, const char *msg, ...);
+extern void test_assertion_fail(const char *filename, int line, const char *test, ...);
+
+#endif
+
--- /dev/null
+/*
+ * tests.h
+ * - List of tests used by main.c
+ */
+#ifndef _TESTS_H_
+#define _TESTS_H_
+
+#include "common.h"
+#include <stdbool.h>
+
+extern bool Test_ARP_Basic(void);
+extern bool Test_TCP_Basic(void);
+
+#endif
+
--- /dev/null
+/*
+ */
+#include "common.h"
+#include "ip.h"
+#include "link.h"
+#include <assert.h>
+#include <string.h>
+#include "test.h"
+
+// === STRUCTURES ===
+typedef struct {
+ uint8_t VerLen;
+ uint8_t DiffServices;
+ uint16_t TotalLength;
+ uint16_t Identifcation;
+ uint16_t FragmentInfo; // rsvd:dont:more:[13]offset/8
+ uint8_t TTL;
+ uint8_t Protocol;
+ uint16_t HeaderChecksum;
+ uint8_t SrcAddr[4];
+ uint8_t DstAddr[4];
+ uint8_t Options[];
+} __attribute__((packed)) tIPv4Hdr;
+
+// === CODE ===
+uint16_t IP_Checksum(uint16_t Prev, size_t Length, const void *Data)
+{
+ const uint16_t *words = Data;
+ uint32_t ret = ~Prev;
+ for( int i = 0; i < Length/2; i ++ )
+ {
+ ret += ntohs(*words);
+ words ++;
+ }
+ if( Length & 1 )
+ ret += ntohs(*(uint8_t*)words);
+
+ while( ret >> 16 )
+ ret = (ret & 0xFFFF) + (ret >> 16);
+
+ return ~ret;
+}
+
+void IP_Send(int IfNum, int AF, const void *Src, const void *Dst, uint8_t proto,
+ int BufCount, size_t BufLens[], const void *Bufs[])
+{
+ size_t total_length = 0;
+
+ size_t out_buflens[BufCount+1];
+ const void *out_bufs[BufCount+1];
+
+ for( int i = 0; i < BufCount; i ++ )
+ {
+ total_length += BufLens[i];
+ out_buflens[1+i] = BufLens[i];
+ out_bufs[1+i] = Bufs[i];
+ }
+
+ if( AF == 4 )
+ {
+ tIPv4Hdr hdr;
+ hdr.VerLen = (4 << 4) | (sizeof(hdr)/4);
+ hdr.DiffServices = 0;
+ hdr.TotalLength = htons(sizeof(hdr) + total_length);
+ hdr.Identifcation = 0; // TODO: WTF is this?
+ hdr.FragmentInfo = htons(0);
+ hdr.TTL = 18; // TODO: Progammable TTL
+ hdr.Protocol = proto;
+ hdr.HeaderChecksum = 0;
+ memcpy(hdr.SrcAddr, Src, 4);
+ memcpy(hdr.DstAddr, Dst, 4);
+
+ hdr.HeaderChecksum = htons( IP_Checksum(IP_CHECKSUM_START, sizeof(hdr), &hdr) );
+
+ out_buflens[0] = sizeof(hdr);
+ out_bufs[0] = &hdr;
+
+ // TODO: Don't hard-code MAC addresses
+ Link_Send(IfNum, BLOB(HOST_MAC), BLOB(TEST_MAC), ETHER_PROTO_IPV4,
+ 1+BufCount, out_buflens, out_bufs);
+ }
+ else {
+ TEST_WARN("Invalid AF(%i) in IP_Send", AF);
+ }
+}
+
+bool IP_Pkt_Check(size_t len, const void *data, size_t *ofs_out, int AF, const void *Src, const void *Dst, uint8_t proto)
+{
+ size_t ofs;
+ if( AF == 4 ) {
+ if( !Link_Pkt_Check(len, data, &ofs, BLOB(TEST_MAC), BLOB(HOST_MAC), ETHER_PROTO_IPV4) )
+ return false;
+
+ tIPv4Hdr hdr;
+ memcpy(&hdr, (const uint8_t*)data + ofs, sizeof(hdr));
+ TEST_ASSERT_REL(hdr.VerLen >> 4, ==, 4);
+
+ return false;
+ }
+ else {
+ TEST_WARN("Invalid AF(%i) in IP_Pkt_Check", AF);
+ return false;
+ }
+}
+
--- /dev/null
+/*
+ */
+#include "common.h"
+#include "net.h"
+#include "link.h"
+#include "test.h"
+#include <stdlib.h>
+#include <string.h>
+
+// === CODE ===
+void Link_Send(int IfNum, const void *Src, const void *Dst, uint16_t Proto,
+ int BufCount, size_t BufLens[], const void *Bufs[])
+{
+ size_t total_len = 6+6+2;
+ for( int i = 0; i < BufCount; i ++ )
+ total_len += BufLens[i];
+ uint8_t *data = malloc(total_len);
+
+ uint8_t *pos = data;
+ memcpy(pos, Dst, 6); pos += 6;
+ memcpy(pos, Src, 6); pos += 6;
+ *(uint16_t*)pos = htons(Proto); pos += 2;
+
+ for( int i = 0; i < BufCount; i ++ )
+ {
+ memcpy(pos, Bufs[i], BufLens[i]);
+ pos += BufLens[i];
+ }
+
+ Net_Send(IfNum, total_len, data);
+
+ free(data);
+}
+
+bool Link_Pkt_Check(size_t len, const void *data, size_t *ofs_out,
+ const void *Src, const void *Dst, uint16_t Proto)
+{
+ const uint8_t *data8 = data;
+ TEST_ASSERT_REL(len, >=, 6+6+2);
+
+ if(Src) TEST_ASSERT( memcmp(data8+0, Src, 6) == 0 );
+ if(Dst) TEST_ASSERT( memcmp(data8+6, Dst, 6) == 0 );
+
+ TEST_ASSERT_REL( ntohs(*(uint16_t*)(data8+12)), ==, Proto );
+
+ *ofs_out = 6+6+2;
+ return true;
+}
+
--- /dev/null
+/*
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "net.h"
+#include "stack.h"
+#include "tests.h"
+#include "test.h"
+#include <stdarg.h>
+#include <unistd.h>
+
+// === PROTOTYPES ===
+ int ParseCommandline(int argc, char *argv[]);
+
+// === GLOBALS ===
+const char *gsTestName;
+
+// === CODE ===
+int main(int argc, char *argv[])
+{
+ if( ParseCommandline(argc, argv) )
+ return 1;
+
+ typedef bool t_test(void);
+ t_test *tests[] = {
+ Test_ARP_Basic,
+ Test_TCP_Basic,
+ NULL
+ };
+
+ // TODO: Move to stack.c
+ FILE *fp;
+ fp = fopen("stdout.txt", "w"); fclose(fp);
+ fp = fopen("stderr.txt", "w"); fclose(fp);
+
+ for(int i = 0; tests[i]; i ++ )
+ {
+ Net_Open(0, "/tmp/acess2net");
+
+ Stack_AddDevice("/tmp/acess2net", (char[]){TEST_MAC});
+ Stack_AddInterface("eth0", 4, (const char[]){TEST_IP}, 24);
+ Stack_AddRoute(4, "\0\0\0\0", 0, (const char[]){HOST_IP});
+ if( Stack_Start("cmdline") )
+ goto teardown;
+
+ if( Net_Receive(0, 1, &argc, 1000) == 0 )
+ goto teardown;
+
+ if( tests[i]() )
+ printf("%s: PASS\n", gsTestName);
+ else
+ printf("%s: FAIL\n", gsTestName);
+
+ teardown:
+ Stack_Kill();
+ Net_Close(0);
+ unlink("/tmp/acess2net");
+ }
+
+ return 0;
+}
+
+void PrintUsage(const char *ProgName)
+{
+ fprintf(stderr, "Usage: %s\n", ProgName);
+}
+
+int ParseCommandline(int argc, char *argv[])
+{
+ const char *progname = argv[0];
+ for( int i = 1; i < argc; i ++ )
+ {
+ const char *arg = argv[i];
+ if( arg[0] != '-' ) {
+ // bare args
+ }
+ else if( arg[1] != '-' ) {
+ // short args
+ }
+ else {
+ // long args
+ if( strcmp(arg, "--help") == 0 ) {
+ PrintUsage(progname);
+ exit(0);
+ }
+ else {
+ fprintf(stderr, "Unknown option: %s\n", arg);
+ PrintUsage(progname);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+void test_setname(const char *name)
+{
+ gsTestName = name;
+}
+
+void test_message(const char *filename, int line, const char *msg, ...)
+{
+ fprintf(stderr, "%s:%i [%s] - ", filename, line, gsTestName);
+ va_list args;
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+}
+
+void test_assertion_fail(const char *filename, int line, const char *fmt, ...)
+{
+ fprintf(stderr, "%s:%i [%s] - ASSERT FAIL ", filename, line, gsTestName);
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+}
+
--- /dev/null
+/*
+ */
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <assert.h>
+#include <sys/select.h>
+#include "net.h"
+
+
+#define CONNECT_TIMEOUT 10*1000
+#define MAX_IFS 4
+
+typedef struct {
+ int FD;
+ socklen_t addrlen;
+ struct sockaddr_un addr;
+} tIf;
+
+// === PROTOTYPES ===
+ int Net_int_Open(const char *Path);
+
+// === GLOBALS ===
+tIf gaInterfaces[MAX_IFS];
+
+// === CODE ===
+int Net_Open(int IfNum, const char *Path)
+{
+ if( IfNum >= MAX_IFS )
+ return 1;
+
+ if(gaInterfaces[IfNum].FD != 0) return 1;
+ gaInterfaces[IfNum].addrlen = sizeof(gaInterfaces[IfNum].addr);
+ gaInterfaces[IfNum].FD = Net_int_Open(Path);
+ return 0;
+}
+
+int Net_int_Open(const char *Path)
+{
+ int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ struct sockaddr_un sa = {AF_UNIX, ""};
+ strcpy(sa.sun_path, Path);
+ unlink(Path);
+ if( bind(fd, (struct sockaddr*)&sa, sizeof(sa)) ) {
+ perror("NetTest_OpenUnix - bind");
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+void Net_Close(int IfNum)
+{
+ assert(IfNum < MAX_IFS);
+ close(gaInterfaces[IfNum].FD);
+ gaInterfaces[IfNum].FD = 0;
+}
+
+bool WaitOnFD(int FD, bool Write, unsigned int Timeout)
+{
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(FD, &fds);
+ struct timeval timeout;
+ timeout.tv_sec = Timeout/1000;
+ timeout.tv_usec = (Timeout%1000) * 1000;
+
+ if( Write )
+ select(FD+1, NULL, &fds, NULL, &timeout);
+ else
+ select(FD+1, &fds, NULL, NULL, &timeout);
+ return FD_ISSET(FD, &fds);
+}
+
+bool Net_int_EnsureConnected(int IfNum)
+{
+ assert(IfNum < MAX_IFS);
+ #if 0
+ if( gaInterface_Clients[IfNum] == 0 )
+ {
+ //if( !WaitOnFD(gaInterface_Servers[IfNum], CONNECT_TIMEOUT) )
+ //{
+ // fprintf(stderr, "ERROR: Client has not connected");
+ // return false;
+ //}
+ gaInterface_Clients[IfNum] = accept(gaInterface_Servers[IfNum], NULL, NULL);
+ if( gaInterface_Clients[IfNum] < 0 ) {
+ perror("Net_int_EnsureConnected - accept");
+ return false;
+ }
+ }
+ #endif
+ return true;
+}
+
+size_t Net_Receive(int IfNum, size_t MaxLen, void *DestBuf, unsigned int Timeout)
+{
+ assert(IfNum < MAX_IFS);
+ tIf *If = &gaInterfaces[IfNum];
+
+ if( Net_int_EnsureConnected(IfNum) && WaitOnFD(If->FD, false, Timeout) )
+ {
+ return recvfrom(If->FD, DestBuf, MaxLen, 0, &If->addr, &If->addrlen);
+ }
+ return 0;
+}
+
+void Net_Send(int IfNum, size_t Length, const void *Buf)
+{
+ assert(IfNum < MAX_IFS);
+ tIf *If = &gaInterfaces[IfNum];
+
+ if( !WaitOnFD(If->FD, true, CONNECT_TIMEOUT) )
+ return ;
+ int rv = sendto(If->FD, Buf, Length, 0, &If->addr, If->addrlen);
+ if( rv < 0 )
+ perror("Net_Send - send");
+}
+
+
--- /dev/null
+/*
+ */
+#define _POSIX_C_SOURCE 200809L
+#include "stack.h"
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include <fcntl.h>
+#include <spawn.h>
+
+#define MAX_ARGS 16
+
+extern char **environ;
+
+// === GLOBALS ===
+pid_t giStack_PID;
+ int giStack_InFD = -1;
+ int giNumStackArgs = 1;
+char *gasStackArgs[MAX_ARGS] = {"nettest",NULL};
+
+// === CODE ===
+void Stack_AddDevice(const char *Ident, const void *MacAddr)
+{
+ Stack_AddArg("-dev");
+ Stack_AddArg("%02x%02x%02x%02x%02x%02x:unix:%s",
+ ((uint8_t*)MacAddr)[0],
+ ((uint8_t*)MacAddr)[1],
+ ((uint8_t*)MacAddr)[2],
+ ((uint8_t*)MacAddr)[3],
+ ((uint8_t*)MacAddr)[4],
+ ((uint8_t*)MacAddr)[5],
+ Ident);
+}
+
+void Stack_AddInterface(const char *Name, int AddrType, const void *Addr, int MaskBits)
+{
+ Stack_AddArg("-ip");
+ switch(AddrType)
+ {
+ case 4:
+ Stack_AddArg("%s,%i.%i.%i.%i/%i", Name,
+ ((uint8_t*)Addr)[0],
+ ((uint8_t*)Addr)[1],
+ ((uint8_t*)Addr)[2],
+ ((uint8_t*)Addr)[3],
+ MaskBits
+ );
+ break;
+ default:
+ assert(AddrType == 4);
+ exit(1);
+ }
+}
+
+void Stack_AddRoute(int Type, const void *Network, int MaskBits, const void *NextHop)
+{
+}
+
+void Stack_AddArg(const char *Fmt, ...)
+{
+ va_list args;
+ va_start(args, Fmt);
+ size_t len = vsnprintf(NULL, 0, Fmt, args);
+ va_end(args);
+ char *arg = malloc(len+1);
+ va_start(args, Fmt);
+ vsnprintf(arg, len+1, Fmt, args);
+ va_end(args);
+ gasStackArgs[giNumStackArgs++] = arg;
+}
+
+void sigchld_handler(int signum)
+{
+ int status;
+ wait(&status);
+ fprintf(stderr, "FAILURE: Child exited (%i)\n", status);
+}
+
+int Stack_Start(const char *Subcommand)
+{
+ Stack_AddArg(Subcommand);
+
+ for( int i = 3; i < 16; i ++ )
+ fcntl(i, F_SETFD, FD_CLOEXEC);
+
+ //signal(SIGCHLD, sigchld_handler);
+
+ int fds_in[2];
+ pipe(fds_in);
+ giStack_InFD = fds_in[1];
+ fcntl(giStack_InFD, F_SETFD, FD_CLOEXEC);
+
+ FILE *fp;
+ fp = fopen("stdout.txt", "a"); fprintf(fp, "--- Startup\n"); fclose(fp);
+ fp = fopen("stderr.txt", "a"); fprintf(fp, "--- Startup\n"); fclose(fp);
+
+ posix_spawn_file_actions_t fa;
+ posix_spawn_file_actions_init(&fa);
+ posix_spawn_file_actions_adddup2(&fa, fds_in[0], 0);
+ posix_spawn_file_actions_addopen(&fa, 1, "stdout.txt", O_CREAT|O_APPEND|O_WRONLY, 0644);
+ posix_spawn_file_actions_addopen(&fa, 2, "stderr.txt", O_CREAT|O_APPEND|O_WRONLY, 0644);
+
+ int rv = posix_spawn(&giStack_PID, "./nettest", &fa, NULL, gasStackArgs, environ);
+ if(rv) {
+ giStack_PID = 0;
+ fprintf(stderr, "posix_spawn failed: %s", strerror(rv));
+ return 1;
+ }
+
+ return 0;
+}
+void Stack_Kill(void)
+{
+ if( giStack_PID )
+ {
+ kill(giStack_PID, SIGTERM);
+ giStack_PID = 0;
+ }
+}
+
+int Stack_SendCommand(const char *CommandString)
+{
+ write(giStack_InFD, CommandString, strlen(CommandString));
+ write(giStack_InFD, "\n", 1);
+ return 0;
+}
+
--- /dev/null
+/*
+ */
+#include "common.h"
+#include "tcp.h"
+#include "ip.h"
+#include "test.h" // TEST_ASSERT
+#include <string.h>
+
+typedef struct {
+ uint16_t SPort;
+ uint16_t DPort;
+ uint32_t Seq;
+ uint32_t Ack;
+ uint8_t DataOfs;
+ uint8_t Flags;
+ uint16_t Window;
+ uint16_t Checksum;
+ uint16_t UrgPtr;
+} __attribute__((packed)) tTCPHeader;
+
+// === CODE ===
+void TCP_Send(int IF, int AF, const void *IP, short sport, short dport,
+ uint32_t seq, uint32_t ack, uint8_t flags, uint16_t window,
+ size_t data_len, const void *data
+ )
+{
+ tTCPHeader hdr;
+ hdr.SPort = htons(sport);
+ hdr.DPort = htons(dport);
+ hdr.Seq = htonl(seq);
+ hdr.Ack = htonl(ack);
+ hdr.DataOfs = sizeof(hdr)/4;
+ hdr.Flags = flags;
+ hdr.Window = htons(window);
+ hdr.Checksum = htons(0);
+ hdr.UrgPtr = htons(0);
+
+ uint16_t checksum = IP_CHECKSUM_START;
+ checksum = IP_Checksum(checksum, sizeof(hdr), &hdr);
+ checksum = IP_Checksum(checksum, data_len, data);
+ hdr.Checksum = htons( checksum );
+
+ size_t buflens[] = {sizeof(hdr), data_len};
+ const void *bufs[] = {&hdr, data};
+ IP_Send(IF, AF, BLOB(HOST_IP), IP, IPPROTO_TCP, 2, buflens, bufs);
+}
+
+bool TCP_Pkt_Check(size_t len, const void *data, size_t *out_ofs, int AF, const void *IP, short sport, short dport,
+ uint8_t flags)
+{
+ size_t ofs;
+ if( !IP_Pkt_Check(len, data, &ofs, AF, IP, BLOB(HOST_IP), IPPROTO_TCP) )
+ return false;
+
+ tTCPHeader hdr;
+ TEST_ASSERT_REL(len - ofs, >=, sizeof(hdr));
+ memcpy(&hdr, (char*)data + ofs, sizeof(hdr));
+
+ TEST_ASSERT_REL( ntohs(hdr.SPort), ==, sport );
+ TEST_ASSERT_REL( ntohs(hdr.DPort), ==, dport );
+ // TODO: Checks on Seq/Ack
+ TEST_ASSERT_REL( hdr.Flags, ==, flags);
+
+ uint16_t real_cksum = htons(hdr.Checksum);
+ hdr.Checksum = 0;
+ uint16_t calc_cksum = IP_CHECKSUM_START;
+ calc_cksum = IP_Checksum(calc_cksum, sizeof(hdr), &hdr);
+ calc_cksum = IP_Checksum(calc_cksum, len - ofs - sizeof(hdr), (char*)data+ofs+sizeof(hdr));
+ TEST_ASSERT_REL( real_cksum, ==, calc_cksum );
+
+ *out_ofs = ofs + sizeof(hdr);
+ return true;
+}
+
--- /dev/null
+/*
+ */
+#include "test.h"
+#include "tests.h"
+#include "net.h"
+#include "stack.h"
+#include "arp.h"
+
+bool Test_ARP_Basic(void)
+{
+ TEST_SETNAME(__func__);
+ size_t rxlen;
+ char rxbuf[MTU];
+
+ // Request test machine's IP
+ ARP_SendRequest(0, BLOB(TEST_IP));
+ TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) );
+ TEST_ASSERT( ARP_Pkt_IsResponse(rxlen, rxbuf, BLOB(TEST_IP), BLOB(TEST_MAC)) );
+
+ // Request host machine's IP
+ ARP_SendRequest(0, HOST_IP_STR);
+ TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) == 0 );
+
+ #if 0
+ // Ask test machine to request our IP
+ Stack_SendCommand("arprequest "HOST_IP_STR);
+ TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) );
+ TEST_ASSERT( ARP_Pkt_IsRequest(rxlen, rxbuf, HOST_IP) );
+
+ // Respond
+ ARP_SendResponse(0, HOST_IP, HOST_MAC);
+
+ // Ask test machine to request our IP again (expecting nothing)
+ Stack_SendCommand("arprequest "HOST_IP_STR);
+ TEST_ASSERT( !Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) );
+ #endif
+
+ return true;
+}
--- /dev/null
+/*
+ */
+#include "test.h"
+#include "tests.h"
+#include "net.h"
+#include "stack.h"
+#include "arp.h"
+#include "tcp.h"
+
+bool Test_TCP_Basic(void)
+{
+ TEST_SETNAME(__func__);
+ size_t rxlen, ofs;
+ char rxbuf[MTU];
+
+ // 1. Test connection to closed port
+ uint32_t seq_tx = 0x1000;
+ uint32_t seq_exp = 0;
+ TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN, 0x1000, 0, NULL);
+
+ TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, 1000) );
+ TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, TCP_RST) );
+ TEST_ASSERT_REL(ofs, ==, rxlen);
+
+ return true;
+}
# 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/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
-KOBJ += utf16.o
+KOBJ += mutex.o rwlock.o semaphore.o events.o
+KOBJ += utf16.o lib.o
NOBJ := $(NOBJ:%.o=obj/%.o)
LOBJ := $(LOBJ:%.o=obj/%.o)
#define STR(x) #x
#define EXPAND_STR(x) STR(x)
-#define ASSERT(x) do{}while(0)
-
extern char __buildnum[];
#define BUILD_NUM ((int)(Uint)&__buildnum)
extern const char gsGitHash[];
#define BITS 32
#define NULL ((void*)0)
#include <stdint.h>
+#include <stdbool.h>
typedef uintptr_t Uint;
//typedef unsigned int size_t;
typedef uint32_t tUID;
typedef uint32_t tGID;
typedef uint32_t tTID;
+typedef uint32_t tPGID;
typedef int64_t tTime;
extern tTime now(void);
extern char *strdup(const char *str);
#include <errno.h>
-#include <acess_logging.h>
+//#include <acess_logging.h>
+#include <logdebug.h>
+
+extern void Debug_TraceEnter(const char *Function, const char *Format, ...);
+extern void Debug_TraceLog(const char *Function, const char *Format, ...);
+extern void Debug_TraceLeave(const char *Function, char Type, ...);
+#undef ENTER
+#undef LOG
+#undef LEAVE
+#undef LEAVE_RET
+#if DEBUG
+# define ENTER(str, v...) Debug_TraceEnter(__func__, str, ##v)
+# define LOG(fmt, v...) Debug_TraceLog(__func__, fmt, ##v)
+# define LEAVE(t, v...) Debug_TraceLeave(__func__, t, ##v)
+# define LEAVE_RET(t,v) do{LEAVE('-');return v;}while(0)
+#else
+# define ENTER(...) do{}while(0)
+# define LOG(...) do{}while(0)
+# define LEAVE(...) do{}while(0)
+# define LEAVE_RET(t,v) do{return v;}while(0)
+#endif
// Threads
extern void **Threads_GetHandlesPtr(void);
tShortSpinlock IsLocked;
- uint32_t PendingEvents;
+ uint32_t EventState;
uint32_t WaitingEvents;
tThreadIntSem *WaitSemaphore; // pthreads
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 int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock);
+extern void Semaphore_ForceWake(tThread *Thread);
extern tThreadIntMutex *Threads_int_MutexCreate(void);
extern void Threads_int_MutexDestroy(tThreadIntMutex *Mutex);
#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) {\
+#define LOG_LOCK_ACQUIRE() do{ \
if(!gbThreadInLog) SHORTLOCK(&glDebugLock); \
gbThreadInLog ++; \
+}while(0)
+#define LOG_LOCK_RELEASE() do {\
+ gbThreadInLog --; \
+ if(!gbThreadInLog) SHORTREL(&glDebugLock); \
+} while(0)
+
+#define PUTERR(col,type) {\
+ LOG_LOCK_ACQUIRE(); \
LOGHDR(col,type);\
va_list args; va_start(args, Message);\
vfprintf(stderr, Message, args);\
va_end(args);\
LOGTAIL();\
- gbThreadInLog --; \
- if(!gbThreadInLog) SHORTREL(&glDebugLock); \
+ LOG_LOCK_RELEASE(); \
}
// === GLOBALS ===
const char *Ident = "";
PUTERR("37", "L")
}
+void Debug(const char *Message, ...) {
+ const char *Ident = "";
+ PUTERR("38", "D")
+}
void Debug_HexDump(const char *Prefix, const void *Data, size_t Length)
{
const uint8_t *data = Data;
size_t ofs;
+ LOG_LOCK_ACQUIRE();
fprintf(stderr, "[HexDump ]d %s: %i bytes\n", Prefix, (int)Length);
for( ofs = 0; ofs + 16 <= Length; ofs += 16 )
{
fprintf(stderr, " %02x", data[ofs%16]);
}
fprintf(stderr, "\n");
+ LOG_LOCK_RELEASE();
}
int giDebug_TraceLevel = 0;
void Debug_TraceEnter(const char *Function, const char *Format, ...)
{
const char *Ident = "Trace";
+ LOG_LOCK_ACQUIRE();
LOGHDR("37","T");
for( int i = 0; i < giDebug_TraceLevel; i ++ )
fprintf(stderr, " ");
fprintf(stderr, ")");
LOGTAIL();
giDebug_TraceLevel ++;
+ LOG_LOCK_RELEASE();
}
void Debug_TraceLog(const char *Function, const char *Format, ...)
{
const char *Ident = "Trace";
+ LOG_LOCK_ACQUIRE();
LOGHDR("37","T");
for( int i = 0; i < giDebug_TraceLevel; i ++ )
va_end(args);
LOGTAIL();
+ LOG_LOCK_RELEASE();
}
void Debug_TraceLeave(const char *Function, char Type, ...)
}
const char *Ident = "Trace";
+ LOG_LOCK_ACQUIRE();
LOGHDR("37","T");
va_list args;
va_end(args);
LOGTAIL();
+ LOG_LOCK_RELEASE();
}
#include <acess.h>
#include <threads.h>
#include <threads_int.h>
+#include <mutex.h>
// === PROTOTYPES ===
void Threads_int_Init(void) __attribute__((constructor(101)));
return lpThreads_This;
}
-void Threads_PostEvent(tThread *Thread, Uint32 Events)
-{
- if( !Thread ) {
- // nope.avi
- return ;
- }
- SHORTLOCK( &Thread->IsLocked );
- Thread->PendingEvents |= Events;
- if( Thread->WaitingEvents & Events )
- Threads_int_SemSignal(Thread->WaitSemaphore);
- SHORTREL( &Thread->IsLocked );
-}
-
-Uint32 Threads_WaitEvents(Uint32 Events)
-{
- if( !Threads_int_ThreadingEnabled() ) {
- Log_Notice("Threads", "_WaitEvents: Threading disabled");
- return 0;
- }
- lpThreads_This->WaitingEvents = Events;
- Threads_int_SemWaitAll(lpThreads_This->WaitSemaphore);
- lpThreads_This->WaitingEvents = 0;
- Uint32 rv = lpThreads_This->PendingEvents;
- return rv;
-}
-
-void Threads_ClearEvent(Uint32 Mask)
-{
- if( !Threads_int_ThreadingEnabled() ) {
- Log_Notice("Threads", "_ClearEvent: Threading disabled");
- return ;
- }
- SHORTLOCK(&lpThreads_This->IsLocked);
- lpThreads_This->PendingEvents &= ~Mask;
- SHORTREL(&lpThreads_This->IsLocked);
-}
-
tUID Threads_GetUID(void) { return 0; }
tGID Threads_GetGID(void) { return 0; }
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 )
}
}
+void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
+{
+ tThread *us = Proc_GetCurThread();
+ assert(Status != THREAD_STAT_ACTIVE);
+ assert(Status != THREAD_STAT_DEAD);
+ LOG("%i(%s) - %i", us->TID, us->ThreadName, Status);
+ while( us->Status == Status )
+ {
+ Threads_int_SemWaitAll(us->WaitSemaphore);
+ if( us->Status == Status )
+ Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state",
+ us, us->TID, us->ThreadName, casTHREAD_STAT[Status]);
+ }
+}
+
+int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
+{
+ tThread *us = Proc_GetCurThread();
+ us->Next = NULL;
+ // - Mark as sleeping
+ us->Status = Status;
+ us->WaitPointer = Ptr;
+ us->RetStatus = Num; // Use RetStatus as a temp variable
+
+ // - Add to waiting
+ if( ListTail ) {
+ if(*ListTail) {
+ (*ListTail)->Next = us;
+ }
+ else {
+ *ListHead = us;
+ }
+ *ListTail = us;
+ }
+ else if(ListHead) {
+ us->Next = *ListHead;
+ *ListHead = us;
+ }
+ else {
+ // nothing
+ }
+
+ if( Lock ) {
+ SHORTREL( Lock );
+ }
+ Threads_int_WaitForStatusEnd(Status);
+ us->WaitPointer = NULL;
+ return us->RetStatus;
+}
+
*
* threads_int.c
* - Internal threading functions
+ *
+ * POSIX Mutex/Semaphore management
+ * Wait state
*/
#include <stddef.h>
#include <stdlib.h>
tThreadIntMutex *Threads_int_MutexCreate(void)
{
- if( pthread_mutex_init )
+ if( Threads_int_ThreadingEnabled() )
{
tThreadIntMutex *ret = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init( (void*)ret, NULL );
if( !Mutex ) {
return ;
}
- if( pthread_mutex_lock )
+ if( Threads_int_ThreadingEnabled() )
{
pthread_mutex_lock( (void*)Mutex );
}
return ;
}
- if( pthread_mutex_unlock )
+ if( Threads_int_ThreadingEnabled() )
{
pthread_mutex_unlock( (void*)Mutex );
}
tThreadIntSem *Threads_int_SemCreate(void)
{
- if( sem_init )
+ if( Threads_int_ThreadingEnabled() )
{
tThreadIntSem *ret = malloc(sizeof(sem_t));
sem_init( (void*)ret, 0, 0 );
void Threads_int_SemSignal(tThreadIntSem *Sem)
{
- if( sem_post )
+ if( Threads_int_ThreadingEnabled() )
{
sem_post( (void*)Sem );
}
void Threads_int_SemWaitAll(tThreadIntSem *Sem)
{
- if( sem_wait )
+ if( Threads_int_ThreadingEnabled() )
{
// TODO: Handle multiples
sem_wait( (void*)Sem );
int Threads_int_CreateThread(tThread *Thread)
{
- if( pthread_create )
+ if( Threads_int_ThreadingEnabled() )
{
pthread_t *pthread = malloc(sizeof(pthread_t));
Thread->ThreadHandle = pthread;
void SHORTLOCK(tShortSpinlock *Lock)
{
- if( !pthread_mutex_init )
- {
- if(*Lock) Log_KernelPanic("---", "Double short lock");
- *Lock = (void*)1;
- }
- else
+ if( Threads_int_ThreadingEnabled() )
{
if( !*Lock ) {
*Lock = malloc(sizeof(pthread_mutex_t));
pthread_mutex_lock(*Lock);
// printf("%p: SHORTLOCK held %p\n", lpThreads_This, __builtin_return_address(0));
}
+ else
+ {
+ if(*Lock) Log_KernelPanic("---", "Double short lock");
+ *Lock = (void*)1;
+ }
}
void SHORTREL(tShortSpinlock *Lock)
{
- if( !pthread_mutex_init )
+ if( Threads_int_ThreadingEnabled() )
{
- if(!*Lock) Log_Notice("---", "Short release when not held");
- *Lock = NULL;
+ pthread_mutex_unlock(*Lock);
+// printf("%p: SHORTLOCK rel\n", lpThreads_This);
}
else
{
- pthread_mutex_unlock(*Lock);
-// printf("%p: SHORTLOCK rel\n", lpThreads_This);
+ if(!*Lock) Log_Notice("---", "Short release when not held");
+ *Lock = NULL;
}
}
int CPU_HAS_LOCK(tShortSpinlock *Lock)
{
- return 0;
+ if( Threads_int_ThreadingEnabled() )
+ {
+ Log_KernelPanic("---", "TODO: CPU_HAS_LOCK with threading enabled");
+ return 0;
+ }
+ else
+ {
+ return 0;
+ }
}
-
*/
#include <acess.h>
#include <timers.h>
+#include <events.h>
// === CODE ===
tTimer *Time_AllocateTimer(tTimerCallback *Callback, void *Argument)
}
+void Time_ScheduleEvent(int Delay)
+{
+ Log_Warning("Time", "TODO: EVENT_TIMER in %ims", Delay);
+}
+
+void Time_Delay(int Delay)
+{
+ Time_ScheduleEvent(Delay);
+ Threads_WaitEvents(THREAD_EVENT_TIMER);
+}
+
Sint64 now(void)
{
// TODO: Translate UNIX time into Acess time