1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-03-09 04:09:21 +00:00

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.
This commit is contained in:
Josh Dersch
2019-08-16 02:23:32 +02:00
parent 073a2334b6
commit 6f1b476716
6 changed files with 27 additions and 33 deletions

View File

@@ -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() {

View File

@@ -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

View File

@@ -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<dma_request_c *>(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

View File

@@ -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

View File

@@ -200,16 +200,17 @@ mscp_server::Poll(void)
//
std::queue<shared_ptr<Message>> messages;
int msgCount = 0;
while (!_abort_polling && _pollState != PollingState::InitRestart)
{
shared_ptr<Message> 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> message(messages.front());
messages.pop();
DEBUG("Processing message.");
//
// Handle the message. We dispatch on opcodes to the
// appropriate methods. These methods modify the message

View File

@@ -531,7 +531,7 @@ uda_c::GetNextCommand(void)
DMAReadWord(
messageAddress - 4,
success);
assert(messageLength > 0 && messageLength < MAX_MESSAGE_LENGTH);
std::unique_ptr<Message> cmdMessage(
@@ -591,7 +591,7 @@ uda_c::GetNextCommand(void)
DMAWrite(
descriptorAddress,
sizeof(Descriptor),
reinterpret_cast<uint8_t*>(cmdDescriptor.get()));
reinterpret_cast<uint8_t*>(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;
}
}