Added a separate thread to Qt trace logger whose job is to just write the logged instructions to disk (when disk logging is enabled only). This allows for bottle necks with disk I/O to not slow down the emulation. Also, buffer 4k blocks before writing to disk to make more efficient.
This commit is contained in:
parent
aa5ce14c06
commit
f146a7f7f1
|
@ -139,7 +139,7 @@ consoleWin_t::consoleWin_t(QWidget *parent)
|
||||||
#else
|
#else
|
||||||
mutex = new QMutex( QMutex::Recursive );
|
mutex = new QMutex( QMutex::Recursive );
|
||||||
#endif
|
#endif
|
||||||
emulatorThread = new emulatorThread_t();
|
emulatorThread = new emulatorThread_t(this);
|
||||||
|
|
||||||
connect(emulatorThread, &QThread::finished, emulatorThread, &QObject::deleteLater);
|
connect(emulatorThread, &QThread::finished, emulatorThread, &QObject::deleteLater);
|
||||||
|
|
||||||
|
@ -3370,7 +3370,8 @@ void consoleWin_t::updatePeriodic(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
emulatorThread_t::emulatorThread_t(void)
|
emulatorThread_t::emulatorThread_t( QObject *parent )
|
||||||
|
: QThread(parent)
|
||||||
{
|
{
|
||||||
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
|
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
|
||||||
pself = 0;
|
pself = 0;
|
||||||
|
|
|
@ -36,7 +36,7 @@ class emulatorThread_t : public QThread
|
||||||
void run( void ) override;
|
void run( void ) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
emulatorThread_t(void);
|
emulatorThread_t( QObject *parent = 0 );
|
||||||
|
|
||||||
void setPriority( QThread::Priority priority );
|
void setPriority( QThread::Priority priority );
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,10 @@ static traceRecord_t *recBuf = NULL;
|
||||||
static int recBufMax = 0;
|
static int recBufMax = 0;
|
||||||
static int recBufHead = 0;
|
static int recBufHead = 0;
|
||||||
static int recBufTail = 0;
|
static int recBufTail = 0;
|
||||||
|
static traceRecord_t *logBuf = NULL;
|
||||||
|
static int logBufMax = 1000000;
|
||||||
|
static int logBufHead = 0;
|
||||||
|
static int logBufTail = 0;
|
||||||
static FILE *logFile = NULL;
|
static FILE *logFile = NULL;
|
||||||
static bool overrunWarningArmed = true;
|
static bool overrunWarningArmed = true;
|
||||||
static TraceLoggerDialog_t *traceLogWindow = NULL;
|
static TraceLoggerDialog_t *traceLogWindow = NULL;
|
||||||
|
@ -311,21 +315,23 @@ TraceLoggerDialog_t::TraceLoggerDialog_t(QWidget *parent)
|
||||||
|
|
||||||
connect(updateTimer, &QTimer::timeout, this, &TraceLoggerDialog_t::updatePeriodic);
|
connect(updateTimer, &QTimer::timeout, this, &TraceLoggerDialog_t::updatePeriodic);
|
||||||
|
|
||||||
updateTimer->start(10); // 100hz
|
updateTimer->start(50); // 20hz
|
||||||
|
|
||||||
|
diskThread = new TraceLogDiskThread_t(this);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
TraceLoggerDialog_t::~TraceLoggerDialog_t(void)
|
TraceLoggerDialog_t::~TraceLoggerDialog_t(void)
|
||||||
{
|
{
|
||||||
updateTimer->stop();
|
updateTimer->stop();
|
||||||
|
|
||||||
traceLogWindow = NULL;
|
|
||||||
logging = 0;
|
logging = 0;
|
||||||
|
msleep(1);
|
||||||
|
diskThread->requestInterruption();
|
||||||
|
diskThread->quit();
|
||||||
|
diskThread->wait( 1000 );
|
||||||
|
|
||||||
|
traceLogWindow = NULL;
|
||||||
|
|
||||||
if (logFile)
|
|
||||||
{
|
|
||||||
fclose(logFile);
|
|
||||||
logFile = NULL;
|
|
||||||
}
|
|
||||||
printf("Trace Logger Window Deleted\n");
|
printf("Trace Logger Window Deleted\n");
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
|
@ -366,16 +372,16 @@ void TraceLoggerDialog_t::updatePeriodic(void)
|
||||||
|
|
||||||
if (logFile && logFileCbox->isChecked())
|
if (logFile && logFileCbox->isChecked())
|
||||||
{
|
{
|
||||||
char line[256];
|
//char line[256];
|
||||||
|
|
||||||
while (recBufHead != recBufTail)
|
//while (recBufHead != recBufTail)
|
||||||
{
|
//{
|
||||||
recBuf[recBufTail].convToText(line);
|
// recBuf[recBufTail].convToText(line);
|
||||||
|
|
||||||
fprintf(logFile, "%s\n", line);
|
// fprintf(logFile, "%s\n", line);
|
||||||
|
|
||||||
recBufTail = (recBufTail + 1) % recBufMax;
|
// recBufTail = (recBufTail + 1) % recBufMax;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -427,17 +433,17 @@ void TraceLoggerDialog_t::toggleLoggingOnOff(void)
|
||||||
pushMsgToLogBuffer("Logging Finished");
|
pushMsgToLogBuffer("Logging Finished");
|
||||||
startStopButton->setText(tr("Start Logging"));
|
startStopButton->setText(tr("Start Logging"));
|
||||||
|
|
||||||
if (logFile)
|
diskThread->requestInterruption();
|
||||||
{
|
diskThread->quit();
|
||||||
fclose(logFile);
|
diskThread->wait(1000);
|
||||||
logFile = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (logFileCbox->isChecked())
|
if (logFileCbox->isChecked())
|
||||||
{
|
{
|
||||||
openLogFile();
|
openLogFile();
|
||||||
|
diskThread->start();
|
||||||
|
msleep(100);
|
||||||
}
|
}
|
||||||
pushMsgToLogBuffer("Log Start");
|
pushMsgToLogBuffer("Log Start");
|
||||||
startStopButton->setText(tr("Stop Logging"));
|
startStopButton->setText(tr("Stop Logging"));
|
||||||
|
@ -1026,12 +1032,15 @@ static void pushToLogBuffer(traceRecord_t &rec)
|
||||||
recBuf[recBufHead] = rec;
|
recBuf[recBufHead] = rec;
|
||||||
recBufHead = (recBufHead + 1) % recBufMax;
|
recBufHead = (recBufHead + 1) % recBufMax;
|
||||||
|
|
||||||
if ( logFile != NULL )
|
if ( logBuf )
|
||||||
{
|
{
|
||||||
|
logBuf[logBufHead] = rec;
|
||||||
|
logBufHead = (logBufHead + 1) % logBufMax;
|
||||||
|
|
||||||
if ( overrunWarningArmed )
|
if ( overrunWarningArmed )
|
||||||
{ // Don't spam with buffer overrun warning messages,
|
{ // Don't spam with buffer overrun warning messages,
|
||||||
// we will print once if this happens.
|
// we will print once if this happens.
|
||||||
if (recBufHead == recBufTail)
|
if (logBufHead == logBufTail)
|
||||||
{
|
{
|
||||||
if ( traceLogWindow )
|
if ( traceLogWindow )
|
||||||
{
|
{
|
||||||
|
@ -2157,3 +2166,88 @@ void QTraceLogView::paintEvent(QPaintEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
|
TraceLogDiskThread_t::TraceLogDiskThread_t( QObject *parent )
|
||||||
|
: QThread(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
TraceLogDiskThread_t::~TraceLogDiskThread_t(void)
|
||||||
|
{
|
||||||
|
printf("Disk Thread Cleanup\n");
|
||||||
|
if (logFile)
|
||||||
|
{
|
||||||
|
fclose(logFile);
|
||||||
|
logFile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( logBuf )
|
||||||
|
{
|
||||||
|
free(logBuf);
|
||||||
|
logBuf = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
void TraceLogDiskThread_t::run(void)
|
||||||
|
{
|
||||||
|
char line[256];
|
||||||
|
char buf[8192];
|
||||||
|
int i,idx=0;
|
||||||
|
|
||||||
|
printf("Trace Log Disk Start\n");
|
||||||
|
|
||||||
|
if ( logFile == NULL )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( logBuf == NULL )
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
size = logBufMax * sizeof(traceRecord_t);
|
||||||
|
|
||||||
|
logBufHead = logBufTail = 0;
|
||||||
|
|
||||||
|
logBuf = (traceRecord_t *)malloc(size);
|
||||||
|
}
|
||||||
|
idx = 0;
|
||||||
|
|
||||||
|
while ( !isInterruptionRequested() )
|
||||||
|
{
|
||||||
|
while (logBufHead != logBufTail)
|
||||||
|
{
|
||||||
|
logBuf[logBufTail].convToText(line);
|
||||||
|
|
||||||
|
i=0;
|
||||||
|
while ( line[i] != 0 )
|
||||||
|
{
|
||||||
|
buf[idx] = line[i]; i++; idx++;
|
||||||
|
}
|
||||||
|
buf[idx] = '\n'; idx++;
|
||||||
|
|
||||||
|
logBufTail = (logBufTail + 1) % logBufMax;
|
||||||
|
|
||||||
|
if ( idx >= 4096 )
|
||||||
|
{
|
||||||
|
fwrite( buf, idx, 1, logFile ); idx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_Delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( idx > 0 )
|
||||||
|
{
|
||||||
|
fwrite( buf, idx, 1, logFile ); idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logFile)
|
||||||
|
{
|
||||||
|
fclose(logFile);
|
||||||
|
logFile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Trace Log Disk Exit\n");
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
|
|
@ -131,6 +131,23 @@ private slots:
|
||||||
void ctxMenuAddSym(void);
|
void ctxMenuAddSym(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TraceLogDiskThread_t : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run( void ) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TraceLogDiskThread_t( QObject *parent = 0 );
|
||||||
|
~TraceLogDiskThread_t(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished(void);
|
||||||
|
};
|
||||||
|
|
||||||
class TraceLoggerDialog_t : public QDialog
|
class TraceLoggerDialog_t : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -139,6 +156,8 @@ public:
|
||||||
TraceLoggerDialog_t(QWidget *parent = 0);
|
TraceLoggerDialog_t(QWidget *parent = 0);
|
||||||
~TraceLoggerDialog_t(void);
|
~TraceLoggerDialog_t(void);
|
||||||
|
|
||||||
|
TraceLogDiskThread_t *diskThread;
|
||||||
|
|
||||||
void showBufferWarning(void);
|
void showBufferWarning(void);
|
||||||
protected:
|
protected:
|
||||||
QTimer *updateTimer;
|
QTimer *updateTimer;
|
||||||
|
|
Loading…
Reference in New Issue