The usage of fence.i in openjdk
Vladimir Kempik
vladimir.kempik at gmail.com
Sat Jul 30 10:29:59 UTC 2022
Hello
Thanks for explanation.
that sounds like the fence.i in userspace code is not needed at all
Regards, Vladimir
> 30 июля 2022 г., в 05:41, wangyadong (E) <yadonn.wang at huawei.com> написал(а):
>
>> Lets say you have a thread A running on hart 1.
>> You've changed some code in region 0x11223300 and need fence.i before executing that code.
>> you execute fence.i in your thread A running on hart 1.
>> right after that your thread ( for some reason) got rescheduled ( by kernel) to hart 2.
>> if hart 2 had something in l1i corresponding to region 0x11223300, then you gonna have a problem: l1i on hart 2 has old code, it wasn’t refreshed, because fence.i was executed on hart 1 ( and never on hart 2). And you thread gonna execute old code, or mix of old and new code.
>
> @vladimir Thanks for your explanation. I understand your concern now. We know the fence.i's scope, so the write hart does not rely solely on the fence.i in RISC-V port, but calls the icache_flush syscall in ICache::invalidate_range() every time after modifying the code.
>
> For example:
> Hart 1
> void MacroAssembler::emit_static_call_stub() {
> // CompiledDirectStaticCall::set_to_interpreted knows the
> // exact layout of this stub.
>
> ifence();
> mov_metadata(xmethod, (Metadata*)NULL); <- patchable code here
>
> // Jump to the entry point of the i2c stub.
> int32_t offset = 0;
> movptr_with_offset(t0, 0, offset);
> jalr(x0, t0, offset);
> }
>
> Hart 2 (write hart)
> void NativeMovConstReg::set_data(intptr_t x) {
> // ...
> // Store x into the instruction stream.
> MacroAssembler::pd_patch_instruction_size(instruction_address(), (address)x); <- write code
> ICache::invalidate_range(instruction_address(), movptr_instruction_size); <- syscall here
> // ...
> }
>
More information about the riscv-port-dev
mailing list