PS2SDK
PS2 Homebrew Libraries
thcommon.h
1 #ifndef THCOMMON_H_
2 #define THCOMMON_H_
3 
4 #include "thbase.h"
5 
6 #include "list.h"
7 #include "sysmem.h"
8 #include "thmsgbx.h"
9 
10 #include <tamtypes.h>
11 
12 #define DEBUG_FLAGS (8)
13 
14 #define TAG_THREAD 0x7f01
15 #define TAG_SEMA 0x7f02
16 #define TAG_EVF 0x7f03
17 #define TAG_MBX 0x7f04
18 #define TAG_VPL 0x7f05
19 #define TAG_FPL 0x7f06
20 
21 #define MAKE_HANDLE(ptr) (((u32)(ptr) << 5) | ((((struct heaptag *)(ptr))->id & 0x3f) << 1) | 1)
22 #define HANDLE_PTR(handle) ((void *)((((u32)handle) >> 7) << 2))
23 #define HANDLE_ID(handle) (((handle) >> 1) & 0x3f)
24 #define HANDLE_VERIFY(handle, t) (((struct heaptag *)(HANDLE_PTR(handle)))->tag == (t) && \
25  HANDLE_ID(handle) == ((struct heaptag *)(HANDLE_PTR(handle)))->id)
26 
27 #ifdef ALIGN
28 #undef ALIGN
29 #endif
30 #define ALIGN(i) (((i) + 3) & (~3))
31 #define ALIGN_256(i) (((i) + 0xff) & (~0xff))
32 
33 #define UNIMPLEMENTED() \
34  do { \
35  Kprintf("UNIMPLEMENTED FUNCTION %s\n", __PRETTY_FUNCTION__); \
36  while (1) \
37  ; \
38  } while (0)
39 
40 #define TRACE() \
41  do { \
42  Kprintf("TRACE %s\n", __PRETTY_FUNCTION__); \
43  } while (0)
44 
45 #define TRACE_ERROR() \
46  do { \
47  Kprintf("TRACE %s %s:%d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__); \
48  } while (0)
49 
50 #define RESERVED_REGCTX_SIZE 0xb8
51 
52 // context state, saved and restored by intrman
53 struct regctx
54 {
55  u32 unk, at, v0, v1, a0,
56  a1, a2, a3, t0, t1,
57  t2, t3, t4, t5, t6,
58  t7, s0, s1, s2, s3,
59  s4, s5, s6, s7, t8,
60  t9, unk68, unk6c, gp,
61  sp, fp, ra, hi, lo, sr,
62  pc, I_CTRL, unk2;
63 };
64 
65 struct heaptag
66 {
67  u16 tag;
68  u16 id;
69 };
70 
71 struct event
72 {
73  u32 attr;
74  u32 waiter_count;
75  struct list_head waiters;
76  u32 option;
77 };
78 
79 struct event_flag
80 {
81  struct heaptag tag;
82  struct list_head evf_list;
83  struct event event;
84  u32 bits;
85  u32 init_bits;
86 };
87 
88 struct semaphore
89 {
90  struct heaptag tag;
91  struct list_head sema_list;
92  struct event event;
93  u32 count;
94  u32 max_count;
95  u32 initial_count;
96 };
97 
98 struct mbox
99 {
100  struct heaptag tag;
101  struct list_head mbox_list;
102  struct event event;
103  u32 msg_count;
104  iop_message_t *newest_msg;
105 };
106 
107 struct fpl_block
108 {
109  struct fpl_block *next;
110 };
111 
112 struct fpool
113 {
114  struct heaptag tag;
115  struct list_head fpl_list;
116  struct event event;
117  void *memory;
118  struct fpl_block *free;
119  u32 free_blocks;
120  u32 block_size;
121  u32 blocks;
122  u32 mem_size;
123 };
124 
125 struct vpool
126 {
127  struct heaptag tag;
128  struct list_head vpl_list;
129  struct event event;
130  void *heap;
131  u32 free_size;
132 };
133 
134 struct alarm
135 {
136  struct heaptag tag;
137  struct list_head alarm_list;
138  u64 target;
139  unsigned int (*cb)(void *userdata);
140  void *userptr;
141 };
142 
143 struct thread
144 {
145  struct heaptag tag;
146  struct list_head queue;
147  u8 status;
148  u16 priority;
149  struct regctx *saved_regs;
150  u32 unk14;
151  u32 unk18;
152  u16 wait_type;
153  u16 wakeup_count;
154  union
155  {
156  struct event *wait_event;
157  u32 wait_usecs;
158  };
159  // originally singly linked list of all threads
160  // struct thread *thread_list;
161  struct list_head thread_list;
162  u32 event_bits;
163  u16 event_mode;
164  u16 init_priority;
165  u32 run_clocks_hi;
166  u32 run_clocks_lo;
167  void *entry;
168  void *stack_top;
169  u32 stack_size;
170  void *gp;
171  u32 attr;
172  u32 option;
173  // nothing seems to use wait_return, would be $ra
174  // at the point of calling the wait function
175  // leftover debugging feature?
176  // u32 wait_return;
177  u32 *reason_counter;
178  u32 irq_preemption_count;
179  u32 thread_preemption_count;
180  u32 release_count;
181 };
182 
184 {
185  struct thread *current_thread;
186  struct thread *run_next;
187  u32 queue_map[4]; // bitset of active priorities
188  u32 debug_flags;
189  struct list_head ready_queue[128];
190  s32 timer_id;
191  u32 (*timer_func)();
192  u32 time_hi;
193  u32 time_lo;
194  u32 last_timer;
195  // struct thread *thread_list;
196  // switched to a doubly linked thread list
197  struct list_head thread_list;
198  struct thread *idle_thread;
199  struct list_head semaphore;
200  struct list_head event_flag;
201  struct list_head mbox;
202  struct list_head vpool;
203  struct list_head fpool;
204  struct list_head alarm;
205  struct list_head alarm_pool;
206  u16 thread_id;
207  u16 sema_id;
208  u16 evflag_id;
209  u16 mbox_id;
210  u32 unused_or_padding;
211  u32 alarm_id;
212  u32 alarm_count;
213  struct list_head sleep_queue;
214  struct list_head delay_queue;
215  struct list_head dormant_queue;
216  // struct list_head unused_list1;
217  // struct list_head unused_list2;
218  struct list_head delete_queue;
219  void *heap;
220  s32 sytem_status_flag;
221  u32 thread_switch_count;
222  u32 thread_resume_count;
223  u32 min_wait;
224  u32 unk4c8;
225  u32 unk_clock_mult;
226  u32 unk_clock_div;
227 };
228 
229 extern struct thread_context thctx;
230 
231 static inline u64 add64(u32 hi1, u32 lo1, u32 hi2, u32 lo2)
232 {
233 
234  u32 lo = lo1 + lo2;
235  u32 hi = hi1 + hi2 + (lo1 > (lo1 + lo2));
236  return lo | ((u64)hi << 32);
237 }
238 
239 static inline u64 as_u64(u32 a1, u32 a2)
240 {
241  return (u64)a1 << 32 | a2;
242 }
243 
244 // Maybe uninline these to reduce code size if needed
245 
246 /*
247 ** Schedule at at the end of queeu
248 */
249 static inline void readyq_insert_back(struct thread *thread)
250 {
251  u32 prio = thread->priority;
252  thctx.queue_map[prio >> 5] |= 1 << (prio & 0x1f);
253  list_insert(&thctx.ready_queue[prio], &thread->queue);
254 }
255 
256 /*
257 ** Schedule at at the front of queue
258 */
259 static inline void readyq_insert_front(struct thread *thread)
260 {
261  u32 prio = thread->priority;
262  thctx.queue_map[prio >> 5] |= 1 << (prio & 0x1f);
263  list_insert(thctx.ready_queue[prio].next, &thread->queue);
264 }
265 
266 /*
267 ** Remove from the queue
268 */
269 static inline void readyq_remove(struct thread *thread, u32 prio)
270 {
271  if (list_node_is_last(&thread->queue)) {
272  thctx.queue_map[prio >> 5] &= ~(1 << (prio & 0x1f));
273  }
274 
275  list_remove(&thread->queue);
276 }
277 
278 extern u32 readyq_highest();
279 
280 extern struct alarm *alarm_alloc();
281 extern void alarm_free(struct alarm *alarm);
282 extern void alarm_insert(struct list_head *list, struct alarm *alarm);
283 
284 extern void update_timer_compare(int timid, u64 time, struct list_head *alarm_list);
285 
286 extern void *heap_alloc(u16 tag, u32 bytes);
287 extern int heap_free(struct heaptag *tag);
288 
289 extern int thread_start(struct thread *thread, int intr_state);
290 extern int thread_init_and_start(struct thread *thread, int intr_state);
291 extern int thread_leave(int unk, int unk2, int intr_state, int release);
292 
293 extern unsigned int thread_delay_cb(void *user);
294 
295 extern int read_sys_time(iop_sys_clock_t *clock);
296 
297 extern void waitlist_insert(struct thread *thread, struct event *event, s32 priority);
298 
299 extern int check_thread_stack();
300 
301 #endif // THCOMMON_H_
thbase.h
semaphore
Definition: thcommon.h:88
thread
Definition: thcommon.h:143
event
Definition: thcommon.h:71
alarm
Definition: alarm.c:27
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
list_head
Definition: list.h:10
heaptag
Definition: thcommon.h:65
fpool
Definition: thcommon.h:112
tamtypes.h
fpl_block
Definition: thcommon.h:107
mbox
Definition: thcommon.h:98
sysmem.h
event_flag
Definition: thcommon.h:79
thread_context
Definition: thcommon.h:183
thmsgbx.h
vpool
Definition: thcommon.h:125
_iop_sys_clock
Definition: thbase.h:87
regctx
Definition: thcommon.h:53
_iop_message
Definition: thmsgbx.h:51