summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/common.vcxproj1
-rw-r--r--src/common/common.vcxproj.filters1
-rw-r--r--src/common/common_funcs.h5
-rw-r--r--src/common/log.h4
-rw-r--r--src/common/log_manager.cpp4
-rw-r--r--src/common/thread_queue_list.h216
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
9namespace Common {
10
11template<class IdType>
12struct 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
154private:
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