Why `pthread_rwlock_t`'s ABI differs a lot among versions?

僤鯓⒐⒋嵵緔 提交于 2021-01-29 05:53:52

问题


I am looking into different versions of implementation of pthread_rwlock_t.

  1. GLIBC2.30

    typedef union
    {
      struct __pthread_rwlock_arch_t __data;
      char __size[__SIZEOF_PTHREAD_RWLOCK_T];
      long int __align;
    } pthread_rwlock_t;
    
    struct __pthread_rwlock_arch_t
    {
      unsigned int __readers;
      unsigned int __writers;
      unsigned int __wrphase_futex;
      unsigned int __writers_futex;
      unsigned int __pad3;
      unsigned int __pad4;
      ...
    
  2. GLIBC2.17

    typedef union
    {
    # ifdef __x86_64__
      struct
      {
        int __lock;
        unsigned int __nr_readers;
        unsigned int __readers_wakeup;
        unsigned int __writer_wakeup;
        unsigned int __nr_readers_queued;
        unsigned int __nr_writers_queued;
        int __writer;
        int __shared;
    ...
    
    } pthread_rwlock_t;
    

Their implementations seem different and cause some difficulties for me. Because I have a program a which is linked to GLIBC2.30 and a program b which is linked to GLIBC2.17. Both programs will operate on the same pthread_rwlock_t which is shared on the shm. I achieved this by staticly linking GLIBC.

However, GLIBC2.30 and GLIBC2.17 will interpret the pthread_rwlock_t object on the shm differently, because their definition differ. For example, if __readers is set to 2 by GLIBC2.30 then accessed by GLIBC2.17, it will think the pthread_rwlock_t is locked and sleep on that. However, the pthread_rwlock_t is not locked.

My questions are:

  1. Why pthread_rwlock_t changes this much among versions? Is it because it want to support more features, or enhance performance?
  2. Is there any ways I can may GLIBC2.30 and GLIBC2.17 operate the same rwlock?

UPDATE

I look more source codes, and find:

  1. GLIBC2.17 uses lll_lock to implement
  2. GLIBC2.30 uses atomic operation yo implement

Then I have another question, are different versions of GLIBC not compactible with each other? So I can't use shm between different versions of GLIBC?


回答1:


  1. Why pthread_rwlock_t changes this much among versions? Is it because it want to support more features, or enhance performance?

Because the glibc maintainers decided that there was an advantage to be gained in changing it.

As with most structures defined by the standard headers, the layout of struct pthread_rwlock_t is not standardized. As with some such structures, not even any of the member names are standardized. I presume that the reason the structure is not totally opaque is so that instances can be declared directly instead of requiring them to be produced by some kind of constructor function.

You are going way out on a limb if you construct programs that depend on a specific layout of that structure, except whatever the version of pthreads you build against provides. That definition is provided by the version of pthreads.h used at compile time, and it must be matched with the corresponding library.

  1. Is there any ways I can may GLIBC2.30 and GLIBC2.17 operate the same rwlock?

I think you already know that the answer is "no". Each library implementation has direct dependencies on a specific layout of that structure, and the layouts do not coincide at all. If you want to share a pthreads rwlock among processes then, in addition to configuring its pshared attribute on, you should build the cooperating programs against the same version of libpthread and its headers (or whatever library provides your pthreads implementation). Some version skew may be acceptable in practice, but if you want to risk that then it's on you to test and validate specific combinations.

are different versions of GLIBC not compactible with each other?

Clearly the two versions involved in your particular problem are not compatible in the way you hoped. Glibc is pretty good about link compatibility:

  • a program dynamically linked against one version will very likely interoperate correctly with the shared libraries of later versions; and

  • a program that builds and statically links correctly against one version will almost certainly build and statically link correctly against later versions, even to the point of use of functions removed from the C language standard (I'm looking at you, gets()).

But there is no requirement for, nor reasonable expectation of, consistent internal representations of most structure types provided by the library. Note well that even just adding members, so that a type's size changes, produces an incompatible representation.

So I can't use shm between different versions of GLIBC?

Sharing memory across programs built against different versions of Glibc can probably be done successfully with data types that are fully defined by you based on the C language's built-in data types (int, double, etc.) and those with standardized representations (int32_t, etc.). In principle, however, even the representations of built-in data types might change between versions.

I suppose there might be C libraries designed for this express purpose (though I don't know any), but in general, C implementations make very few guarantees about compatibility of in-memory data representation. You cannot, in general, rely on different versions of the library to provide interoperable in-memory representations of most other data types.



来源:https://stackoverflow.com/questions/65230865/why-pthread-rwlock-ts-abi-differs-a-lot-among-versions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!