Skip to content

Commit 6cb2d9e

Browse files
committed
Exterimental: LV2: Add cpu_flag::unmem
1 parent acc2fea commit 6cb2d9e

33 files changed

+369
-337
lines changed

rpcs3/Emu/CPU/CPUThread.cpp

+33-13
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
4646
case cpu_flag::stop: return "STOP";
4747
case cpu_flag::exit: return "EXIT";
4848
case cpu_flag::wait: return "w";
49+
case cpu_flag::unmem: return "un";
4950
case cpu_flag::temp: return "t";
5051
case cpu_flag::pause: return "p";
5152
case cpu_flag::suspend: return "s";
@@ -498,10 +499,10 @@ void cpu_thread::operator()()
498499
cpu_thread* _cpu = get_current_cpu_thread();
499500

500501
// Wait flag isn't set asynchronously so this should be thread-safe
501-
if (progress == 0 && _cpu->state.none_of(cpu_flag::wait + cpu_flag::temp))
502+
if (progress == 0 && _cpu->state.none_of(cpu_flag::unmem + cpu_flag::temp + cpu_flag::wait))
502503
{
503504
// Operation just started and syscall is imminent
504-
_cpu->state += cpu_flag::wait + cpu_flag::temp;
505+
_cpu->state += cpu_flag::unmem + cpu_flag::temp;
505506
wait_set = true;
506507
return;
507508
}
@@ -661,12 +662,12 @@ bool cpu_thread::check_state() noexcept
661662

662663
if (flags & cpu_flag::pause && s_tls_thread_slot != umax)
663664
{
664-
// Save value before state is saved and cpu_flag::wait is observed
665+
// Save value before state is saved and cpu_flag::unmem is observed
665666
if (s_tls_sctr == umax)
666667
{
667668
u64 ctr = g_suspend_counter;
668669

669-
if (flags & cpu_flag::wait)
670+
if (flags & (cpu_flag::unmem + cpu_flag::wait))
670671
{
671672
if ((ctr & 3) == 2)
672673
{
@@ -695,7 +696,6 @@ bool cpu_thread::check_state() noexcept
695696
{
696697
// Sticky flag, indicates check_state() is not allowed to return true
697698
flags -= cpu_flag::temp;
698-
flags -= cpu_flag::wait;
699699
cpu_can_stop = false;
700700
store = true;
701701
}
@@ -756,19 +756,39 @@ bool cpu_thread::check_state() noexcept
756756
return store;
757757
}
758758

759-
if (flags & cpu_flag::wait)
759+
if (flags & (cpu_flag::wait + cpu_flag::unmem))
760760
{
761-
flags -= cpu_flag::wait;
761+
flags -= (cpu_flag::wait + cpu_flag::unmem);
762762
store = true;
763763
}
764764

765765
retval = false;
766766
}
767767
else
768768
{
769-
if (cpu_can_stop && !(flags & cpu_flag::wait))
769+
if (cpu_can_stop)
770770
{
771-
flags += cpu_flag::wait;
771+
if (flags & (cpu_flag::yield + cpu_flag::preempt))
772+
{
773+
flags -= (cpu_flag::yield + cpu_flag::preempt);
774+
store = true;
775+
}
776+
777+
if (::is_stopped(flags) == !(flags & cpu_flag::wait))
778+
{
779+
flags ^= cpu_flag::wait;
780+
store = true;
781+
}
782+
783+
if (!(flags & cpu_flag::unmem))
784+
{
785+
flags += cpu_flag::unmem;
786+
store = true;
787+
}
788+
}
789+
else if (flags & (cpu_flag::wait + cpu_flag::unmem))
790+
{
791+
flags -= (cpu_flag::wait + cpu_flag::unmem);
772792
store = true;
773793
}
774794

@@ -780,7 +800,7 @@ bool cpu_thread::check_state() noexcept
780800
return store;
781801
}).first;
782802

783-
if (state0 & cpu_flag::preempt && cpu_can_stop)
803+
if ((state0 - state1) & cpu_flag::preempt)
784804
{
785805
if (cpu_flag::wait - state0)
786806
{
@@ -1116,7 +1136,7 @@ std::string cpu_thread::dump_misc() const
11161136
bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
11171137
{
11181138
// Can't allow pre-set wait bit (it'd be a problem)
1119-
ensure(!_this || !(_this->state & cpu_flag::wait));
1139+
ensure(!_this || !(_this->state & (cpu_flag::unmem + cpu_flag::wait)));
11201140

11211141
do
11221142
{
@@ -1168,7 +1188,7 @@ bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
11681188

11691189
copy = cpu_counter::for_all_cpu(copy, [&](cpu_thread* cpu, u32 /*index*/)
11701190
{
1171-
if (cpu->state.fetch_add(cpu_flag::pause) & cpu_flag::wait)
1191+
if (cpu->state.fetch_add(cpu_flag::pause) & (cpu_flag::unmem + cpu_flag::wait))
11721192
{
11731193
// Clear bits as long as wait flag is set
11741194
return false;
@@ -1182,7 +1202,7 @@ bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
11821202
// Check only CPUs which haven't acknowledged their waiting state yet
11831203
copy = cpu_counter::for_all_cpu(copy, [&](cpu_thread* cpu, u32 /*index*/)
11841204
{
1185-
if (cpu->state & cpu_flag::wait)
1205+
if (cpu->state & (cpu_flag::unmem + cpu_flag::wait))
11861206
{
11871207
return false;
11881208
}

rpcs3/Emu/CPU/CPUThread.h

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ enum class cpu_flag : u32
1515
stop, // Thread not running (HLE, initial state)
1616
exit, // Irreversible exit
1717
wait, // Indicates waiting state, set by the thread itself
18+
unmem, // Thread has unlocked memory mutex
1819
temp, // Indicates that the thread cannot properly return after next check_state()
1920
pause, // Thread suspended by suspend_all technique
2021
suspend, // Thread suspended

rpcs3/Emu/Cell/Modules/cellVdec.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,7 @@ error_code cellVdecClose(ppu_thread& ppu, u32 handle)
998998

999999
error_code cellVdecStartSeq(ppu_thread& ppu, u32 handle)
10001000
{
1001-
ppu.state += cpu_flag::wait;
1001+
ppu.state += cpu_flag::unmem;
10021002

10031003
cellVdec.warning("cellVdecStartSeq(handle=0x%x)", handle);
10041004

@@ -1050,7 +1050,7 @@ error_code cellVdecStartSeq(ppu_thread& ppu, u32 handle)
10501050

10511051
error_code cellVdecEndSeq(ppu_thread& ppu, u32 handle)
10521052
{
1053-
ppu.state += cpu_flag::wait;
1053+
ppu.state += cpu_flag::unmem;
10541054

10551055
cellVdec.warning("cellVdecEndSeq(handle=0x%x)", handle);
10561056

@@ -1083,7 +1083,7 @@ error_code cellVdecEndSeq(ppu_thread& ppu, u32 handle)
10831083

10841084
error_code cellVdecDecodeAu(ppu_thread& ppu, u32 handle, CellVdecDecodeMode mode, vm::cptr<CellVdecAuInfo> auInfo)
10851085
{
1086-
ppu.state += cpu_flag::wait;
1086+
ppu.state += cpu_flag::unmem;
10871087

10881088
cellVdec.trace("cellVdecDecodeAu(handle=0x%x, mode=%d, auInfo=*0x%x)", handle, +mode, auInfo);
10891089

@@ -1131,7 +1131,7 @@ error_code cellVdecDecodeAu(ppu_thread& ppu, u32 handle, CellVdecDecodeMode mode
11311131

11321132
error_code cellVdecDecodeAuEx2(ppu_thread& ppu, u32 handle, CellVdecDecodeMode mode, vm::cptr<CellVdecAuInfoEx2> auInfo)
11331133
{
1134-
ppu.state += cpu_flag::wait;
1134+
ppu.state += cpu_flag::unmem;
11351135

11361136
cellVdec.todo("cellVdecDecodeAuEx2(handle=0x%x, mode=%d, auInfo=*0x%x)", handle, +mode, auInfo);
11371137

@@ -1187,7 +1187,7 @@ error_code cellVdecDecodeAuEx2(ppu_thread& ppu, u32 handle, CellVdecDecodeMode m
11871187

11881188
error_code cellVdecGetPictureExt(ppu_thread& ppu, u32 handle, vm::cptr<CellVdecPicFormat2> format, vm::ptr<u8> outBuff, u32 arg4)
11891189
{
1190-
ppu.state += cpu_flag::wait;
1190+
ppu.state += cpu_flag::unmem;
11911191

11921192
cellVdec.trace("cellVdecGetPictureExt(handle=0x%x, format=*0x%x, outBuff=*0x%x, arg4=*0x%x)", handle, format, outBuff, arg4);
11931193

@@ -1334,7 +1334,7 @@ error_code cellVdecGetPictureExt(ppu_thread& ppu, u32 handle, vm::cptr<CellVdecP
13341334

13351335
error_code cellVdecGetPicture(ppu_thread& ppu, u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u8> outBuff)
13361336
{
1337-
ppu.state += cpu_flag::wait;
1337+
ppu.state += cpu_flag::unmem;
13381338

13391339
cellVdec.trace("cellVdecGetPicture(handle=0x%x, format=*0x%x, outBuff=*0x%x)", handle, format, outBuff);
13401340

@@ -1355,7 +1355,7 @@ error_code cellVdecGetPicture(ppu_thread& ppu, u32 handle, vm::cptr<CellVdecPicF
13551355

13561356
error_code cellVdecGetPicItem(ppu_thread& ppu, u32 handle, vm::pptr<CellVdecPicItem> picItem)
13571357
{
1358-
ppu.state += cpu_flag::wait;
1358+
ppu.state += cpu_flag::unmem;
13591359

13601360
cellVdec.trace("cellVdecGetPicItem(handle=0x%x, picItem=**0x%x)", handle, picItem);
13611361

rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ void sys_initialize_tls(ppu_thread& ppu, u64 main_thread_id, u32 tls_seg_addr, u
125125

126126
error_code sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::cptr<char> threadname)
127127
{
128-
ppu.state += cpu_flag::wait;
128+
ppu.state += cpu_flag::unmem;
129129

130130
sysPrxForUser.warning("sys_ppu_thread_create(thread_id=*0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname=%s)",
131131
thread_id, entry, arg, prio, stacksize, flags, threadname);

rpcs3/Emu/Cell/PPUThread.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1501,8 +1501,8 @@ void ppu_thread::cpu_sleep()
15011501
// Clear reservation
15021502
raddr = 0;
15031503

1504-
// Setup wait flag and memory flags to relock itself
1505-
state += g_use_rtm ? cpu_flag::wait : cpu_flag::wait + cpu_flag::memory;
1504+
// Setup unmem flag and memory flags to relock itself
1505+
state += g_use_rtm ? cpu_flag::unmem : cpu_flag::unmem + cpu_flag::memory;
15061506

15071507
if (auto ptr = vm::g_tls_locked)
15081508
{

rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1446,7 +1446,7 @@ void spu_recompiler::RDCH(spu_opcode_t op)
14461446

14471447
if (out > 1500)
14481448
{
1449-
_spu->state += cpu_flag::wait;
1449+
_spu->state += cpu_flag::unmem;
14501450
std::this_thread::yield();
14511451

14521452
if (_spu->test_stopped())

rpcs3/Emu/Cell/SPURecompiler.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -6195,7 +6195,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
61956195

61966196
if (res > 1500 && g_cfg.core.spu_loop_detection)
61976197
{
6198-
_spu->state += cpu_flag::wait;
6198+
_spu->state += cpu_flag::unmem;
61996199
std::this_thread::yield();
62006200
static_cast<void>(_spu->test_stopped());
62016201
}

rpcs3/Emu/Cell/SPUThread.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -4248,6 +4248,7 @@ s64 spu_thread::get_ch_value(u32 ch)
42484248
spu_function_logger logger(*this, "MFC Events read");
42494249

42504250
lv2_obj::prepare_for_sleep(*this);
4251+
state += cpu_flag::wait;
42514252

42524253
using resrv_ptr = std::add_pointer_t<const decltype(rdata)>;
42534254

@@ -4958,6 +4959,7 @@ bool spu_thread::stop_and_signal(u32 code)
49584959
}
49594960

49604961
lv2_obj::prepare_for_sleep(*this);
4962+
state += cpu_flag::wait;
49614963

49624964
spu_function_logger logger(*this, "sys_spu_thread_receive_event");
49634965

@@ -5057,7 +5059,7 @@ bool spu_thread::stop_and_signal(u32 code)
50575059

50585060
while (auto old = +state)
50595061
{
5060-
if (old & cpu_flag::signal && state.test_and_reset(cpu_flag::signal))
5062+
if (old & cpu_flag::signal)
50615063
{
50625064
break;
50635065
}

rpcs3/Emu/Cell/lv2/lv2.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -1341,7 +1341,7 @@ bool lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout, u64 current_time)
13411341
{
13421342
if (!(val & cpu_flag::signal))
13431343
{
1344-
val += cpu_flag::suspend;
1344+
val += cpu_flag::suspend + cpu_flag::wait;
13451345

13461346
// Flag used for forced timeout notification
13471347
ensure(!timeout || !(val & cpu_flag::notify));
@@ -1471,6 +1471,7 @@ bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
14711471
}
14721472

14731473
ppu->start_time = get_guest_system_time();
1474+
ppu->state += cpu_flag::suspend + cpu_flag::wait;
14741475
break;
14751476
}
14761477

@@ -1554,12 +1555,16 @@ bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
15541555
// Suspend threads if necessary
15551556
for (usz i = 0, thread_count = g_cfg.core.ppu_threads; target; target = target->next_ppu, i++)
15561557
{
1557-
if (i >= thread_count && cpu_flag::suspend - target->state)
1558+
if (i >= thread_count && cpu_flag::suspend - target->state && target->state.atomic_op([](bs_t<cpu_flag>& state)
1559+
{
1560+
ensure(cpu_flag::suspend - state);
1561+
state += cpu_flag::suspend;
1562+
return state.none_of(cpu_flag::wait + cpu_flag::signal);
1563+
}))
15581564
{
15591565
ppu_log.trace("suspend(): %s", target->id);
15601566
target->ack_suspend = true;
15611567
g_pending++;
1562-
ensure(!target->state.test_and_set(cpu_flag::suspend));
15631568

15641569
if (is_paused(target->state - cpu_flag::suspend))
15651570
{
@@ -1605,9 +1610,13 @@ void lv2_obj::schedule_all(u64 current_time)
16051610
if (target->state & cpu_flag::suspend)
16061611
{
16071612
ppu_log.trace("schedule(): %s", target->id);
1608-
target->state.atomic_op(FN(x += cpu_flag::signal, x -= cpu_flag::suspend));
16091613
target->start_time = 0;
16101614

1615+
if ((cpu_flag::signal + cpu_flag::wait) - target->state.fetch_op(FN(x += cpu_flag::signal, x -= cpu_flag::suspend, void())) != cpu_flag::signal)
1616+
{
1617+
continue;
1618+
}
1619+
16111620
if (notify_later_idx == std::size(g_to_notify))
16121621
{
16131622
// Out of notification slots, notify locally (resizable container is not worth it)

rpcs3/Emu/Cell/lv2/sys_cond.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void lv2_cond::save(utils::serial& ar)
7272

7373
error_code sys_cond_create(ppu_thread& ppu, vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribute_t> attr)
7474
{
75-
ppu.state += cpu_flag::wait;
75+
ppu.state += cpu_flag::unmem;
7676

7777
sys_cond.warning("sys_cond_create(cond_id=*0x%x, mutex_id=0x%x, attr=*0x%x)", cond_id, mutex_id, attr);
7878

@@ -105,7 +105,7 @@ error_code sys_cond_create(ppu_thread& ppu, vm::ptr<u32> cond_id, u32 mutex_id,
105105

106106
error_code sys_cond_destroy(ppu_thread& ppu, u32 cond_id)
107107
{
108-
ppu.state += cpu_flag::wait;
108+
ppu.state += cpu_flag::unmem;
109109

110110
sys_cond.warning("sys_cond_destroy(cond_id=0x%x)", cond_id);
111111

@@ -138,7 +138,7 @@ error_code sys_cond_destroy(ppu_thread& ppu, u32 cond_id)
138138

139139
error_code sys_cond_signal(ppu_thread& ppu, u32 cond_id)
140140
{
141-
ppu.state += cpu_flag::wait;
141+
ppu.state += cpu_flag::unmem;
142142

143143
sys_cond.trace("sys_cond_signal(cond_id=0x%x)", cond_id);
144144

@@ -176,7 +176,7 @@ error_code sys_cond_signal(ppu_thread& ppu, u32 cond_id)
176176

177177
error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id)
178178
{
179-
ppu.state += cpu_flag::wait;
179+
ppu.state += cpu_flag::unmem;
180180

181181
sys_cond.trace("sys_cond_signal_all(cond_id=0x%x)", cond_id);
182182

@@ -224,7 +224,7 @@ error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id)
224224

225225
error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id)
226226
{
227-
ppu.state += cpu_flag::wait;
227+
ppu.state += cpu_flag::unmem;
228228

229229
sys_cond.trace("sys_cond_signal_to(cond_id=0x%x, thread_id=0x%x)", cond_id, thread_id);
230230

@@ -279,7 +279,7 @@ error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id)
279279

280280
error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout)
281281
{
282-
ppu.state += cpu_flag::wait;
282+
ppu.state += cpu_flag::unmem;
283283

284284
sys_cond.trace("sys_cond_wait(cond_id=0x%x, timeout=%lld)", cond_id, timeout);
285285

@@ -360,7 +360,7 @@ error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout)
360360

361361
while (auto state = +ppu.state)
362362
{
363-
if (state & cpu_flag::signal && ppu.state.test_and_reset(cpu_flag::signal))
363+
if (state & cpu_flag::signal)
364364
{
365365
break;
366366
}

0 commit comments

Comments
 (0)