Задать вопрос
MAKAPOH
@MAKAPOH
многостаночник

Какие гарантии на выравнивание адреса указателя?

Добрый день.
Представим такой код:
type A struct{}

func (a *A) method1() {
  // some code
}

var pointerToA *A

func init() {
  pointerToA = &A{}
}

func goroutine1() {
  // ....
  pointerToA.method1()
  // ....
}

func goroutine2() {
  // ....
  pointerToA = pointerToAnotherA
  // ....
}

Есть ли какие либо гарантии на то что внутри goroutine1 указатель pointerToA всегда будет указывать либо на старый адрес либо на новый, но никогда не случится так что в pointerToA находится часть от старого адреса и часть от нового? Интересует случай архитектуры AMD64.

В AMD64 Architecture Programmers Manual Volumes 2, в разделе 7.3.2 Access Atomicity написано следующее:

Cacheable, naturally-aligned single loads or stores of up to a quadword are atomic on any processor
model, as are misaligned loads or stores of less than a quadword that are contained entirely within a
naturally-aligned quadword. Misaligned load or store accesses typically incur a small latency penalty.
Model-specific relaxations of this quadword atomicity boundary, with respect to this latency penalty,
may be found in a given processor's Software Optimization Guide.
Misaligned accesses can be subject to interleaved accesses from other processors or cache-coherent
devices which can result in unintended behavior. Atomicity for misaligned accesses can be achieved
where necessary by using the XCHG instruction or any suitable LOCK-prefixed instruction.

Что говорит нам (как я понимаю) что если адрес который мы читаем/пишем выровнен (в данном случае на 8 байт) то чтение/запись атомарны. Остаётся понять есть ли какие либо гарантии от компилятора Go на выравнивание указателя. Единственное мето в спецификации Go где говорится про выравниевание это Size and alignment guarantees:

The following minimal alignment properties are guaranteed:

For a variable x of any type: unsafe.Alignof(x) is at least 1.
For a variable x of struct type: unsafe.Alignof(x) is the largest of all the values unsafe.Alignof(x.f) for each field f of x, but at least 1.
For a variable x of array type: unsafe.Alignof(x) is the same as the alignment of a variable of the array's element type.

A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory.


И вот тут самое непонятное. Каких то конкретных гарантий на адреса указателей нет. Можно вызвать функцию unsafe.Alignof(*A) и получить то что мне нужно. Но будет ли результат Alignof(*A) для AMD64 всегда постоянным?
Как один из вариантов решения проблемы использовать atomic.Pointer[A] вместо *A, но судя по тестам он медленее в два раза. Поэтому хочется понять можно ли тут как то улучшить ситуацию.
Надеюсь понятно изложил суть вопроса.
Всем заранее спасибо за ответы.
  • Вопрос задан
  • 139 просмотров
Подписаться 2 Средний 1 комментарий
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы