diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/common.vcxproj | 1 | ||||
| -rw-r--r-- | src/common/common.vcxproj.filters | 1 | ||||
| -rw-r--r-- | src/common/common_funcs.h | 5 | ||||
| -rw-r--r-- | src/common/log.h | 4 | ||||
| -rw-r--r-- | src/common/log_manager.cpp | 4 | ||||
| -rw-r--r-- | src/common/thread_queue_list.h | 216 |
6 files changed, 228 insertions, 3 deletions
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 5dc6ff790..86295a480 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj | |||
| @@ -190,6 +190,7 @@ | |||
| 190 | <ClInclude Include="swap.h" /> | 190 | <ClInclude Include="swap.h" /> |
| 191 | <ClInclude Include="symbols.h" /> | 191 | <ClInclude Include="symbols.h" /> |
| 192 | <ClInclude Include="thread.h" /> | 192 | <ClInclude Include="thread.h" /> |
| 193 | <ClInclude Include="thread_queue_list.h" /> | ||
| 193 | <ClInclude Include="thunk.h" /> | 194 | <ClInclude Include="thunk.h" /> |
| 194 | <ClInclude Include="timer.h" /> | 195 | <ClInclude Include="timer.h" /> |
| 195 | <ClInclude Include="utf8.h" /> | 196 | <ClInclude Include="utf8.h" /> |
diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index 268730228..84cfa8837 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | <ClInclude Include="symbols.h" /> | 40 | <ClInclude Include="symbols.h" /> |
| 41 | <ClInclude Include="scm_rev.h" /> | 41 | <ClInclude Include="scm_rev.h" /> |
| 42 | <ClInclude Include="bit_field.h" /> | 42 | <ClInclude Include="bit_field.h" /> |
| 43 | <ClInclude Include="thread_queue_list.h" /> | ||
| 43 | </ItemGroup> | 44 | </ItemGroup> |
| 44 | <ItemGroup> | 45 | <ItemGroup> |
| 45 | <ClCompile Include="break_points.cpp" /> | 46 | <ClCompile Include="break_points.cpp" /> |
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index f8d10eb3e..dca4dc47f 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -22,6 +22,11 @@ template<> struct CompileTimeAssert<true> {}; | |||
| 22 | #define b32(x) (b16(x) | (b16(x) >>16) ) | 22 | #define b32(x) (b16(x) | (b16(x) >>16) ) |
| 23 | #define ROUND_UP_POW2(x) (b32(x - 1) + 1) | 23 | #define ROUND_UP_POW2(x) (b32(x - 1) + 1) |
| 24 | 24 | ||
| 25 | #define MIN(a, b) ((a)<(b)?(a):(b)) | ||
| 26 | #define MAX(a, b) ((a)>(b)?(a):(b)) | ||
| 27 | |||
| 28 | #define CLAMP(x, min, max) (((x) > max) ? max : (((x) < min) ? min : (x))) | ||
| 29 | |||
| 25 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) | 30 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) |
| 26 | 31 | ||
| 27 | #ifndef _WIN32 | 32 | #ifndef _WIN32 |
diff --git a/src/common/log.h b/src/common/log.h index d95f51f56..8b39b03a1 100644 --- a/src/common/log.h +++ b/src/common/log.h | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #ifndef _LOG_H_ | 5 | #ifndef _LOG_H_ |
| 6 | #define _LOG_H_ | 6 | #define _LOG_H_ |
| 7 | 7 | ||
| 8 | #define LOGGING | ||
| 9 | |||
| 8 | #define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and OSReports. | 10 | #define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and OSReports. |
| 9 | #define ERROR_LEVEL 2 // Critical errors | 11 | #define ERROR_LEVEL 2 // Critical errors |
| 10 | #define WARNING_LEVEL 3 // Something is suspicious. | 12 | #define WARNING_LEVEL 3 // Something is suspicious. |
| @@ -53,7 +55,7 @@ enum LOG_TYPE { | |||
| 53 | WII_IPC_ES, | 55 | WII_IPC_ES, |
| 54 | WII_IPC_FILEIO, | 56 | WII_IPC_FILEIO, |
| 55 | WII_IPC_HID, | 57 | WII_IPC_HID, |
| 56 | WII_IPC_HLE, | 58 | KERNEL, |
| 57 | SVC, | 59 | SVC, |
| 58 | NDMA, | 60 | NDMA, |
| 59 | HLE, | 61 | HLE, |
diff --git a/src/common/log_manager.cpp b/src/common/log_manager.cpp index 80fd473b9..146472888 100644 --- a/src/common/log_manager.cpp +++ b/src/common/log_manager.cpp | |||
| @@ -60,13 +60,13 @@ LogManager::LogManager() | |||
| 60 | m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader"); | 60 | m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader"); |
| 61 | m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System"); | 61 | m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System"); |
| 62 | m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID"); | 62 | m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID"); |
| 63 | m_Log[LogTypes::WII_IPC_HLE] = new LogContainer("WII_IPC_HLE", "WII IPC HLE"); | 63 | m_Log[LogTypes::KERNEL] = new LogContainer("KERNEL", "KERNEL HLE"); |
| 64 | m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD"); | 64 | m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD"); |
| 65 | m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES"); | 65 | m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES"); |
| 66 | m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO", "WII IPC FILEIO"); | 66 | m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO", "WII IPC FILEIO"); |
| 67 | m_Log[LogTypes::RENDER] = new LogContainer("RENDER", "RENDER"); | 67 | m_Log[LogTypes::RENDER] = new LogContainer("RENDER", "RENDER"); |
| 68 | m_Log[LogTypes::LCD] = new LogContainer("LCD", "LCD"); | 68 | m_Log[LogTypes::LCD] = new LogContainer("LCD", "LCD"); |
| 69 | m_Log[LogTypes::SVC] = new LogContainer("SVC", "Supervisor Call"); | 69 | m_Log[LogTypes::SVC] = new LogContainer("SVC", "Supervisor Call HLE"); |
| 70 | m_Log[LogTypes::NDMA] = new LogContainer("NDMA", "NDMA"); | 70 | m_Log[LogTypes::NDMA] = new LogContainer("NDMA", "NDMA"); |
| 71 | m_Log[LogTypes::HLE] = new LogContainer("HLE", "High Level Emulation"); | 71 | m_Log[LogTypes::HLE] = new LogContainer("HLE", "High Level Emulation"); |
| 72 | m_Log[LogTypes::HW] = new LogContainer("HW", "Hardware"); | 72 | m_Log[LogTypes::HW] = new LogContainer("HW", "Hardware"); |
diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h new file mode 100644 index 000000000..4a89572f6 --- /dev/null +++ b/src/common/thread_queue_list.h | |||
| @@ -0,0 +1,216 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project / PPSSPP Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common.h" | ||
| 8 | |||
| 9 | namespace Common { | ||
| 10 | |||
| 11 | template<class IdType> | ||
| 12 | struct ThreadQueueList { | ||
| 13 | // Number of queues (number of priority levels starting at 0.) | ||
| 14 | static const int NUM_QUEUES = 128; | ||
| 15 | |||
| 16 | // Initial number of threads a single queue can handle. | ||
| 17 | static const int INITIAL_CAPACITY = 32; | ||
| 18 | |||
| 19 | struct Queue { | ||
| 20 | // Next ever-been-used queue (worse priority.) | ||
| 21 | Queue *next; | ||
| 22 | // First valid item in data. | ||
| 23 | int first; | ||
| 24 | // One after last valid item in data. | ||
| 25 | int end; | ||
| 26 | // A too-large array with room on the front and end. | ||
| 27 | IdType *data; | ||
| 28 | // Size of data array. | ||
| 29 | int capacity; | ||
| 30 | }; | ||
| 31 | |||
| 32 | ThreadQueueList() { | ||
| 33 | memset(queues, 0, sizeof(queues)); | ||
| 34 | first = invalid(); | ||
| 35 | } | ||
| 36 | |||
| 37 | ~ThreadQueueList() { | ||
| 38 | for (int i = 0; i < NUM_QUEUES; ++i) | ||
| 39 | { | ||
| 40 | if (queues[i].data != NULL) | ||
| 41 | free(queues[i].data); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | // Only for debugging, returns priority level. | ||
| 46 | int contains(const IdType uid) { | ||
| 47 | for (int i = 0; i < NUM_QUEUES; ++i) | ||
| 48 | { | ||
| 49 | if (queues[i].data == NULL) | ||
| 50 | continue; | ||
| 51 | |||
| 52 | Queue *cur = &queues[i]; | ||
| 53 | for (int j = cur->first; j < cur->end; ++j) | ||
| 54 | { | ||
| 55 | if (cur->data[j] == uid) | ||
| 56 | return i; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | return -1; | ||
| 61 | } | ||
| 62 | |||
| 63 | inline IdType pop_first() { | ||
| 64 | Queue *cur = first; | ||
| 65 | while (cur != invalid()) | ||
| 66 | { | ||
| 67 | if (cur->end - cur->first > 0) | ||
| 68 | return cur->data[cur->first++]; | ||
| 69 | cur = cur->next; | ||
| 70 | } | ||
| 71 | |||
| 72 | //_dbg_assert_msg_(SCEKERNEL, false, "ThreadQueueList should not be empty."); | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | inline IdType pop_first_better(u32 priority) { | ||
| 77 | Queue *cur = first; | ||
| 78 | Queue *stop = &queues[priority]; | ||
| 79 | while (cur < stop) | ||
| 80 | { | ||
| 81 | if (cur->end - cur->first > 0) | ||
| 82 | return cur->data[cur->first++]; | ||
| 83 | cur = cur->next; | ||
| 84 | } | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | inline void push_front(u32 priority, const IdType threadID) { | ||
| 90 | Queue *cur = &queues[priority]; | ||
| 91 | cur->data[--cur->first] = threadID; | ||
| 92 | if (cur->first == 0) | ||
| 93 | rebalance(priority); | ||
| 94 | } | ||
| 95 | |||
| 96 | inline void push_back(u32 priority, const IdType threadID) { | ||
| 97 | Queue *cur = &queues[priority]; | ||
| 98 | cur->data[cur->end++] = threadID; | ||
| 99 | if (cur->end == cur->capacity) | ||
| 100 | rebalance(priority); | ||
| 101 | } | ||
| 102 | |||
| 103 | inline void remove(u32 priority, const IdType threadID) { | ||
| 104 | Queue *cur = &queues[priority]; | ||
| 105 | //_dbg_assert_msg_(SCEKERNEL, cur->next != NULL, "ThreadQueueList::Queue should already be linked up."); | ||
| 106 | |||
| 107 | for (int i = cur->first; i < cur->end; ++i) | ||
| 108 | { | ||
| 109 | if (cur->data[i] == threadID) | ||
| 110 | { | ||
| 111 | int remaining = --cur->end - i; | ||
| 112 | if (remaining > 0) | ||
| 113 | memmove(&cur->data[i], &cur->data[i + 1], remaining * sizeof(IdType)); | ||
| 114 | return; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | // Wasn't there. | ||
| 119 | } | ||
| 120 | |||
| 121 | inline void rotate(u32 priority) { | ||
| 122 | Queue *cur = &queues[priority]; | ||
| 123 | //_dbg_assert_msg_(SCEKERNEL, cur->next != NULL, "ThreadQueueList::Queue should already be linked up."); | ||
| 124 | |||
| 125 | if (cur->end - cur->first > 1) | ||
| 126 | { | ||
| 127 | cur->data[cur->end++] = cur->data[cur->first++]; | ||
| 128 | if (cur->end == cur->capacity) | ||
| 129 | rebalance(priority); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | inline void clear() { | ||
| 134 | for (int i = 0; i < NUM_QUEUES; ++i) | ||
| 135 | { | ||
| 136 | if (queues[i].data != NULL) | ||
| 137 | free(queues[i].data); | ||
| 138 | } | ||
| 139 | memset(queues, 0, sizeof(queues)); | ||
| 140 | first = invalid(); | ||
| 141 | } | ||
| 142 | |||
| 143 | inline bool empty(u32 priority) const { | ||
| 144 | const Queue *cur = &queues[priority]; | ||
| 145 | return cur->first == cur->end; | ||
| 146 | } | ||
| 147 | |||
| 148 | inline void prepare(u32 priority) { | ||
| 149 | Queue *cur = &queues[priority]; | ||
| 150 | if (cur->next == NULL) | ||
| 151 | link(priority, INITIAL_CAPACITY); | ||
| 152 | } | ||
| 153 | |||
| 154 | private: | ||
| 155 | Queue *invalid() const { | ||
| 156 | return (Queue *) -1; | ||
| 157 | } | ||
| 158 | |||
| 159 | void link(u32 priority, int size) { | ||
| 160 | //_dbg_assert_msg_(SCEKERNEL, queues[priority].data == NULL, "ThreadQueueList::Queue should only be initialized once."); | ||
| 161 | |||
| 162 | if (size <= INITIAL_CAPACITY) | ||
| 163 | size = INITIAL_CAPACITY; | ||
| 164 | else | ||
| 165 | { | ||
| 166 | int goal = size; | ||
| 167 | size = INITIAL_CAPACITY; | ||
| 168 | while (size < goal) | ||
| 169 | size *= 2; | ||
| 170 | } | ||
| 171 | Queue *cur = &queues[priority]; | ||
| 172 | cur->data = (IdType *) malloc(sizeof(IdType) * size); | ||
| 173 | cur->capacity = size; | ||
| 174 | cur->first = size / 2; | ||
| 175 | cur->end = size / 2; | ||
| 176 | |||
| 177 | for (int i = (int) priority - 1; i >= 0; --i) | ||
| 178 | { | ||
| 179 | if (queues[i].next != NULL) | ||
| 180 | { | ||
| 181 | cur->next = queues[i].next; | ||
| 182 | queues[i].next = cur; | ||
| 183 | return; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | cur->next = first; | ||
| 188 | first = cur; | ||
| 189 | } | ||
| 190 | |||
| 191 | void rebalance(u32 priority) { | ||
| 192 | Queue *cur = &queues[priority]; | ||
| 193 | int size = cur->end - cur->first; | ||
| 194 | if (size >= cur->capacity - 2) { | ||
| 195 | IdType *new_data = (IdType *)realloc(cur->data, cur->capacity * 2 * sizeof(IdType)); | ||
| 196 | if (new_data != NULL) { | ||
| 197 | cur->capacity *= 2; | ||
| 198 | cur->data = new_data; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | int newFirst = (cur->capacity - size) / 2; | ||
| 203 | if (newFirst != cur->first) { | ||
| 204 | memmove(&cur->data[newFirst], &cur->data[cur->first], size * sizeof(IdType)); | ||
| 205 | cur->first = newFirst; | ||
| 206 | cur->end = newFirst + size; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | // The first queue that's ever been used. | ||
| 211 | Queue *first; | ||
| 212 | // The priority level queues of thread ids. | ||
| 213 | Queue queues[NUM_QUEUES]; | ||
| 214 | }; | ||
| 215 | |||
| 216 | } // namespace | ||