Files
hakmem/scripts/verify_atomic_freelist_conversion.sh

256 lines
9.6 KiB
Bash
Raw Normal View History

#!/bin/bash
# verify_atomic_freelist_conversion.sh - Track atomic freelist conversion progress
set -e
cd "$(dirname "$0")/.."
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo "========================================"
echo "Atomic Freelist Conversion Verification"
echo "========================================"
echo ""
# Check if accessor header exists
echo "=== ACCESSOR HEADER CHECK ==="
if [ -f "core/box/slab_freelist_atomic.h" ]; then
echo -e "${GREEN}✅ core/box/slab_freelist_atomic.h exists${NC}"
# Check if it has required functions
if grep -q "slab_freelist_pop_lockfree" core/box/slab_freelist_atomic.h; then
echo -e "${GREEN}✅ slab_freelist_pop_lockfree() defined${NC}"
else
echo -e "${RED}❌ slab_freelist_pop_lockfree() NOT FOUND${NC}"
fi
if grep -q "slab_freelist_push_lockfree" core/box/slab_freelist_atomic.h; then
echo -e "${GREEN}✅ slab_freelist_push_lockfree() defined${NC}"
else
echo -e "${RED}❌ slab_freelist_push_lockfree() NOT FOUND${NC}"
fi
if grep -q "slab_freelist_is_empty" core/box/slab_freelist_atomic.h; then
echo -e "${GREEN}✅ slab_freelist_is_empty() defined${NC}"
else
echo -e "${RED}❌ slab_freelist_is_empty() NOT FOUND${NC}"
fi
else
echo -e "${YELLOW}⚠️ core/box/slab_freelist_atomic.h does NOT exist yet${NC}"
echo " Run: cp core/box/slab_freelist_atomic.h.TEMPLATE core/box/slab_freelist_atomic.h"
fi
echo ""
# Count remaining direct accesses
echo "=== DIRECT ACCESS CHECK ==="
DIRECT_ACCESSES=$(grep -rn "meta->freelist" core/ --include="*.c" --include="*.h" 2>/dev/null | wc -l)
echo "Total 'meta->freelist' occurrences: ${DIRECT_ACCESSES}"
# Count converted sites
CONVERTED_CHECKS=$(grep -rn "slab_freelist_is_empty\|slab_freelist_is_nonempty" core/ --include="*.c" --include="*.h" 2>/dev/null | wc -l || echo "0")
CONVERTED_POPS=$(grep -rn "slab_freelist_pop_lockfree" core/ --include="*.c" --include="*.h" 2>/dev/null | wc -l || echo "0")
CONVERTED_PUSHES=$(grep -rn "slab_freelist_push_lockfree" core/ --include="*.c" --include="*.h" 2>/dev/null | wc -l || echo "0")
CONVERTED_LOADS=$(grep -rn "slab_freelist_load_relaxed" core/ --include="*.c" --include="*.h" 2>/dev/null | wc -l || echo "0")
CONVERTED_STORES=$(grep -rn "slab_freelist_store_relaxed" core/ --include="*.c" --include="*.h" 2>/dev/null | wc -l || echo "0")
echo "Converted operations:"
echo " NULL checks: ${CONVERTED_CHECKS}"
echo " POP operations: ${CONVERTED_POPS}"
echo " PUSH operations: ${CONVERTED_PUSHES}"
echo " Load operations: ${CONVERTED_LOADS}"
echo " Store operations: ${CONVERTED_STORES}"
TOTAL_CONVERTED=$((CONVERTED_CHECKS + CONVERTED_POPS + CONVERTED_PUSHES + CONVERTED_LOADS + CONVERTED_STORES))
echo -e "${BLUE}Total converted sites: ${TOTAL_CONVERTED}${NC}"
echo ""
# Estimate progress
BASELINE_TOTAL=90
if [ ${TOTAL_CONVERTED} -eq 0 ]; then
PROGRESS=0
else
PROGRESS=$((TOTAL_CONVERTED * 100 / BASELINE_TOTAL))
fi
echo "=== CONVERSION PROGRESS ==="
echo -e "Progress: ${BLUE}${PROGRESS}%${NC} (${TOTAL_CONVERTED}/${BASELINE_TOTAL} sites)"
# Progress bar
BAR_WIDTH=40
FILLED=$((PROGRESS * BAR_WIDTH / 100))
EMPTY=$((BAR_WIDTH - FILLED))
printf "["
printf "%${FILLED}s" | tr ' ' '='
printf "%${EMPTY}s" | tr ' ' '-'
printf "]\n"
echo ""
# Check Phase 1 files
echo "=== PHASE 1 FILES CHECK ==="
PHASE1_FILES=(
"core/tiny_superslab_alloc.inc.h"
"core/hakmem_tiny_refill_p0.inc.h"
"core/box/carve_push_box.c"
"core/hakmem_tiny_tls_ops.h"
)
PHASE1_DONE=0
for file in "${PHASE1_FILES[@]}"; do
if [ -f "$file" ]; then
# Check if file includes atomic header
if grep -q "slab_freelist_atomic.h" "$file"; then
echo -e "${GREEN}$file (includes atomic.h)${NC}"
PHASE1_DONE=$((PHASE1_DONE + 1))
else
echo -e "${YELLOW}⚠️ $file (not converted yet)${NC}"
fi
else
echo -e "${RED}$file (not found)${NC}"
fi
done
echo "Phase 1 files converted: ${PHASE1_DONE}/${#PHASE1_FILES[@]}"
echo ""
# Check for potential bugs
echo "=== POTENTIAL BUG CHECK ==="
# Check for double POP (pop + tiny_next_read)
DOUBLE_POP=$(grep -A1 "slab_freelist_pop_lockfree" core/ -r --include="*.c" --include="*.h" 2>/dev/null | grep "tiny_next_read" | wc -l || echo "0")
if [ ${DOUBLE_POP} -gt 0 ]; then
echo -e "${RED}❌ POTENTIAL BUG: Found ${DOUBLE_POP} sites with pop_lockfree + tiny_next_read${NC}"
echo " (slab_freelist_pop_lockfree already calls tiny_next_read internally!)"
grep -A1 "slab_freelist_pop_lockfree" core/ -r --include="*.c" --include="*.h" 2>/dev/null | grep -B1 "tiny_next_read"
else
echo -e "${GREEN}✅ No double-POP bugs detected${NC}"
fi
# Check for double PUSH (tiny_next_write + push)
DOUBLE_PUSH=$(grep -B1 "slab_freelist_push_lockfree" core/ -r --include="*.c" --include="*.h" 2>/dev/null | grep "tiny_next_write" | wc -l || echo "0")
if [ ${DOUBLE_PUSH} -gt 0 ]; then
echo -e "${RED}❌ POTENTIAL BUG: Found ${DOUBLE_PUSH} sites with tiny_next_write + push_lockfree${NC}"
echo " (slab_freelist_push_lockfree already calls tiny_next_write internally!)"
grep -B1 "slab_freelist_push_lockfree" core/ -r --include="*.c" --include="*.h" 2>/dev/null | grep "tiny_next_write"
else
echo -e "${GREEN}✅ No double-PUSH bugs detected${NC}"
fi
# Check for missing NULL checks after POP
MISSING_NULL_CHECK=$(grep -A3 "slab_freelist_pop_lockfree" core/ -r --include="*.c" --include="*.h" 2>/dev/null | grep -B3 -A3 "slab_freelist_pop_lockfree" | grep -v "if.*!.*block\|if.*block.*==.*NULL\|if.*!.*p\|if.*p.*==.*NULL" | grep "slab_freelist_pop_lockfree" | wc -l || echo "0")
# This is a heuristic check - may have false positives
if [ ${MISSING_NULL_CHECK} -gt 0 ]; then
echo -e "${YELLOW}⚠️ POTENTIAL ISSUE: ${MISSING_NULL_CHECK} POP sites may be missing NULL check${NC}"
echo " (Manual review recommended - this is a heuristic check)"
else
echo -e "${GREEN}✅ All POP operations appear to have NULL checks${NC}"
fi
echo ""
# Compile check
echo "=== COMPILE CHECK ==="
if make bench_random_mixed_hakmem 2>&1 | grep -i "error" > /dev/null; then
echo -e "${RED}❌ Compilation FAILED${NC}"
echo " Run: make bench_random_mixed_hakmem 2>&1 | grep -i error"
else
echo -e "${GREEN}✅ Compilation succeeded${NC}"
fi
echo ""
# Test binary check
echo "=== TEST BINARY CHECK ==="
if [ -f "out/release/bench_random_mixed_hakmem" ]; then
echo -e "${GREEN}✅ out/release/bench_random_mixed_hakmem exists${NC}"
# Check modification time (is it recent?)
MTIME=$(stat -c %Y out/release/bench_random_mixed_hakmem 2>/dev/null || stat -f %m out/release/bench_random_mixed_hakmem)
NOW=$(date +%s)
AGE=$((NOW - MTIME))
if [ ${AGE} -lt 3600 ]; then
echo -e "${GREEN}✅ Binary is recent (${AGE} seconds old)${NC}"
else
echo -e "${YELLOW}⚠️ Binary is old (${AGE} seconds). Consider rebuilding.${NC}"
fi
else
echo -e "${YELLOW}⚠️ out/release/bench_random_mixed_hakmem not found. Run: make bench_random_mixed_hakmem${NC}"
fi
if [ -f "out/release/larson_hakmem" ]; then
echo -e "${GREEN}✅ out/release/larson_hakmem exists${NC}"
else
echo -e "${YELLOW}⚠️ out/release/larson_hakmem not found. Run: make larson_hakmem${NC}"
fi
echo ""
# Recommendations
echo "=== RECOMMENDATIONS ==="
if [ ${PROGRESS} -eq 0 ]; then
echo "1. Create accessor header:"
echo " cp core/box/slab_freelist_atomic.h.TEMPLATE core/box/slab_freelist_atomic.h"
echo ""
echo "2. Start Phase 1 conversion (5 files, 25 sites):"
echo " See ATOMIC_FREELIST_SITE_BY_SITE_GUIDE.md"
elif [ ${PROGRESS} -lt 30 ]; then
echo "Phase 1 in progress..."
echo "1. Continue converting Phase 1 files (${PHASE1_DONE}/4 done)"
echo "2. Test after each file: make bench_random_mixed_hakmem"
echo "3. Phase 1 final test: ./out/release/larson_hakmem 8 100000 256"
elif [ ${PROGRESS} -lt 60 ]; then
echo "Phase 1 likely complete, start Phase 2..."
echo "1. Test Phase 1 results: ./out/release/larson_hakmem 8 100000 256"
echo "2. Start Phase 2 conversion (10 files, 40 sites)"
echo "3. See ATOMIC_FREELIST_SITE_BY_SITE_GUIDE.md for Phase 2 files"
elif [ ${PROGRESS} -lt 90 ]; then
echo "Phase 2 in progress, prepare for Phase 3..."
echo "1. Test Phase 2 results: for t in 1 2 4 8; do ./out/release/larson_hakmem \$t 100000 256; done"
echo "2. Start Phase 3 cleanup (5 files, 25 sites)"
echo "3. Focus on debug/stats sites (use SLAB_FREELIST_DEBUG_PTR)"
else
echo "Nearly complete! Final verification..."
echo "1. Run full test suite: ./run_all_tests.sh"
echo "2. Check for remaining direct accesses: grep -rn 'meta->freelist' core/"
echo "3. ASan/TSan tests: ./build.sh tsan larson_hakmem"
fi
echo ""
# Summary
echo "=== SUMMARY ==="
echo "Baseline total sites: ${BASELINE_TOTAL}"
echo "Converted sites: ${TOTAL_CONVERTED}"
echo "Remaining sites: $((BASELINE_TOTAL - TOTAL_CONVERTED))"
echo "Progress: ${PROGRESS}%"
echo ""
if [ ${PROGRESS} -ge 100 ]; then
echo -e "${GREEN}🎉 CONVERSION COMPLETE! 🎉${NC}"
echo ""
echo "Final checklist:"
echo "[ ] All tests pass"
echo "[ ] No ASan/TSan warnings"
echo "[ ] Performance regression <3%"
echo "[ ] Larson 8T stable"
echo "[ ] Documentation updated (CLAUDE.md)"
else
PHASE=""
if [ ${PROGRESS} -lt 30 ]; then
PHASE="Phase 1 (Critical Hot Paths)"
elif [ ${PROGRESS} -lt 60 ]; then
PHASE="Phase 2 (Important Paths)"
else
PHASE="Phase 3 (Cleanup)"
fi
echo -e "${BLUE}Currently working on: ${PHASE}${NC}"
fi
echo ""
echo "========================================"
echo "Verification Complete"
echo "========================================"