User Guide

  • 2020
  • 10/21/2020
  • Public Content
Contents

Lock Hierarchy Violation

Occurs when the acquisition order of multiple synchronization objects (such as mutexes, critical sections, and thread handles) in one thread differs from the acquisition order in another thread, and these synchronization objects are owned by the acquiring thread and must be released by the same thread.
The
Intel Inspector
reports a
Lock hierarchy violation
problem as multiple problems in a problem set. Each problem shows a portion of the
Lock hierarchy violation
from the perspective of a single thread.
Problem type: Lock hierarchy violation
ID
Code Location
Description
1
Allocation site
If present, represents the location and associated call stack where the synchronization object acquired by a thread (usually the object acquired first) was created.
2
Lock owned
Represents the location and associated call stack where a synchronization object was acquired by a thread.
3
Lock owned
Represents the location and associated call stack where another synchronization object was later acquired by the same thread.
Deadlock
problems are usually, but not always, caused by
Lock hierarchy violation
problems. If the
Intel Inspector
detects a
Deadlock
problem caused by a
Lock hierarchy violation
problem, it reports only the
Deadlock
problem.
C Example
Preparation
CRITICAL_SECTION cs1; CRITICAL_SECTION cs2; int x = 0; int y = 0; InitializeCriticalSection(&cs1); // Allocation Site (cs1) InitializeCriticalSection(&cs2); // Allocation Site (cs2)
Thread #1
EnterCriticalSection(&cs1); // Lock Owned (cs1) x++; EnterCriticalSection(&cs2); // Lock Owned (cs2) y++; LeaveCriticalSection(&cs2); LeaveCriticalSection(&cs1);
Thread #2
EnterCriticalSection(&cs2); // Lock Owned (cs2) y++; EnterCriticalSection(&cs1); // Lock Owned (cs1) x++; LeaveCriticalSection(&cs1); LeaveCriticalSection(&cs2);
If thread #1 and thread #2 are concurrent and there is no other synchronization between them, the
Intel Inspector
detects a
Lock hierarchy violation
problem instead of a
Deadlock
problem if synchronization occurs in the following order:
  1. EnterCriticalSection(&cs1);
    in thread #1
  2. EnterCriticalSection(&cs2);
    in thread #1
  3. EnterCriticalSection(&cs2);
    in thread #2
  4. EnterCriticalSection(&cs1);
    in thread #2
Fortran Example
Preparation
include "omp_lib.h" integer(omp_lock_kind) lock1 integer(omp_lock_kind) lock2 call omp_init_lock(lock1) call omp_init_lock(lock2)
Thread #1
call omp_set_lock(lock1) . . . call omp_set_lock(lock2) . . . call omp_unset_lock(lock2) . . . call omp_unset_lock(lock1)
Thread #2
call omp_set_lock(lock2) . . . call omp_set_lock(lock1) . . . call omp_unset_lock(lock1) . . . call omp_unset_lock(lock2)
If thread #1 and thread #2 are concurrent and there is no other synchronization between them, the
Intel Inspector
detects a
Lock hierarchy violation
problem instead of a
Deadlock
problem if synchronization occurs in the following order:
  1. call omp_set_lock(lock1)
    in thread #1
  2. call omp_set_lock(lock2)
    in thread #1
  3. call omp_set_lock(lock2)
    in thread #2
  4. call omp_set_lock(lock1)
    in thread #2

Possible Correction Strategies

  • Do not use multiple synchronization objects if one synchronization object is sufficient.
  • Use recursive synchronization objects such as recursive mutexes if a thread must acquire the same object more than once.
  • Avoid the case where two threads wait for each other to terminate. Instead, use a third thread to wait for both threads to terminate.
  • Establish a global lock hierarchy and honor the same lock hierarchy in each thread. For example:
    • C language: If you have critical sections
      cs1
      and
      cs2
      and establish a global lock hierarchy (
      cs1
      ,
      cs2
      ), always acquire
      cs1
      before acquiring
      cs2
      and release
      cs1
      after releasing
      cs2
      .
    • Fortran language: If you have locks
      lock1
      and
      lock2
      and establish a global lock hierarchy (
      lock1
      ,
      lock2
      ), always acquire
      lock1
      before acquiring
      lock2
      and release
      lock1
      after releasing
      lock2
      .
  • C language: Consider acquiring multiple synchronization objects at the same time using, for example, Microsoft Windows* system APIs such as
    WaitForMultipleObjects()
    .

Product and Performance Information

1

Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and SSSE3 instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors. Certain optimizations not specific to Intel microarchitecture are reserved for Intel microprocessors. Please refer to the applicable product User and Reference Guides for more information regarding the specific instruction sets covered by this notice.

Notice revision #20110804