Доступ к 4-байтовой границе вокруг переменной неопределенного поведения? (необходимо для futex ждать)C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Доступ к 4-байтовой границе вокруг переменной неопределенного поведения? (необходимо для futex ждать)

Сообщение Anonymous »

Поскольку C ++ 20, стандартная библиотека имеет std :: atomic :: wait и std :: atomic :: notify_one/all . Тем не менее, они не подходят для меня, так как им не хватает расширенных функций (например, ожидания времени, разделяемые между процессами и т. Д.). < /P>
По этой причине и для обучения я хочу использовать Syscall Futex (2) Linux непосредственно, чтобы ждать и побудить в определенном условии. Подождите, ожидаемое значение должно быть рассчитано и передано в качестве параметра для Futex_wait < /code> syscall.
Для этого (с 1-байтовыми типами) мне нужно получить доступ к не связанной с внешней памяти, которая, вероятно, является неопределенным поведением (ub). < /p>
, что, вероятно, является неопределенным поведением (ub).

Код: Выделить всё

futex_wake
не имеет этой проблемы, так как существует только соответствующий 4-байтовый выравнированный указатель, который должен быть рассчитан и передавать в Futex Syscall, не требуется фактически обогнать его там.#include [*]
#include
#include

#include
#include
#include
#include

long futex(uint32_t* uaddr, int futex_op, uint32_t val,
const struct timespec* timeout, uint32_t* uaddr2, uint32_t val3) {
return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);
}

//! Get the 4-byte aligned pointer where uaddr is included.
uint32_t* calculate_futex_ptr(uint8_t* uaddr) {
const auto addr = reinterpret_cast(uaddr);
return reinterpret_cast(addr & ~(0x3));
}

//! Get offset (0-3) where uaddr is in relation to calculate_futex_ptr(uaddr).
int calculate_offset(uint8_t* uaddr) {
return reinterpret_cast(uaddr) & 0x3;
}

long futex_wake(uint8_t* uaddr) {
const auto futex_addr = calculate_futex_ptr(uaddr);
return futex(futex_addr, FUTEX_WAKE_PRIVATE, 123, nullptr, nullptr, 0);
}

long futex_wait(uint8_t* uaddr, uint8_t val) {
const auto futex_addr = calculate_futex_ptr(uaddr);

// Attention! Undefined behaviour.
uint32_t futex_val = *futex_addr;
// Inject val to correct location inside futex_val.
uint8_t* dest_addr = reinterpret_cast(&futex_val) + calculate_offset(uaddr);
*dest_addr = val;

return futex(futex_addr, FUTEX_WAIT_PRIVATE, futex_val, nullptr, nullptr, 0);
}

uint8_t before{6};
uint8_t wait_condition{1};
uint8_t after{5};

void thread_func() {
std::this_thread::sleep_for(std::chrono::seconds{1});
std::atomic_ref(wait_condition).store(3);
futex_wake(&wait_condition);
}

int main() {
std::thread thd(thread_func);
futex_wait(&wait_condition, 1);
thd.join();
}
< /code>
Мои вопросы: < /p>
  • действительно ли отмеченная линия UB, и это единственная UB в этой программе? Стандартная библиотека имеет дело с проблемой?


Подробнее здесь: https://stackoverflow.com/questions/797 ... ded-for-fu
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»