From 6f1b4767164c31a6798194e91ef8f51b2cb2b4de Mon Sep 17 00:00:00 2001 From: Josh Dersch Date: Fri, 16 Aug 2019 02:23:32 +0200 Subject: [PATCH] Cleaned up signaling of DMA/INTR completion (using pthread_cond_wait). Tweaked MSYN timeout value from 350ns to 400ns to compensate for timing changes with latest PRU code -- MSCP works reliably on PDP-11/84 again. --- 10.01_base/2_src/arm/priorityrequest.cpp | 2 +- 10.01_base/2_src/arm/priorityrequest.hpp | 2 +- 10.01_base/2_src/arm/unibusadapter.cpp | 41 +++++++++++------------- 10.01_base/2_src/shared/tuning.h | 2 +- 10.02_devices/2_src/mscp_server.cpp | 7 ++-- 10.02_devices/2_src/uda.cpp | 6 ++-- 6 files changed, 27 insertions(+), 33 deletions(-) diff --git a/10.01_base/2_src/arm/priorityrequest.cpp b/10.01_base/2_src/arm/priorityrequest.cpp index 309645f..d239ab8 100644 --- a/10.01_base/2_src/arm/priorityrequest.cpp +++ b/10.01_base/2_src/arm/priorityrequest.cpp @@ -37,7 +37,7 @@ priority_request_c::priority_request_c(unibusdevice_c *device) { this->executing_on_PRU = false; this->slot = 0xff; // uninitialized, asserts() if used complete_mutex = PTHREAD_MUTEX_INITIALIZER; - //complete_cond = PTHREAD_COND_INITIALIZER; // PRU signal notifies request on completeness + complete_cond = PTHREAD_COND_INITIALIZER; // PRU signal notifies request on completeness } priority_request_c::~priority_request_c() { diff --git a/10.01_base/2_src/arm/priorityrequest.hpp b/10.01_base/2_src/arm/priorityrequest.hpp index 41c86e5..c6c61e5 100644 --- a/10.01_base/2_src/arm/priorityrequest.hpp +++ b/10.01_base/2_src/arm/priorityrequest.hpp @@ -82,7 +82,7 @@ public: // PRU -> signal -> worker() -> request -> device. INTR/DMA pthread_mutex_t complete_mutex; - //pthread_cond_t complete_cond; // PRU signal notifies request on completeness + pthread_cond_t complete_cond; // PRU signal notifies request on completeness priority_request_c(unibusdevice_c *device); virtual ~priority_request_c(); // not used, but need dynamic_cast diff --git a/10.01_base/2_src/arm/unibusadapter.cpp b/10.01_base/2_src/arm/unibusadapter.cpp index d83333b..d8b3a9f 100644 --- a/10.01_base/2_src/arm/unibusadapter.cpp +++ b/10.01_base/2_src/arm/unibusadapter.cpp @@ -296,13 +296,14 @@ void unibusadapter_c::requests_cancel_scheduled(void) { if ((req = prl->slot_request[slot])) { dma_request_c *dmareq; req->executing_on_PRU = false; - req->complete = true; if ((dmareq = dynamic_cast(req))) dmareq->success = false; // device gets an DMA error, but will not understand prl->slot_request[slot] = NULL; - // signal to blockin DMA() or INTR() - pthread_mutex_unlock(&req->complete_mutex); - //pthread_cond_signal(&req->complete_cond); + // signal to blocking DMA() or INTR() + pthread_mutex_lock(&req->complete_mutex); + req->complete = true; + pthread_cond_signal(&req->complete_cond); + pthread_mutex_unlock(&req->complete_mutex); } } } @@ -489,12 +490,10 @@ void unibusadapter_c::request_active_complete(unsigned level_index) { prl->active = NULL; // signal to DMA() or INTR() - tmprq->complete = true; // close to signal - pthread_mutex_unlock(&tmprq->complete_mutex); - -// pthread_cond_signal(&tmprq->complete_cond); - -// pthread_cond_broadcast(&tmprq->complete_cond); + pthread_mutex_lock(&tmprq->complete_mutex); + tmprq->complete = true; + pthread_cond_signal(&tmprq->complete_cond); + pthread_mutex_unlock(&tmprq->complete_mutex); } // Request a DMA cycle from Arbitrator. @@ -522,9 +521,9 @@ void unibusadapter_c::DMA(dma_request_c& dma_request, bool blocking, uint8_t uni priority_request_level_c *prl = &request_levels[PRIORITY_LEVEL_INDEX_NPR]; assert(prl->slot_request[dma_request.slot] == NULL); // not scheduled or prev completed - pthread_mutex_lock(&dma_request.complete_mutex); // lock early, else PRU can signal cond before we lock // dma_request.level-index, priority_slot in constructor dma_request.complete = false; + dma_request.success = false; dma_request.executing_on_PRU = false; dma_request.unibus_control = unibus_control; dma_request.unibus_start_addr = unibus_addr; @@ -549,20 +548,13 @@ void unibusadapter_c::DMA(dma_request_c& dma_request, bool blocking, uint8_t uni // DEBUG("device DMA start: %s @ %06o, len=%d", unibus->control2text(unibus_control), unibus_addr, wordcount); if (blocking) { - // acquire locked mutex => wait for worker to release pthread_mutex_lock(&dma_request.complete_mutex); + // DMA() is blocking: Wait for request to finish. + while (!dma_request.complete) { + int res = pthread_cond_wait(&dma_request.complete_cond, &dma_request.complete_mutex); + assert(!res); + } pthread_mutex_unlock(&dma_request.complete_mutex); - - /* - // DMA() is blocking: Wait for request to finish. - // pthread_mutex_lock(&dma_request.mutex); - while (!dma_request.complete) { - // busy waiting OK - int res = pthread_cond_wait(&dma_request.complete_cond, &dma_request.complete_mutex); - assert(!res) ; - dma_request.dbg_complete_sig_received++ ; - } - */ } } @@ -685,6 +677,9 @@ void unibusadapter_c::cancel_INTR(intr_request_c& intr_request) { } // both empty, or both filled assert((prl->slot_request_mask == 0) == (prl->active == NULL)); + + pthread_mutex_lock(&intr_request.complete_mutex); + pthread_cond_signal(&intr_request.complete_cond); pthread_mutex_unlock(&intr_request.complete_mutex); pthread_mutex_unlock(&requests_mutex); // lock schedule table operations diff --git a/10.01_base/2_src/shared/tuning.h b/10.01_base/2_src/shared/tuning.h index d677d7f..6f6de3e 100644 --- a/10.01_base/2_src/shared/tuning.h +++ b/10.01_base/2_src/shared/tuning.h @@ -81,4 +81,4 @@ // Addtional delay on PDP11s with private memory interconnect (PMI) // and UNIBUS/PMI translation? // Experiments with "250" made still occasional errors. -#define UNIBUS_DMA_MASTER_PRE_MSYN_NS 350 +#define UNIBUS_DMA_MASTER_PRE_MSYN_NS 400 diff --git a/10.02_devices/2_src/mscp_server.cpp b/10.02_devices/2_src/mscp_server.cpp index cc4e17f..39582a2 100644 --- a/10.02_devices/2_src/mscp_server.cpp +++ b/10.02_devices/2_src/mscp_server.cpp @@ -200,16 +200,17 @@ mscp_server::Poll(void) // std::queue> messages; + int msgCount = 0; while (!_abort_polling && _pollState != PollingState::InitRestart) { shared_ptr message(_port->GetNextCommand()); - if (nullptr == message) { - DEBUG("End of command ring; %d messages to be executed."); + DEBUG("End of command ring; %d messages to be executed.", msgCount); break; } + msgCount++; messages.push(message); } @@ -221,8 +222,6 @@ mscp_server::Poll(void) shared_ptr message(messages.front()); messages.pop(); - DEBUG("Processing message."); - // // Handle the message. We dispatch on opcodes to the // appropriate methods. These methods modify the message diff --git a/10.02_devices/2_src/uda.cpp b/10.02_devices/2_src/uda.cpp index c00ed52..d7a12d9 100644 --- a/10.02_devices/2_src/uda.cpp +++ b/10.02_devices/2_src/uda.cpp @@ -531,7 +531,7 @@ uda_c::GetNextCommand(void) DMAReadWord( messageAddress - 4, success); - + assert(messageLength > 0 && messageLength < MAX_MESSAGE_LENGTH); std::unique_ptr cmdMessage( @@ -591,7 +591,7 @@ uda_c::GetNextCommand(void) DMAWrite( descriptorAddress, sizeof(Descriptor), - reinterpret_cast(cmdDescriptor.get())); + reinterpret_cast(cmdDescriptor.get())); // // Move to the next descriptor in the ring for next time. @@ -1007,6 +1007,6 @@ uda_c::DMARead( } else { - return nullptr; + return nullptr; } }