mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 17:11:23 +00:00
sys_cond/mutex: Fix race between sys_cond_create and sys_mutex, Fix IPC support in sys_cond/mutex
This commit is contained in:
parent
8d8fb4a2e4
commit
92b7c56f29
@ -59,7 +59,7 @@ error_code sys_cond_destroy(ppu_thread& ppu, u32 cond_id)
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
cond.mutex->cond_count--;
|
||||
cond.mutex->obj_count.atomic_op([](typename lv2_mutex::count_info& info){ info.cond_count--; });
|
||||
return {};
|
||||
});
|
||||
|
||||
|
@ -40,7 +40,22 @@ struct lv2_cond final : lv2_obj
|
||||
, mtx_id(mtx_id)
|
||||
, mutex(std::move(mutex))
|
||||
{
|
||||
this->mutex->cond_count++;
|
||||
}
|
||||
|
||||
CellError on_id_create()
|
||||
{
|
||||
if (!mutex->obj_count.fetch_op([](typename lv2_mutex::count_info& info)
|
||||
{
|
||||
if (info.mutex_count)
|
||||
return info.cond_count++, true;
|
||||
return false;
|
||||
}).second)
|
||||
{
|
||||
// Mutex has been destroyed, cannot create conditional variable
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -88,7 +88,17 @@ error_code sys_mutex_destroy(ppu_thread& ppu, u32 mutex_id)
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
if (mutex.cond_count)
|
||||
if (!mutex.obj_count.fetch_op([](typename lv2_mutex::count_info& info)
|
||||
{
|
||||
if (info.cond_count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decrement mutex copies count
|
||||
info.mutex_count--;
|
||||
return true;
|
||||
}).second)
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
@ -33,10 +33,16 @@ struct lv2_mutex final : lv2_obj
|
||||
const u64 name;
|
||||
const s32 flags;
|
||||
|
||||
struct alignas(8) count_info
|
||||
{
|
||||
u32 mutex_count; // Mutex copies count (0 means doesn't exist anymore)
|
||||
u32 cond_count; // Condition Variables
|
||||
};
|
||||
|
||||
shared_mutex mutex;
|
||||
atomic_t<u32> owner{0}; // Owner Thread ID
|
||||
atomic_t<u32> owner{0};
|
||||
atomic_t<u32> lock_count{0}; // Recursive Locks
|
||||
atomic_t<u32> cond_count{0}; // Condition Variables
|
||||
atomic_t<count_info> obj_count{};
|
||||
std::deque<cpu_thread*> sq;
|
||||
|
||||
lv2_mutex(u32 protocol, u32 recursive, u32 shared, u32 adaptive, u64 key, s32 flags, u64 name)
|
||||
@ -50,6 +56,12 @@ struct lv2_mutex final : lv2_obj
|
||||
{
|
||||
}
|
||||
|
||||
CellError on_id_create()
|
||||
{
|
||||
obj_count.atomic_op([](count_info& info){ info.mutex_count++; });
|
||||
return {};
|
||||
}
|
||||
|
||||
CellError try_lock(u32 id)
|
||||
{
|
||||
const u32 value = owner;
|
||||
|
@ -75,6 +75,12 @@ private:
|
||||
enqueue_cmd,
|
||||
};
|
||||
|
||||
// Function executed under IDM mutex, error will make the object creation fail and the error will be returned
|
||||
CellError on_id_create()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static std::string name64(u64 name_u64)
|
||||
@ -205,23 +211,45 @@ public:
|
||||
{
|
||||
std::shared_ptr<T> result = make();
|
||||
|
||||
if (!ipc_manager<T, u64>::add(ipc_key, [&] { if (!idm::import_existing<lv2_obj, T>(result)) result.reset(); return result; }, &result))
|
||||
CellError error{};
|
||||
|
||||
if (!ipc_manager<T, u64>::add(ipc_key, [&]()
|
||||
{
|
||||
if (!idm::import<lv2_obj, T>([&]()
|
||||
{
|
||||
if (result && (error = result->on_id_create()))
|
||||
result.reset();
|
||||
return result;
|
||||
}))
|
||||
{
|
||||
result.reset();
|
||||
}
|
||||
|
||||
return result;
|
||||
}, &result))
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
if (flags == SYS_SYNC_NEWLY_CREATED)
|
||||
{
|
||||
return CELL_EEXIST;
|
||||
}
|
||||
|
||||
if (!idm::import_existing<lv2_obj, T>(result))
|
||||
error = CELL_EAGAIN;
|
||||
|
||||
if (!idm::import<lv2_obj, T>([&]() { if (result && (error = result->on_id_create())) result.reset(); return std::move(result); }))
|
||||
{
|
||||
return CELL_EAGAIN;
|
||||
return error;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
else if (!result)
|
||||
{
|
||||
return CELL_EAGAIN;
|
||||
return error ? CELL_EAGAIN : error;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -237,9 +265,11 @@ public:
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!idm::import_existing<lv2_obj, T>(result))
|
||||
CellError error = CELL_EAGAIN;
|
||||
|
||||
if (!idm::import<lv2_obj, T>([&]() { if (result && (error = result->on_id_create())) result.reset(); return std::move(result); }))
|
||||
{
|
||||
return CELL_EAGAIN;
|
||||
return error;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -252,9 +282,13 @@ public:
|
||||
}
|
||||
case SYS_SYNC_NOT_PROCESS_SHARED:
|
||||
{
|
||||
if (!idm::import<lv2_obj, T>(std::forward<F>(make)))
|
||||
std::shared_ptr<T> result = make();
|
||||
|
||||
CellError error = CELL_EAGAIN;
|
||||
|
||||
if (!idm::import<lv2_obj, T>([&]() { if (result && (error = result->on_id_create())) result.reset(); return std::move(result); }))
|
||||
{
|
||||
return CELL_EAGAIN;
|
||||
return error;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -292,7 +292,7 @@ void kernel_explorer::Update()
|
||||
{
|
||||
auto& mutex = static_cast<lv2_mutex&>(obj);
|
||||
add_leaf(node, qstr(fmt::format(u8"Mutex 0x%08x: “%s”, %s,%s Owner: %#x, Locks: %u, Key: %#llx, Conds: %u, Wq: %zu", id, lv2_obj::name64(mutex.name), mutex.protocol,
|
||||
mutex.recursive == SYS_SYNC_RECURSIVE ? " Recursive," : "", mutex.owner >> 1, +mutex.lock_count, mutex.key, +mutex.cond_count, mutex.sq.size())));
|
||||
mutex.recursive == SYS_SYNC_RECURSIVE ? " Recursive," : "", mutex.owner >> 1, +mutex.lock_count, mutex.key, mutex.obj_count.load().cond_count, mutex.sq.size())));
|
||||
break;
|
||||
}
|
||||
case SYS_COND_OBJECT:
|
||||
|
Loading…
Reference in New Issue
Block a user