Complete C annotation rules for dftracer — START/END placement, comp types, linker setup, coverage verification, and the full checklist
Instalação
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Complete C annotation rules for dftracer — START/END placement, comp types, linker setup, coverage verification, and the full checklist
C Annotation Rules (dftracer)
Before reading the detail rules below, check the dftracer-cheatsheet skill for
the five critical rules (C1–C5), seven corner cases (CC1–CC7), and the top-10
known mistakes (M1–M10). The rules below provide the full explanation and examples.
C Rule 1 — Include and one START per function, at the very top
Add the include after all existing #include lines in the .c file (never in a header):
#include<dftracer/dftracer.h>
Then for each selected function:
return_type function_name(params) {
DFTRACER_C_FUNCTION_START(); // ← FIRST statement after {, nothing before it
...
}
One and only one START per function body.
START goes after the opening {, never before it.
It must be the first executable statement — no variable declarations, no assignments before it.
Never place START inside a control-flow block (if, else, for, while,
switch, do). Control-flow blocks are NOT functions.
Never annotate: struct/union/enum definitions, typedefs, macro bodies,
#ifdef guard blocks, forward declarations, or function pointer declarations.
C Rule 2 — DFTRACER_C_FUNCTION_END before every exit point
return_type function_name(params) {
DFTRACER_C_FUNCTION_START();
...
if (error) {
DFTRACER_C_FUNCTION_END(); // ← before early returnreturn-1;
}
...
DFTRACER_C_FUNCTION_END(); // ← before normal returnreturn0;
}
Place END immediately before every return statement (on its own line, same indent as return).
For void functions that fall off the end (no explicit return), place END
as the last statement before the closing }:
voidhelper(int x) {
DFTRACER_C_FUNCTION_START();
do_work(x);
DFTRACER_C_FUNCTION_END(); // ← last statement, void function
}
Every function with a START must have a corresponding END at every exit path.
Never place END after a return (it would be unreachable).
END indentation must match the surrounding block — not at column 0.
C Rule 3 — DFTRACER_C_FINI in main before every exit; order around MPI
Without MPI — INIT goes right after the opening { of main:
With MPI — INIT must come AFTER MPI_Init/MPI_Init_thread, and FINI must
come BEFORE MPI_Finalize. dftracer uses MPI internals; initialising before MPI
is ready causes crashes, and finalising after MPI shuts down loses trace data:
intmain(int argc, char **argv) {
MPI_Init(&argc, &argv); // ← MPI first
DFTRACER_C_INIT(NULL, NULL, NULL); // ← dftracer after MPI_Init
DFTRACER_C_FUNCTION_START();
...
if (bad) {
DFTRACER_C_FUNCTION_END(); // ← END first
DFTRACER_C_FINI(); // ← dftracer FINI before MPI_Finalize
MPI_Finalize(); // ← MPI lastreturn1;
}
...
DFTRACER_C_FUNCTION_END();
DFTRACER_C_FINI(); // ← dftracer FINI before MPI_Finalize
MPI_Finalize();
return0;
}
Scan main for MPI_Init or MPI_Init_thread before placing DFTRACER_C_INIT.
If found, place INIT on the line immediately after the MPI_Init(...) call.
Scan every return path and every MPI_Finalize() call in main. Place
DFTRACER_C_FUNCTION_END() then DFTRACER_C_FINI() immediately before
each MPI_Finalize().
The full order at every exit from an MPI main:
FUNCTION_END → DFTRACER_C_FINI → MPI_Finalize → return
Also place FINI before any process-exit call (exit(), _exit(), abort(),
quick_exit()) that bypasses MPI_Finalize.
DFTRACER_C_FINI() must appear **in the same function as DFTRACER_C_INIT() (i.e., main).
C Rule 4 — Classify every annotated function with comp=TYPE
Every annotated function MUST include a comp classification UPDATE immediately
after DFTRACER_C_FUNCTION_START(). This tags functions in the trace so analysis
tools can group and filter by operation type.
String params (const char *): use DFTRACER_C_FUNCTION_UPDATE_STR("name", ptr)
Numeric params (size_t, off_t, int, long): use DFTRACER_C_FUNCTION_UPDATE_INT("name", (int)val)
The variable name in the UPDATE call must exactly match the parameter name in
the function definition — otherwise you get undeclared identifier compile errors.
Opaque handle typedefs (MPI_File, hid_t, ncid, hsize_t) use UPDATE_INT with (int) cast.
C Rule 5 — Error-checking macros that embed early exits
ssize_tmy_write(...) {
DFTRACER_C_FUNCTION_START();
...
DFTRACER_C_FUNCTION_END(); // ← before macro that may return/goto
NCMPI_CHECK(ncmpi_put_vara(...), "write failed");
...
DFTRACER_C_FUNCTION_END(); // ← before normal returnreturn0;
err:
DFTRACER_C_FUNCTION_END(); // ← before goto-target fallthroughreturn-1;
}
For goto-based error handling (HDF5):
ssize_thdf5_write(...) {
DFTRACER_C_FUNCTION_START();
...
if ((fid = H5Fcreate(...)) < 0) goto done;
...
done:
DFTRACER_C_FUNCTION_END(); // ← place END at the goto label, not before each gotoreturn ret;
}
C Rule 7 — Forward declarations vs definitions: only annotate definitions
// ❌ DO NOT annotate — forward declaration (no body, no param names)static IOR_offset_t POSIX_Xfer(int, aiori_fd_t *, IOR_size_t *,
IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *);
// ✅ Annotate this one — definition with named params and bodystatic IOR_offset_t POSIX_Xfer(int access, aiori_fd_t *file, IOR_size_t *buffer,
IOR_offset_t length, IOR_offset_t offset,
aiori_mod_opt_t *param)
{
DFTRACER_C_FUNCTION_START();
...
}
Quick filter to find only definitions: grep -n "FUNCTION_NAME" file.c | grep -v ";$"
C Rule 8 — Vendor-specific filesystem functions are I/O functions
Prefix
Filesystem
Examples
gpfs_*
IBM GPFS/Spectrum Scale
gpfs_free_all_locks, gpfs_access_start
beegfs_*
BeeGFS
beegfs_getStriping, beegfs_createFilePath
lustre_*
Lustre
lustre_disable_file_locks
hdfs_*
Hadoop HDFS
Any HDFS JNI wrapper
ceph_*
Ceph
Any libcephfs wrapper
daos_*
DAOS
Any DAOS API wrapper
C Rule 9 — Coverage verification: scan all definitions after each file
# Check 1 — list every annotated function
awk '/^[a-zA-Z].*\(/ {func=$0} /DFTRACER_C_FUNCTION_START/ {print NR": "func}' \
annotated/src/foo.c
# Check 2 — verify comp=TYPE present in every annotated function
grep -c "DFTRACER_C_FUNCTION_START" annotated/src/foo.c
grep -c 'DFTRACER_C_FUNCTION_UPDATE_STR.*comp' annotated/src/foo.c
# Both counts must be equal
C Rule 10 — Header include and linker setup
10a — Header placement
Add #include <dftracer/dftracer.h> as the last #include in each .c/.cpp file.
Never add it to a .h header file.
10e — Always resolve the dftracer.h include path before clang_syntax_check
clang_syntax_check needs -I<dftracer_include_dir> or it reports false "file not
found" errors on #include <dftracer/dftracer.h> even when the annotation is correct.
Locate the include dir once per session (before the first syntax check, not per-file)
and pass it on every clang_syntax_check / clang_lint_annotations call: