<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Harshith Sunku — Blog</title><description>Systems engineer who lives below the abstraction layer. Networking, kernel internals, performance engineering — I write about the things most people hand-wave past.</description><link>https://harshith.in/</link><language>en-us</language><lastBuildDate>Sun, 26 Apr 2026 07:09:53 GMT</lastBuildDate><managingEditor>harshithsunku@gmail.com (Harshith Sunku)</managingEditor><webMaster>harshithsunku@gmail.com (Harshith Sunku)</webMaster><item><title>GDB for Multi-threaded C: Hunting Race Conditions Without Losing Your Mind</title><link>https://harshith.in/blog/gdb-multithreaded-c-debugging/</link><guid isPermaLink="true">https://harshith.in/blog/gdb-multithreaded-c-debugging/</guid><description>Multi-threaded bugs vanish under the debugger. Stack traces lie. Variables seem to change value between two prints. The GDB techniques that actually find races: thread-pinned breakpoints, non-stop mode, watchpoints, TSan-then-GDB, and rr.</description><pubDate>Sun, 26 Apr 2026 07:07:12 GMT</pubDate><category>debugging</category><category>c</category><category>threading</category><category>linux</category></item><item><title>Spinlocks, Mutexes, and Futexes: Picking the Right Lock</title><link>https://harshith.in/blog/spinlocks-mutexes-futexes/</link><guid isPermaLink="true">https://harshith.in/blog/spinlocks-mutexes-futexes/</guid><description>Three primitives cover almost every locking decision: spinlocks, mutexes, and futexes. They solve the same problem with very different cost models — burning CPU vs trapping to the kernel vs the hybrid approach modern mutexes actually use.</description><pubDate>Sun, 26 Apr 2026 07:06:25 GMT</pubDate><category>threading</category><category>kernel</category><category>performance</category><category>linux</category></item><item><title>Decoding ELF: How Linux Actually Loads Your Binary</title><link>https://harshith.in/blog/decoding-elf-how-linux-loads-binaries/</link><guid isPermaLink="true">https://harshith.in/blog/decoding-elf-how-linux-loads-binaries/</guid><description>You type ./a.out and a program runs. Behind that: a four-byte magic number, two parallel header tables, mmap-and-fault, and a dynamic linker that bootstraps itself. A guided tour of ELF and what execve actually does.</description><pubDate>Sun, 26 Apr 2026 07:05:42 GMT</pubDate><category>linux</category><category>systems</category><category>c</category><category>debugging</category></item><item><title>Bypassing the Kernel: How DPDK Hits 10 Million Packets per Second</title><link>https://harshith.in/blog/dpdk-kernel-bypass-networking/</link><guid isPermaLink="true">https://harshith.in/blog/dpdk-kernel-bypass-networking/</guid><description>The Linux network stack tops out at ~2 Mpps per core. DPDK reaches 20 Mpps. The difference isn&apos;t speed — it&apos;s removing work: no syscalls, no allocations, no demux, no locks. Why kernel-bypass exists and when it earns its complexity.</description><pubDate>Sun, 26 Apr 2026 07:04:58 GMT</pubDate><category>networking</category><category>performance</category><category>systems</category><category>linux</category></item><item><title>eBPF Maps: The Data Structures That Power Kernel Programs</title><link>https://harshith.in/blog/ebpf-maps-explained/</link><guid isPermaLink="true">https://harshith.in/blog/ebpf-maps-explained/</guid><description>eBPF programs are stateless — maps are how they remember. A walk through the five map types that cover most real programs: hash, array, per-CPU, ring buffer, and LRU, with concrete code for each.</description><pubDate>Sun, 26 Apr 2026 07:04:13 GMT</pubDate><category>ebpf</category><category>kernel</category><category>linux</category></item><item><title>Writing Your First Linux Kernel Module: A Minimal Character Device</title><link>https://harshith.in/blog/first-linux-kernel-module/</link><guid isPermaLink="true">https://harshith.in/blog/first-linux-kernel-module/</guid><description>Kernel modules sound intimidating, but the ceremony is small. In about a hundred lines: a working /dev/echo0 character device, with proper error unwinding, copy_to_user, and the patterns the rest of the kernel uses everywhere.</description><pubDate>Sun, 26 Apr 2026 07:03:29 GMT</pubDate><category>kernel</category><category>linux</category><category>c</category><category>systems</category></item><item><title>The Journey of a Received Packet: From NIC Interrupt to recv()</title><link>https://harshith.in/blog/received-packet-journey-nic-to-recv/</link><guid isPermaLink="true">https://harshith.in/blog/received-packet-journey-nic-to-recv/</guid><description>When recv() returns, dozens of layers ran behind your back — DMA, NAPI, sk_buff, protocol demux, the socket queue. A trace of the entire receive path with the cost of each hop and where the latency actually lives.</description><pubDate>Sun, 26 Apr 2026 07:02:49 GMT</pubDate><category>networking</category><category>kernel</category><category>linux</category><category>tcp-ip</category></item><item><title>Memory Barriers Demystified: Acquire, Release, and Why They Matter</title><link>https://harshith.in/blog/memory-barriers-acquire-release/</link><guid isPermaLink="true">https://harshith.in/blog/memory-barriers-acquire-release/</guid><description>Compilers reorder. CPUs reorder. Single-threaded code never notices — multi-threaded code crashes mysteriously. A clear walk through acquire and release semantics, what the hardware actually does, and the spinlock that ties it all together.</description><pubDate>Sun, 26 Apr 2026 07:02:08 GMT</pubDate><category>systems</category><category>threading</category><category>c</category><category>performance</category></item><item><title>Cache Lines and False Sharing: The Hidden Tax on Multithreaded C</title><link>https://harshith.in/blog/cache-lines-and-false-sharing/</link><guid isPermaLink="true">https://harshith.in/blog/cache-lines-and-false-sharing/</guid><description>Two threads, two variables, no shared state — and a 4x slowdown. False sharing is the cache coherence tax you pay when unrelated data lands on the same 64-byte line. How to spot it and fix it.</description><pubDate>Sun, 26 Apr 2026 07:01:30 GMT</pubDate><category>performance</category><category>systems</category><category>threading</category><category>c</category></item><item><title>How epoll Actually Works: Inside the Kernel&apos;s Event Loop</title><link>https://harshith.in/blog/how-epoll-actually-works/</link><guid isPermaLink="true">https://harshith.in/blog/how-epoll-actually-works/</guid><description>select and poll were O(n). epoll is O(1). The reason isn&apos;t smarter scanning — it&apos;s that the kernel pushes ready events into a list as they happen. A walk through the data structures that make it work.</description><pubDate>Sun, 26 Apr 2026 07:00:53 GMT</pubDate><category>networking</category><category>kernel</category><category>linux</category><category>performance</category></item><item><title>eBPF for Production Debugging: Kernel Instrumentation Without Rebooting</title><link>https://harshith.in/blog/ebpf-production-debugging/</link><guid isPermaLink="true">https://harshith.in/blog/ebpf-production-debugging/</guid><description>How eBPF changed production debugging — attaching probes to kernel functions, tracing syscalls, measuring latency histograms, and XDP packet processing, all without touching application code or rebooting.</description><pubDate>Sat, 21 Mar 2026 07:53:59 GMT</pubDate><category>ebpf</category><category>kernel</category><category>performance</category><category>debugging</category><category>linux</category></item><item><title>ESP32 Wake-on-LAN over MQTT with ESP-IDF</title><link>https://harshith.in/blog/esp32-mqtt-wake-on-lan/</link><guid isPermaLink="true">https://harshith.in/blog/esp32-mqtt-wake-on-lan/</guid><description>Using an ESP32 and ESP-IDF to build a network-aware Wake-on-LAN trigger — power on machines remotely over MQTT without an always-on server in between.</description><pubDate>Sat, 21 Mar 2026 07:53:59 GMT</pubDate><category>embedded</category><category>networking</category><category>systems</category><category>c</category></item><item><title>Writing a 16-bit Real Mode Bootloader in x86 Assembly</title><link>https://harshith.in/blog/real-mode-bootloader-assembly/</link><guid isPermaLink="true">https://harshith.in/blog/real-mode-bootloader-assembly/</guid><description>The first 512 bytes that run when your machine powers on. A walkthrough of x86 real mode, the BIOS interrupt interface, segment:offset addressing, and what it takes to load a second stage.</description><pubDate>Sat, 21 Mar 2026 07:53:59 GMT</pubDate><category>assembly</category><category>systems</category><category>kernel</category><category>linux</category></item><item><title>Thread-Safe Logging in C: Lock-Free Queues and Why They&apos;re Hard</title><link>https://harshith.in/blog/thread-safe-logging-c-lock-free/</link><guid isPermaLink="true">https://harshith.in/blog/thread-safe-logging-c-lock-free/</guid><description>Inside ThreadSafeCLogger: how to build a high-performance logging library that doesn&apos;t serialize your threads, using per-thread SPSC ring buffers and careful memory ordering.</description><pubDate>Sat, 21 Mar 2026 07:53:59 GMT</pubDate><category>c</category><category>threading</category><category>performance</category><category>systems</category></item><item><title>Building a Software TCP/IP Stack from Scratch in C</title><link>https://harshith.in/blog/software-tcp-ip-stack-c/</link><guid isPermaLink="true">https://harshith.in/blog/software-tcp-ip-stack-c/</guid><description>A deep dive into implementing a functional TCP/IP stack entirely in software — covering Ethernet framing, ARP, IP routing, TCP state machines, and the painful lessons learned along the way.</description><pubDate>Sat, 21 Mar 2026 07:53:59 GMT</pubDate><category>networking</category><category>c</category><category>tcp-ip</category><category>systems</category></item></channel></rss>