Switched to file-based mutex

This commit is contained in:
Tony Kuker 2023-02-02 21:22:10 -06:00
parent 83a83e9e74
commit 1f178e4f60
6 changed files with 135 additions and 43 deletions

View File

@ -106,6 +106,10 @@ class BUS : public PinControl
// Set SCSI output signal value
static const int SEND_NO_DELAY = -1;
// Passed into SendHandShake when we don't want to delay
// This is only applicable for the Virtual bus type
virtual bool SharedMemValid() const {return true;}
private:
static const array<phase_t, 8> phase_table;

View File

@ -115,6 +115,12 @@ class GPIOBUS_Virtual final : public GPIOBUS
// Get DAT signal
void SetDAT(uint8_t dat) override;
// Set DAT signal
bool SharedMemValid() const override
{
return signals->is_valid();
}
private:
// SCSI I/O signal control
void MakeTable() override;

View File

@ -8,10 +8,10 @@
//
//---------------------------------------------------------------------------
#include "scsisim_core.h"
#include "hal/data_sample_raspberry.h"
#include "shared/log.h"
#include "shared/piscsi_util.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "hal/data_sample_raspberry.h"
#include "scsisim_defs.h"
#include <iostream>
@ -124,7 +124,7 @@ bool ScsiSim::ParseArgument(const vector<char*>& args)
int ScsiSim::run(const vector<char*>& args)
{
running = true;
running = true;
scsi_sim = this;
// added setvbuf to override stdout buffering, so logs are written immediately and not when the process exits.
@ -146,7 +146,7 @@ int ScsiSim::run(const vector<char*>& args)
// We just want to run the test client. After we're done, we can
// return.
if(test_mode){
if (test_mode) {
TestClient();
return EXIT_SUCCESS;
}
@ -162,24 +162,34 @@ int ScsiSim::run(const vector<char*>& args)
signals = make_unique<SharedMemory>(SHARED_MEM_NAME, true);
uint32_t prev_value = signals->get();
int dot_counter = 0;
int dot_counter = 0;
int char_counter = 0;
while (running) {
if (enable_debug) {
uint32_t new_value = signals->get();
PrintDifferences(DataSample_Raspberry(new_value), DataSample_Raspberry(prev_value));
// Note, this won't necessarily print ever data change. It will
// just give an indication of activity
if (new_value != prev_value) {
LOGTRACE("%s Value changed to %08X", __PRETTY_FUNCTION__, new_value);
}
PrintDifferences(DataSample_Raspberry(new_value), DataSample_Raspberry(prev_value));
prev_value = new_value;
if(++dot_counter > 1000){
printf(".");
dot_counter = 0;
}
if (++dot_counter > 100) {
if (char_counter == 0) {
std::cout << "\r/" << flush;
} else if (char_counter == 1) {
std::cout << "\r-" << flush;
} else if (char_counter == 2) {
std::cout << "\r\\" << flush;
} else if (char_counter == 3) {
std::cout << "\r|" << flush;
}
char_counter = (char_counter + 1) % 4;
dot_counter = 0;
}
}
usleep(1000);
}

View File

@ -7,11 +7,12 @@
// [ SCSI Bus Emulator ]
//
//---------------------------------------------------------------------------
#include "hal/gpiobus_factory.h"
#include "hal/gpiobus_virtual.h"
#include "scsisim_core.h"
#include "shared/log.h"
#include "shared/piscsi_util.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "hal/gpiobus_factory.h"
#include "hal/data_sample.h"
#include "scsisim_defs.h"
@ -27,9 +28,6 @@ void ScsiSim::PrintDifferences(const DataSample& current, const DataSample& prev
stringstream s;
s << "Data changed: <";
// << setfill('0') << setw(2) << hex << GetBuffer()[0];
// logger.Trace(s.str());
if (current.GetDAT() != previous.GetDAT()) {
s << "DAT(" << setw(2) << hex << (int)current.GetDAT() << ") ";
}
@ -69,32 +67,78 @@ void ScsiSim::PrintDifferences(const DataSample& current, const DataSample& prev
}
}
void ScsiSim::TestClient(){
void ScsiSim::TestClient()
{
LOGINFO("TESTING!!!")
int sleep_time = 10000;
unique_ptr<BUS> bus = GPIOBUS_Factory::Create(BUS::mode_e::INITIATOR);
unique_ptr<BUS> bus = GPIOBUS_Factory::Create(BUS::mode_e::TARGET);
LOGINFO("bus->SetBSY"); bus->SetBSY(1); usleep(sleep_time); bus->SetBSY(0); usleep(sleep_time);
LOGINFO("bus->SetSEL"); bus->SetSEL(1); usleep(sleep_time); bus->SetSEL(0); usleep(sleep_time);
LOGINFO("bus->SetATN"); bus->SetATN(1); usleep(sleep_time); bus->SetATN(0); usleep(sleep_time);
LOGINFO("bus->SetACK"); bus->SetACK(1); usleep(sleep_time); bus->SetACK(0); usleep(sleep_time);
LOGINFO("bus->SetRST"); bus->SetRST(1); usleep(sleep_time); bus->SetRST(0); usleep(sleep_time);
LOGINFO("bus->SetMSG"); bus->SetMSG(1); usleep(sleep_time); bus->SetMSG(0); usleep(sleep_time);
LOGINFO("bus->SetCD"); bus->SetCD(1); usleep(sleep_time); bus->SetCD(0); usleep(sleep_time);
LOGINFO("bus->SetIO"); bus->SetIO(1); usleep(sleep_time); bus->SetIO(0); usleep(sleep_time);
LOGINFO("bus->SetREQ"); bus->SetREQ(1); usleep(sleep_time); bus->SetREQ(0); usleep(sleep_time);
LOGINFO("bus->SetACT"); bus->SetACT(1); usleep(sleep_time); bus->SetACT(0); usleep(sleep_time);
for(uint32_t i = 0; i <= 0xFF; i++){
LOGINFO("bus->SetDAT(%02X)", i); bus->SetDAT((uint8_t)i); usleep(sleep_time); bus->SetDAT(0); usleep(sleep_time);
if (!bus->SharedMemValid()) {
LOGWARN("Unable to set up shared memory region");
return;
}
LOGINFO("bus->SetBSY");
bus->SetBSY(1);
usleep(sleep_time);
bus->SetBSY(0);
usleep(sleep_time);
LOGINFO("bus->SetSEL");
bus->SetSEL(1);
usleep(sleep_time);
bus->SetSEL(0);
usleep(sleep_time);
LOGINFO("bus->SetATN");
bus->SetATN(1);
usleep(sleep_time);
bus->SetATN(0);
usleep(sleep_time);
LOGINFO("bus->SetACK");
bus->SetACK(1);
usleep(sleep_time);
bus->SetACK(0);
usleep(sleep_time);
LOGINFO("bus->SetRST");
bus->SetRST(1);
usleep(sleep_time);
bus->SetRST(0);
usleep(sleep_time);
LOGINFO("bus->SetMSG");
bus->SetMSG(1);
usleep(sleep_time);
bus->SetMSG(0);
usleep(sleep_time);
LOGINFO("bus->SetCD");
bus->SetCD(1);
usleep(sleep_time);
bus->SetCD(0);
usleep(sleep_time);
LOGINFO("bus->SetIO");
bus->SetIO(1);
usleep(sleep_time);
bus->SetIO(0);
usleep(sleep_time);
LOGINFO("bus->SetREQ");
bus->SetREQ(1);
usleep(sleep_time);
bus->SetREQ(0);
usleep(sleep_time);
LOGINFO("bus->SetACT");
bus->SetACT(1);
usleep(sleep_time);
bus->SetACT(0);
usleep(sleep_time);
for (uint32_t i = 0; i <= 0xFF; i++) {
LOGINFO("bus->SetDAT(%02X)", i);
bus->SetDAT((uint8_t)i);
usleep(sleep_time);
bus->SetDAT(0);
usleep(sleep_time);
}
// LOGINFO("bus->SetDAT(0x01)"); bus->SetDAT(1); usleep(sleep_time); bus->SetDAT(0); usleep(sleep_time);
// LOGINFO("bus->SetDAT(0xFF)"); bus->SetDAT(1); usleep(sleep_time); bus->SetDAT(0); usleep(sleep_time);
if (bus != nullptr) {
LOGTRACE("%s trying bus cleanup", __PRETTY_FUNCTION__)
bus->Cleanup();
}
}

View File

@ -45,6 +45,22 @@ SharedMemory::SharedMemory(std::string region_name, bool is_primary)
return;
}
LOGINFO("%s Shared memory region successfully memory mapped", __PRETTY_FUNCTION__)
if (m_primary) {
oflag = O_CREAT;
} else {
oflag = 0;
}
m_lock_name = m_name + "_lock";
LOGINFO("%s Open file lock name: %s", __PRETTY_FUNCTION__, m_lock_name.c_str())
m_file_lock = open(m_lock_name.c_str(), oflag);
if (m_file_lock == -1) {
LOGWARN("%s Unable to open the file lock (%s). Is scsisim running? Are you running as root?",
__PRETTY_FUNCTION__, m_lock_name.c_str())
m_valid = false;
}
}
// Note: The normal logging functions can not be used here. The logger objects

View File

@ -15,30 +15,38 @@
#include <semaphore.h>
#include <shared_mutex>
#include <string>
#include <sys/file.h>
#include <sys/mman.h>
#include <thread>
#include "shared/log.h"
#pragma once
class SharedMemory
{
public:
SharedMemory(std::string, bool is_primary=false);
SharedMemory(std::string, bool is_primary = false);
~SharedMemory();
inline uint32_t get() const
{
std::shared_lock lock(m_shared_mem->mutex_);
return m_shared_mem->value_;
uint32_t value;
flock(m_file_lock, LOCK_EX);
value = m_shared_mem->value_;
flock(m_file_lock, LOCK_UN);
return value;
}
inline void set(uint32_t new_val)
{
std::unique_lock lock(m_shared_mem->mutex_);
flock(m_file_lock, LOCK_EX);
m_shared_mem->value_ = new_val;
flock(m_file_lock, LOCK_UN);
}
inline void set_bit(int bit_num, int value)
{
std::unique_lock lock(m_shared_mem->mutex_);
flock(m_file_lock, LOCK_EX);
if (value) {
// Set bit
m_shared_mem->value_ |= (1 << bit_num);
@ -46,22 +54,26 @@ class SharedMemory
// Clear bit
m_shared_mem->value_ &= ~(1 << bit_num);
}
flock(m_file_lock, LOCK_UN);
}
inline bool is_valid(){
inline bool is_valid()
{
return m_valid;
}
private:
typedef struct lockable_data {
mutable std::shared_mutex mutex_;
uint32_t value_;
} lockable_data_t;
lockable_data_t* m_shared_mem;
int m_file_lock;
bool m_valid;
bool m_primary;
int m_fd_shared_mem;
std::string m_name;
std::string m_lock_name;
};