syncLFQueueCompletePopPointer + bugfix

This commit is contained in:
Nekotekina 2014-08-18 01:35:10 +04:00
parent cf5dbdbdb5
commit 64935ccee6
1 changed files with 68 additions and 81 deletions

View File

@ -1066,30 +1066,27 @@ s32 syncLFQueueGetPushPointer(mem_ptr_t<CellSyncLFQueue> queue, s32& pointer, u3
}
res = CELL_OK;
}
else if (!isBlocking)
{
res = CELL_SYNC_ERROR_AGAIN;
if (!new_queue.m_h7.ToBE() || res)
{
return res;
}
break;
}
else if (!useEventQueue)
{
continue;
}
else
{
if (!isBlocking)
res = CELL_OK;
new_queue.m_h7 = 3;
if (isBlocking != 3)
{
res = CELL_SYNC_ERROR_AGAIN;
if (!new_queue.m_h7.ToBE() || res)
{
return res;
}
break;
}
else if (!useEventQueue)
{
continue;
}
else
{
res = CELL_OK;
new_queue.m_h7 = 3;
if (isBlocking != 3)
{
break;
}
}
}
}
@ -1158,8 +1155,9 @@ s32 syncLFQueueCompletePushPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer
new_queue.m_push2() = old_data;
const u32 old_data2 = queue->m_push3();
new_queue.m_push3() = old_data2;
s32 var1 = pointer - (u16)queue->m_h5;
s32 var1 = pointer - (u16)new_queue.m_h5;
if (var1 < 0)
{
var1 += depth * 2;
@ -1181,7 +1179,7 @@ s32 syncLFQueueCompletePushPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer
{
var9_ = 1 << var9_;
}
s32 var9 = ~(var9_ | (u16)queue->m_h6);
s32 var9 = ~(var9_ | (u16)new_queue.m_h6);
// count leading zeros in u16
{
u16 v = var9;
@ -1194,7 +1192,7 @@ s32 syncLFQueueCompletePushPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer
}
}
s32 var5 = (s32)(u16)queue->m_h6 | var9_;
s32 var5 = (s32)(u16)new_queue.m_h6 | var9_;
if (var9 & 0x30)
{
var5 = 0;
@ -1204,13 +1202,13 @@ s32 syncLFQueueCompletePushPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer
var5 <<= var9;
}
s32 var3 = (u16)queue->m_h5 + var9;
s32 var3 = (u16)new_queue.m_h5 + var9;
if (var3 >= depth * 2)
{
var3 -= depth * 2;
}
const u16 pack = new_queue.m_hs[0]; // three packed 5-bit fields
u16 pack = new_queue.m_hs[0]; // three packed 5-bit fields
s32 var4 = ((pack >> 10) & 0x1f) - ((pack >> 5) & 0x1f);
if (var4 < 0)
@ -1260,11 +1258,12 @@ s32 syncLFQueueCompletePushPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer
if (InterlockedCompareExchange(&queue->m_push2(), new_queue.m_push2(), old_data) == old_data)
{
// break;
assert(var2 + var4 < 16);
if (var6 != -1)
{
if (InterlockedCompareExchange(&queue->m_push3(), re32(var7), old_data2) == old_data2)
bool exch = InterlockedCompareExchange(&queue->m_push3(), re32(var7), old_data2) == old_data2;
assert(exch);
if (exch)
{
assert(fpSendSignal);
return fpSendSignal((u64)queue->m_eaSignal, var6);
@ -1272,18 +1271,14 @@ s32 syncLFQueueCompletePushPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer
}
else
{
const u16 pack2 = queue->m_hs[0];
if ((pack2 & 0x1f) == ((pack >> 10) & 0x1f))
pack = queue->m_hs[0];
if ((pack & 0x1f) == ((pack >> 10) & 0x1f))
{
if (InterlockedCompareExchange(&queue->m_push3(), re32(var7), old_data2) == old_data2)
{
return CELL_OK;
}
}
else
{
assert(queue->m_push3() == old_data2);
}
}
}
}
@ -1461,30 +1456,27 @@ s32 syncLFQueueGetPopPointer(mem_ptr_t<CellSyncLFQueue> queue, s32& pointer, u32
}
res = CELL_OK;
}
else if (!isBlocking)
{
res = CELL_SYNC_ERROR_AGAIN;
if (!new_queue.m_h3.ToBE() || res)
{
return res;
}
break;
}
else if (!useEventQueue)
{
continue;
}
else
{
if (!isBlocking)
res = CELL_OK;
new_queue.m_h3 = 3;
if (isBlocking != 3)
{
res = CELL_SYNC_ERROR_AGAIN;
if (!new_queue.m_h3.ToBE() || res)
{
return res;
}
break;
}
else if (!useEventQueue)
{
continue;
}
else
{
res = CELL_OK;
new_queue.m_h3 = 3;
if (isBlocking != 3)
{
break;
}
}
}
}
@ -1539,9 +1531,7 @@ s32 _cellSyncLFQueueGetPopPointer2(mem_ptr_t<CellSyncLFQueue> queue, mem32_t poi
s32 syncLFQueueCompletePopPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer, const std::function<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull)
{
assert(0); // TODO
if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_PPU2SPU))
if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_SPU2PPU))
{
return CELL_SYNC_ERROR_PERM;
}
@ -1550,19 +1540,20 @@ s32 syncLFQueueCompletePopPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer,
while (true)
{
const u32 old_data = InterlockedCompareExchange(&queue->m_push2(), 0, 0);
const u32 old_data = InterlockedCompareExchange(&queue->m_pop2(), 0, 0);
CellSyncLFQueue new_queue;
new_queue.m_push2() = old_data;
new_queue.m_pop2() = old_data;
const u32 old_data2 = queue->m_push3();
const u32 old_data2 = queue->m_pop3();
new_queue.m_pop3() = old_data2;
s32 var1 = pointer - (u16)queue->m_h5;
s32 var1 = pointer - (u16)new_queue.m_h1;
if (var1 < 0)
{
var1 += depth * 2;
}
s32 var2 = (s32)(s16)queue->m_h4 - (s32)(u16)queue->m_h1;
s32 var2 = (s32)(s16)queue->m_h8 - (s32)(u16)queue->m_h5;
if (var2 < 0)
{
var2 += depth * 2;
@ -1578,7 +1569,7 @@ s32 syncLFQueueCompletePopPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer,
{
var9_ = 1 << var9_;
}
s32 var9 = ~(var9_ | (u16)queue->m_h6);
s32 var9 = ~(var9_ | (u16)new_queue.m_h2);
// count leading zeros in u16
{
u16 v = var9;
@ -1591,7 +1582,7 @@ s32 syncLFQueueCompletePopPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer,
}
}
s32 var5 = (s32)(u16)queue->m_h6 | var9_;
s32 var5 = (s32)(u16)new_queue.m_h2 | var9_;
if (var9 & 0x30)
{
var5 = 0;
@ -1601,13 +1592,13 @@ s32 syncLFQueueCompletePopPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer,
var5 <<= var9;
}
s32 var3 = (u16)queue->m_h5 + var9;
s32 var3 = (u16)new_queue.m_h1 + var9;
if (var3 >= depth * 2)
{
var3 -= depth * 2;
}
const u16 pack = new_queue.m_hs[0]; // three packed 5-bit fields
u16 pack = new_queue.m_hs[16]; // three packed 5-bit fields
s32 var4 = ((pack >> 10) & 0x1f) - ((pack >> 5) & 0x1f);
if (var4 < 0)
@ -1616,7 +1607,11 @@ s32 syncLFQueueCompletePopPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer,
}
u32 var6;
if (var2 + var4 <= 15 && ((pack >> 10) & 0x1f) != (pack & 0x1f))
if (noQueueFull || var2 + var4 > 15 || ((pack >> 10) & 0x1f) == (pack & 0x1f))
{
var6 = -1;
}
else
{
s32 var8 = (pack & 0x1f) - ((pack >> 10) & 0x1f);
if (var8 < 0)
@ -1646,22 +1641,18 @@ s32 syncLFQueueCompletePopPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer,
}
new_queue.m_hs[0] = (pack & 0x83ff) | var12;
var6 = (u16)queue->m_hs[1 + 2 * var11];
}
else
{
var6 = -1;
var6 = (u16)queue->m_hs[17 + 2 * var11];
}
s32 var7 = (var3 << 16) | (var5 & 0xffff);
if (InterlockedCompareExchange(&queue->m_push2(), new_queue.m_push2(), old_data) == old_data)
if (InterlockedCompareExchange(&queue->m_pop2(), new_queue.m_pop2(), old_data) == old_data)
{
// break;
assert(var2 + var4 < 16);
if (var6 != -1)
{
if (InterlockedCompareExchange(&queue->m_push3(), re32(var7), old_data2) == old_data2)
bool exch = InterlockedCompareExchange(&queue->m_pop3(), re32(var7), old_data2) == old_data2;
assert(exch);
if (exch)
{
assert(fpSendSignal);
return fpSendSignal((u64)queue->m_eaSignal, var6);
@ -1669,18 +1660,14 @@ s32 syncLFQueueCompletePopPointer(mem_ptr_t<CellSyncLFQueue> queue, s32 pointer,
}
else
{
const u16 pack2 = queue->m_hs[0];
if ((pack2 & 0x1f) == ((pack >> 10) & 0x1f))
pack = queue->m_hs[16];
if ((pack & 0x1f) == ((pack >> 10) & 0x1f))
{
if (InterlockedCompareExchange(&queue->m_push3(), re32(var7), old_data2) == old_data2)
if (InterlockedCompareExchange(&queue->m_pop3(), re32(var7), old_data2) == old_data2)
{
return CELL_OK;
}
}
else
{
assert(queue->m_push3() == old_data2);
}
}
}
}
@ -1776,7 +1763,7 @@ s32 _cellSyncLFQueuePopBody(mem_ptr_t<CellSyncLFQueue> queue, u32 buffer_addr, u
s32 res;
if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY))
{
#ifdef PRX_DEBUG
#ifdef PRX_DEBUG_XXX
res = GetCurrentPPUThread().FastCall(libsre + 0x2CA8, queue.GetAddr(), position, 0, 0);
#else
res = syncLFQueueCompletePopPointer(queue, position, nullptr, 0);