summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/file_util.cpp43
-rw-r--r--src/common/file_util.h35
-rw-r--r--src/common/thread.h46
-rw-r--r--src/common/x64/emitter.cpp28
-rw-r--r--src/common/x64/emitter.h2
5 files changed, 79 insertions, 75 deletions
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 9ada09f8a..53700c865 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -824,13 +824,12 @@ size_t WriteStringToFile(bool text_file, const std::string &str, const char *fil
824 824
825size_t ReadFileToString(bool text_file, const char *filename, std::string &str) 825size_t ReadFileToString(bool text_file, const char *filename, std::string &str)
826{ 826{
827 FileUtil::IOFile file(filename, text_file ? "r" : "rb"); 827 IOFile file(filename, text_file ? "r" : "rb");
828 auto const f = file.GetHandle();
829 828
830 if (!f) 829 if (!file)
831 return false; 830 return false;
832 831
833 str.resize(static_cast<u32>(GetSize(f))); 832 str.resize(static_cast<u32>(file.GetSize()));
834 return file.ReadArray(&str[0], str.size()); 833 return file.ReadArray(&str[0], str.size());
835} 834}
836 835
@@ -877,15 +876,10 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
877} 876}
878 877
879IOFile::IOFile() 878IOFile::IOFile()
880 : m_file(nullptr), m_good(true) 879{
881{} 880}
882
883IOFile::IOFile(std::FILE* file)
884 : m_file(file), m_good(true)
885{}
886 881
887IOFile::IOFile(const std::string& filename, const char openmode[]) 882IOFile::IOFile(const std::string& filename, const char openmode[])
888 : m_file(nullptr), m_good(true)
889{ 883{
890 Open(filename, openmode); 884 Open(filename, openmode);
891} 885}
@@ -896,7 +890,6 @@ IOFile::~IOFile()
896} 890}
897 891
898IOFile::IOFile(IOFile&& other) 892IOFile::IOFile(IOFile&& other)
899 : m_file(nullptr), m_good(true)
900{ 893{
901 Swap(other); 894 Swap(other);
902} 895}
@@ -935,26 +928,12 @@ bool IOFile::Close()
935 return m_good; 928 return m_good;
936} 929}
937 930
938std::FILE* IOFile::ReleaseHandle() 931u64 IOFile::GetSize() const
939{
940 std::FILE* const ret = m_file;
941 m_file = nullptr;
942 return ret;
943}
944
945void IOFile::SetHandle(std::FILE* file)
946{
947 Close();
948 Clear();
949 m_file = file;
950}
951
952u64 IOFile::GetSize()
953{ 932{
954 if (IsOpen()) 933 if (IsOpen())
955 return FileUtil::GetSize(m_file); 934 return FileUtil::GetSize(m_file);
956 else 935
957 return 0; 936 return 0;
958} 937}
959 938
960bool IOFile::Seek(s64 off, int origin) 939bool IOFile::Seek(s64 off, int origin)
@@ -965,12 +944,12 @@ bool IOFile::Seek(s64 off, int origin)
965 return m_good; 944 return m_good;
966} 945}
967 946
968u64 IOFile::Tell() 947u64 IOFile::Tell() const
969{ 948{
970 if (IsOpen()) 949 if (IsOpen())
971 return ftello(m_file); 950 return ftello(m_file);
972 else 951
973 return -1; 952 return -1;
974} 953}
975 954
976bool IOFile::Flush() 955bool IOFile::Flush()
diff --git a/src/common/file_util.h b/src/common/file_util.h
index a85121aa6..b54a9fb72 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -14,6 +14,10 @@
14 14
15#include "common/common_types.h" 15#include "common/common_types.h"
16 16
17#ifdef _MSC_VER
18#include "common/string_util.h"
19#endif
20
17// User directory indices for GetUserPath 21// User directory indices for GetUserPath
18enum { 22enum {
19 D_USER_IDX, 23 D_USER_IDX,
@@ -172,7 +176,6 @@ class IOFile : public NonCopyable
172{ 176{
173public: 177public:
174 IOFile(); 178 IOFile();
175 IOFile(std::FILE* file);
176 IOFile(const std::string& filename, const char openmode[]); 179 IOFile(const std::string& filename, const char openmode[]);
177 180
178 ~IOFile(); 181 ~IOFile();
@@ -188,6 +191,9 @@ public:
188 template <typename T> 191 template <typename T>
189 size_t ReadArray(T* data, size_t length) 192 size_t ReadArray(T* data, size_t length)
190 { 193 {
194 static_assert(std::is_standard_layout<T>(), "Given array does not consist of standard layout objects");
195 static_assert(std::is_trivially_copyable<T>(), "Given array does not consist of trivially copyable objects");
196
191 if (!IsOpen()) { 197 if (!IsOpen()) {
192 m_good = false; 198 m_good = false;
193 return -1; 199 return -1;
@@ -203,9 +209,8 @@ public:
203 template <typename T> 209 template <typename T>
204 size_t WriteArray(const T* data, size_t length) 210 size_t WriteArray(const T* data, size_t length)
205 { 211 {
206 static_assert(std::is_standard_layout<T>::value, "Given array does not consist of standard layout objects"); 212 static_assert(std::is_standard_layout<T>(), "Given array does not consist of standard layout objects");
207 // TODO: gcc 4.8 does not support is_trivially_copyable, but we really should check for it here. 213 static_assert(std::is_trivially_copyable<T>(), "Given array does not consist of trivially copyable objects");
208 //static_assert(std::is_trivially_copyable<T>::value, "Given array does not consist of trivially copyable objects");
209 214
210 if (!IsOpen()) { 215 if (!IsOpen()) {
211 m_good = false; 216 m_good = false;
@@ -235,32 +240,24 @@ public:
235 return WriteArray(&object, 1); 240 return WriteArray(&object, 1);
236 } 241 }
237 242
238 bool IsOpen() { return nullptr != m_file; } 243 bool IsOpen() const { return nullptr != m_file; }
239 244
240 // m_good is set to false when a read, write or other function fails 245 // m_good is set to false when a read, write or other function fails
241 bool IsGood() { return m_good; } 246 bool IsGood() const { return m_good; }
242 operator void*() { return m_good ? m_file : nullptr; } 247 explicit operator bool() const { return IsGood(); }
243
244 std::FILE* ReleaseHandle();
245
246 std::FILE* GetHandle() { return m_file; }
247
248 void SetHandle(std::FILE* file);
249 248
250 bool Seek(s64 off, int origin); 249 bool Seek(s64 off, int origin);
251 u64 Tell(); 250 u64 Tell() const;
252 u64 GetSize(); 251 u64 GetSize() const;
253 bool Resize(u64 size); 252 bool Resize(u64 size);
254 bool Flush(); 253 bool Flush();
255 254
256 // clear error state 255 // clear error state
257 void Clear() { m_good = true; std::clearerr(m_file); } 256 void Clear() { m_good = true; std::clearerr(m_file); }
258 257
259 std::FILE* m_file;
260 bool m_good;
261private: 258private:
262 IOFile(IOFile&); 259 std::FILE* m_file = nullptr;
263 IOFile& operator=(IOFile& other); 260 bool m_good = true;
264}; 261};
265 262
266} // namespace 263} // namespace
diff --git a/src/common/thread.h b/src/common/thread.h
index 8255ee6d3..bbfa8befa 100644
--- a/src/common/thread.h
+++ b/src/common/thread.h
@@ -30,8 +30,7 @@
30# endif 30# endif
31#endif 31#endif
32 32
33namespace Common 33namespace Common {
34{
35 34
36int CurrentThreadId(); 35int CurrentThreadId();
37 36
@@ -43,55 +42,55 @@ public:
43 Event() : is_set(false) {} 42 Event() : is_set(false) {}
44 43
45 void Set() { 44 void Set() {
46 std::lock_guard<std::mutex> lk(m_mutex); 45 std::lock_guard<std::mutex> lk(mutex);
47 if (!is_set) { 46 if (!is_set) {
48 is_set = true; 47 is_set = true;
49 m_condvar.notify_one(); 48 condvar.notify_one();
50 } 49 }
51 } 50 }
52 51
53 void Wait() { 52 void Wait() {
54 std::unique_lock<std::mutex> lk(m_mutex); 53 std::unique_lock<std::mutex> lk(mutex);
55 m_condvar.wait(lk, [&]{ return is_set; }); 54 condvar.wait(lk, [&]{ return is_set; });
56 is_set = false; 55 is_set = false;
57 } 56 }
58 57
59 void Reset() { 58 void Reset() {
60 std::unique_lock<std::mutex> lk(m_mutex); 59 std::unique_lock<std::mutex> lk(mutex);
61 // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration 60 // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
62 is_set = false; 61 is_set = false;
63 } 62 }
64 63
65private: 64private:
66 bool is_set; 65 bool is_set;
67 std::condition_variable m_condvar; 66 std::condition_variable condvar;
68 std::mutex m_mutex; 67 std::mutex mutex;
69}; 68};
70 69
71class Barrier { 70class Barrier {
72public: 71public:
73 Barrier(size_t count) : m_count(count), m_waiting(0) {} 72 explicit Barrier(size_t count_) : count(count_), waiting(0), generation(0) {}
74 73
75 /// Blocks until all "count" threads have called Sync() 74 /// Blocks until all "count" threads have called Sync()
76 void Sync() { 75 void Sync() {
77 std::unique_lock<std::mutex> lk(m_mutex); 76 std::unique_lock<std::mutex> lk(mutex);
77 const size_t current_generation = generation;
78 78
79 // TODO: broken when next round of Sync()s 79 if (++waiting == count) {
80 // is entered before all waiting threads return from the notify_all 80 generation++;
81 81 waiting = 0;
82 if (++m_waiting == m_count) { 82 condvar.notify_all();
83 m_waiting = 0;
84 m_condvar.notify_all();
85 } else { 83 } else {
86 m_condvar.wait(lk, [&]{ return m_waiting == 0; }); 84 condvar.wait(lk, [this, current_generation]{ return current_generation != generation; });
87 } 85 }
88 } 86 }
89 87
90private: 88private:
91 std::condition_variable m_condvar; 89 std::condition_variable condvar;
92 std::mutex m_mutex; 90 std::mutex mutex;
93 const size_t m_count; 91 const size_t count;
94 size_t m_waiting; 92 size_t waiting;
93 size_t generation; // Incremented once each time the barrier is used
95}; 94};
96 95
97void SleepCurrentThread(int ms); 96void SleepCurrentThread(int ms);
@@ -100,8 +99,7 @@ void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
100// Use this function during a spin-wait to make the current thread 99// Use this function during a spin-wait to make the current thread
101// relax while another thread is working. This may be more efficient 100// relax while another thread is working. This may be more efficient
102// than using events because event functions use kernel calls. 101// than using events because event functions use kernel calls.
103inline void YieldCPU() 102inline void YieldCPU() {
104{
105 std::this_thread::yield(); 103 std::this_thread::yield();
106} 104}
107 105
diff --git a/src/common/x64/emitter.cpp b/src/common/x64/emitter.cpp
index 1dcf2416c..5662f7f86 100644
--- a/src/common/x64/emitter.cpp
+++ b/src/common/x64/emitter.cpp
@@ -455,6 +455,18 @@ void XEmitter::CALL(const void* fnptr)
455 Write32(u32(distance)); 455 Write32(u32(distance));
456} 456}
457 457
458FixupBranch XEmitter::CALL()
459{
460 FixupBranch branch;
461 branch.type = 1;
462 branch.ptr = code + 5;
463
464 Write8(0xE8);
465 Write32(0);
466
467 return branch;
468}
469
458FixupBranch XEmitter::J(bool force5bytes) 470FixupBranch XEmitter::J(bool force5bytes)
459{ 471{
460 FixupBranch branch; 472 FixupBranch branch;
@@ -531,6 +543,22 @@ void XEmitter::SetJumpTarget(const FixupBranch& branch)
531 } 543 }
532} 544}
533 545
546void XEmitter::SetJumpTarget(const FixupBranch& branch, const u8* target)
547{
548 if (branch.type == 0)
549 {
550 s64 distance = (s64)(target - branch.ptr);
551 ASSERT_MSG(distance >= -0x80 && distance < 0x80, "Jump target too far away, needs force5Bytes = true");
552 branch.ptr[-1] = (u8)(s8)distance;
553 }
554 else if (branch.type == 1)
555 {
556 s64 distance = (s64)(target - branch.ptr);
557 ASSERT_MSG(distance >= -0x80000000LL && distance < 0x80000000LL, "Jump target too far away, needs indirect register");
558 ((s32*)branch.ptr)[-1] = (s32)distance;
559 }
560}
561
534//Single byte opcodes 562//Single byte opcodes
535//There is no PUSHAD/POPAD in 64-bit mode. 563//There is no PUSHAD/POPAD in 64-bit mode.
536void XEmitter::INT3() {Write8(0xCC);} 564void XEmitter::INT3() {Write8(0xCC);}
diff --git a/src/common/x64/emitter.h b/src/common/x64/emitter.h
index 7c6548fb5..a33724146 100644
--- a/src/common/x64/emitter.h
+++ b/src/common/x64/emitter.h
@@ -425,12 +425,14 @@ public:
425#undef CALL 425#undef CALL
426#endif 426#endif
427 void CALL(const void* fnptr); 427 void CALL(const void* fnptr);
428 FixupBranch CALL();
428 void CALLptr(OpArg arg); 429 void CALLptr(OpArg arg);
429 430
430 FixupBranch J_CC(CCFlags conditionCode, bool force5bytes = false); 431 FixupBranch J_CC(CCFlags conditionCode, bool force5bytes = false);
431 void J_CC(CCFlags conditionCode, const u8* addr, bool force5Bytes = false); 432 void J_CC(CCFlags conditionCode, const u8* addr, bool force5Bytes = false);
432 433
433 void SetJumpTarget(const FixupBranch& branch); 434 void SetJumpTarget(const FixupBranch& branch);
435 void SetJumpTarget(const FixupBranch& branch, const u8* target);
434 436
435 void SETcc(CCFlags flag, OpArg dest); 437 void SETcc(CCFlags flag, OpArg dest);
436 // Note: CMOV brings small if any benefit on current cpus. 438 // Note: CMOV brings small if any benefit on current cpus.