Commit 53cce0dd authored by Andreas Schmidt's avatar Andreas Schmidt
Browse files

Add xlap C-files.

parent 00888d45
Loading
Loading
Loading
Loading

pp.h

0 → 100644
+4225 −0

File added.

Preview size limit exceeded, changes collapsed.

xlap.c

0 → 100644
+32 −0
Original line number Diff line number Diff line
#include "xlap.h"

#include <stdatomic.h>

void XlapTimestampTableDumpHeader(FILE *out)
{
	fprintf(out, "SeqNo,Kind" );
#	define OUT(id) fprintf(out, ",%s_T,%s_C", #id, #id);
	PP_foreach(PP_join_space, OUT, TIMESTAMP_ID_LIST)
#	undef OUT
	fprintf(out, "\n");
}

static inline unsigned long long timestampByTime(struct timespec *ts)
{
	// convert timespec to microseconds
	unsigned long long x = ts->tv_sec;
	x *= 1000000ULL;
	x += ts->tv_nsec / 1000;
	return x;
}

void XlapTimestampTableDump(FILE *out, XlapTimestampPacketKind kind, XlapTimestampTable *table)
{
#	define OUT(id) fprintf(out, ",%llu,%llu", timestampByTime(&table->rows[row].time[ts_##id].actual.t), (unsigned long long) table->rows[row].time[ts_##id].actual.c);
	for (unsigned int row = 0; row < TS_ROWS; row++) {
		fprintf(out, "%u,%u", row, (unsigned) kind);
		PP_foreach(PP_join_space, OUT, TIMESTAMP_ID_LIST)
		fprintf(out, "\n");
	}
#	undef OUT
}

xlap.h

0 → 100644
+165 −0
Original line number Diff line number Diff line
#ifndef XLAP_H
#define XLAP_H

#include <stdio.h>
#include <stdint.h>
#include <time.h>

/*
 * Each timestamp contains both a cycle value and a time value, but some values
 * might remain zero
 */
typedef union XlapTimestamp {
	struct XlapActualTimestamp {
		uint64_t c;
		struct timespec t;
	} actual;
	char _cacheline[64];
} XlapTimestamp;

#include "pp.h"

/*
 * Comma-separated list of timestamp IDs
 */
#define TIMESTAMP_ID_LIST \
	PrrtSendStart, \
	PrrtSendEnd, \
	PrrtSubmitPackage, \
	PrrtEncodeStart, \
	PrrtEncodeEnd, \
	PrrtTransmitStart, \
	PrrtTransmitEnd, \
	LinkTransmitStart, \
	LinkTransmitEnd, \
	LinkReceive, \
	DecodeStart, \
	DecodeEnd, \
	HandlePacketStart, \
	HandlePacketEnd, \
	CopyOutputStart, \
	CopyOutputEnd, \
	SendFeedbackStart, \
	SendFeedbackEnd, \
	PrrtReturnPackage, \
	PrrtReceivePackage, \
	PrrtDeliver \

#define TIMESSTAMP_ID_TO_NAME(id) ts_##id

/*
 * enum containing all timestamp IDs
 */
typedef enum XlapTimestampId {
	PP_foreach(PP_join_comma, TIMESSTAMP_ID_TO_NAME, TIMESTAMP_ID_LIST),
	ts_count
} XlapTimestampId;

/*
 * enum to distinguish between data and redundancy packet timstamps
 */
typedef enum XlapTimestampPacketKind {
	ts_data_packet = 0,
	ts_any_packet = 0,
	ts_redundancy_packet = 1,
} XlapTimestampPacketKind;

/*
 * Table that stores timestamps for each timestamp ID
 */
typedef struct XlapTimestampTableRow {
	XlapTimestamp time[ts_count];
} XlapTimestampTableRow;

/*
 * by default, store timestamps for 128 packages
 */
#ifndef TS_ROWS
#define TS_ROWS (1u<<12)
#endif

/*
 * Table that stores timestamp table rows
 */
typedef struct XlapTimestampTable {
	XlapTimestampTableRow rows[TS_ROWS];
} XlapTimestampTable;

/*
 * Dummy data structure to store a single timestamp table row.
 */
typedef struct XlapTimestampPlaceholder {
	_Atomic(XlapTimestampTable *) tstable[1];
	XlapTimestampTableRow rows[1];
} XlapTimestampPlaceholder;

/*
 * update the clock value of a timestamp
 *
 * This macro will cause a SIGSEGV if the application does not install a
 * timestamp table to the socket.
 */
#define XlapTimeStampClock(sck, kind, seqno, id) do { \
		clock_gettime(CLOCK_MONOTONIC, &atomic_load_explicit(&(sck)->tstable[kind], memory_order_acquire)->rows[(seqno) % TS_ROWS].time[ts_##id].actual.t); \
	} while (0);

/*
 * update the cycle value of a timestamp
 *
 * This macro will cause a SIGSEGV if the application does not install a
 * timestamp table to the socket.
 */
#define XlapTimeStampCycle(sck, kind, seqno, id) do { \
		atomic_load_explicit(&(sck)->tstable[kind], memory_order_acquire)->rows[(seqno) % TS_ROWS].time[ts_##id].actual.c = __builtin_ia32_rdtsc(); \
	} while (0);

/*
 * install a time stamp table to a socket
 */
#define XlapTimestampTableInstall(sck, kind, tstp) do { \
		XlapTimestampTable *__tstp = (tstp); \
		memset(__tstp, 0, sizeof(XlapTimestampTable)); \
		atomic_store_explicit(&(sck)->tstable[kind], __tstp, memory_order_release); \
	} while (0)

/*
 * print a timestamp dump header
 */
extern void XlapTimestampTableDumpHeader(FILE *);

/*
 * dump a timestamp table
 */
extern void XlapTimestampTableDump(FILE *, XlapTimestampPacketKind, XlapTimestampTable *);

/*
 * use a specific timestamp table
 */
extern void XlapTimestampTableUse(XlapTimestampTable *);

/*
 * intialize a timestamp table placeholder
 */
#define XlapTimestampPlaceholderInitialize(ph) do { \
		XlapTimestampPlaceholder *__ph = (ph); \
		atomic_store_explicit(&__ph->tstable[0], (XlapTimestampTable *) &__ph->rows, memory_order_release); \
		memset(&__ph->rows, 0x0, sizeof(XlapTimestampTableRow)); \
	} while (0);

/*
 * copy a timestamp table placeholder into an actual timestamp table
 *
 * Since every timestamp is taken at most once, either the timestamptable or
 * the placeholder value must be zero (for each timestamp).
 */
#define XlapTimestampPlaceholderUse(sck, kind, seqno, ph) do { \
		XlapTimestampPlaceholder *__ph = (ph); \
		XlapTimestampTable       *__ts = atomic_load_explicit(&(sck)->tstable[kind], memory_order_acquire); \
		for (unsigned int __t = 0; __t < ts_count; __t++) { \
			__ts->rows[seqno % TS_ROWS].time[__t].actual.t.tv_sec  += __ph->rows[0].time[__t].actual.t.tv_sec; \
			__ts->rows[seqno % TS_ROWS].time[__t].actual.t.tv_nsec += __ph->rows[0].time[__t].actual.t.tv_nsec; \
			__ts->rows[seqno % TS_ROWS].time[__t].actual.c         += __ph->rows[0].time[__t].actual.c; \
		} \
	} while (0)

#endif // XLAP_H