mirror of https://github.com/RPCS3/rpcs3.git
Bugfix
This commit is contained in:
parent
11b409907e
commit
a62eeaaecc
|
@ -211,9 +211,9 @@ template<typename T> inline static typename std::enable_if<std::is_arithmetic<T>
|
||||||
|
|
||||||
template<typename T> inline static typename std::enable_if<std::is_arithmetic<T>::value, T>::type operator --(_atomic_base<be_t<T>>& left, int)
|
template<typename T> inline static typename std::enable_if<std::is_arithmetic<T>::value, T>::type operator --(_atomic_base<be_t<T>>& left, int)
|
||||||
{
|
{
|
||||||
u64 result;
|
T result;
|
||||||
|
|
||||||
left.atomic_op([&result](be_t<u64>& value)
|
left.atomic_op([&result](be_t<T>& value)
|
||||||
{
|
{
|
||||||
result = value--;
|
result = value--;
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,13 +25,13 @@ s32 syncMutexInitialize(vm::ptr<CellSyncMutex> mutex)
|
||||||
{
|
{
|
||||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mutex.addr() % 4)
|
if (mutex.addr() % 4)
|
||||||
{
|
{
|
||||||
return CELL_SYNC_ERROR_ALIGN;
|
return CELL_SYNC_ERROR_ALIGN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prx: set zero and sync
|
mutex->sync_var.exchange({});
|
||||||
mutex->data.exchange({});
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -51,26 +51,22 @@ s32 cellSyncMutexLock(vm::ptr<CellSyncMutex> mutex)
|
||||||
{
|
{
|
||||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mutex.addr() % 4)
|
if (mutex.addr() % 4)
|
||||||
{
|
{
|
||||||
return CELL_SYNC_ERROR_ALIGN;
|
return CELL_SYNC_ERROR_ALIGN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prx: increase m_acq and remember its old value
|
// prx: increase acquire_count and remember its old value
|
||||||
be_t<u16> order;
|
const be_t<u16> order = be_t<u16>::make(mutex->acquire_count++);
|
||||||
mutex->data.atomic_op([&order](CellSyncMutex::data_t& mutex)
|
|
||||||
{
|
|
||||||
order = mutex.m_acq++;
|
|
||||||
});
|
|
||||||
|
|
||||||
// prx: wait until this old value is equal to m_rel
|
// prx: wait until release_count is equal to old acquire_count
|
||||||
g_sync_mutex_wm.wait_op(mutex.addr(), [mutex, order]()
|
g_sync_mutex_wm.wait_op(mutex.addr(), [mutex, order]()
|
||||||
{
|
{
|
||||||
return order == mutex->data.read_relaxed().m_rel;
|
return order == mutex->release_count.read_relaxed();
|
||||||
});
|
});
|
||||||
|
|
||||||
// prx: sync
|
mutex->sync_var.read_sync();
|
||||||
mutex->data.read_sync();
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -83,19 +79,16 @@ s32 cellSyncMutexTryLock(vm::ptr<CellSyncMutex> mutex)
|
||||||
{
|
{
|
||||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mutex.addr() % 4)
|
if (mutex.addr() % 4)
|
||||||
{
|
{
|
||||||
return CELL_SYNC_ERROR_ALIGN;
|
return CELL_SYNC_ERROR_ALIGN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prx: exit if m_acq and m_rel are not equal, increase m_acq
|
// prx: lock only if acquire_count and release_count are equal
|
||||||
return mutex->data.atomic_op(CELL_OK, [](CellSyncMutex::data_t& mutex) -> s32
|
return mutex->sync_var.atomic_op(CELL_OK, [](CellSyncMutex::sync_t& mutex) -> s32
|
||||||
{
|
{
|
||||||
if (mutex.m_acq++ != mutex.m_rel)
|
return (mutex.acquire_count++ != mutex.release_count) ? CELL_SYNC_ERROR_BUSY : CELL_OK;
|
||||||
{
|
|
||||||
return CELL_SYNC_ERROR_BUSY;
|
|
||||||
}
|
|
||||||
return CELL_OK;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,10 +105,8 @@ s32 cellSyncMutexUnlock(vm::ptr<CellSyncMutex> mutex)
|
||||||
return CELL_SYNC_ERROR_ALIGN;
|
return CELL_SYNC_ERROR_ALIGN;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex->data.atomic_op_sync([](CellSyncMutex::data_t& mutex)
|
// prx: increase release count
|
||||||
{
|
mutex->release_count++;
|
||||||
mutex.m_rel++;
|
|
||||||
});
|
|
||||||
|
|
||||||
g_sync_mutex_wm.notify(mutex.addr());
|
g_sync_mutex_wm.notify(mutex.addr());
|
||||||
|
|
||||||
|
|
|
@ -29,15 +29,21 @@ enum
|
||||||
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, // ???
|
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, // ???
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSyncMutex
|
union CellSyncMutex
|
||||||
{
|
{
|
||||||
struct data_t
|
struct sync_t
|
||||||
{
|
{
|
||||||
be_t<u16> m_rel; // release order (increased when mutex is unlocked)
|
be_t<u16> release_count; // increased when mutex is unlocked
|
||||||
be_t<u16> m_acq; // acquire order (increased when mutex is locked)
|
be_t<u16> acquire_count; // increased when mutex is locked
|
||||||
};
|
};
|
||||||
|
|
||||||
atomic_t<data_t> data;
|
struct
|
||||||
|
{
|
||||||
|
atomic_t<u16> release_count;
|
||||||
|
atomic_t<u16> acquire_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
atomic_t<sync_t> sync_var;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(CellSyncMutex) == 4, "CellSyncMutex: wrong size");
|
static_assert(sizeof(CellSyncMutex) == 4, "CellSyncMutex: wrong size");
|
||||||
|
|
Loading…
Reference in New Issue