# 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 mode_cmdline.o
+L_OBJ = vfs_shim.o nic.o tcpclient.o tcpserver.o helpers.o cmdline_backend.o
# Native Sources (compiled as usual)
-N_OBJ = main.o tap.o
+N_OBJ = main.o tap.o mode_cmdline.o
# Compilation Options
CFLAGS := -Wall -std=gnu99 -g -Werror -O0 -pthread
--- /dev/null
+/*
+ */
+#define DEBUG 1
+#include "cmdline.h"
+#include "tcpserver.h"
+#include <vfs_ext.h>
+#include <threads.h>
+#include <events.h>
+
+// === PROTOTYES ===
+void Cmdline_Backend_Thread(void *unused);
+
+// === GLOBALS ===
+tThread *gpCmdline_WorkerThread;
+tNetTest_TCPServer *gpCmdline_TCPEchoServer;
+
+// === CODE ===
+void Cmdline_Backend_StartThread(void)
+{
+ ASSERT(!gpCmdline_WorkerThread);
+ gpCmdline_WorkerThread = Proc_SpawnWorker(Cmdline_Backend_Thread, NULL);
+}
+
+void Cmdline_Backend_Thread(void *unused)
+{
+ Threads_SetName("Cmdline Worker");
+ for( ;; )
+ {
+ fd_set rfd, wfd, efd;
+ int max = -1;
+
+ FD_ZERO(&rfd);
+
+ LOG("gpCmdline_TCPEchoServer = %p", gpCmdline_TCPEchoServer);
+ if(gpCmdline_TCPEchoServer)
+ max = MAX(max, NetTest_TCPServer_FillSelect(gpCmdline_TCPEchoServer, &rfd));
+
+ memcpy(&wfd, &rfd, sizeof(rfd));
+ memcpy(&efd, &rfd, sizeof(rfd));
+
+ LOG("max = %i", max);
+ int rv = VFS_Select(max+1, &rfd, &wfd, &efd, NULL, THREAD_EVENT_USER1, true);
+ LOG("rv = %i", rv);
+
+ if(gpCmdline_TCPEchoServer)
+ NetTest_TCPServer_HandleSelect(gpCmdline_TCPEchoServer, &rfd, &wfd, &efd);
+ }
+}
+
+void Cmdline_Backend_StartEchoServer(int Port)
+{
+ if(gpCmdline_TCPEchoServer)
+ {
+ // Oops, two
+ }
+ else
+ {
+ gpCmdline_TCPEchoServer = NetTest_TCPServer_Create(Port);
+ Log_Debug("Cmdline", "Echo Server = %p", gpCmdline_TCPEchoServer);
+ Threads_PostEvent(gpCmdline_WorkerThread, THREAD_EVENT_USER1);
+ }
+}
--- /dev/null
+/*
+ */
+#ifndef _CMDLINE_H_
+#define _CMDLINE_H_
+
+extern void Cmdline_Backend_StartThread(void);
+extern void Cmdline_Backend_StartEchoServer(int Port);
+
+#endif
+
#ifndef _NETTEST_H_
#define _NETTEST_H_
-#include <stddef.h>
+#ifndef NULL
+# include <stddef.h>
+#endif
extern int NativeNic_AddDev(char *Desc);
extern void NetTest_Suite_Cmdline(void);
extern int Net_ParseAddress(const char *String, void *Addr);
+extern int Net_OpenSocket(int AddrType, void *Addr, const char *Filename);
extern int Net_OpenSocket_TCPC(int AddrType, void *Addr, int Port);
#endif
--- /dev/null
+/*
+ */
+#ifndef _TCPSERVER_H_
+#define _TCPSERVER_H_
+
+#include <acess.h>
+#include <vfs_ext.h>
+
+typedef struct sNetTest_TCPServer tNetTest_TCPServer;
+
+extern tNetTest_TCPServer *NetTest_TCPServer_Create(int Port);
+extern void NetTest_TCPServer_Close(tNetTest_TCPServer *Srv);
+extern int NetTest_TCPServer_FillSelect(tNetTest_TCPServer *Srv, fd_set *fds);
+extern void NetTest_TCPServer_HandleSelect(tNetTest_TCPServer *Srv, const fd_set *rfds, const fd_set *wfds, const fd_set *efds);
+
+#endif
+
*/
#include <nettest.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include "cmdline.h"
// === CODE ===
void NetTest_Suite_Cmdline(void)
{
char line[BUFSIZ];
+ Cmdline_Backend_StartThread();
while( fgets(line, sizeof(line)-1, stdin) )
{
- const char *cmd = strtok(line, " ");
+ const char *const sep = " \n\r";
+ const char *cmd = strtok(line, sep);
if(!cmd)
continue;
if( strcmp(cmd, "exit") == 0 ) {
return ;
}
- else if( strcmp(cmd, "request") == 0 ) {
- //const char *addr = strtok(NULL, " ");
+ else if( strcmp(cmd, "tcp_echo_server") == 0 ) {
+ const char *port_str = strtok(NULL, sep);
+ char *end;
+ int port = strtol(port_str, &end, 0);
+ if(*end != '\0') {
+ fprintf(stderr, "ERROR: Port number '%s' not valid\n", port_str);
+ continue ;
+ }
+ Cmdline_Backend_StartEchoServer(port);
+ // TODO: Allow stopping of the server?
}
else {
fprintf(stderr, "ERROR: Unknown command '%s'\n", cmd);
}
}
+
+ // TODO: Tear down backend?
}
+/*
+ * Acess2 Networking Test Suite (NetTest)
+ * - By John Hodge (thePowersGang)
+ *
+ * tcpserver.c
+ * - TCP Client tester
+ */
+#include <vfs.h>
+#include <vfs_ext.h>
+#include <nettest.h>
+#include "tcpserver.h"
+
+#define MAX_CLIENTS 4
+
+struct sNetTest_TCPServer
+{
+ int ServerFD;
+ int nClients;
+ struct sClient {
+ int FD;
+ } Clients[MAX_CLIENTS];
+};
+
+// === CODE ===
+tNetTest_TCPServer *NetTest_TCPServer_Create(int Port)
+{
+ tNetTest_TCPServer *ret;
+ ret = calloc(sizeof(*ret), 1);
+ ret->ServerFD = VFS_Open("/Devices/ip/1/tcps", VFS_OPENFLAG_READ);
+ ASSERT(ret->ServerFD >= 0);
+ VFS_IOCtl(ret->ServerFD, 4, &Port);
+ return ret;
+}
+
+void NetTest_TCPServer_Close(tNetTest_TCPServer *Srv)
+{
+ VFS_Close(Srv->ServerFD);
+ for( int i = 0; i < Srv->nClients; i ++ )
+ {
+ struct sClient *client = &Srv->Clients[i];
+ VFS_Close(client->FD);
+ }
+ free(Srv);
+}
+
+int NetTest_TCPServer_FillSelect(tNetTest_TCPServer *Srv, fd_set *fds)
+{
+ ASSERT(Srv->ServerFD >= 0);
+ int max = -1;
+
+ if( Srv->nClients == MAX_CLIENTS ) {
+ max = Srv->ServerFD;
+ FD_SET(Srv->ServerFD, fds);
+ }
+ for( int i = 0; i < Srv->nClients; i ++ )
+ {
+ int fd = Srv->Clients[i].FD;
+ if( fd > max ) max = fd;
+ FD_SET(fd, fds);
+ }
+ return max;
+}
+
+void NetTest_TCPServer_HandleSelect(tNetTest_TCPServer *Srv, const fd_set *rfds, const fd_set *wfds, const fd_set *efds)
+{
+ if( FD_ISSET(Srv->ServerFD, rfds) )
+ {
+ // New connection!
+ ASSERT(Srv->nClients != MAX_CLIENTS);
+ struct sClient *client = &Srv->Clients[Srv->nClients++];
+ client->FD = VFS_OpenChild(Srv->ServerFD, "", VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);
+ }
+
+ for( int i = 0; i < Srv->nClients; i ++ )
+ {
+ struct sClient *client = &Srv->Clients[i];
+ if( FD_ISSET(client->FD, rfds) )
+ {
+ // RX'd data on client
+ }
+
+ if( FD_ISSET(client->FD, efds) )
+ {
+ // Drop client
+ VFS_Close(client->FD);
+ memmove(client, client+1, (Srv->nClients-i-1) * sizeof(*client));
+ Srv->nClients --;
+ i --; // counteract i++
+ }
+ }
+}
+
extern int Stack_Start(const char *Subcommand);
extern void Stack_Kill(void);
-extern int Stack_SendCommand(const char *CommandString);
+extern int Stack_SendCommand(const char *CommandString, ...);
#endif
#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
+#define TCP_PSH 0x08
+#define TCP_ACK 0x10
+#define TCP_URG 0x20
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);
+
+
+// The following skip the next check of each field
+extern void TCP_SkipCheck_Seq(bool Skip);
+
+extern bool TCP_Pkt_Check(size_t len, const void *data, size_t *ofs, int AF, const void *IP, short sport, short dport, uint32_t seq, uint32_t ack, uint8_t flags);
+
+// - Get a field from a previously validated packet
+extern uint32_t TCP_Pkt_GetSeq(size_t len, const void *data, int AF);
#endif
#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_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(0x%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);
tIPv4Hdr hdr;
memcpy(&hdr, (const uint8_t*)data + ofs, sizeof(hdr));
TEST_ASSERT_REL(hdr.VerLen >> 4, ==, 4);
+ TEST_ASSERT_REL(IP_Checksum(IP_CHECKSUM_START, sizeof(hdr), &hdr), ==, 0);
+
+ TEST_ASSERT_REL(ntohs(hdr.TotalLength), <=, len - ofs);
+ TEST_ASSERT_REL(ntohs(hdr.FragmentInfo), ==, 0);
+
+ TEST_ASSERT_REL(hdr.TTL, >, 1); // >1 because there's no intervening hops
+ TEST_ASSERT_REL(hdr.Protocol, ==, proto);
+
+ TEST_ASSERT( memcmp(hdr.SrcAddr, Src, 4) == 0 );
+ TEST_ASSERT( memcmp(hdr.DstAddr, Dst, 4) == 0 );
- return false;
+ *ofs_out = ofs + (hdr.VerLen & 0xF) * 4;
+ return true;
}
else {
TEST_WARN("Invalid AF(%i) in IP_Pkt_Check", AF);
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 );
+ if(Dst) TEST_ASSERT( memcmp(data8+0, Dst, 6) == 0 );
+ if(Src) TEST_ASSERT( memcmp(data8+6, Src, 6) == 0 );
TEST_ASSERT_REL( ntohs(*(uint16_t*)(data8+12)), ==, Proto );
}
}
-int Stack_SendCommand(const char *CommandString)
+int Stack_SendCommand(const char *Fmt, ...)
{
- write(giStack_InFD, CommandString, strlen(CommandString));
+ va_list args;
+ va_start(args, Fmt);
+ size_t len = vsnprintf(NULL, 0, Fmt, args);
+ va_end(args);
+ char command[len+1];
+ va_start(args, Fmt);
+ vsnprintf(command, len+1, Fmt, args);
+ va_end(args);
+
+ write(giStack_InFD, command, len);
write(giStack_InFD, "\n", 1);
return 0;
}
} __attribute__((packed)) tTCPHeader;
// === CODE ===
+uint16_t TCP_int_GetPseudoHeader(int AF, const void *SrcAddr, const void *DstAddr, uint8_t pctl, size_t Len)
+{
+ if( AF == 4 ) {
+ uint8_t phdr[12];
+ memcpy(phdr+0, SrcAddr, 4);
+ memcpy(phdr+4, DstAddr, 4);
+ phdr[8] = 0;
+ phdr[9] = pctl;
+ *(uint16_t*)(phdr+10) = htons(Len);
+ return IP_Checksum(IP_CHECKSUM_START, 12, phdr);
+ }
+ else {
+ TEST_WARN("TCP unknown AF %i", AF);
+ return 0;
+ }
+}
+
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
hdr.DPort = htons(dport);
hdr.Seq = htonl(seq);
hdr.Ack = htonl(ack);
- hdr.DataOfs = sizeof(hdr)/4;
+ hdr.DataOfs = (sizeof(hdr)/4) << 4;
hdr.Flags = flags;
hdr.Window = htons(window);
hdr.Checksum = htons(0);
hdr.UrgPtr = htons(0);
- uint16_t checksum = IP_CHECKSUM_START;
+ uint16_t checksum;
+ checksum = TCP_int_GetPseudoHeader(AF, BLOB(HOST_IP), IP, IPPROTO_TCP, sizeof(hdr)+data_len);
checksum = IP_Checksum(checksum, sizeof(hdr), &hdr);
checksum = IP_Checksum(checksum, data_len, data);
hdr.Checksum = htons( checksum );
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)
+struct {
+ bool Seq;
+ bool Ack;
+ bool SPort;
+} gTCP_Skips;
+
+void TCP_SkipCheck_Seq(bool Skip) {
+ gTCP_Skips.Seq = Skip;
+}
+
+bool TCP_Pkt_Check(size_t len, const void *data, size_t *out_ofs,
+ int AF, const void *IP, short sport, short dport,
+ uint32_t seq, uint32_t ack, uint8_t flags)
{
size_t ofs;
if( !IP_Pkt_Check(len, data, &ofs, AF, IP, BLOB(HOST_IP), IPPROTO_TCP) )
return false;
+ // TODO: IP has its own length field, use that?
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( hdr.DataOfs >> 4, >=, sizeof(hdr)/4 );
+ if( !gTCP_Skips.SPort ) TEST_ASSERT_REL( ntohs(hdr.SPort), ==, sport );
TEST_ASSERT_REL( ntohs(hdr.DPort), ==, dport );
- // TODO: Checks on Seq/Ack
+ if( !gTCP_Skips.Seq ) TEST_ASSERT_REL( ntohl(hdr.Seq), ==, seq );
+ if( !gTCP_Skips.Ack ) TEST_ASSERT_REL( ntohl(hdr.Ack), ==, ack );
TEST_ASSERT_REL( hdr.Flags, ==, flags);
uint16_t real_cksum = htons(hdr.Checksum);
hdr.Checksum = 0;
- uint16_t calc_cksum = IP_CHECKSUM_START;
+ uint16_t calc_cksum;
+ calc_cksum = TCP_int_GetPseudoHeader(AF, IP, BLOB(HOST_IP), IPPROTO_TCP, len-ofs);
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 );
-
+
+ memset(&gTCP_Skips, 0, sizeof(gTCP_Skips));
+
*out_ofs = ofs + sizeof(hdr);
return true;
}
+uint32_t TCP_Pkt_GetSeq(size_t len, const void *data, int AF) {
+ size_t ofs;
+ IP_Pkt_Check(len, data, &ofs, AF, NULL, NULL, IPPROTO_TCP);
+
+ tTCPHeader hdr;
+ memcpy(&hdr, (char*)data + ofs, sizeof(hdr));
+ return ntohl(hdr.Seq);
+}
+
#include "arp.h"
#include "tcp.h"
+#define TEST_ASSERT_rx() TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) )
+#define TEST_ASSERT_no_rx() TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 )
+
bool Test_TCP_Basic(void)
{
TEST_SETNAME(__func__);
size_t rxlen, ofs;
char rxbuf[MTU];
+ const int ERX_TIMEOUT = 1000; // Expect RX timeout (timeout=failure)
+ const int NRX_TIMEOUT = 1000; // Not expect RX timeout (timeout=success)
+
+ const char testblob[] = "HelloWorld, this is some random testing data for TCP\xFF\x00\x66\x12\x12";
+ const size_t testblob_len = sizeof(testblob);
- // 1. Test connection to closed port
+ // 1. Test packets to closed port
+ // > RFC793 Pg.65
+ const uint16_t our_window = 0x1000;
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);
+ uint32_t seq_exp = 0x33456;
+
+ // 1.1. Send SYN packet
+ TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN, 0x1000, testblob_len, testblob);
+ // Expect a TCP_RST|TCP_ACK with SEQ=0,ACK=SEQ+LEN
+ TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) );
+ TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234,
+ 0, seq_tx+testblob_len, TCP_RST|TCP_ACK) );
+ TEST_ASSERT_REL(ofs, ==, rxlen);
- 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) );
+ // 1.2. Send a SYN,ACK packet
+ TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_SYN|TCP_ACK, 0x1000, 0, NULL);
+ // Expect a TCP_RST with SEQ=ACK
+ TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) );
+ TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, seq_exp, seq_tx+0, TCP_RST) );
TEST_ASSERT_REL(ofs, ==, rxlen);
+ // 1.3. Send a RST packet
+ TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_RST, 0x1000, 0, NULL);
+ // Expect nothing
+ TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 );
+
+ // 1.3. Send a RST,ACK packet
+ TCP_Send(0, 4, BLOB(TEST_IP), 1234, 80, seq_tx, seq_exp, TCP_RST|TCP_ACK, 0x1000, 0, NULL);
+ // Expect nothing
+ TEST_ASSERT_no_rx();
+
+
+ // 2. Establishing connection with a server
+ const int server_port = 1024;
+ const int local_port = 11234;
+ Stack_SendCommand("tcp_echo_server %i", server_port);
+
+ // >>> STATE: LISTEN
+
+ // 2.1. Send RST
+ TCP_Send(0, 4, BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, TCP_RST, our_window, 0, NULL);
+ // - Expect nothing
+ TEST_ASSERT_no_rx();
+ // 2.2. Send ACK
+ TCP_Send(0, 4, BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, TCP_ACK, our_window, 0, NULL);
+ // - Expect RST
+ TEST_ASSERT_rx();
+ TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), 80, 1234, seq_exp, seq_tx+0, TCP_RST) );
+
+ // 2.3. Begin hanshake (SYN)
+ // TODO: "If the SYN bit is set, check the security."
+ TCP_Send(0, 4, BLOB(TEST_IP), local_port, server_port, seq_tx, 0, TCP_SYN, our_window, 0, NULL);
+ // - Expect SYN,ACK with ACK == SEQ+1
+ TEST_ASSERT_rx();
+ TCP_SkipCheck_Seq(true);
+ TEST_ASSERT( TCP_Pkt_Check(rxlen, rxbuf, &ofs, 4, BLOB(TEST_IP), server_port, local_port,
+ 0, seq_tx+1, TCP_SYN|TCP_ACK) );
+ seq_exp = TCP_Pkt_GetSeq(rxlen, rxbuf, 4);
+
+ // >>> STATE: SYN-RECEIVED
+ // TODO: Test other transitions from SYN-RECEIVED
+
+ // 2.4. Complete handshake, TCP ACK
+ TCP_Send(0,4,BLOB(TEST_IP), local_port, server_port, seq_tx, seq_exp, TCP_ACK, our_window, 0, NULL);
+ // - Expect nothing
+ TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 );
+
+ // >>> STATE: ESTABLISHED
+
+ // 2.5. Send data
+
return true;
}
void Debug_TraceEnter(const char *Function, const char *Format, ...)
{
- const char *Ident = "Trace";
LOG_LOCK_ACQUIRE();
- LOGHDR("37","T");
+ //const char *Ident = "Trace";
+ //LOGHDR("37","T");
for( int i = 0; i < giDebug_TraceLevel; i ++ )
fprintf(stderr, " ");
fprintf(stderr, "%s: (", Function);
void Debug_TraceLog(const char *Function, const char *Format, ...)
{
- const char *Ident = "Trace";
LOG_LOCK_ACQUIRE();
- LOGHDR("37","T");
+ //const char *Ident = "Trace";
+ //LOGHDR("37","T");
for( int i = 0; i < giDebug_TraceLevel; i ++ )
fprintf(stderr, " ");
Log_Error("Debug", "Function %s called LEAVE without ENTER", Function);
}
- const char *Ident = "Trace";
LOG_LOCK_ACQUIRE();
- LOGHDR("37","T");
+ //const char *Ident = "Trace";
+ //LOGHDR("37","T");
va_list args;
va_start(args, Type);
* threads.c
* - Threads handling
*/
+#define DEBUG 1
#include <acess.h>
#include <threads.h>
#include <threads_int.h>
{
Thread->Status = THREAD_STAT_ACTIVE;
// Increment state-change semaphore
+ LOG("Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
Threads_int_SemSignal(Thread->WaitSemaphore);
}
Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state",
us, us->TID, us->ThreadName, casTHREAD_STAT[Status]);
}
+ LOG("%p(%i %s) Awake", us, us->TID, us->ThreadName);
}
int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
* POSIX Mutex/Semaphore management
* Wait state
*/
+#define DEBUG 1
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
if( Threads_int_ThreadingEnabled() )
{
// TODO: Handle multiples
+ LOG("Waiting on %p", Sem);
sem_wait( (void*)Sem );
- while( sem_trywait((void*)Sem) )
+ LOG("Wait 1 done, cleaning up");
+ while( sem_trywait((void*)Sem) == 0 )
;
+ LOG("Wait over");
}
else
{