Skip to content

Commit

Permalink
Remove each_frame and some unused system calls
Browse files Browse the repository at this point in the history
  • Loading branch information
fwsGonzo committed Jan 14, 2024
1 parent c5a399c commit 936a53e
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 172 deletions.
26 changes: 1 addition & 25 deletions engine/scripts/src/level1_threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,33 +41,9 @@ void do_threads_stuff()
auto retval = microthread::join(thread);
print("Full thread exited, return value: ", retval, "\n");

/* GDB can be automatically opened at this point. */
Game::breakpoint();

/* Create events that will run each physics tick.
We will be waiting immediately, so that we don't run the
event code now, but instead when each tick happens. */
each_tick(
[]
{
while (true)
{
wait_next_tick();
static int i = 0;
print("Tick ", i++, "!\n");
}
});
int physics_value = 44;
each_tick(
[physics_value]
{
int v = physics_value;
while (true)
{
wait_next_tick();
print("I have a ", v++, "!\n");
}
});

/* This creates a new thread with no arguments and immediately starts
executing it. The sleep() will block the thread until some time has
passed, and then resume. At the end we make a remote function call
Expand Down
5 changes: 0 additions & 5 deletions engine/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,6 @@ int main()

level2.call("start");

strf::to(stdout)("...\n");
/* Simulate some physics ticks */
for (int n = 0; n < 3; n++)
level1.each_tick_event();

strf::to(stdout)("...\n");
/* Ordinarily a game engine has a physics loop that ticks regularly,
but we don't in this example. Instead we will just sleep until
Expand Down
20 changes: 0 additions & 20 deletions engine/src/script/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ void Script::add_shared_memory()

bool Script::initialize()
{
// clear some state belonging to previous initialization
this->m_tick_event = 0;
// run through the initialization
try
{
Expand Down Expand Up @@ -306,24 +304,6 @@ std::string Script::symbol_name(gaddr_t address) const
return callsite.name;
}

void Script::each_tick_event()
{
if (this->m_tick_event == 0)
return;
auto& mt = machine().threads();
assert(mt.get_tid() == 0 && "Avoid clobbering regs");

int count = 0;
for (auto* thread : mt.blocked_threads())
{
if (thread->block_word == this->m_tick_block_word)
count++;
}
this->preempt(
this->m_tick_event, (int)count, (int)this->m_tick_block_word);
assert(mt.get_thread()->tid == 0 && "Avoid clobbering regs");
}

void Script::set_dynamic_call(const std::string& def, ghandler_t handler)
{
// Uses the definition as both name and hash
Expand Down
73 changes: 54 additions & 19 deletions engine/src/script/script.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,62 @@ struct Script
/// @brief The max number of instructions allowed during calls
static constexpr uint64_t MAX_CALL_INSTR = 32'000'000ull;

// Call any script function, with any parameters
/// @brief Make a function call into the script
/// @param func The function to call. Must be a visible symbol in the program.
/// @param args The arguments to pass to the function.
/// @return The optional integral return value.
template <typename... Args>
long call(const std::string& name, Args&&...);
long call(const std::string& func, Args&&... args);

/// @brief Make a function call into the script
/// @param addr The functions direct address.
/// @param args The arguments to pass to the function.
/// @return The optional integral return value.
template <typename... Args>
long call(gaddr_t addr, Args&&...);

long call(gaddr_t addr, Args&&... args);

/// @brief Make a preempted function call into the script, saving and
/// restoring the current execution state.
/// Preemption allows callers to temporarily interrupt the virtual machine,
/// such that it can be resumed like normal later on.
/// @param func The function to call. Must be a visible symbol in the program.
/// @param args The arguments to the function call.
/// @return The optional integral return value.
template <typename... Args>
long preempt(const std::string& func, Args&&... args);

/// @brief Make a preempted function call into the script, saving and
/// restoring the current execution state.
/// Preemption allows callers to temporarily interrupt the virtual machine,
/// such that it can be resumed like normal later on.
/// @param addr The functions address to call.
/// @param args The arguments to the function call.
/// @return The optional integral return value.
template <typename... Args>
long preempt(gaddr_t addr, Args&&...);
long preempt(gaddr_t addr, Args&&... args);

// Run for a bit, then stop
/// @brief Resume execution of the script, until @param instruction_count has been reached,
/// then stop execution and return. This function can be used to drive long-running tasks
/// over time, by continually resuming them.
/// @param instruction_count The max number of instructions to execute before returning.
void resume(uint64_t instruction_count);

/// @brief Returns the pointer provided at instantiation of the Script instance.
/// @tparam T The real type of the user-provided pointer.
/// @return Returns the user-provided pointer.
template <typename T> T* userptr() noexcept
{
return (T*)m_userptr;
}

/// @brief Returns the pointer provided at instantiation of the Script instance.
/// @tparam T The real type of the user-provided pointer.
/// @return Returns the user-provided pointer.
template <typename T> const T* userptr() const noexcept
{
return (const T*)m_userptr;
}

void set_tick_event(gaddr_t addr, int reason)
{
this->m_tick_event = addr;
this->m_tick_block_word = reason;
}

void each_tick_event();

// Install a callback function using a string name
// Can be invoked from the guest using the same string name
static void set_dynamic_call(const std::string& def, ghandler_t);
Expand Down Expand Up @@ -201,8 +226,6 @@ struct Script
std::shared_ptr<const std::vector<uint8_t>> m_binary;
void* m_userptr;
gaddr_t m_heap_area = 0;
gaddr_t m_tick_event = 0;
uint32_t m_tick_block_word = 0;
std::string m_name;
std::string m_filename;
uint32_t m_hash;
Expand Down Expand Up @@ -263,13 +286,13 @@ inline long Script::call(gaddr_t address, Args&&... args)
template <typename... Args>
inline long Script::call(const std::string& func, Args&&... args)
{
const auto address = machine().address_of(func.c_str());
if (UNLIKELY(address == 0))
const auto address = this->address_of(func.c_str());
if (UNLIKELY(address == 0x0))
{
this->could_not_find(func);
return -1;
}
return call(address, std::forward<Args>(args)...);
return this->call(address, std::forward<Args>(args)...);
}

template <typename... Args>
Expand All @@ -287,6 +310,18 @@ inline long Script::preempt(gaddr_t address, Args&&... args)
return -1;
}

template <typename... Args>
inline long Script::preempt(const std::string& func, Args&&... args)
{
const auto address = this->address_of(func.c_str());
if (UNLIKELY(address == 0x0))
{
this->could_not_find(func);
return -1;
}
return this->preempt(address, std::forward<Args>(args)...);
}

inline void Script::resume(uint64_t cycles)
{
try
Expand Down
50 changes: 1 addition & 49 deletions engine/src/script/script_syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,34 +66,6 @@ APICALL(api_measure)
machine.set_result(time_ns);
}

template <bool Preempt = false>
inline void do_farcall(machine_t& machine, Script& dest, gaddr_t addr)
{
// copy argument registers (1 less integer register)
const auto& current = machine.cpu.registers();
auto& regs = dest.machine().cpu.registers();
for (int i = 0; i < 6; i++)
{
regs.get(10 + i) = current.get(12 + i);
}
for (int i = 0; i < 8; i++)
{
regs.getfl(10 + i) = current.getfl(10 + i);
}

// vmcall with no arguments to avoid clobbering registers
if constexpr (!Preempt)
{
machine.set_result(dest.call(addr));
}
else
{
machine.set_result(dest.preempt(addr));
}
// we short-circuit the ret pseudo-instruction:
machine.cpu.jump(machine.cpu.reg(riscv::REG_RA) - 4);
}

APICALL(api_dyncall)
{
auto& regs = machine.cpu.registers();
Expand All @@ -114,31 +86,14 @@ APICALL(api_dyncall_args)
scr.dynargs().clear();
}

APICALL(api_farcall)
{
machine.set_result(-1);
}

APICALL(api_farcall_direct)
{
machine.set_result(-1);
}

APICALL(api_interrupt)
{
machine.set_result(-1);
}

APICALL(api_machine_hash)
{
machine.set_result(script(machine).hash());
}

APICALL(api_each_frame)
{
auto [addr, reason] = machine.sysargs<gaddr_t, int>();
script(machine).set_tick_event(addr, reason);
machine.set_result(0);
machine.set_result(-1);
}

APICALL(api_game_setting)
Expand Down Expand Up @@ -220,9 +175,6 @@ void Script::setup_syscall_interface()
{ECALL_MEASURE, api_measure},
{ECALL_DYNCALL, api_dyncall},
{ECALL_DYNARGS, api_dyncall_args},
{ECALL_FARCALL, api_farcall},
{ECALL_FARCALL_DIRECT, api_farcall_direct},
{ECALL_INTERRUPT, api_interrupt},
{ECALL_MACHINE_HASH, api_machine_hash},
{ECALL_EACH_FRAME, api_each_frame},

Expand Down
5 changes: 0 additions & 5 deletions programs/micro/api/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,6 @@ namespace api
static Label label(Widget& parent, const std::string& text);
};

/** Events **/
template <typename T, typename... Args>
void each_tick(const T& func, Args&&... args);
void wait_next_tick();

/** Timers **/

struct Timer
Expand Down
23 changes: 0 additions & 23 deletions programs/micro/api/api_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,29 +80,6 @@ inline uint32_t Game::current_machine()

#define RUNNING_ON(mach) (api::current_machine() == crc32(mach))

inline void each_frame_helper(int count, int reason)
{
for (int i = 0; i < count; i++)
microthread::wakeup_one_blocked(reason);
}

inline void wait_next_tick()
{
microthread::block(REASON_FRAME);
}

template <typename T, typename... Args>
inline void each_tick(const T& func, Args&&... args)
{
static bool init = false;
if (!init)
{
init = true;
(void)syscall(ECALL_EACH_FRAME, (long)each_frame_helper, REASON_FRAME);
}
microthread::oneshot(func, std::forward<Args>(args)...);
}

/** Game **/

inline void Game::exit()
Expand Down
11 changes: 4 additions & 7 deletions programs/micro/api/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@
#define ECALL_MEASURE (GAME_API_BASE+3)
#define ECALL_DYNCALL (GAME_API_BASE+4)
#define ECALL_DYNARGS (GAME_API_BASE+5)
#define ECALL_FARCALL (GAME_API_BASE+6)
#define ECALL_FARCALL_DIRECT (GAME_API_BASE+7)
#define ECALL_INTERRUPT (GAME_API_BASE+8)
#define ECALL_MACHINE_HASH (GAME_API_BASE+9)
#define ECALL_EACH_FRAME (GAME_API_BASE+10)
#define ECALL_GAME_SETTING (GAME_API_BASE+11)
#define ECALL_GAME_EXIT (GAME_API_BASE+12)
#define ECALL_MACHINE_HASH (GAME_API_BASE+6)
#define ECALL_EACH_FRAME (GAME_API_BASE+7)
#define ECALL_GAME_SETTING (GAME_API_BASE+8)
#define ECALL_GAME_EXIT (GAME_API_BASE+9)

enum game_api_ids
{
Expand Down
19 changes: 0 additions & 19 deletions programs/micro/libc/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,3 @@ asm(".global sys_write\n"
" li a7, " STRINGIFY(ECALL_WRITE) "\n"
" ecall\n"
" ret\n");

asm(".global farcall_helper\n"
"farcall_helper:\n"
" li a7, " STRINGIFY(ECALL_FARCALL) "\n"
" ecall\n"
" ret\n");

asm(".global direct_farcall_helper\n"
"direct_farcall_helper:\n"
" li a7, " STRINGIFY(ECALL_FARCALL_DIRECT) "\n"
" ecall\n"
" ret\n");

asm(".global sys_interrupt\n"
"sys_interrupt:\n"
" li a7, " STRINGIFY(ECALL_INTERRUPT) "\n"
" ecall\n"
" ret\n"
""); // The system call handler must jump back to caller

0 comments on commit 936a53e

Please sign in to comment.