lib/ldso: coalesce RPC calls for ROM dataspaces

A dataspace capability request to a ROM service may invalidate any
previously issued dataspace. Therefor no requests should be made while a
session dataspace is mapped. Reducing calls to the session also improves
performance where servicing a ROM request has a significant cost.

Fix #2418
This commit is contained in:
Emery Hemingway
2017-05-18 15:21:24 -05:00
committed by Christian Helmuth
parent 5f27c7b9eb
commit 419da32ee3

View File

@ -77,13 +77,13 @@ struct Linker::Elf_file : File
{ {
Env &env; Env &env;
Constructible<Rom_connection> rom_connection; Constructible<Rom_connection> rom_connection;
Rom_session_client rom; Rom_dataspace_capability rom_cap;
Ram_dataspace_capability ram_cap[Phdr::MAX_PHDR]; Ram_dataspace_capability ram_cap[Phdr::MAX_PHDR];
bool const loaded; bool const loaded;
typedef String<64> Name; typedef String<64> Name;
Rom_session_capability _rom_cap(Name const &name) Rom_dataspace_capability _rom_dataspace(Name const &name)
{ {
/* request the linker and binary from the component environment */ /* request the linker and binary from the component environment */
Session_capability cap; Session_capability cap;
@ -91,16 +91,18 @@ struct Linker::Elf_file : File
cap = env.parent().session_cap(Parent::Env::binary()); cap = env.parent().session_cap(Parent::Env::binary());
if (name == linker_name()) if (name == linker_name())
cap = env.parent().session_cap(Parent::Env::linker()); cap = env.parent().session_cap(Parent::Env::linker());
if (cap.valid()) if (cap.valid()) {
return reinterpret_cap_cast<Rom_session>(cap); Rom_session_client client(reinterpret_cap_cast<Rom_session>(cap));
return client.dataspace();
}
rom_connection.construct(env, name.string()); rom_connection.construct(env, name.string());
return *rom_connection; return rom_connection->dataspace();
} }
Elf_file(Env &env, Allocator &md_alloc, char const *name, bool load) Elf_file(Env &env, Allocator &md_alloc, char const *name, bool load)
: :
env(env), rom(_rom_cap(name)), loaded(load) env(env), rom_cap(_rom_dataspace(name)), loaded(load)
{ {
load_phdr(); load_phdr();
@ -150,7 +152,7 @@ struct Linker::Elf_file : File
{ {
{ {
/* temporary map the binary to read the program header */ /* temporary map the binary to read the program header */
Attached_dataspace ds(env.rm(), rom.dataspace()); Attached_dataspace ds(env.rm(), rom_cap);
Elf::Ehdr const &ehdr = *ds.local_addr<Elf::Ehdr>(); Elf::Ehdr const &ehdr = *ds.local_addr<Elf::Ehdr>();
@ -242,7 +244,7 @@ struct Linker::Elf_file : File
*/ */
void load_segment_rx(Elf::Phdr const &p) void load_segment_rx(Elf::Phdr const &p)
{ {
Region_map::r()->attach_executable(rom.dataspace(), Region_map::r()->attach_executable(rom_cap,
trunc_page(p.p_vaddr) + reloc_base, trunc_page(p.p_vaddr) + reloc_base,
round_page(p.p_memsz), round_page(p.p_memsz),
trunc_page(p.p_offset)); trunc_page(p.p_offset));
@ -253,7 +255,7 @@ struct Linker::Elf_file : File
*/ */
void load_segment_rw(Elf::Phdr const &p, int nr) void load_segment_rw(Elf::Phdr const &p, int nr)
{ {
void *src = env.rm().attach(rom.dataspace(), 0, p.p_offset); void *src = env.rm().attach(rom_cap, 0, p.p_offset);
addr_t dst = p.p_vaddr + reloc_base; addr_t dst = p.p_vaddr + reloc_base;
ram_cap[nr] = env.ram().alloc(p.p_memsz); ram_cap[nr] = env.ram().alloc(p.p_memsz);