💻 Exemplos: Capítulo 18: Programação de Baixo Nível: Bitwise, Cache Lines e Alinhamento

Especialização em Sistemas com C++ • Demonstrações Práticas Compiláveis


🎯 Objetivo dos Exemplos

Apresentar as otimizações de microarquitetura essenciais em sistemas de tempo real: operações bit a bit (bitwise manipulation) para flags compactas de hardware, o uso de alignas(64) para isolar variáveis em linhas de cache L1/L2 distintas e eliminar a degradação de performance por Falso Compartilhamento (False Sharing) em sistemas multiprocessados.


1. Código Fonte Completo (main.cpp)

/**
 * @file main.cpp
 * @brief Otimizações de baixo nível: bitwise masks e prevenção de false sharing com alignas em C++20.
 */

#include <iostream>
#include <cstdint>
#include <thread>
#include <vector>
#include <new> // std::hardware_destructive_interference_size

// 1. Bitwise Flags para Registrador de Hardware
namespace FlagsHardware {
    constexpr std::uint8_t SENSOR_HABILITADO   = 1 << 0; // 0000 0001 (0x01)
    constexpr std::uint8_t INTERRUPCAO_ATIVA   = 1 << 1; // 0000 0010 (0x02)
    constexpr std::uint8_t MODO_ALTA_PRECISAO  = 1 << 2; // 0000 0100 (0x04)
    constexpr std::uint8_t FALHA_SINAL_PARIDADE = 1 << 3; // 0000 1000 (0x08)
}

// 2. Estrutura Sujeita a Falso Compartilhamento (False Sharing)
struct ContadoresFalseSharing {
    uint64_t worker_1{0}; // Mesma cache line de 64 bytes
    uint64_t worker_2{0}; // Linha invalidada a cada escrita concorrente!
};

// 3. Estrutura Otimizada com Alinhamento Explicito de Cache Line (64 Bytes)
struct ContadoresAlinhados {
    alignas(64) uint64_t worker_1{0}; // Isolado em sua própria cache line
    alignas(64) uint64_t worker_2{0}; // Zero contenção de barramento de cache!
};

int main() {
    std::cout << "=== CAPÍTULO 18: BAIXO NÍVEL, BITWISE E CACHE LINES ===" << '\n';

    // 4. Manipulação de Flags Bitwise
    std::uint8_t registrador = 0;
    
    // Ativa SENSOR_HABILITADO e MODO_ALTA_PRECISAO (OR)
    registrador |= (FlagsHardware::SENSOR_HABILITADO | FlagsHardware::MODO_ALTA_PRECISAO);
    std::cout << "Registrador apos ligar bits (0x01 | 0x04): 0x" 
              << std::hex << static_cast<int>(registrador) << std::dec << '\n';

    // Testa se INTERRUPCAO_ATIVA está ligada (AND)
    bool isr_on = (registrador & FlagsHardware::INTERRUPCAO_ATIVA) != 0;
    std::cout << "Interrupcao esta ativa? " << (isr_on ? "SIM" : "NAO") << '\n';

    // Limpa MODO_ALTA_PRECISAO (AND com NOT)
    registrador &= ~FlagsHardware::MODO_ALTA_PRECISAO;
    std::cout << "Registrador apos desligar alta precisao: 0x" 
              << std::hex << static_cast<int>(registrador) << std::dec << '\n';

    // Inverte estado do sensor (XOR)
    registrador ^= FlagsHardware::SENSOR_HABILITADO;
    std::cout << "Registrador apos toggle do sensor (XOR): 0x" 
              << std::hex << static_cast<int>(registrador) << std::dec << '\n';

    // 5. Análise de Alinhamento de Memória e False Sharing
    std::cout << "\n--- Inspeção de Cache Line e Estruturas ---" << '\n';
    std::cout << "Tamanho de ContadoresFalseSharing: " << sizeof(ContadoresFalseSharing) << " bytes." << '\n';
    std::cout << "Tamanho de ContadoresAlinhados:    " << sizeof(ContadoresAlinhados) << " bytes." << '\n';
    std::cout << "Alinhamento de ContadoresAlinhados: " << alignof(ContadoresAlinhados) << " bytes." << '\n';

    ContadoresAlinhados pool;
    std::cout << "Endereco worker_1: " << static_cast<void*>(&pool.worker_1) << '\n';
    std::cout << "Endereco worker_2: " << static_cast<void*>(&pool.worker_2) << '\n';
    
    auto delta_enderecos = reinterpret_cast<uintptr_t>(&pool.worker_2) - reinterpret_cast<uintptr_t>(&pool.worker_1);
    std::cout << "Distancia fisica entre workers: " << delta_enderecos << " bytes (Cache Line Boundary Protegida!)" << '\n';

    return 0;
}

2. Instruções de Compilação e Execução

# Compilação com GCC / Clang
g++ -std=c++20 -Wall -Wextra -O2 main.cpp -o app_baixo_nivel
./app_baixo_nivel

# Compilação com MSVC
cl /std:c++20 /EHsc /W4 /O2 main.cpp /Fe:app_baixo_nivel.exe
.\app_baixo_nivel.exe

3. Saída Esperada no Terminal

=== CAPÍTULO 18: BAIXO NÍVEL, BITWISE E CACHE LINES ===
Registrador apos ligar bits (0x01 | 0x04): 0x5
Interrupcao esta ativa? NAO
Registrador apos desligar alta precisao: 0x1
Registrador apos toggle do sensor (XOR): 0x0

--- Inspeção de Cache Line e Estruturas ---
Tamanho de ContadoresFalseSharing: 16 bytes.
Tamanho de ContadoresAlinhados:    128 bytes.
Alinhamento de ContadoresAlinhados: 64 bytes.
Endereco worker_1: 0x7ffd9b80a080
Endereco worker_2: 0x7ffd9b80a0c0
Distancia fisica entre workers: 64 bytes (Cache Line Boundary Protegida!)