cellSync: global mutex avoided

cellAudio: level bug fixed
This commit is contained in:
Nekotekina 2014-04-03 15:01:14 +04:00
parent b6d8f1e028
commit 1e02598903
7 changed files with 450 additions and 422 deletions

View file

@ -25,11 +25,13 @@ enum
#pragma pack(push, 1)
struct CellSyncMutex {
be_t<u16> m_freed;
be_t<u16> m_order;
volatile u32& m_data(){
return *reinterpret_cast<u32*>(this);
};
be_t<u16> m_freed;
be_t<u16> m_order;
volatile u32& m_data()
{
return *reinterpret_cast<u32*>(this);
};
/*
(???) Initialize: set zeros
(???) Lock: increase m_order and wait until m_freed == old m_order
@ -52,16 +54,8 @@ int cellSyncMutexInitialize(mem_ptr_t<CellSyncMutex> mutex)
return CELL_SYNC_ERROR_ALIGN;
}
{
SMutexLocker lock(reservation.mutex);
if ((reservation.addr + reservation.size > mutex.GetAddr() && reservation.addr <= mutex.GetAddr() + 4) ||
(mutex.GetAddr() + 4 > reservation.addr && mutex.GetAddr() <= reservation.addr + reservation.size))
{
reservation.clear();
}
mutex->m_data() = 0;
return CELL_OK;
}
mutex->m_data() = 0;
return CELL_OK;
}
int cellSyncMutexLock(mem_ptr_t<CellSyncMutex> mutex)
@ -78,22 +72,18 @@ int cellSyncMutexLock(mem_ptr_t<CellSyncMutex> mutex)
}
be_t<u16> old_order;
while (true)
{
SMutexLocker lock(reservation.mutex);
if ((reservation.addr + reservation.size > mutex.GetAddr() && reservation.addr <= mutex.GetAddr() + 4) ||
(mutex.GetAddr() + 4 > reservation.addr && mutex.GetAddr() <= reservation.addr + reservation.size))
{
reservation.clear();
}
old_order = mutex->m_order;
mutex->m_order = mutex->m_order + 1;
if (old_order == mutex->m_freed)
{
return CELL_OK;
}
const u32 old_data = mutex->m_data();
CellSyncMutex new_mutex;
new_mutex.m_data() = old_data;
old_order = new_mutex.m_order;
new_mutex.m_order++;
if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break;
}
while (old_order != Memory.Read16(mutex.GetAddr()))
while (old_order != mutex->m_freed)
{
Sleep(1);
if (Emu.IsStopped())
@ -118,20 +108,28 @@ int cellSyncMutexTryLock(mem_ptr_t<CellSyncMutex> mutex)
{
return CELL_SYNC_ERROR_ALIGN;
}
int res;
while (true)
{
SMutexLocker lock(reservation.mutex);
if ((reservation.addr + reservation.size > mutex.GetAddr() && reservation.addr <= mutex.GetAddr() + 4) ||
(mutex.GetAddr() + 4 > reservation.addr && mutex.GetAddr() <= reservation.addr + reservation.size))
const u32 old_data = mutex->m_data();
CellSyncMutex new_mutex;
new_mutex.m_data() = old_data;
if (new_mutex.m_order != new_mutex.m_freed)
{
reservation.clear();
res = CELL_SYNC_ERROR_BUSY;
}
if (mutex->m_order != mutex->m_freed)
else
{
return CELL_SYNC_ERROR_BUSY;
new_mutex.m_order++;
res = CELL_OK;
}
mutex->m_order = mutex->m_order + 1;
return CELL_OK;
if (InterlockedCompareExchange(&mutex->m_data(), new_mutex.m_data(), old_data) == old_data) break;
}
return res;
}
int cellSyncMutexUnlock(mem_ptr_t<CellSyncMutex> mutex)
@ -147,16 +145,17 @@ int cellSyncMutexUnlock(mem_ptr_t<CellSyncMutex> mutex)
return CELL_SYNC_ERROR_ALIGN;
}
{ /* global mutex */
SMutexLocker lock(reservation.mutex);
if ((reservation.addr + reservation.size > mutex.GetAddr() && reservation.addr <= mutex.GetAddr() + 4) ||
(mutex.GetAddr() + 4 > reservation.addr && mutex.GetAddr() <= reservation.addr + reservation.size))
{
reservation.clear();
}
mutex->m_freed = mutex->m_freed + 1;
return CELL_OK;
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;
}
return CELL_OK;
}
void cellSync_init()