Locks

From Linux PARISC Wiki
(Difference between revisions)
Jump to: navigation, search
m (formatting update)
m
 
Line 3: Line 3:
 
We have tried a number of schemes in the past, such as tagging locks with the GCC extension <tt>{{{__attribute__((aligned(16)))}}}</tt>.  This fails when dealing with objects allocated on the stack; we are only guaranteed an 8-byte alignment for these.
 
We have tried a number of schemes in the past, such as tagging locks with the GCC extension <tt>{{{__attribute__((aligned(16)))}}}</tt>.  This fails when dealing with objects allocated on the stack; we are only guaranteed an 8-byte alignment for these.
  
In the kernel, we can do without the alignment when running on a PA 2.0 processor as we know they relaxed the architectural requirement.  See [http://lists.parisc-linux.org/pipermail/parisc-linux/2005-June/026670.html Jim Hull's message] for details.
+
In the kernel, we can do without the alignment when running on a PA 2.0 processor as we know they relaxed the architectural requirement.  See [https://lore.kernel.org/linux-parisc/200506091732.KAA07794@lucy.cup.hp.com/#t Jim Hull's message] for details.
  
 
In glibc, things are more complex.  Not only do we want to support PA 1.1 processors which require the 16-byte alignment, we also want to support locks which have been initialised to 0 (with memset).  Here's the current scheme, sometimes called Lock-Equivalent Position Deferred:
 
In glibc, things are more complex.  Not only do we want to support PA 1.1 processors which require the 16-byte alignment, we also want to support locks which have been initialised to 0 (with memset).  Here's the current scheme, sometimes called Lock-Equivalent Position Deferred:

Latest revision as of 13:39, 14 October 2019

PA-RISC provides a spartan set of atomic locking primitives; the two instructions 'LDCW' and 'LDCD' which load and zero (respectively) a 4 byte and 8 byte quantity. The latter is only available in 64-bit mode and we don't have a use for it at the moment. While this would be tricky enough, there is also the alignment restriction that they both operate on a 16-byte aligned address.

We have tried a number of schemes in the past, such as tagging locks with the GCC extension {{{__attribute__((aligned(16)))}}}. This fails when dealing with objects allocated on the stack; we are only guaranteed an 8-byte alignment for these.

In the kernel, we can do without the alignment when running on a PA 2.0 processor as we know they relaxed the architectural requirement. See Jim Hull's message for details.

In glibc, things are more complex. Not only do we want to support PA 1.1 processors which require the 16-byte alignment, we also want to support locks which have been initialised to 0 (with memset). Here's the current scheme, sometimes called Lock-Equivalent Position Deferred:

  1. Define locks to be an array of 4 words. The Lock word is the word which is 16-byte aligned. The Sentinel word is the first word of the array, unless the array is 16-byte aligned, in which case it is the second word.
  2. To acquire a lock, first execute Load-and-Clear-Word on the lock word. If the contents were 1, we now have acquired the lock. Return.
  3. Load the value from the sentinel word. If it is non-zero, the lock has been initialised, so spin on the lock word.
  4. Use the CAS lightweight syscall to atomically set the sentinel word to a non-zero value
  5. If we lost the race to initialise the lock, spin on the lock word
  6. If we successfully initialised the lock, set the other two words of the lock to a non-zero value, then return.
Personal tools