Small changes, some bugs fixed

This commit is contained in:
Nekotekina 2014-02-05 15:55:32 +04:00
parent aeca523a34
commit cfe154d916
13 changed files with 242 additions and 94 deletions

View file

@ -78,7 +78,7 @@ void DynamicMemoryBlockBase<PT>::Delete()
template<typename PT>
bool DynamicMemoryBlockBase<PT>::AllocFixed(u64 addr, u32 size)
{
size = PAGE_4K(size); // align size
size = PAGE_4K(size + (addr & 4095)); // align size
addr &= ~4095; // align start address

View file

@ -7,7 +7,7 @@ extern gcmInfo gcm_info;
int cellGcmCallback(u32 context_addr, u32 count)
{
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); // could stall on exit
CellGcmContextData& ctx = (CellGcmContextData&)Memory[context_addr];
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];

View file

@ -95,7 +95,7 @@ int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
const u32 tid = GetCurrentPPUThread().GetId();
mem_ptr_t<sys_lwmutex_t> lwmutex((u32)lwcond->lwmutex_addr);
if ((u32)lwmutex->owner != tid) return CELL_EPERM; // caller must own this lwmutex
if ((u32)lwmutex->owner.GetOwner() != tid) return CELL_EPERM; // caller must own this lwmutex
lwc->begin_waiting(tid);
u32 counter = 0;

View file

@ -1,12 +1,11 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/lv2/SC_Lwmutex.h"
#include "Utilities/SMutex.h"
#include <mutex>
SysCallBase sc_lwmutex("sys_lwmutex");
std::mutex g_lwmutex;
int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr)
{
sc_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
@ -49,20 +48,9 @@ int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
if (!lwmutex->attribute) return CELL_EINVAL;
{ // global lock
std::lock_guard<std::mutex> lock(g_lwmutex);
if (!lwmutex->owner)
{
lwmutex->owner = ~0; // make it unable to lock
lwmutex->attribute = 0;
}
else
{
return CELL_EBUSY;
}
}
// try to make it unable to lock
if (lwmutex->owner.trylock(~0) != SMR_OK) return CELL_EBUSY;
lwmutex->attribute = 0;
return CELL_OK;
}
@ -74,35 +62,7 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
if (!lwmutex->attribute) return CELL_EINVAL;
const u32 tid = GetCurrentPPUThread().GetId();
int res = lwmutex->trylock(tid);
if (res != CELL_EBUSY) return res;
u32 counter = 0;
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
do // waiting
{
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
Sleep(1);
res = lwmutex->trylock(tid);
if (res != CELL_EBUSY) return res;
if (!lwmutex->attribute) return CELL_EINVAL;
if (counter++ > max_counter)
{
if (!timeout)
{
sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr());
counter = 0;
}
else
{
return CELL_ETIMEDOUT;
}
}
} while (true);
return lwmutex->lock(GetCurrentPPUThread().GetId(), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0);
}
int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex)

View file

@ -1,4 +1,5 @@
#pragma once
#include <Utilities/SMutex.h>
// attr_protocol (waiting scheduling policy)
enum
@ -33,16 +34,14 @@ struct sys_lwmutex_attribute_t
char name[8];
};
extern std::mutex g_lwmutex;
struct sys_lwmutex_t
{
union // sys_lwmutex_variable_t
{
struct // sys_lwmutex_lock_info_t
{
/* volatile */ be_t<u32> owner;
/* volatile */ be_t<u32> waiter;
/* volatile */ SMutexBE owner;
/* volatile */ be_t<u32> waiter; // not used
};
struct
{
@ -56,75 +55,74 @@ struct sys_lwmutex_t
int trylock(u32 tid)
{
std::lock_guard<std::mutex> lock(g_lwmutex); // global lock
if ((u32)attribute & SYS_SYNC_RECURSIVE)
if (tid == (u32)owner.GetOwner()) // recursive or deadlock
{
if (tid == (u32)owner)
if (attribute & se32(SYS_SYNC_RECURSIVE))
{
recursive_count = (u32)recursive_count + 1;
if ((u32)recursive_count == 0xffffffff) return CELL_EKRESOURCE;
recursive_count += 1;
if (!recursive_count) return CELL_EKRESOURCE;
return CELL_OK;
}
}
else // recursive not allowed
{
if (tid == (u32)owner)
else
{
return CELL_EDEADLK;
}
}
if (!(u32)owner) // try lock
switch (owner.trylock(tid))
{
owner = tid;
recursive_count = 1;
return CELL_OK;
}
else
{
return CELL_EBUSY;
case SMR_OK: recursive_count = 1; return CELL_OK;
default: return CELL_EBUSY;
}
}
bool unlock(u32 tid)
{
std::lock_guard<std::mutex> lock(g_lwmutex); // global lock
if (tid != (u32)owner)
if (tid != (u32)owner.GetOwner())
{
return false;
}
else
{
recursive_count = (u32)recursive_count - 1;
if (!(u32)recursive_count)
recursive_count -= 1;
if (!recursive_count)
{
waiter = 0; // not used yet
owner = 0; // release
owner.unlock(tid);
}
return true;
}
}
int lock(u32 tid, u64 timeout)
{
switch (int res = trylock(tid))
{
case CELL_OK: return CELL_OK;
case CELL_EBUSY: break;
default: return res;
}
switch (owner.lock(tid, timeout))
{
case SMR_OK: recursive_count = 1; return CELL_OK;
case SMR_TIMEOUT: return CELL_ETIMEDOUT;
default: return CELL_EINVAL;
}
}
};
struct lwmutex_locker
class lwmutex_locker
{
private:
mem_ptr_t<sys_lwmutex_t> m_mutex;
u32 m_id;
public:
const int res;
lwmutex_locker(u32 lwmutex_addr, u32 tid)
lwmutex_locker(u32 lwmutex_addr, u32 tid, u64 timeout = 0)
: m_id(tid)
, m_mutex(lwmutex_addr)
, res(m_mutex->trylock(m_id))
{
if (int res = m_mutex->lock(m_id, timeout)) throw "lwmutex_locker: m_mutex->lock failed";
}
~lwmutex_locker()
{
if (res == CELL_OK) m_mutex->unlock(m_id);
m_mutex->unlock(m_id);
}
};

View file

@ -45,18 +45,18 @@ int sys_memory_container_destroy(u32 cid)
int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr)
{
//0x30000100;
sc_mem.Warning("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
sc_mem.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
u32 addr;
switch(flags)
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000);
addr = Memory.Alloc(size, 1);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000);
addr = Memory.Alloc(size, 1);
break;
default: return CELL_EINVAL;

View file

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "SC_Mutex.h"
#include "Utilities/SMutex.h"
SysCallBase sys_mtx("sys_mutex");

View file

@ -10,16 +10,16 @@ int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t<sys_rwlock_attribute_t> attr
if (!rw_lock_id.IsGood() || !attr.IsGood()) return CELL_EFAULT;
switch ((u32)attr->attr_protocol)
switch (attr->attr_protocol)
{
case SYS_SYNC_PRIORITY: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY attr"); break;
case SYS_SYNC_RETRY: sys_rwlock.Error("Invalid SYS_SYNC_RETRY attr"); break;
case SYS_SYNC_PRIORITY_INHERIT: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
case SYS_SYNC_FIFO: break;
case se32(SYS_SYNC_PRIORITY): sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY attr"); break;
case se32(SYS_SYNC_RETRY): sys_rwlock.Error("Invalid SYS_SYNC_RETRY attr"); break;
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
case se32(SYS_SYNC_FIFO): break;
default: return CELL_EINVAL;
}
if ((u32)attr->attr_pshared != 0x200)
if (attr->attr_pshared != se32(0x200))
{
sys_rwlock.Error("Invalid attr_pshared(0x%x)", (u32)attr->attr_pshared);
return CELL_EINVAL;