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