Search code examples
cx86intelglibcintel-tsx

Enable/Disable Hardware Lock Elision


I am using glibc 2.24 version. It has lock elision path included for pthread_mutex_lock implementation with Transactional Synchronization Extensions such as _xbegin() and _xend(). The hardware is supposed to support lock elision as hle CPU flag is for Hardware Lock Elision I think. The processor I am using is Intel(R) Xeon(R) Gold 6130 with Skylake architecture.

First I wanted to disable Lock elision but when I run the program that uses pthread_mutex_lock, with perf stat -T to monitor transactional cycles, I got 0. I assume this means pthread_mutex_lock does not use transactional path at all. After googling I found that it might be necessary to use export GLIBC_TUNABLES=glibc.elision.enable=1 first, to enable lock elision but after this step I still don't see any transactions with perf.

On the other hand when I include _xbegin(); and _xend(); directly in the process, I get some number of transactional cycles with perf stat -T, which should mean that I am looking for the right counters with perf, hopefully.

So any advice to how I can enable lock elision would be helpful. Or am I checking it incorrectly?

Update for TSX I'm using this two instructions in the main function, just like this:

_xbegin();
_xend();

I'm not sure which library it needs, I already have tens of them included. For compilation I'm using the following flags: -O3 -march=native -lpthread that are relevant for this example.

For locks I have mutex:

pthread_mutex_t * mutex;
mutex = (pthread_mutex_t *) malloc(10 * sizeof(pthread_mutex_t));
for(int k=0; k<10; k++){
    pthread_mutex_init(&mutex[k], NULL);
  }

Maybe for elision I should initialize it differently?


Solution

  • In earlier versions of glibc, before 2.27, support for TSX could only be controlled using a compile-time flag called enable-lock-elision. I don't know which versions have enable-lock-elision enabled or disabled, but that's how it used to work1. So if you wanted to enable/dsiable TSX, you'll have to compile glibc yourself and use that flag accordingly. Starting with glibc 2.27, that compile-time option was removed and replaced by a run-time option called glibc.elision.enable. That is, glibc is always compiled with support for TSX, but TSX will only be used if the environment variable glibc.elision.enable is set to 1 before running the application (e.g., by executing export GLIBC_TUNABLES=glibc.elision.enable=1).

    Before 2.27, glibc.elision.enable doesn't exist and so it has no effect. Whether TSX is used depends on the compile-time flag enable-lock-elision. You're using 2.24. So the easiest solution would be to move to 2.27 or a more recent version.

    Note that all current Intel processors that support TSX appear to have the same bug that "using Intel TSX Instructions May Lead to Unpredictable System Behavior" according to the respective specification updates. For some processors, Intel has released microcode updates to actually disable TSX. However, the implementation on your processor continues to be enabled.


    Footnotes:

    (1) According to this bug report, lock elision has been disabled in glibc starting with 2.23. I think this is done by disabling enable-lock-elision when building glibc, but I've not verified this by looking at the code. But this is consistent with your observation that it is disabled in 2.24.