This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libstdc++/66842] New: libatomic uses multiple locks for locked atomics


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66842

            Bug ID: 66842
           Summary: libatomic uses multiple locks for locked atomics
           Product: gcc
           Version: 4.9.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: bin.x.fan at oracle dot com
  Target Milestone: ---

Hi GCC folks,

I'm opening this bug to report an issue that may or may not be a real bug. I
notice that GCC libatomic uses multiple locks for a locked atomic object whose
size is greater than 64 bytes. The granularity seems to be 64 because for every
64 bytes added to the size, one more lock is added.

It seems that this is to protect overlapping locked atomic object. If locked
atomic objects never overlap, then a more efficient way to do locked atomic
operations would be each object being protected by just one lock that is hashed
from its address.

Accessing a member of an atomic struct object is undefined behavior in C11
standard. So, does GCC support it as an extension or using multiple locks is
unnecessary therefore itâs a performance bug?

Here is my code to illustrate the issue. I interpose pthread_mutex_lock to
count how many times it is called. My GCC version is 4.9.2, and its target is
x86_64-unknown-linux-gnu. The libatomic.so I use comes with the GCC 4.9.2
installation.

-bash-4.2$ cat libmythread.c
#define _GNU_SOURCE
#include <pthread.h>
#include <dlfcn.h>
#include <stdio.h>
#include <assert.h>

static int counter = 0;

int pthread_mutex_lock (pthread_mutex_t *mutex)
{
    static int (*real_pthread_mutex_lock)(pthread_mutex_t *) = NULL;
    if (real_pthread_mutex_lock == NULL) {
        real_pthread_mutex_lock = dlsym (RTLD_NEXT, "pthread_mutex_lock");
    }
    assert (real_pthread_mutex_lock);
    counter++;
    return real_pthread_mutex_lock (mutex);
}

void display_nlocks ()
{
    printf ("pthread_mutex_lock is called %d times\n", counter);
    return;
}
-bash-4.2$ cat c11_locked_atomics.c
#include <stdatomic.h>

#ifndef SIZE
#define SIZE 1024
#endif

typedef struct {
    char a[SIZE];
} lock_obj_t;

extern void display_nlocks ();

int main()
{
    lock_obj_t v2 = {0};
    _Atomic lock_obj_t v1 = ATOMIC_VAR_INIT(v2);
    v2 = atomic_load (&v1);
    display_nlocks ();
    return 0;
}

-bash-4.2$ gcc -shared -ldl -fPIC libmythread.c -o libmythread.so
-bash-4.2$ gcc -latomic c11_locked_atomics.c -DSIZE=2048 -L./ -Wl,-rpath=./
-lmythread
-bash-4.2$ LD_PRELOAD=./libmythread.so a.out
pthread_mutex_lock is called 32 times

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]