sys_cond/mutex: Fix race between sys_cond_create and sys_mutex, Fix IPC support in sys_cond/mutex

This commit is contained in:
Eladash 2020-06-04 06:37:25 +03:00 committed by Ivan
parent 8d8fb4a2e4
commit 92b7c56f29
6 changed files with 85 additions and 14 deletions

View File

@ -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 {};
});

View File

@ -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 {};
}
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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: