3 ms·
Cutler Normal Form! I love it, use it exclusively now on all my projects. _Use_decl_annotations_ PVOID TraceStoreAllocateRecordsWithTimestamp(
by trentnelson 10y ago
Cutler Normal Form! I love it, use it exclusively now on all my projects.
_Use_decl_annotations_
PVOID
TraceStoreAllocateRecordsWithTimestamp(
PTRACE_CONTEXT TraceContext,
PTRACE_STORE TraceStore,
ULONG_PTR NumberOfRecords,
ULONG_PTR RecordSize,
PLARGE_INTEGER TimestampPointer
)
/*++
Routine Description:
This routine allocates records from a trace store. It can be considered
the TraceStore-equivalent of a calloc()-type interface, in that the record
size and number of records are specified rather than the total size.
The memory to satisfy the total size is sourced from the trace store's
active memory map. If sufficient space is available, allocation is simply
a matter of adjusting the relevant pointers and returning.
If the required size can't be satisfied by the remaining memory in the
map, this routine consumes the "next" memory map that has been prepared
asynchronously in a threadpool if one is available. If the prepared map
is not yet available, the allocation fails and NULL is returned.
N.B. This routine should be called indirectly through the TraceStore's
AllocationRoutine function pointer.
The total size that can be allocated is limited to the maximum size of the
memory map. The allocator is geared more toward lots of small allocations
versus larger ones.
Arguments:
TraceContext - Supplies a pointer to a TRACE_CONTEXT structure.
TraceStore - Supplies a pointer to a TRACE_STORE structure that the memory
is to be allocated from.
NumberOfRecords - Supplies the number of records to allocate. The total
size is derived by multiplying RecordSize with NumberOfRecords.
RecordSize - Supplies the size of the record to allocate.
TimestampPointer - Optionally supplies a pointer to a timestamp value to
associate with the allocation. When non-NULL, the 64-bit integer
pointed to by the variable will be written to the allocation timestamp
metadata store. This should be NULL if the trace store is a metadata
store, or if the trace store's traits indicates that it is a linked
store (implying that allocation timestamp information will be provided
elsewhere).
Return Value:
A pointer to the base memory address satisfying the total requested size
if the memory could be obtained successfully, NULL otherwise.
--*/
- quotemstr 10y agoI wish there were explicit pre- and post-condition sections. The pointer-typedef stuff never made much sense to me either.
- trentnelson 10y agoI'm definitely on-board these days with the typedef-everything approach used by NT. Every public function gets a typedef with SAL annotations exposed in the module's public header file, e.g. in this case, TraceStore.h has: typedef _Check_return_ _Success_(return != 0) PVOID (ALLOCATE_RECORDS_WITH_TIMESTAMP)( _In_ PTRACE_CONTEXT TraceContext, _In_ PTRACE_STORE TraceStore, _In_ ULONG_PTR NumberOfRecords, _In_ ULONG_PTR RecordSize, _In_opt_ PLARGE_INTEGER TimestampPointer ); typedef ALLOCATE_RECORDS_WITH_TIMESTAMP *PALLOCATE_RECORDS_WITH_TIMESTAMP; typedef PALLOCATE_RECORDS_WITH_TIMESTAMP \ volatile VPALLOCATE_RECORDS_WITH_TIMESTAMP; That allows me to include it in a public struct via: typedef struct _TRACE_STORE { ... VPALLOCATE_RECORDS_WITH_TIMESTAMP AllocateRecordsWithTimestamp; ... } TRACE_STORE, *PTRACE_STORE; Basically I've resigned to living with the ugliest possible function typedefs, complete with SAL annotations and whatnot, at the benefit of much cleaner interaction elsewhere in the code, e.g. to call it I'd just do: Foo = (PFOO)TraceStore->AllocateRecordsWithTimestamp( TraceContext, TraceStore, 4, sizeof(*Foo), &Timestamp ); _Use_decl_annotations is a life saver.
- quotemstr 10y agoOh, sure. I miss SAL terribly. The consensus outside Microsoft seems to be that we need annotation-less static analysis because developers will never add annotations --- annotation-less static analysis, IME, has a much higher false positive rate than prefast. Windows is proof that extremely robust static analysis works. Back when I was in Windows, the system was so robust that if the static analyzer reported on your code, it was your code that had the problem, not the analyzer. It did bounds checking, nullability analysis, and tons of useful stuff. It's fantastic. The thing about NT-style pointer typedefs is that they discourage const-correctness: it's enough of a pain to make a PFOO. You want a PCFOO too? That said, I'd be more than happy to live with poiner typedefs if I got SAL back. BTW, I also used a hacked-up cc-mode that understood all the SAL annotations and fontified them using font-lock-keyword-face. It worked great.