FreeBSD/sys/kern/subr_devstat.c
/*
 * Record the ending of a transaction, and incrment the various counters.
 *
 * Ordering in this function, and in devstat_start_transaction() is VERY
 * important.  The idea here is to run without locks, so we are very
 * careful to only modify some fields on the way "down" (i.e. at
 * transaction start) and some fields on the way "up" (i.e. at transaction
 * completion).  One exception is busy_from, which we only modify in
 * devstat_start_transaction() when there are no outstanding transactions,
 * and thus it can't be modified in devstat_end_transaction()
 * simultaneously.
 *
 * The sequence0 and sequence1 fields are provided to enable an application
 * spying on the structures with mmap(2) to tell when a structure is in a
 * consistent state or not.
 *
 * For this to work 100% reliably, it is important that the two fields
 * are at opposite ends of the structure and that they are incremented
 * in the opposite order of how a memcpy(3) in userland would copy them.
 * We assume that the copying happens front to back, but there is actually
 * no way short of writing your own memcpy(3) replacement to guarantee
 * this will be the case.
 *
 * In addition to this, being a kind of locks, they must be updated with
 * atomic instructions using appropriate memory barriers.
 */
Record the ending of a transaction, and incrment the various counters.
Ordering in this function, and in devstat_start_transaction() is VERY
important.  The idea here is to run without locks, so we are very
careful to only modify some fields on the way "down"  and some fields on the way "up" .  One exception is busy_from, which we only modify in
devstat_start_transaction() when there are no outstanding transactions,
and thus it can't be modified in devstat_end_transaction()
simultaneously.

The sequence0 and sequence1 fields are provided to enable an application
spying on the structures with mmap(2) to tell when a structure is in a
consistent state or not.

For this to work 100% reliably, it is important that the two fields
are at opposite ends of the structure and that they are incremented
in the opposite order of how a memcpy(3) in userland would copy them.
We assume that the copying happens front to back, but there is actually
no way short of writing your own memcpy(3) replacement to guarantee
this will be the case.

In addition to this, being a kind of locks, they must be updated with
atomic instructions using appropriate memory barriers.
Record the ending of a transaction and incrment the various counters . Ordering in this function and in devstat_start_transaction () is VERY important . The idea here is to run without locks so we are very careful to only modify some fields on the way " down " and some fields on the way " up " . One exception is busy_from which we only modify in devstat_start_transaction () when there are no outstanding transactions and thus it can ' t be modified in devstat_end_transaction () simultaneously . The sequence0 and sequence1 fields are provided to enable an application spying on the structures with mmap ( 2 ) to tell when a structure is in a consistent state or not . For this to work 100% reliably it is important that the two fields are at opposite ends of the structure and that they are incremented in the opposite order of how a memcpy ( 3 ) in userland would copy them . We assume that the copying happens front to back but there is actually no way short of writing your own memcpy ( 3 ) replacement to guarantee this will be the case . In addition to this being a kind of locks they must be updated with atomic instructions using appropriate memory barriers .
void
devstat_end_transaction(struct devstat *ds, uint32_t bytes, 
			devstat_tag_type tag_type, devstat_trans_flags flags,
			struct bintime *now, struct bintime *then)
{
	struct bintime dt, lnow;
	if (ds == NULL)
		return;
	if (now == NULL) {
		now = &lnow;
		binuptime(now);
	}
	atomic_add_acq_int(&ds->sequence1, 1);
	ds->bytes[flags] += bytes;
	ds->operations[flags]++;
	if ((ds->flags & DEVSTAT_NO_ORDERED_TAGS) == 0 &&
	    tag_type != DEVSTAT_TAG_NONE)
		ds->tag_types[tag_type]++;
	if (then != NULL) {
		dt = *now;
		bintime_sub(&dt, then);
		bintime_add(&ds->duration[flags], &dt);
	}
	dt = *now;
	bintime_sub(&dt, &ds->busy_from);
	bintime_add(&ds->busy_time, &dt);
	ds->busy_from = *now;
	ds->end_count++;
	atomic_add_rel_int(&ds->sequence0, 1);
	DTRACE_DEVSTAT_DONE();
}
void devstat_end_transaction ( struct devstat * ds , uint32_t bytes , devstat_tag_type tag_type , devstat_trans_flags flags , struct bintime * now , struct bintime * then ) { struct bintime dt , lnow ; if ( ds == NULL ) return ; if ( now == NULL ) { now = & lnow ; binuptime ( now ) ; } atomic_add_acq_int ( & ds -> sequence1 , 1 ) ; ds -> bytes [ flags ] += bytes ; ds -> operations [ flags ] ++ ; if ( ( ds -> flags & DEVSTAT_NO_ORDERED_TAGS ) == 0 && tag_type != DEVSTAT_TAG_NONE ) ds -> tag_types [ tag_type ] ++ ; if ( then != NULL ) { dt = * now ; bintime_sub ( & dt , then ) ; bintime_add ( & ds -> duration [ flags ] , & dt ) ; } dt = * now ; bintime_sub ( & dt , & ds -> busy_from ) ; bintime_add ( & ds -> busy_time , & dt ) ; ds -> busy_from = * now ; ds -> end_count ++ ; atomic_add_rel_int ( & ds -> sequence0 , 1 ) ; DTRACE_DEVSTAT_DONE ( ) ; }
Record the ending of a transaction, and incrment the various counters.
Record the ending of a transaction and incrment the various counters .
/* sanity check */ /* Update byte and operations counts */ /*
	 * Keep a count of the various tag types sent.
	 */ /* Update duration of operations */ /* Accumulate busy time */