Views: 1,611,514 | Main | Rules/FAQ | Memberlist | Active users | Last posts | Calendar | Stats | Online users | Search | 12-02-24 09:06 PM |
Guest: |
0 users reading blargSNES: event scheduler design | 1 bot |
Main - Homebrew projects - blargSNES: event scheduler design | Hide post layouts | New reply |
StapleButter |
| ||
Member blarg Level: 30 Posts: 145/184 EXP: 151592 Next: 14277 Since: 10-27-14 From: France Last post: 2660 days ago Last view: 2570 days ago |
at some point we'll need a proper event scheduler for it, it's a mess right now
* event timestamps: cycles from previous event * CPU execution: take next event's timestamp, run instructions for that amount of cycles * just skip straight to the event if: 1) WAI opcode 2) speedhacking around an IRQ wait loop 3) DMA transfer * insert event: knowing the amount of cycles to wait -- for each stored event, if the stored event's timestamp is greater, move further into the queue -- if the stored event's timestamp is less or equal, store event there -- linked list structure? -- give event a unique ID (or just use a pointer to it?) -- fix timestamp for event right after it * remove event (if for example a IRQ was enabled then disabled before firing): -- find event with matching uniqueID/pointer, remove -- yep, double-linked list would definitely be a bonus there -- fix timestamp for event right after it can be subject to changes ____________________ blargSNES -- SNES emu for 3DS More cool stuff |
profi200 |
| ||
Member Who knows? Level: 19 Posts: 39/70 EXP: 34564 Next: 1213 Since: 05-21-15 From: Germany Last post: 3004 days ago Last view: 2872 days ago |
You might want to use light locks or maybe the coming light events. That's a lot better than using sys calls every time. |
StapleButter |
| ||
Member blarg Level: 30 Posts: 146/184 EXP: 151592 Next: 14277 Since: 10-27-14 From: France Last post: 2660 days ago Last view: 2570 days ago |
I'm referring to events in SNES emulation, not the 3DS ones.
The light events could be interesting for things like the DSP sync though. ____________________ blargSNES -- SNES emu for 3DS More cool stuff |
plutoo |
| ||
Member Normal user Level: 11 Posts: 15/19 EXP: 4803 Next: 1182 Since: 09-17-15 Last post: 3283 days ago Last view: 3207 days ago |
I'd just use a priority queue (or a sorted singly linked list), and I would never ever "remove" events. In the case of an irq that gets disabled, I would simply check whether the irq is enabled or not when "popping" that event (and ignore it if it has been disabled).
When any event is added to the front of the queue, I'd interrupt the CPU execution, and recalculate the number of cycles left before next event occurs. This is the simplest and cleanest way of doing things. Edit: I should elaborate why removing an event is a really bad idea. What would happen if the program disabled interrupts, then enables them again? Then that event would be removed, and never added again. Also for the timestamp you'd want an absolute value. This way, you don't need to loop and update all events each time you handle them. Of course you will need to handle integer overflow, but that's no problem since the list is ordered. |
StapleButter |
| ||
Member blarg Level: 30 Posts: 147/184 EXP: 151592 Next: 14277 Since: 10-27-14 From: France Last post: 2660 days ago Last view: 2570 days ago |
The issue in this case is that the SNES supports an IRQ that can be programmed to fire at any screen position. Not only can it be disabled before firing, but it could also be changed to occur later or earlier.
The idea for timestamps would be that an event's timestamps is how many cycles away it is from the event before it. Each event would be relative to the one before itself, which would minimize overhead in updating (only one event to update really) and completely avoid integer overflow. ____________________ blargSNES -- SNES emu for 3DS More cool stuff |
coto |
| ||
Member (u32)(0xffff & (~0x3f8f)) Level: 11 Posts: 13/19 EXP: 4886 Next: 1099 Since: 05-23-15 From: chili Last post: 2973 days ago Last view: 2972 days ago |
About the IRQ that may trigger an event after set, and then would be unset right before the IRQ cycle count IRQ says it would be triggered:
spinlock_sched() runs on any hardware IRQ (for example vblank) handler. (or at least in a process that runs separately from the cycle counter thread) process_id = you assign one up to 10 or any other number u8 status = 0/1 (enabled/disabled) callback = (u32)&handler pointer spinlock_createproc(u8 process_id,u8 status,u32cback_ptr new_callback) //allocate a process spinlock_modifyproc and spinlock_deleteproc should speak for themselves - //if set to 0 it will run the handler registered / 1 it wont spinlock_perm(u8 process_id,u8 status) - SPINLOCK.H http://pastebin.com/Hzg5FAuf SPINLOCK.C http://pastebin.com/Jqeam9kX Very basic I know, but it really works. For example if you want to run process #0 registered Only on scanline # 100 and #110 currentscanline_thread(){ if((scanline == 110) || (scanline == 100)){ spinlock_perm(0,0); } } //then later on scanline end nextscanline_thread(){ spinlock_perm(0,1); scanline++; } |
yuriks |
| ||
Newcomer Normal user Level: 7 Posts: 7/8 EXP: 1373 Next: 75 Since: 10-30-14 From: Brazil Last post: 3293 days ago Last view: 3275 days ago |
I'd do this with a simple sorted array. Your number of outstanding events at any given time is likely to be a small number. Simply give each event entry an auto-incrementing unique id, and insert it into the array mantaining a sorted order. For removing events iterate until you find a matching id.
Since the number of events is small, a linked list or other more complex structure will probably not give you any significant advantage (and could even be slower with a naive implementation.) To optimize for the common case, you could sort the array in reverse order, so that popping the next event just requires decrementing the size. Another option is to use a circular array instead, though the implementation there is slightly more complicated. |
gudenau |
| ||
Member Normal user Level: 14 Posts: 2/34 EXP: 11585 Next: 1486 Since: 07-29-15 From: /dev/random Last post: 3122 days ago Last view: 3067 days ago |
Posted by yuriks You might be able to abuse memory mapping to make a ring buffer; that could be fun. |
yuriks |
| ||
Newcomer Normal user Level: 7 Posts: 8/8 EXP: 1373 Next: 75 Since: 10-30-14 From: Brazil Last post: 3293 days ago Last view: 3275 days ago |
That's not particularly helpful here, since it's only useful if you need to have a pointer to a window in the buffer that appears contiguous, which isn't the case here. |
plutoo |
| ||
Member Normal user Level: 11 Posts: 18/19 EXP: 4803 Next: 1182 Since: 09-17-15 Last post: 3283 days ago Last view: 3207 days ago |
I kinda agree, if you can live with a hard limit on the number of events then a circular array would be optimal. But removals in the "middle" of the array can be painful to implement. |
gudenau |
| ||
Member Normal user Level: 14 Posts: 11/34 EXP: 11585 Next: 1486 Since: 07-29-15 From: /dev/random Last post: 3122 days ago Last view: 3067 days ago |
Posted by plutoo Check for nulls and skip them, keep the holes in mind while updating the pointer? Given an array that is a little oversized and smart coding, that should not be to big of a preformance hit. |
Main - Homebrew projects - blargSNES: event scheduler design | Hide post layouts | New reply |
Page rendered in 0.021 seconds. (2048KB of memory used) MySQL - queries: 28, rows: 85/85, time: 0.009 seconds. Acmlmboard 2.064 (2018-07-20) © 2005-2008 Acmlm, Xkeeper, blackhole89 et al. |