diff --git a/configure b/configure index d7861ac60..780fcde83 100755 --- a/configure +++ b/configure @@ -320,6 +320,9 @@ case $_host in retron77) _host_os=retron77 ;; +rtstella) + _host_os=rtstella + ;; mingw32-cross) _host_os=mingw32msvc _host_cpu=i386 @@ -543,6 +546,10 @@ if test -n "$_host"; then _build_cheats=no _build_httplib=no ;; + rtstella) + echo "Compiling rtstella" + DEFINES="$DEFINES -DRTSTELLA" + ;; mingw32-cross) echo "Cross-compiling for Windows using MinGW." DEFINES="$DEFINES -DWIN32" @@ -567,7 +574,7 @@ else echo_n "Checking hosttype... " echo $_host_os case $_host_os in - linux* | openbsd* | freebsd* | kfreebsd* | netbsd* | bsd* | gnu0.* | sunos* | hpux* | beos*) + linux* | openbsd* | freebsd* | kfreebsd* | netbsd* | bsd* | gnu0.* | sunos* | hpux* | beos* ) DEFINES="$DEFINES -DUNIX" _host_os=unix ;; @@ -834,6 +841,12 @@ case $_host_os in MODULES="$MODULES $SRC_OS/unix" INCLUDES="$INCLUDES -I$SRC_OS/unix" ;; + rtstella) + DEFINES="$DEFINES -DBSPF_UNIX" + MODULES="$MODULES $SRC_OS/unix $SRC_OS/rtstella" + INCLUDES="$INCLUDES -I$SRC_OS/unix -I$SRC_OS/rtstella" + LIBS="$LIBS -lpthread" + ;; darwin) DEFINES="$DEFINES -DBSPF_UNIX -DMACOS_KEYS" MODULES="$MODULES $SRC_OS/unix" diff --git a/src/common/AudioQueue.cxx b/src/common/AudioQueue.cxx index 8b73602fc..436f44832 100644 --- a/src/common/AudioQueue.cxx +++ b/src/common/AudioQueue.cxx @@ -54,7 +54,7 @@ uInt32 AudioQueue::capacity() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 AudioQueue::size() const { - const lock_guard guard(myMutex); + const lock_guard guard(myLock); return mySize; } @@ -74,7 +74,7 @@ uInt32 AudioQueue::fragmentSize() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Int16* AudioQueue::enqueue(Int16* fragment) { - const lock_guard guard(myMutex); + const lock_guard guard(myLock); Int16* newFragment = nullptr; @@ -105,7 +105,7 @@ Int16* AudioQueue::enqueue(Int16* fragment) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Int16* AudioQueue::dequeue(Int16* fragment) { - const lock_guard guard(myMutex); + const lock_guard guard(myLock); if (mySize == 0) return nullptr; @@ -128,7 +128,7 @@ Int16* AudioQueue::dequeue(Int16* fragment) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AudioQueue::closeSink(Int16* fragment) { - const lock_guard guard(myMutex); + const lock_guard guard(myLock); if (myFirstFragmentForDequeue && fragment) throw runtime_error("attempt to return unknown buffer on closeSink"); diff --git a/src/common/AudioQueue.hxx b/src/common/AudioQueue.hxx index 61d25f38d..cabc61f96 100644 --- a/src/common/AudioQueue.hxx +++ b/src/common/AudioQueue.hxx @@ -23,6 +23,10 @@ #include "bspf.hxx" #include "StaggeredLogger.hxx" +#ifdef RTSTELLA +#include "Spinlock.hxx" +#endif + /** This class implements an audio queue that acts both like a ring buffer and a pool of audio fragments. The TIA emulation core fills a fragment @@ -36,6 +40,11 @@ */ class AudioQueue { + #ifdef RTSTELLA + using Lock = Spinlock; + #else + using Lock = std::Mutex; + #endif public: /** @@ -120,7 +129,8 @@ class AudioQueue uInt32 myNextFragment{0}; // We need a mutex for thread safety. - mutable std::mutex myMutex; + mutable Lock myLock; + // The first (empty) enqueue call returns this fragment. Int16* myFirstFragmentForEnqueue{nullptr}; diff --git a/src/os/rtstella/Spinlock.cxx b/src/os/rtstella/Spinlock.cxx new file mode 100644 index 000000000..0c06d1897 --- /dev/null +++ b/src/os/rtstella/Spinlock.cxx @@ -0,0 +1,39 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2023 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "bspf.hxx" +#include "Spinlock.hxx" + +Spinlock::Spinlock() +{ + pthread_spin_init(&mySpinlock, PTHREAD_PROCESS_PRIVATE); +} + +Spinlock::~Spinlock() +{ + pthread_spin_destroy(&mySpinlock); +} + +void Spinlock::lock() +{ + pthread_spin_lock(&mySpinlock); +} + +void Spinlock::unlock() +{ + pthread_spin_unlock(&mySpinlock); +} diff --git a/src/os/rtstella/Spinlock.hxx b/src/os/rtstella/Spinlock.hxx new file mode 100644 index 000000000..92cb70ee7 --- /dev/null +++ b/src/os/rtstella/Spinlock.hxx @@ -0,0 +1,39 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2023 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include + +#ifndef SPINLOCK_HXX +#define SPINLOCK_HXX + +class Spinlock +{ + public: + Spinlock(); + + ~Spinlock(); + + void lock(); + + void unlock(); + + private: + + pthread_spinlock_t mySpinlock; +}; + +#endif // SPINLOCK_HXX diff --git a/src/os/rtstella/module.mk b/src/os/rtstella/module.mk new file mode 100644 index 000000000..2048ec2cb --- /dev/null +++ b/src/os/rtstella/module.mk @@ -0,0 +1,10 @@ +MODULE := src/os/rtstella + +MODULE_OBJS := \ + src/os/rtstella/Spinlock.o + +MODULE_DIRS += \ + src/os/rtstella + +# Include common rules +include $(srcdir)/common.rules