RFR: 8203227: Introduce os::processor_id() for Linux and Solaris
David Holmes
david.holmes at oracle.com
Wed May 16 22:14:22 UTC 2018
On 16/05/2018 10:54 PM, Per Liden wrote:
> Hi David,
>
> On 05/16/2018 02:16 PM, David Holmes wrote:
> [...]
>>>>> We're using this in ZGC to do various CPU-local operations. We
>>>>> currently
>>>>
>>>> So there's a requirement that the CPU value returned by
>>>> processor_id() is compatible with some other API's that take a
>>>> processor id? Does that need documenting in some form?
>>>
>>> Good point, this should be made more clear. We currently assume that
>>> os::processor_id() returns a value from 0 to (os::processor_count() -
>>> 1). Adding a comment in os.hpp clarifying that.
>>
>> Thanks. Not every value in that range may be a valid processor id, but
>> every valid processor id should be within that range.
>
> Yep.
>
>>
>>>>> only need this for Linux and Solaris, which is what this patch adds.
>>>>
>>>> Are the API's that take the processor id defined in os as well?
>>>> Otherwise it seems this functionality should just be localized to
>>>> the specific os_<os>.cpp file from which it is used (and/or the
>>>> os::<OS> class).
>>>
>>> The os::processor_id() call-sites we have are in shared os-agnostic
>>> code. This function is also fairly closely related to
>>> os::processor_count(), so it seems like os:: would be the natural
>>> place for this.
>>
>> I'm curious as to what functions in os-agnostic code consume the
>> processor id value? Or are you storing/caching it in the shared code
>> and only using it later from OS specific code?
>
> The typical way we use this in ZGC is to have CPU-local data,
> conceptually equivalent to this toy example:
>
> // Allocate per-CPU data
> MyData* my_per_cpu_data = alloc(sizeof(MyData) * os::processor_count());
>
> // Read CPU-local data
> ... = my_per_cpu_data[os::processor_id()];
Ah! I see. Not what I initially expected - I thought you'd end up using
the id to pass to some other OS specific function to "operate" with
respect to a given cpu. But it's simply an index for "cpu-local" data.
Thanks,
David
------
> Have a look at the ZPerCPU template class if you're interested in more
> details:
> http://hg.openjdk.java.net/zgc/zgc/file/118cb3e3517d/src/hotspot/share/gc/z/zValue.hpp
>
>
> This template basically allows us to just say:
>
> // Allocate per-CPU data
> ZPerCPU<MyData> my_per_cpu_data;
>
> // Read CPU-local data
> ... = my_per_cpu_data.get();
>
> It should be noted that ZGC is only ever built (controlled by sh
> configure) for supported platforms (Linux & Solaris at this moment),
> which is why it's fine to have os::processor_id() calls in this shared
> code.
>
>>
>>>>
>>>>> Support for additional platforms can be added when needed. I didn't
>>>>> add dummy os::processor_id() to the not-yet-implemented platforms,
>>>>> since I think it's better to get a early compile-time error instead
>>>>> of a Unimplemented() at runtime, if you try to use them.
>>>>
>>>> I'd rather not see the runtime support of our primary platforms of
>>>> interest fragmented like this. Are there technical challenges to
>>>> doing this?
>>>
>>> I'm a bit reluctant to add this for other platforms at this point,
>>> since some platforms might require non-trivial implementations, which
>>> would go unused/untested. For macOS I believe we would need something
>>> like this:
>>>
>>> http://cr.openjdk.java.net/~gziemski/zgc_os_processor_id/webrev/src/hotspot/os/bsd/os_bsd.cpp.udiff.html
>>
>>
>>
>> Yeah direct use of cpuid is not pleasant.
>>
>>> (I should add that I don't know if this patch does the right thing,
>>> but Gerard apparently had some success with it)
>>>
>>> For Windows, I believe a call to GetCurrentProcessorNumber() should
>>> be enough (we don't seem to handle/support logical processor groups
>>> in os::processor_count() so should be safe to do the same thing here).
>>
>> The current processor should always be correct regardless of what
>> logical/virtual processor configuration exists.
>
> Check.
>
>>
>>> The plan has been to add support for these if/when ZGC supports these
>>> platforms (unless someone else needs and adds them before that). But
>>> adding them now makes me a bit uneasy, especially given the
>>> non-trivial nature of the macOS implementation.
>>
>> Okay. I'd prefer to see all platforms covered, but not with the risk
>> of untested code being used.
>>
>>>>
>>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8203227
>>>>> Webrev: http://cr.openjdk.java.net/~pliden/8203227/webrev.0
>>>>
>>>> For Solaris there is no need to introduce Solaris::getcpuid() just
>>>> because Linux already has that. (Unless this ends up not being
>>>> needed in the os class of course :) ).
>>>
>>> Check.
>>>
>>>>
>>>> Are you allowing for the -1 return value on Linux or assuming it
>>>> will never happen in practice? If the former then that should be
>>>> documented as part of the semantics of os::processor_id(). If the
>>>> latter then you should probably add an assert or guarantee. I
>>>> suspect this is a historical restriction no longer relevant to us -
>>>> in which case we can probably clean out the dynamic lookup/linking!).
>>>
>>> We're assuming it will never happen in practice, and this is
>>> currently guarded with a guarantee() during initialization of ZGC.
>>> sched_getcpu() has "only" been around since glibc 2.14 (June 2011).
>>> However, we can also receive -1 if the kernel doesn't have the
>>> getcpu() syscall (first introduced in Linux 2.6.19, Nov 2006).
>>>
>>> So, it seems safe to at least assume that the getcpu() syscall is
>>> available, and only have an single check for that during startup
>>> (with a vm_exit_during_initialization() if it's unavailable).
>>
>> Okay. We should clean up the syscall and dynamic lookup code use here.
>>
>>> Here's an updated webrev for continued discussion:
>>>
>>> http://cr.openjdk.java.net/~pliden/8203227/webrev.1
>>
>> Looks fine to me.
>
> Ok, thanks David!
>
> /Per
>
>>
>> Thanks,
>> David
>>
>>> cheers,
>>> Per
>>>
>>>>
>>>> Thanks,
>>>> David
>>>>
>>>>> /Per
More information about the hotspot-dev
mailing list