Loading pp.h 0 → 100644 +4225 −0 File added.Preview size limit exceeded, changes collapsed. Show changes 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 Loading
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