RFR: 8297389: resexhausted003 fails with assert(!thread->owns_locks()) failed: must release all locks when leaving VM
David Holmes
dholmes at openjdk.org
Wed Nov 23 21:46:24 UTC 2022
On Wed, 23 Nov 2022 11:56:45 GMT, Tobias Hartmann <thartmann at openjdk.org> wrote:
> `Method::build_profiling_method_data` acquires the `MethodData_lock` when initializing `Method::_method_data` to prevent multiple allocations by different threads. The problem is that when metaspace allocation fails and `JvmtiExport::should_post_resource_exhausted()` is set, we assert during the `ThreadToNativeFromVM` transition in JVMTI code.
>
> Since concurrent initialization is a rare event, I suggest to get rid of the lock and perform the initialization with a `cmpxchg`, similar to how method counters are initialized:
> https://github.com/openjdk/jdk/blob/f4b5065c37e86f4b2ca26da6ce678febe4a52950/src/hotspot/share/oops/method.cpp#L644-L646
>
> Since [current code](https://github.com/openjdk/jdk/blob/f4b5065c37e86f4b2ca26da6ce678febe4a52950/src/hotspot/share/oops/method.inline.hpp#L41-L46) in `Method::set_method_data` uses a `Atomic::release_store`, I added a `OrderAccess::release()`.
>
> Thanks,
> Tobias
If `MethodData::allocate` cannot be called whilst holding a lock then perhaps we can assert that in there?
I think there is a broader problem here that metaspace allocation can occur in numerous places and any failure could post the resource-exhausted event and potentially lead to problems like this.
This fix side-steps one problematic call-site, but going lock-free has its own concerns.
src/hotspot/share/oops/method.cpp line 594:
> 592:
> 593: ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
> 594: MethodData* method_data = MethodData::allocate(loader_data, method, THREAD);
So the downside of lock-free here is that we have to pre-allocate and then later free. How expensive is that? How likely are we to get multiple threads attempting this at the same time? We might trigger a resource-exhausted event unnecessarily due to the temporary use of metaspace.
src/hotspot/share/oops/method.cpp line 604:
> 602: // total store order (TSO) the reference may become visible before
> 603: // the initialization of data otherwise.
> 604: OrderAccess::release();
A release here is not necessary as `Atomic::replace_if_null` will by default have `memory_order_conservative` which maintains the full bi-directional fence of the internal `cmpxchg`.
-------------
Changes requested by dholmes (Reviewer).
PR: https://git.openjdk.org/jdk/pull/11316
More information about the hotspot-dev
mailing list