Exemple #1
0
s32 sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout)
{
	sys_semaphore.trace("sys_semaphore_wait(sem_id=0x%x, timeout=0x%llx)", sem_id, timeout);

	const u64 start_time = get_system_time();

	LV2_LOCK;

	const auto sem = idm::get<lv2_sema_t>(sem_id);

	if (!sem)
	{
		return CELL_ESRCH;
	}

	if (sem->value > 0)
	{
		sem->value--;
		
		return CELL_OK;
	}

	// add waiter; protocol is ignored in current implementation
	sleep_entry<cpu_thread> waiter(sem->sq, ppu);

	while (!ppu.state.test_and_reset(cpu_state::signal))
	{
		CHECK_EMU_STATUS;

		if (timeout)
		{
			const u64 passed = get_system_time() - start_time;

			if (passed >= timeout)
			{
				return CELL_ETIMEDOUT;
			}

			get_current_thread_cv().wait_for(lv2_lock, std::chrono::microseconds(timeout - passed));
		}
		else
		{
			get_current_thread_cv().wait(lv2_lock);
		}
	}

	return CELL_OK;
}
Exemple #2
0
bool cpu_thread::check_status()
{
	std::unique_lock<std::mutex> lock(get_current_thread_mutex(), std::defer_lock);

	while (true)
	{
		CHECK_EMU_STATUS; // check at least once

		if (state & cpu_state::exit)
		{
			return true;
		}

		if (!state.test(cpu_state_pause) && !state.test(cpu_state::interrupt))
		{
			break;
		}

		if (!lock)
		{
			lock.lock();
			continue;
		}

		if (!state.test(cpu_state_pause) && state & cpu_state::interrupt && handle_interrupt())
		{
			continue;
		}

		get_current_thread_cv().wait(lock);
	}

	const auto state_ = state.load();

	if (state_ & make_bitset(cpu_state::ret, cpu_state::stop))
	{
		return true;
	}

	if (state_ & cpu_state::dbg_step)
	{
		state += cpu_state::dbg_pause;
		state -= cpu_state::dbg_step;
	}

	return false;
}
Exemple #3
0
void cpu_thread::on_task()
{
	state -= cpu_state::exit;

	g_tls_current_cpu_thread = this;

	Emu.SendDbgCommand(DID_CREATE_THREAD, this);

	std::unique_lock<std::mutex> lock(get_current_thread_mutex());

	// Check thread status
	while (!(state & cpu_state::exit))
	{
		CHECK_EMU_STATUS;

		// check stop status
		if (!(state & cpu_state::stop))
		{
			if (lock) lock.unlock();

			try
			{
				cpu_task();
			}
			catch (cpu_state _s)
			{
				state += _s;
			}
			catch (const std::exception&)
			{
				LOG_NOTICE(GENERAL, "\n%s", dump());
				throw;
			}

			state -= cpu_state::ret;
			continue;
		}

		if (!lock)
		{
			lock.lock();
			continue;
		}

		get_current_thread_cv().wait(lock);
	}
}
Exemple #4
0
void lv2_int_serv_t::join(ppu_thread& ppu, lv2_lock_t lv2_lock)
{
	// Enqueue _sys_ppu_thread_exit call
	thread->cmd_list
	({
		{ ppu_cmd::set_args, 1 }, u64{0},
		{ ppu_cmd::set_gpr, 11 }, u64{41},
		{ ppu_cmd::opcode, ppu_instructions::SC(0) },
	});

	thread->lock_notify();

	// Join thread (TODO)
	while (!test(thread->state & cpu_flag::exit))
	{
		CHECK_EMU_STATUS;

		get_current_thread_cv().wait_for(lv2_lock, 1ms);
	}

	// Cleanup
	idm::remove<lv2_int_serv_t>(id);
}