Now have thread safe plugging / unplugging of USBs / serial ports

This commit is contained in:
Peter Slattery 2021-02-20 18:21:52 -08:00
parent 0807abc08e
commit b470a63ec5
8 changed files with 121 additions and 56 deletions

View File

@ -123,7 +123,7 @@ BlumenLumen_CustomInit(app_state* State, context Context)
BLState->MicListenJobData.OutgoingMsgQueue = &BLState->OutgoingMsgQueue;
BLState->MicListenJobData.ListenSocket = CreateSocket(Context.SocketManager, "127.0.0.1", "20185");
BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData);
//BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData);
gs_const_string SculpturePath = ConstString("data/test_blumen.fold");
LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog);

View File

@ -130,11 +130,6 @@ UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assembli
SLLPushOrInit(BuffersNeededHead, BuffersNeededTail, BufferSelected);
BuffersNeededCount += 1;
gs_string Temp = PushStringF(Transient, 256, "Found Com Port: %S\n\tStrip: %d\n", StripAt.UARTAddr.ComPort.ConstString,
StripIdx);
NullTerminate(&Temp);
OutputDebugString(Temp.Str);
}
Assert(BufferSelected->StripIndicesCount < BufferSelected->StripIndicesCountMax);

View File

@ -56,6 +56,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->LedSystem = LedSystem_Create(Context.ThreadContext.Allocator, 128);
State->AssemblyDebugState = AssemblyDebug_Create(&State->Permanent);
State->AssemblyDebugState.Brightness = 255;
State->AssemblyDebugState.Override = ADS_Override_AllRed;
GlobalDebugServices->Interface.RenderSculpture = true;

View File

@ -404,6 +404,10 @@ Win32_SendAddressedDataBuffer(gs_thread_context Context, addressed_data_buffer*
BuffersSent += 1;
DataSizeSent += BufferAt->Data.Size;
}
else
{
Win32SerialArray_Close(BufferAt->ComPort);
}
}
}
else
@ -497,7 +501,7 @@ WinMain (
*Context.ThreadManager = CreatePlatformThreadManager(Win32CreateThread, Win32KillThread);
Context.SocketManager = PushStruct(&PlatformPermanent, platform_socket_manager);
*Context.SocketManager = CreatePlatformSocketManager(Win32CreateSocket, Win32CloseSocket, Win32SocketQueryStatus, Win32SocketPeek, Win32SocketReceive, Win32SocketSend);
*Context.SocketManager = CreatePlatformSocketManager(Win32ConnectSocket, Win32CloseSocket, Win32SocketQueryStatus, Win32SocketPeek, Win32SocketReceive, Win32SocketSend);
win32_dll_refresh DLLRefresh = InitializeDLLHotReloading(DLLName, WorkingDLLName, DLLLockFileName);
if (!ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, true)) { return -1; }
@ -546,7 +550,7 @@ WinMain (
Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData);
bool Multithread = true;
bool Multithread = false;
if (Multithread)
{
for (addressed_data_buffer* At = OutputData.Root;

View File

@ -6,9 +6,9 @@
#ifndef WIN32_SERIAL_H
global u32 Win32SerialHandlesCountMax;
global u32 Win32SerialHandlesCount;
global HANDLE* Win32SerialHandles;
global gs_string* Win32SerialPortNames;
global s32* Win32SerialPortFilled;
DCB
Win32SerialPort_GetState(HANDLE ComPortHandle)
@ -137,7 +137,18 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer)
{
OutputDebugStringA("Error: Unable to write to port\n");
s32 Error = GetLastError();
//InvalidCodePath;
switch (Error)
{
case ERROR_OPERATION_ABORTED:
case ERROR_GEN_FAILURE:
{
// NOTE(pjs): Probably means that the serial port became invalid
// ie. the usb stick was removed
}break;
case ERROR_INVALID_HANDLE:
InvalidDefaultCase;
}
}
return Success;
@ -183,12 +194,15 @@ Win32SerialArray_Create(gs_thread_context Context)
DEBUG_TRACK_FUNCTION;
Win32SerialHandlesCountMax = 32;
Win32SerialHandlesCount = 0;
Win32SerialHandles = AllocatorAllocArray(Context.Allocator, HANDLE, Win32SerialHandlesCountMax);
Win32SerialPortNames = AllocatorAllocArray(Context.Allocator, gs_string, Win32SerialHandlesCountMax);
Win32SerialPortFilled = AllocatorAllocArray(Context.Allocator, s32, Win32SerialHandlesCountMax);
for (u32 i = 0; i < Win32SerialHandlesCountMax; i++)
{
Win32SerialPortNames[i] = AllocatorAllocString(Context.Allocator, 256);
Win32SerialPortFilled[i] = 0;
}
}
@ -197,10 +211,28 @@ Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName)
{
DEBUG_TRACK_FUNCTION;
Assert(Win32SerialHandlesCount < Win32SerialHandlesCountMax);
u32 Index = Win32SerialHandlesCount++;
Win32SerialHandles[Index] = SerialHandle;
PrintF(&Win32SerialPortNames[Index], "%S", PortName);
bool Found = false;
for (u32 i = 0; i < Win32SerialHandlesCountMax; i++)
{
bool WasFilled = InterlockedCompareExchange((LONG volatile*)Win32SerialPortFilled + i, 1, 0);
if (!WasFilled)
{
Win32SerialHandles[i] = SerialHandle;
PrintF(&Win32SerialPortNames[i], "%S", PortName);
Found = true;
break;
}
}
Assert(Found);
}
void
Win32SerialArray_Pop(u32 Index)
{
bool WasFilled = InterlockedCompareExchange((LONG volatile*)Win32SerialPortFilled + Index, 0, 1);
Assert(WasFilled);
Win32SerialPortFilled[Index] = false;
Win32SerialHandles[Index] = INVALID_HANDLE_VALUE;
}
HANDLE
@ -209,9 +241,10 @@ Win32SerialArray_Get(gs_const_string PortName)
DEBUG_TRACK_FUNCTION;
HANDLE PortHandle = INVALID_HANDLE_VALUE;
for (u32 i = 0; i < Win32SerialHandlesCount; i++)
for (u32 i = 0; i < Win32SerialHandlesCountMax; i++)
{
if (StringsEqual(Win32SerialPortNames[i].ConstString, PortName))
if (Win32SerialPortFilled[i] &&
StringsEqual(Win32SerialPortNames[i].ConstString, PortName))
{
PortHandle = Win32SerialHandles[i];
break;
@ -239,5 +272,19 @@ Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize,
return PortHandle;
}
void
Win32SerialArray_Close(gs_const_string PortName)
{
for (u32 i = 0; i < Win32SerialHandlesCountMax; i++)
{
if (Win32SerialPortFilled[i] && StringsEqual(Win32SerialPortNames[i].ConstString, PortName))
{
Win32SerialPort_Close(Win32SerialHandles[i]);
Win32SerialArray_Pop(i);
break;
}
}
}
#define WIN32_SERIAL_H
#endif // WIN32_SERIAL_H

View File

@ -132,7 +132,7 @@ Win32Socket_ConnectToAddress(char* Address, char* DefaultPort)
}
internal bool
Win32CreateSocket(platform_socket* Socket, char* Address, char* DefaultPort)
Win32ConnectSocket(platform_socket* Socket)
{
bool Result = false;
@ -142,7 +142,7 @@ Win32CreateSocket(platform_socket* Socket, char* Address, char* DefaultPort)
Hints.ai_protocol = IPPROTO_TCP;
addrinfo* PotentialConnections;
s32 Error = getaddrinfo(Address, DefaultPort, &Hints, &PotentialConnections);
s32 Error = getaddrinfo(Socket->Addr, Socket->Port, &Hints, &PotentialConnections);
if (Error == 0)
{
for (addrinfo* InfoAt = PotentialConnections; InfoAt != NULL; InfoAt = InfoAt->ai_next)
@ -175,7 +175,7 @@ Win32CreateSocket(platform_socket* Socket, char* Address, char* DefaultPort)
FD_ZERO(&SocketSet);
FD_SET(SocketHandle, &SocketSet);
Assert(FD_ISSET(SocketHandle, &SocketSet));
Status = select(0, &SocketSet, 0, 0, {});
Status = select(0, &SocketSet, 0, 0, (const TIMEVAL*)&Timeout);
if (Status == SOCKET_ERROR)
{
@ -196,7 +196,6 @@ Win32CreateSocket(platform_socket* Socket, char* Address, char* DefaultPort)
}
}
Socket->PlatformHandle = (u8*)Win32Alloc(sizeof(SOCKET), 0);
*(SOCKET*)Socket->PlatformHandle = SocketHandle;
Result = true;
@ -429,17 +428,17 @@ Win32Socket_Receive(win32_socket* Socket, gs_memory_arena* Storage)
{
// TODO(pjs): Error logging
s32 Error = WSAGetLastError();
if (Error == 10053)
switch (Error)
{
// WSAECONNABORTED - aborted by the software
}
else if (Error == 10093)
{
// WSANOTINITIALISED
}
else
{
InvalidCodePath;
case WSAECONNABORTED:
case WSANOTINITIALISED:
break;
case WSAENOTCONN:
{
}break;
InvalidDefaultCase;
}
}
Result.Size = BytesReceived;

View File

@ -3349,7 +3349,7 @@ KillThread(platform_thread_manager* Manager, platform_thread_handle Handle)
//
// Socket Manager
CREATE_SOCKET(PlatformCreateSocket_Stub)
CONNECT_SOCKET(PlatformConnectSocket_Stub)
{
return false;
}
@ -3380,7 +3380,7 @@ SOCKET_SEND(PlatformSocketSend_Stub)
}
internal platform_socket_manager
CreatePlatformSocketManager(platform_create_socket* CreateSocketProc,
CreatePlatformSocketManager(platform_connect_socket* ConnectSocketProc,
platform_close_socket* CloseSocketProc,
platform_socket_query_status* SocketQueryStatusProc,
platform_socket_peek* SocketPeekProc,
@ -3388,16 +3388,16 @@ CreatePlatformSocketManager(platform_create_socket* CreateSocketProc,
platform_socket_send* SocketSendProc)
{
platform_socket_manager Result = {};
Result.CreateSocketProc = CreateSocketProc;
Result.ConnectSocketProc = ConnectSocketProc;
Result.CloseSocketProc = CloseSocketProc;
Result.SocketQueryStatusProc = SocketQueryStatusProc;
Result.SocketPeekProc = SocketPeekProc;
Result.SocketRecieveProc = SocketRecieveProc;
Result.SocketSendProc = SocketSendProc;
if (!CreateSocketProc)
if (!ConnectSocketProc)
{
Result.CreateSocketProc = PlatformCreateSocket_Stub;
Result.ConnectSocketProc = PlatformConnectSocket_Stub;
}
if (!CloseSocketProc)
{
@ -3422,6 +3422,33 @@ CreatePlatformSocketManager(platform_create_socket* CreateSocketProc,
return Result;
}
internal platform_socket*
SocketManagerGetSocket(platform_socket_manager* Manager, platform_socket_handle_ Handle)
{
platform_socket* Result = 0;
if (Manager->SocketsUsed[Handle.Index])
{
platform_socket* Socket = &Manager->Sockets[Handle.Index];
if (Socket->PlatformHandle != 0)
{
Result = Socket;
}
}
return Result;
}
internal bool
ConnectSocket(platform_socket_manager* Manager, platform_socket_handle_ Handle)
{
bool Result = false;
platform_socket* Socket = SocketManagerGetSocket(Manager, Handle);
if (Socket)
{
Result = Manager->ConnectSocketProc(Socket);
}
return Result;
}
internal platform_socket_handle_
CreateSocket(platform_socket_manager* Manager, char* Addr, char* Port)
{
@ -3438,23 +3465,12 @@ CreateSocket(platform_socket_manager* Manager, char* Addr, char* Port)
Assert(Result.Index != 0);
platform_socket* Socket = &Manager->Sockets[Result.Index];
Manager->CreateSocketProc(Socket, Addr, Port);
CopyArray(Addr, Socket->Addr, char, CStringLength(Addr) + 1);
CopyArray(Port, Socket->Port, char, CStringLength(Port) + 1);
return Result;
}
bool Success = Manager->ConnectSocketProc(Socket);
Assert(Success);
internal platform_socket*
SocketManagerGetSocket(platform_socket_manager* Manager, platform_socket_handle_ Handle)
{
platform_socket* Result = 0;
if (Manager->SocketsUsed[Handle.Index])
{
platform_socket* Socket = &Manager->Sockets[Handle.Index];
if (Socket->PlatformHandle != 0)
{
Result = Socket;
}
}
return Result;
}

View File

@ -575,7 +575,8 @@ CStringLength(char* Str)
{
char* At = Str;
while (*At) { At++; }
return PointerDifference(At, Str);
u64 Result = PointerDifference(At, Str);
return Result;
}
#define StringExpand(str) (int)(str).Length, (str).Str
@ -1095,11 +1096,13 @@ typedef struct platform_socket_handle_
typedef struct platform_socket
{
char Addr[128];
char Port[32];
u8* PlatformHandle;
} platform_socket;
#define CREATE_SOCKET(name) bool name(platform_socket* Socket, char* Addr, char* DefaultPort)
typedef CREATE_SOCKET(platform_create_socket);
#define CONNECT_SOCKET(name) bool name(platform_socket* Socket)
typedef CONNECT_SOCKET(platform_connect_socket);
#define CLOSE_SOCKET(name) bool name(platform_socket* Socket)
typedef CLOSE_SOCKET(platform_close_socket);
@ -1126,7 +1129,7 @@ typedef struct platform_socket_manager
b8 SocketsUsed[SOCKETS_COUNT_MAX];
platform_socket Sockets[SOCKETS_COUNT_MAX];
platform_create_socket* CreateSocketProc;
platform_connect_socket* ConnectSocketProc;
platform_close_socket* CloseSocketProc;
platform_socket_query_status* SocketQueryStatusProc;
platform_socket_peek* SocketPeekProc;