Example #1
0
int sys_semaphore_trywait(u32 sem_id)
{
	sys_sem.Log("sys_semaphore_trywait(sem_id=%d)", sem_id);

	Semaphore* sem;
	if (!Emu.GetIdManager().GetIDData(sem_id, sem))
	{
		return CELL_ESRCH;
	}

	std::lock_guard<std::mutex> lock(sem->m_mutex);

	if (sem->m_value > 0)
	{
		sem->m_value--;
		return CELL_OK;
	}
	else
	{
		return CELL_EBUSY;
	}
}
Example #2
0
//175
s32 sys_spu_thread_group_resume(u32 id)
{
	sc_spu.Log("sys_spu_thread_group_resume(id=%d)", id);

	SpuGroupInfo* group_info;
	if(!Emu.GetIdManager().GetIDData(id, group_info))
	{
		return CELL_ESRCH;
	}

	// TODO: check group state

	for (u32 i = 0; i < group_info->list.size(); i++)
	{
		if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
		{
			t->Resume();
		}
	}

	return CELL_OK;
}
Example #3
0
//166
int sys_spu_thread_set_argument(u32 id, mem_ptr_t<sys_spu_thread_argument> arg)
{
	sc_spu.Warning("sys_spu_thread_set_argument(id=0x%x, arg_addr=0x%x)", id, arg.GetAddr());
	CPUThread* thr = Emu.GetCPU().GetThread(id);

	if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
	{
		return CELL_ESRCH;
	}

	if(!arg.IsGood())
	{
		return CELL_EFAULT;
	}

	thr->SetArg(0, arg->arg1);
	thr->SetArg(1, arg->arg2);
	thr->SetArg(2, arg->arg3);
	thr->SetArg(3, arg->arg4);

	return CELL_OK;
}
Example #4
0
s32 sys_interrupt_tag_destroy(u32 intrtag)
{
	sys_interrupt.Warning("sys_interrupt_tag_destroy(intrtag=0x%x)", intrtag);

	LV2_LOCK;

	const auto tag = idm::get<lv2_int_tag_t>(intrtag);

	if (!tag)
	{
		return CELL_ESRCH;
	}

	if (tag->handler)
	{
		return CELL_EBUSY;
	}

	idm::remove<lv2_int_tag_t>(intrtag);

	return CELL_OK;
}
Example #5
0
s32 _sys_lwmutex_destroy(u32 lwmutex_id)
{
	sys_lwmutex.Warning("_sys_lwmutex_destroy(lwmutex_id=0x%x)", lwmutex_id);

	LV2_LOCK;

	const auto mutex = Emu.GetIdManager().get<lv2_lwmutex_t>(lwmutex_id);

	if (!mutex)
	{
		return CELL_ESRCH;
	}

	if (!mutex->sq.empty())
	{
		return CELL_EBUSY;
	}

	Emu.GetIdManager().remove<lv2_lwmutex_t>(lwmutex_id);

	return CELL_OK;
}
Example #6
0
s32 sys_cond_signal(u32 cond_id)
{
	sys_cond.Log("sys_cond_signal(cond_id=%d)", cond_id);

	LV2_LOCK;

	std::shared_ptr<cond_t> cond;

	if (!Emu.GetIdManager().GetIDData(cond_id, cond))
	{
		return CELL_ESRCH;
	}

	if (cond->waiters)
	{
		cond->signaled++;
		cond->waiters--;
		cond->cv.notify_one();
	}

	return CELL_OK;
}
Example #7
0
s32 sys_cond_destroy(u32 cond_id)
{
	sys_cond.Warning("sys_cond_destroy(cond_id=%d)", cond_id);

	LV2_LOCK(0);

	Cond* cond;
	if (!Emu.GetIdManager().GetIDData(cond_id, cond))
	{
		return CELL_ESRCH;
	}

	if (!cond->m_queue.finalize())
	{
		return CELL_EBUSY;
	}

	cond->mutex->cond_count--;
	Emu.GetIdManager().RemoveID(cond_id);
	Emu.GetSyncPrimManager().EraseSyncPrimData(TYPE_COND, cond_id);
	return CELL_OK;
}
Example #8
0
s32 sys_raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask)
{
    sys_spu.Log("sys_raw_spu_set_int_mask(id=%d, class_id=%d, mask=0x%llx)", id, class_id, mask);

    if (class_id != 0 && class_id != 2)
    {
        return CELL_EINVAL;
    }

    const auto thread = Emu.GetCPU().GetRawSPUThread(id);

    if (!thread)
    {
        return CELL_ESRCH;
    }

    auto& tag = class_id ? thread->int2 : thread->int0;

    tag.mask.exchange(mask);

    return CELL_OK;
}
Example #9
0
s32 sys_event_port_destroy(u32 eport_id)
{
    sys_event.warning("sys_event_port_destroy(eport_id=0x%x)", eport_id);

    LV2_LOCK;

    const auto port = idm::get<lv2_event_port_t>(eport_id);

    if (!port)
    {
        return CELL_ESRCH;
    }

    if (!port->queue.expired())
    {
        return CELL_EISCONN;
    }

    idm::remove<lv2_event_port_t>(eport_id);

    return CELL_OK;
}
Example #10
0
s32 _sys_lwmutex_trylock(u32 lwmutex_id)
{
	sys_lwmutex.Log("_sys_lwmutex_trylock(lwmutex_id=0x%x)", lwmutex_id);

	LV2_LOCK;

	const auto mutex = Emu.GetIdManager().get<lv2_lwmutex_t>(lwmutex_id);

	if (!mutex)
	{
		return CELL_ESRCH;
	}

	if (!mutex->sq.empty() || !mutex->signaled)
	{
		return CELL_EBUSY;
	}

	mutex->signaled--;

	return CELL_OK;
}
Example #11
0
s32 sys_rwlock_destroy(u32 rw_lock_id)
{
	sys_rwlock.Warning("sys_rwlock_destroy(rw_lock_id=0x%x)", rw_lock_id);

	LV2_LOCK;

	const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id);

	if (!rwlock)
	{
		return CELL_ESRCH;
	}

	if (rwlock->readers || rwlock->writer || rwlock->rsq.size() || rwlock->wsq.size())
	{
		return CELL_EBUSY;
	}

	idm::remove<lv2_rwlock_t>(rw_lock_id);

	return CELL_OK;
}
Example #12
0
s32 sys_event_flag_destroy(u32 id)
{
	sys_event_flag.Warning("sys_event_flag_destroy(id=0x%x)", id);

	LV2_LOCK;

	const auto eflag = idm::get<lv2_event_flag_t>(id);

	if (!eflag)
	{
		return CELL_ESRCH;
	}

	if (!eflag->sq.empty())
	{
		return CELL_EBUSY;
	}

	idm::remove<lv2_event_flag_t>(id);

	return CELL_OK;
}
Example #13
0
s32 sys_cond_signal(u32 cond_id)
{
	sys_cond.Log("sys_cond_signal(cond_id=0x%x)", cond_id);

	LV2_LOCK;

	const auto cond = Emu.GetIdManager().get<lv2_cond_t>(cond_id);

	if (!cond)
	{
		return CELL_ESRCH;
	}

	// signal one waiting thread; protocol is ignored in current implementation
	if (!cond->sq.empty())
	{
		cond->notify(lv2_lock, cond->sq.begin());
		cond->sq.pop_front();
	}

	return CELL_OK;
}
Example #14
0
s32 sys_timer_usleep(u64 sleep_time)
{
	sys_timer.trace("sys_timer_usleep(sleep_time=0x%llx)", sleep_time);

	const u64 start_time = get_system_time();

	u64 passed;

	while (sleep_time > (passed = get_system_time() - start_time) + 1000)
	{
		CHECK_EMU_STATUS;

		std::this_thread::sleep_for(std::chrono::milliseconds(1));
	}

	if (sleep_time > passed)
	{
		std::this_thread::sleep_for(std::chrono::microseconds(sleep_time - passed));
	}

	return CELL_OK;
}
Example #15
0
s32 sys_timer_destroy(u32 timer_id)
{
	sys_timer.warning("sys_timer_destroy(timer_id=0x%x)", timer_id);

	LV2_LOCK;

	const auto timer = idm::get<lv2_timer_t>(timer_id);

	if (!timer)
	{
		return CELL_ESRCH;
	}

	if (!timer->port.expired())
	{
		return CELL_EISCONN;
	}

	idm::remove<lv2_timer_t>(timer_id);

	return CELL_OK;
}
Example #16
0
s32 sys_raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat)
{
    sys_spu.Log("sys_raw_spu_set_int_stat(id=%d, class_id=%d, stat=0x%llx)", id, class_id, stat);

    if (class_id != 0 && class_id != 2)
    {
        return CELL_EINVAL;
    }

    const auto thread = Emu.GetCPU().GetRawSPUThread(id);

    if (!thread)
    {
        return CELL_ESRCH;
    }

    auto& tag = class_id ? thread->int2 : thread->int0;

    tag.clear(stat);

    return CELL_OK;
}
Example #17
0
s32 sys_raw_spu_get_int_stat(u32 id, u32 class_id, vm::ptr<u64> stat)
{
    sys_spu.Log("sys_raw_spu_get_int_stat(id=%d, class_id=%d, stat=*0x%x)", id, class_id, stat);

    if (class_id != 0 && class_id != 2)
    {
        return CELL_EINVAL;
    }

    const auto thread = Emu.GetCPU().GetRawSPUThread(id);

    if (!thread)
    {
        return CELL_ESRCH;
    }

    auto& tag = class_id ? thread->int2 : thread->int0;

    *stat = tag.stat.load();

    return CELL_OK;
}
Example #18
0
s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_t> event_array, s32 size, vm::ptr<u32> number)
{
	sys_event.Log("sys_event_queue_tryreceive(equeue_id=0x%x, event_array=*0x%x, size=%d, number=*0x%x)", equeue_id, event_array, size, number);

	LV2_LOCK;

	const auto queue = idm::get<lv2_event_queue_t>(equeue_id);

	if (!queue)
	{
		return CELL_ESRCH;
	}

	if (size < 0)
	{
		throw EXCEPTION("Negative size");
	}

	if (queue->type != SYS_PPU_QUEUE)
	{
		return CELL_EINVAL;
	}

	s32 count = 0;

	while (queue->sq.empty() && count < size && queue->events.size())
	{
		auto& dest = event_array[count++];

		std::tie(dest.source, dest.data1, dest.data2, dest.data3) = queue->events.front();

		queue->events.pop_front();
	}

	*number = count;

	return CELL_OK;
}
Example #19
0
//178
s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
{
	sc_spu.Warning("sys_spu_thread_group_join(id=%d, cause_addr=0x%x, status_addr=0x%x)", id, cause.GetAddr(), status.GetAddr());

	SpuGroupInfo* group_info;
	if(!Emu.GetIdManager().GetIDData(id, group_info))
	{
		return CELL_ESRCH;
	}

	if (group_info->lock.exchange(1)) // acquire lock
	{
		return CELL_EBUSY;
	}

	cause = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT;
	status = 0; //unspecified because of ALL_THREADS_EXIT

	for (u32 i = 0; i < group_info->list.size(); i++)
	{
		while (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
		{
			if (!t->IsRunning())
			{
				break;
			}
			if (Emu.IsStopped())
			{
				LOG_WARNING(Log::SPU, "sys_spu_thread_group_join(id=%d, ...) aborted", id);
				return CELL_OK;
			}
			std::this_thread::sleep_for(std::chrono::milliseconds(1));
		}
	}

	group_info->lock = 0; // release lock
	return CELL_OK;
}
Example #20
0
s32 sys_interrupt_thread_establish(vm::ptr<be_t<u32>> ih, u32 intrtag, u64 intrthread, u64 arg)
{
	sys_interrupt.Warning("sys_interrupt_thread_establish(ih_addr=0x%x, intrtag=%d, intrthread=%lld, arg=0x%llx)", ih.addr(), intrtag, intrthread, arg);

	u32 id = intrtag & 0xff;
	u32 class_id = intrtag >> 8;
	RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);

	if (!t || class_id > 2 || class_id == 1)
	{
		return CELL_ESRCH;
	}

	if (!t->m_intrtag[class_id].enabled)
	{
		return CELL_ESRCH;
	}

	if (t->m_intrtag[class_id].thread) // ???
	{
		return CELL_ESTAT;
	}

	CPUThread* it = Emu.GetCPU().GetThread(intrthread);
	if (!it)
	{
		return CELL_ESRCH;
	}

	if (it->m_has_interrupt || !it->m_is_interrupt)
	{
		return CELL_EAGAIN;
	}

	*ih = (t->m_intrtag[class_id].thread = intrthread);
	it->m_interrupt_arg = arg;
	return CELL_OK;
}
Example #21
0
s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
{
	sys_event.Warning("sys_event_queue_destroy(equeue_id=0x%x, mode=%d)", equeue_id, mode);

	LV2_LOCK;

	const auto queue = Emu.GetIdManager().get<lv2_event_queue_t>(equeue_id);

	if (!queue)
	{
		return CELL_ESRCH;
	}

	if (mode && mode != SYS_EVENT_QUEUE_DESTROY_FORCE)
	{
		return CELL_EINVAL;
	}

	if (!mode && queue->waiters)
	{
		return CELL_EBUSY;
	}

	if (queue->cancelled.exchange(true))
	{
		throw EXCEPTION("Unexpected value");
	}

	if (queue->waiters)
	{
		queue->cv.notify_all();
	}

	Emu.GetEventManager().UnregisterKey(queue->key);
	Emu.GetIdManager().remove<lv2_event_queue_t>(equeue_id);

	return CELL_OK;
}
Example #22
0
s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_data> event_array, int size, vm::ptr<be_t<u32>> number)
{
	sys_event.Todo("sys_event_queue_tryreceive(equeue_id=%d, event_array_addr=0x%x, size=%d, number_addr=0x%x)",
		equeue_id, event_array.addr(), size, number.addr());

	EventQueue* eq;
	if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
	{
		return CELL_ESRCH;
	}

	if (eq->type != SYS_PPU_QUEUE)
	{
		return CELL_EINVAL;
	}

	if (size == 0)
	{
		*number = 0;
		return CELL_OK;
	}

	u32 tid = GetCurrentPPUThread().GetId();

	eq->sq.m_mutex.lock();
	eq->owner.lock(tid);
	if (eq->sq.list.size())
	{
		*number = 0;
		eq->owner.unlock(tid);
		eq->sq.m_mutex.unlock();
		return CELL_OK;
	}
	*number = eq->events.pop_all(event_array.get_ptr(), size);
	eq->owner.unlock(tid);
	eq->sq.m_mutex.unlock();
	return CELL_OK;
}
Example #23
0
//173
int sys_spu_thread_group_start(u32 id)
{
	sc_spu.Warning("sys_spu_thread_group_start(id=0x%x)", id);

	if(!Emu.GetIdManager().CheckID(id))
	{
		return CELL_ESRCH;
	}

	ID& id_data = Emu.GetIdManager().GetIDData(id);
	SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data;

	//Emu.Pause();
	for(int i=0; i<g_spu_group_thr_count; i++)
	{
		if(group_info.threads[i])
		{
			group_info.threads[i]->Exec();
		}
	}

	return CELL_OK;
}
Example #24
0
s32 sys_raw_spu_get_int_stat(u32 id, u32 class_id, mem64_t stat)
{
	sc_spu.Log("sys_raw_spu_get_int_stat(id=%d, class_id=%d, stat_addr=0xx)", id, class_id, stat.GetAddr());

	if (!stat.IsGood())
	{
		return CELL_EFAULT;
	}

	RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
	if (!t)
	{
		return CELL_ESRCH;
	}

	if (class_id != 0 && class_id != 2)
	{
		return CELL_EINVAL;
	}

	stat = t->m_intrtag[class_id].stat;
	return CELL_OK;
}
Example #25
0
s32 sys_raw_spu_get_int_mask(u32 id, u32 class_id, mem64_t mask)
{
	sc_spu.Log("sys_raw_spu_get_int_mask(id=%d, class_id=%d, mask_addr=0x%x)", id, class_id, mask.GetAddr());

	if (!mask.IsGood())
	{
		return CELL_EFAULT;
	}

	RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id);
	if (!t)
	{
		return CELL_ESRCH;
	}

	if (class_id != 0 && class_id != 2)
	{
		return CELL_EINVAL;
	}

	mask = t->m_intrtag[class_id].mask;
	return CELL_OK;
}
Example #26
0
//173
int sys_spu_thread_group_start(u32 id)
{
    sc_spu.Warning("sys_spu_thread_group_start(id=%d)", id);

    SpuGroupInfo* group_info;
    if(!Emu.GetIdManager().GetIDData(id, group_info))
    {
        return CELL_ESRCH;
    }

    // TODO: check group state

    for (u32 i = 0; i < group_info->list.size(); i++)
    {
        CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]);
        if (t)
        {
            t->Exec();
        }
    }

    return CELL_OK;
}
Example #27
0
s32 sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond)
{
	sys_lwcond.Warning("sys_lwcond_destroy(lwcond_addr=0x%x)", lwcond.addr());

	LV2_LOCK(0);

	u32 id = lwcond->lwcond_queue;

	Lwcond* lw;
	if (!Emu.GetIdManager().GetIDData(id, lw))
	{
		return CELL_ESRCH;
	}

	if (!lw->m_queue.finalize())
	{
		return CELL_EBUSY;
	}

	Emu.GetIdManager().RemoveID(id);
	Emu.GetSyncPrimManager().EraseSyncPrimData(TYPE_LWCOND, id);
	return CELL_OK;
}
Example #28
0
s32 sys_timer_disconnect_event_queue(u32 timer_id)
{
	sys_timer.Warning("sys_timer_disconnect_event_queue(timer_id=0x%x)", timer_id);

	LV2_LOCK;

	const auto timer = idm::get<lv2_timer_t>(timer_id);

	if (!timer)
	{
		return CELL_ESRCH;
	}

	if (timer->port.expired())
	{
		return CELL_ENOTCONN;
	}

	timer->port.reset(); // disconnect event queue
	timer->state = SYS_TIMER_STATE_STOP; // stop timer

	return CELL_OK;
}
Example #29
0
//171
int sys_spu_thread_group_destroy(u32 id)
{
	sc_spu.Warning("sys_spu_thread_group_destroy(id=%d)", id);

	SpuGroupInfo* group_info;
	if(!Emu.GetIdManager().GetIDData(id, group_info))
	{
		return CELL_ESRCH;
	}

	if (group_info->lock) // ???
	{
		return CELL_EBUSY;
	}

	for (u32 i = 0; i < group_info->list.GetCount(); i++)
	{
		Emu.GetCPU().RemoveThread(group_info->list[i]);
	}

	Emu.GetIdManager().RemoveID(id);
	return CELL_OK;
}
Example #30
0
s32 sys_cond_signal_all(u32 cond_id)
{
	sys_cond.Log("sys_cond_signal_all(cond_id=0x%x)", cond_id);

	LV2_LOCK;

	const auto cond = Emu.GetIdManager().get<lv2_cond_t>(cond_id);

	if (!cond)
	{
		return CELL_ESRCH;
	}

	// signal all waiting threads; protocol is ignored in current implementation
	for (auto it = cond->sq.begin(); it != cond->sq.end(); it++)
	{
		cond->notify(lv2_lock, it);
	}

	cond->sq.clear();

	return CELL_OK;
}