change LocalMP to use separate queue buffers, clean things up (also fix a nasty bug in the process)

This commit is contained in:
Arisotura 2024-06-09 11:40:39 +02:00
parent 15bb45d069
commit 027c93b207
1 changed files with 44 additions and 70 deletions

View File

@ -16,27 +16,10 @@
with melonDS. If not, see http://www.gnu.org/licenses/. with melonDS. If not, see http://www.gnu.org/licenses/.
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __WIN32__
#include <windows.h>
#else
#include <fcntl.h>
#include <semaphore.h>
#include <time.h>
#ifdef __APPLE__
#include "sem_timedwait.h"
#endif
#endif
#include <string> #include <string>
#include <QSharedMemory>
#include <QMutex> #include <QMutex>
#include <QSemaphore> #include <QSemaphore>
#include "Config.h"
#include "LocalMP.h" #include "LocalMP.h"
#include "Platform.h" #include "Platform.h"
@ -69,16 +52,14 @@ struct MPPacketHeader
QMutex MPQueueLock; QMutex MPQueueLock;
MPStatusData MPStatus; MPStatusData MPStatus;
u8* MPQueue = nullptr; u8* MPPacketQueue = nullptr;
u8* MPReplyQueue = nullptr;
u32 PacketReadOffset[16]; u32 PacketReadOffset[16];
u32 ReplyReadOffset[16]; u32 ReplyReadOffset[16];
const u32 kQueueSize = 0x20000; const u32 kPacketQueueSize = 0x10000;
const u32 kMaxFrameSize = 0x800; const u32 kReplyQueueSize = 0x10000;
const u32 kPacketStart = 0; const u32 kMaxFrameSize = 0x948;
const u32 kReplyStart = kQueueSize / 2;
const u32 kPacketEnd = kReplyStart;
const u32 kReplyEnd = kQueueSize;
int RecvTimeout; int RecvTimeout;
@ -119,8 +100,10 @@ bool Init()
{ {
MPQueueLock.lock(); MPQueueLock.lock();
MPQueue = new u8[kQueueSize]; MPPacketQueue = new u8[kPacketQueueSize];
memset(MPQueue, 0, kQueueSize); MPReplyQueue = new u8[kReplyQueueSize];
memset(MPPacketQueue, 0, kPacketQueueSize);
memset(MPReplyQueue, 0, kReplyQueueSize);
memset(&MPStatus, 0, sizeof(MPStatus)); memset(&MPStatus, 0, sizeof(MPStatus));
memset(PacketReadOffset, 0, sizeof(PacketReadOffset)); memset(PacketReadOffset, 0, sizeof(PacketReadOffset));
memset(ReplyReadOffset, 0, sizeof(ReplyReadOffset)); memset(ReplyReadOffset, 0, sizeof(ReplyReadOffset));
@ -144,8 +127,10 @@ bool Init()
void DeInit() void DeInit()
{ {
delete MPQueue; delete MPPacketQueue;
MPQueue = nullptr; delete MPReplyQueue;
MPPacketQueue = nullptr;
MPReplyQueue = nullptr;
} }
void SetRecvTimeout(int timeout) void SetRecvTimeout(int timeout)
@ -155,8 +140,6 @@ void SetRecvTimeout(int timeout)
void Begin(int inst) void Begin(int inst)
{ {
if (!MPQueue) return;
MPQueueLock.lock(); MPQueueLock.lock();
PacketReadOffset[inst] = MPStatus.PacketWriteOffset; PacketReadOffset[inst] = MPStatus.PacketWriteOffset;
ReplyReadOffset[inst] = MPStatus.ReplyWriteOffset; ReplyReadOffset[inst] = MPStatus.ReplyWriteOffset;
@ -168,8 +151,6 @@ void Begin(int inst)
void End(int inst) void End(int inst)
{ {
if (!MPQueue) return;
MPQueueLock.lock(); MPQueueLock.lock();
MPStatus.ConnectedBitmask &= ~(1 << inst); MPStatus.ConnectedBitmask &= ~(1 << inst);
MPQueueLock.unlock(); MPQueueLock.unlock();
@ -177,28 +158,28 @@ void End(int inst)
void FIFORead(int inst, int fifo, void* buf, int len) void FIFORead(int inst, int fifo, void* buf, int len)
{ {
u8* data = MPQueue; u8* data;
u32 offset, start, end; u32 offset, datalen;
if (fifo == 0) if (fifo == 0)
{ {
offset = PacketReadOffset[inst]; offset = PacketReadOffset[inst];
start = kPacketStart; data = MPPacketQueue;
end = kPacketEnd; datalen = kPacketQueueSize;
} }
else else
{ {
offset = ReplyReadOffset[inst]; offset = ReplyReadOffset[inst];
start = kReplyStart; data = MPReplyQueue;
end = kReplyEnd; datalen = kReplyQueueSize;
} }
if ((offset + len) >= end) if ((offset + len) >= datalen)
{ {
u32 part1 = end - offset; u32 part1 = datalen - offset;
memcpy(buf, &data[offset], part1); memcpy(buf, &data[offset], part1);
memcpy(&((u8*)buf)[part1], &data[start], len - part1); memcpy(&((u8*)buf)[part1], data, len - part1);
offset = start + len - part1; offset = len - part1;
} }
else else
{ {
@ -212,28 +193,28 @@ void FIFORead(int inst, int fifo, void* buf, int len)
void FIFOWrite(int inst, int fifo, void* buf, int len) void FIFOWrite(int inst, int fifo, void* buf, int len)
{ {
u8* data = MPQueue; u8* data;
u32 offset, start, end; u32 offset, datalen;
if (fifo == 0) if (fifo == 0)
{ {
offset = MPStatus.PacketWriteOffset; offset = MPStatus.PacketWriteOffset;
start = kPacketStart; data = MPPacketQueue;
end = kPacketEnd; datalen = kPacketQueueSize;
} }
else else
{ {
offset = MPStatus.ReplyWriteOffset; offset = MPStatus.ReplyWriteOffset;
start = kReplyStart; data = MPReplyQueue;
end = kReplyEnd; datalen = kReplyQueueSize;
} }
if ((offset + len) >= end) if ((offset + len) >= datalen)
{ {
u32 part1 = end - offset; u32 part1 = datalen - offset;
memcpy(&data[offset], buf, part1); memcpy(&data[offset], buf, part1);
memcpy(&data[start], &((u8*)buf)[part1], len - part1); memcpy(data, &((u8*)buf)[part1], len - part1);
offset = start + len - part1; offset = len - part1;
} }
else else
{ {
@ -247,7 +228,12 @@ void FIFOWrite(int inst, int fifo, void* buf, int len)
int SendPacketGeneric(int inst, u32 type, u8* packet, int len, u64 timestamp) int SendPacketGeneric(int inst, u32 type, u8* packet, int len, u64 timestamp)
{ {
if (!MPQueue) return 0; if (len > kMaxFrameSize)
{
Log(LogLevel::Warn, "wifi: attempting to send frame too big (len=%d max=%d)\n", len, kMaxFrameSize);
return 0;
}
MPQueueLock.lock(); MPQueueLock.lock();
u16 mask = MPStatus.ConnectedBitmask; u16 mask = MPStatus.ConnectedBitmask;
@ -301,7 +287,6 @@ int SendPacketGeneric(int inst, u32 type, u8* packet, int len, u64 timestamp)
int RecvPacketGeneric(int inst, u8* packet, bool block, u64* timestamp) int RecvPacketGeneric(int inst, u8* packet, bool block, u64* timestamp)
{ {
if (!MPQueue) return 0;
for (;;) for (;;)
{ {
if (!SemWait(inst, block ? RecvTimeout : 0)) if (!SemWait(inst, block ? RecvTimeout : 0))
@ -327,8 +312,8 @@ int RecvPacketGeneric(int inst, u8* packet, bool block, u64* timestamp)
{ {
// skip this packet // skip this packet
PacketReadOffset[inst] += pktheader.Length; PacketReadOffset[inst] += pktheader.Length;
if (PacketReadOffset[inst] >= kPacketEnd) if (PacketReadOffset[inst] >= kPacketQueueSize)
PacketReadOffset[inst] += kPacketStart - kPacketEnd; PacketReadOffset[inst] -= kPacketQueueSize;
MPQueueLock.unlock(); MPQueueLock.unlock();
continue; continue;
@ -376,16 +361,11 @@ int SendAck(int inst, u8* packet, int len, u64 timestamp)
int RecvHostPacket(int inst, u8* packet, u64* timestamp) int RecvHostPacket(int inst, u8* packet, u64* timestamp)
{ {
if (!MPQueue) return -1;
if (LastHostID != -1) if (LastHostID != -1)
{ {
// check if the host is still connected // check if the host is still connected
MPQueueLock.lock();
u8* data = MPQueue;
u16 curinstmask = MPStatus.ConnectedBitmask; u16 curinstmask = MPStatus.ConnectedBitmask;
MPQueueLock.unlock();
if (!(curinstmask & (1 << LastHostID))) if (!(curinstmask & (1 << LastHostID)))
return -1; return -1;
@ -396,17 +376,11 @@ int RecvHostPacket(int inst, u8* packet, u64* timestamp)
u16 RecvReplies(int inst, u8* packets, u64 timestamp, u16 aidmask) u16 RecvReplies(int inst, u8* packets, u64 timestamp, u16 aidmask)
{ {
if (!MPQueue) return 0;
u16 ret = 0; u16 ret = 0;
u16 myinstmask = (1 << inst); u16 myinstmask = (1 << inst);
u16 curinstmask; u16 curinstmask;
{ curinstmask = MPStatus.ConnectedBitmask;
//MPQueueLock.lock();
curinstmask = MPStatus.ConnectedBitmask;
//MPQueueLock.unlock();
}
// if all clients have left: return early // if all clients have left: return early
if ((myinstmask & curinstmask) == curinstmask) if ((myinstmask & curinstmask) == curinstmask)
@ -439,8 +413,8 @@ u16 RecvReplies(int inst, u8* packets, u64 timestamp, u16 aidmask)
{ {
// skip this packet // skip this packet
ReplyReadOffset[inst] += pktheader.Length; ReplyReadOffset[inst] += pktheader.Length;
if (ReplyReadOffset[inst] >= kReplyEnd) if (ReplyReadOffset[inst] >= kReplyQueueSize)
ReplyReadOffset[inst] += kReplyStart - kReplyEnd; ReplyReadOffset[inst] -= kReplyQueueSize;
MPQueueLock.unlock(); MPQueueLock.unlock();
continue; continue;