2013-12-31 12:10:24 +01:00
|
|
|
#include "stdafx.h"
|
2014-06-17 17:44:03 +02:00
|
|
|
#include "Utilities/Log.h"
|
2014-06-02 19:27:24 +02:00
|
|
|
#include "Emu/Memory/Memory.h"
|
|
|
|
|
#include "Emu/System.h"
|
|
|
|
|
#include "Emu/SysCalls/Modules.h"
|
2013-12-31 12:10:24 +01:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
#include "cellSync.h"
|
|
|
|
|
|
2014-05-02 08:30:32 +02:00
|
|
|
//void cellSync_init();
|
|
|
|
|
//Module cellSync("cellSync", cellSync_init);
|
|
|
|
|
Module *cellSync = nullptr;
|
2013-12-31 12:10:24 +01:00
|
|
|
|
2014-01-10 02:30:59 +01:00
|
|
|
int cellSyncMutexInitialize(mem_ptr_t<CellSyncMutex> mutex)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
2014-05-02 08:30:32 +02:00
|
|
|
cellSync->Log("cellSyncMutexInitialize(mutex=0x%x)", mutex.GetAddr());
|
2014-01-10 02:30:59 +01:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
if (!mutex)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SYNC_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
2014-01-10 02:30:59 +01:00
|
|
|
if (mutex.GetAddr() % 4)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SYNC_ERROR_ALIGN;
|
|
|
|
|
}
|
2014-01-12 11:27:59 +01:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
// prx: set zero and sync
|
2014-07-20 19:59:59 +02:00
|
|
|
mutex->m_data() = 0;
|
2014-07-20 19:52:27 +02:00
|
|
|
InterlockedCompareExchange(&mutex->m_data(), 0, 0);
|
2014-04-03 13:01:14 +02:00
|
|
|
return CELL_OK;
|
2013-12-31 12:10:24 +01:00
|
|
|
}
|
|
|
|
|
|
2014-01-10 02:30:59 +01:00
|
|
|
int cellSyncMutexLock(mem_ptr_t<CellSyncMutex> mutex)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
2014-05-02 08:30:32 +02:00
|
|
|
cellSync->Log("cellSyncMutexLock(mutex=0x%x)", mutex.GetAddr());
|
2014-01-12 11:27:59 +01:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
if (!mutex)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SYNC_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
2014-01-10 02:30:59 +01:00
|
|
|
if (mutex.GetAddr() % 4)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SYNC_ERROR_ALIGN;
|
|
|
|
|
}
|
2014-01-10 02:30:59 +01:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
// prx: increase u16 and remember its old value
|
2014-01-10 02:30:59 +01:00
|
|
|
be_t<u16> old_order;
|
2014-04-03 13:01:14 +02:00
|
|
|
while (true)
|
2014-02-06 23:55:48 +01:00
|
|
|
{
|
2014-04-03 13:01:14 +02:00
|
|
|
const u32 old_data = mutex->m_data();
|
|
|
|
|
CellSyncMutex new_mutex;
|
|
|
|
|
new_mutex.m_data() = old_data;
|
|
|
|
|
|
|
|
|
|
old_order = new_mutex.m_order;
|
2014-07-20 19:14:04 +02:00
|
|
|
new_mutex.m_order++; // increase m_order
|
2014-04-03 13:01:14 +02:00
|
|
|
if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break;
|
2014-01-10 02:30:59 +01:00
|
|
|
}
|
2014-01-12 11:27:59 +01:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
// prx: wait until another u16 value == old value
|
|
|
|
|
while (old_order != mutex->m_freed)
|
2014-01-12 11:27:59 +01:00
|
|
|
{
|
2014-07-12 09:02:39 +02:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
2014-02-15 22:16:35 +01:00
|
|
|
if (Emu.IsStopped())
|
2014-01-12 11:27:59 +01:00
|
|
|
{
|
2014-06-27 15:26:46 +02:00
|
|
|
LOG_WARNING(HLE, "cellSyncMutexLock(mutex=0x%x) aborted", mutex.GetAddr());
|
2014-02-15 22:16:35 +01:00
|
|
|
break;
|
2014-01-12 11:27:59 +01:00
|
|
|
}
|
|
|
|
|
}
|
2014-07-20 19:14:04 +02:00
|
|
|
|
|
|
|
|
// prx: sync
|
|
|
|
|
InterlockedCompareExchange(&mutex->m_data(), 0, 0);
|
2013-12-31 12:10:24 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-10 02:30:59 +01:00
|
|
|
int cellSyncMutexTryLock(mem_ptr_t<CellSyncMutex> mutex)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
2014-05-02 08:30:32 +02:00
|
|
|
cellSync->Log("cellSyncMutexTryLock(mutex=0x%x)", mutex.GetAddr());
|
2014-01-12 11:27:59 +01:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
if (!mutex)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SYNC_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
2014-01-10 02:30:59 +01:00
|
|
|
if (mutex.GetAddr() % 4)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SYNC_ERROR_ALIGN;
|
|
|
|
|
}
|
2014-04-03 13:01:14 +02:00
|
|
|
|
|
|
|
|
while (true)
|
2014-02-06 23:55:48 +01:00
|
|
|
{
|
2014-04-03 13:01:14 +02:00
|
|
|
const u32 old_data = mutex->m_data();
|
|
|
|
|
CellSyncMutex new_mutex;
|
|
|
|
|
new_mutex.m_data() = old_data;
|
|
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
// prx: compare two u16 values and exit if not equal
|
2014-04-03 13:01:14 +02:00
|
|
|
if (new_mutex.m_order != new_mutex.m_freed)
|
2014-02-06 23:55:48 +01:00
|
|
|
{
|
2014-07-20 19:14:04 +02:00
|
|
|
return CELL_SYNC_ERROR_BUSY;
|
2014-02-06 23:55:48 +01:00
|
|
|
}
|
2014-04-03 13:01:14 +02:00
|
|
|
else
|
2014-01-12 11:27:59 +01:00
|
|
|
{
|
2014-04-03 13:01:14 +02:00
|
|
|
new_mutex.m_order++;
|
2014-01-12 11:27:59 +01:00
|
|
|
}
|
2014-04-03 13:01:14 +02:00
|
|
|
if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break;
|
2013-12-31 12:10:24 +01:00
|
|
|
}
|
2014-04-03 13:01:14 +02:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
return CELL_OK;
|
2013-12-31 12:10:24 +01:00
|
|
|
}
|
|
|
|
|
|
2014-01-10 02:30:59 +01:00
|
|
|
int cellSyncMutexUnlock(mem_ptr_t<CellSyncMutex> mutex)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
2014-05-02 08:30:32 +02:00
|
|
|
cellSync->Log("cellSyncMutexUnlock(mutex=0x%x)", mutex.GetAddr());
|
2014-01-12 11:27:59 +01:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
if (!mutex)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SYNC_ERROR_NULL_POINTER;
|
|
|
|
|
}
|
2014-01-10 02:30:59 +01:00
|
|
|
if (mutex.GetAddr() % 4)
|
2013-12-31 12:10:24 +01:00
|
|
|
{
|
|
|
|
|
return CELL_SYNC_ERROR_ALIGN;
|
|
|
|
|
}
|
2014-01-10 02:30:59 +01:00
|
|
|
|
2014-07-20 19:14:04 +02:00
|
|
|
InterlockedCompareExchange(&mutex->m_data(), 0, 0);
|
|
|
|
|
|
2014-04-03 13:01:14 +02:00
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
const u32 old_data = mutex->m_data();
|
|
|
|
|
CellSyncMutex new_mutex;
|
|
|
|
|
new_mutex.m_data() = old_data;
|
|
|
|
|
|
|
|
|
|
new_mutex.m_freed++;
|
|
|
|
|
if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break;
|
2014-01-12 11:27:59 +01:00
|
|
|
}
|
2014-04-03 13:01:14 +02:00
|
|
|
|
|
|
|
|
return CELL_OK;
|
2013-12-31 12:10:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void cellSync_init()
|
|
|
|
|
{
|
2014-05-02 08:30:32 +02:00
|
|
|
cellSync->AddFunc(0xa9072dee, cellSyncMutexInitialize);
|
|
|
|
|
cellSync->AddFunc(0x1bb675c2, cellSyncMutexLock);
|
|
|
|
|
cellSync->AddFunc(0xd06918c4, cellSyncMutexTryLock);
|
|
|
|
|
cellSync->AddFunc(0x91f2b7b0, cellSyncMutexUnlock);
|
2014-02-23 17:52:52 +01:00
|
|
|
}
|