cellMsgDialog race condition fixed

This commit is contained in:
Nekotekina 2015-07-27 04:06:05 +03:00
commit 3d665148ca
4 changed files with 57 additions and 44 deletions

View file

@ -14,7 +14,6 @@ extern u64 get_system_time();
std::unique_ptr<MsgDialogInstance> g_msg_dialog; std::unique_ptr<MsgDialogInstance> g_msg_dialog;
MsgDialogInstance::MsgDialogInstance() MsgDialogInstance::MsgDialogInstance()
: state(msgDialogNone)
{ {
} }
@ -83,7 +82,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
} }
MsgDialogState old = msgDialogNone; MsgDialogState old = msgDialogNone;
if (!g_msg_dialog->state.compare_exchange_strong(old, msgDialogOpen)) if (!g_msg_dialog->state.compare_exchange_strong(old, msgDialogInit))
{ {
return CELL_SYSUTIL_ERROR_BUSY; return CELL_SYSUTIL_ERROR_BUSY;
} }
@ -105,8 +104,6 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
std::string msg = msgString.get_ptr(); std::string msg = msgString.get_ptr();
thread_t(WRAP_EXPR("MsgDialog Thread"), [=]()
{
switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE) switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE)
{ {
case CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL: cellSysutil.Warning("%s", msg); break; case CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL: cellSysutil.Warning("%s", msg); break;
@ -115,23 +112,37 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
g_msg_dialog->status = CELL_MSGDIALOG_BUTTON_NONE; g_msg_dialog->status = CELL_MSGDIALOG_BUTTON_NONE;
volatile bool m_signal = false; CallAfter([type, msg]()
CallAfter([type, msg, &m_signal]()
{ {
if (Emu.IsStopped()) return; if (Emu.IsStopped())
{
g_msg_dialog->state.exchange(msgDialogNone);
return;
}
g_msg_dialog->Create(type, msg); g_msg_dialog->Create(type, msg);
m_signal = true; g_msg_dialog->state.exchange(msgDialogOpen);
}); });
while (!m_signal) while (g_msg_dialog->state == msgDialogInit)
{ {
if (Emu.IsStopped())
{
if (g_msg_dialog->state != msgDialogNone)
{
break;
}
CHECK_EMU_STATUS; CHECK_EMU_STATUS;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
} }
thread_t(WRAP_EXPR("MsgDialog Thread"), [=]()
{
while (g_msg_dialog->state == msgDialogOpen || (s64)(get_system_time() - g_msg_dialog->wait_until) < 0) while (g_msg_dialog->state == msgDialogOpen || (s64)(get_system_time() - g_msg_dialog->wait_until) < 0)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
@ -142,7 +153,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
} }
if (callback && (g_msg_dialog->state != msgDialogAbort)) if (callback && g_msg_dialog->state != msgDialogAbort)
{ {
const s32 status = g_msg_dialog->status; const s32 status = g_msg_dialog->status;
@ -350,6 +361,8 @@ s32 cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta)
void cellSysutil_MsgDialog_init() void cellSysutil_MsgDialog_init()
{ {
g_msg_dialog->state = msgDialogNone;
REG_FUNC(cellSysutil, cellMsgDialogOpen2); REG_FUNC(cellSysutil, cellMsgDialogOpen2);
REG_FUNC(cellSysutil, cellMsgDialogOpenErrorCode); REG_FUNC(cellSysutil, cellMsgDialogOpenErrorCode);
REG_FUNC(cellSysutil, cellMsgDialogProgressBarSetMsg); REG_FUNC(cellSysutil, cellMsgDialogProgressBarSetMsg);

View file

@ -82,11 +82,12 @@ enum : s32
CELL_MSGDIALOG_BUTTON_ESCAPE = 3, CELL_MSGDIALOG_BUTTON_ESCAPE = 3,
}; };
typedef void(CellMsgDialogCallback)(s32 buttonType, vm::ptr<void> userData); using CellMsgDialogCallback = void(s32 buttonType, vm::ptr<void> userData);
enum MsgDialogState enum MsgDialogState
{ {
msgDialogNone, msgDialogNone,
msgDialogInit,
msgDialogOpen, msgDialogOpen,
msgDialogClose, msgDialogClose,
msgDialogAbort, msgDialogAbort,
@ -96,9 +97,9 @@ struct MsgDialogInstance
{ {
std::atomic<MsgDialogState> state; std::atomic<MsgDialogState> state;
s32 status = 0; s32 status;
u64 wait_until = 0; u64 wait_until;
u32 progress_bar_count = 0; u32 progress_bar_count;
MsgDialogInstance(); MsgDialogInstance();
virtual ~MsgDialogInstance() = default; virtual ~MsgDialogInstance() = default;

View file

@ -17,27 +17,27 @@ void MsgDialogFrame::Create(u32 type, std::string msg)
m_button_yes = nullptr; m_button_yes = nullptr;
m_button_no = nullptr; m_button_no = nullptr;
m_dialog = new wxDialog(parent, wxID_ANY, type & CELL_MSGDIALOG_TYPE_SE_TYPE ? "" : "Error", wxDefaultPosition, wxDefaultSize); m_dialog = std::make_unique<wxDialog>(parent, wxID_ANY, type & CELL_MSGDIALOG_TYPE_SE_TYPE ? "" : "Error", wxDefaultPosition, wxDefaultSize);
m_dialog->SetExtraStyle(m_dialog->GetExtraStyle() | wxWS_EX_TRANSIENT); m_dialog->SetExtraStyle(m_dialog->GetExtraStyle() | wxWS_EX_TRANSIENT);
m_dialog->SetTransparent(127 + (type & CELL_MSGDIALOG_TYPE_BG) * (128 / CELL_MSGDIALOG_TYPE_BG_INVISIBLE)); m_dialog->SetTransparent(127 + (type & CELL_MSGDIALOG_TYPE_BG) * (128 / CELL_MSGDIALOG_TYPE_BG_INVISIBLE));
m_sizer1 = new wxBoxSizer(wxVERTICAL); m_sizer1 = new wxBoxSizer(wxVERTICAL);
m_text = new wxStaticText(m_dialog, wxID_ANY, wxString(msg.c_str(), wxConvUTF8)); m_text = new wxStaticText(m_dialog.get(), wxID_ANY, wxString(msg.c_str(), wxConvUTF8));
m_sizer1->Add(m_text, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16); m_sizer1->Add(m_text, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT | wxTOP, 16);
switch (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR) switch (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR)
{ {
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE: case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE:
m_gauge2 = new wxGauge(m_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH); m_gauge2 = new wxGauge(m_dialog.get(), wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH);
m_text2 = new wxStaticText(m_dialog, wxID_ANY, ""); m_text2 = new wxStaticText(m_dialog.get(), wxID_ANY, "");
m_text2->SetAutoLayout(true); m_text2->SetAutoLayout(true);
// fallthrough // fallthrough
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE:
m_gauge1 = new wxGauge(m_dialog, wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH); m_gauge1 = new wxGauge(m_dialog.get(), wxID_ANY, 100, wxDefaultPosition, wxSize(300, -1), wxGA_HORIZONTAL | wxGA_SMOOTH);
m_text1 = new wxStaticText(m_dialog, wxID_ANY, ""); m_text1 = new wxStaticText(m_dialog.get(), wxID_ANY, "");
m_text1->SetAutoLayout(true); m_text1->SetAutoLayout(true);
} }
@ -59,9 +59,9 @@ void MsgDialogFrame::Create(u32 type, std::string msg)
if (type & CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO) if (type & CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO)
{ {
m_button_yes = new wxButton(m_dialog, wxID_YES); m_button_yes = new wxButton(m_dialog.get(), wxID_YES);
m_buttons->Add(m_button_yes, 0, wxALIGN_CENTER_HORIZONTAL | wxRIGHT, 8); m_buttons->Add(m_button_yes, 0, wxALIGN_CENTER_HORIZONTAL | wxRIGHT, 8);
m_button_no = new wxButton(m_dialog, wxID_NO); m_button_no = new wxButton(m_dialog.get(), wxID_NO);
m_buttons->Add(m_button_no, 0, wxALIGN_CENTER_HORIZONTAL, 16); m_buttons->Add(m_button_no, 0, wxALIGN_CENTER_HORIZONTAL, 16);
if ((type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR) == CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NO) if ((type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR) == CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NO)
@ -78,7 +78,7 @@ void MsgDialogFrame::Create(u32 type, std::string msg)
if (type & CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK) if (type & CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK)
{ {
m_button_ok = new wxButton(m_dialog, wxID_OK); m_button_ok = new wxButton(m_dialog.get(), wxID_OK);
m_buttons->Add(m_button_ok, 0, wxALIGN_CENTER_HORIZONTAL, 16); m_buttons->Add(m_button_ok, 0, wxALIGN_CENTER_HORIZONTAL, 16);
if ((type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR) == CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_OK) if ((type & CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR) == CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_OK)
@ -119,8 +119,7 @@ void MsgDialogFrame::Create(u32 type, std::string msg)
void MsgDialogFrame::Destroy() void MsgDialogFrame::Destroy()
{ {
delete m_dialog; m_dialog.reset();
m_dialog = nullptr;
} }
void MsgDialogFrame::ProgressBarSetMsg(u32 index, std::string msg) void MsgDialogFrame::ProgressBarSetMsg(u32 index, std::string msg)

View file

@ -4,7 +4,7 @@
class MsgDialogFrame : public MsgDialogInstance class MsgDialogFrame : public MsgDialogInstance
{ {
wxDialog* m_dialog; std::unique_ptr<wxDialog> m_dialog;
wxGauge* m_gauge1; wxGauge* m_gauge1;
wxGauge* m_gauge2; wxGauge* m_gauge2;
wxStaticText* m_text1; wxStaticText* m_text1;