xlap.h 7.44 KB
Newer Older
1 2 3 4 5 6 7
#ifndef XLAP_H
#define XLAP_H

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

8 9 10 11 12 13 14
#ifndef __cplusplus
# include <stdatomic.h>
#else
# include <atomic>
# define _Atomic(X) std::atomic< X >
#endif

15 16 17 18 19
/*
 * Each timestamp contains both a cycle value and a time value, but some values
 * might remain zero
 */
typedef union XlapTimestamp {
20 21 22 23 24
    struct XlapActualTimestamp {
        uint64_t c;
        struct timespec t;
    } actual;
    char _cacheline[64];
25 26 27 28 29 30 31 32
} XlapTimestamp;

#include "pp.h"

/*
 * Comma-separated list of timestamp IDs
 */
#define TIMESTAMP_ID_LIST \
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
    PrrtSendStart, \
    PrrtSendEnd, \
    PrrtSubmitPackage, \
    PrrtEncodeStart, \
    PrrtEncodeEnd, \
    PrrtTransmitStart, \
    PrrtTransmitEnd, \
    LinkTransmitStart, \
    LinkTransmitEnd, \
    ChannelTransmit, \
    ChannelReceive, \
    LinkReceive, \
    DecodeStart, \
    DecodeEnd, \
    HandlePacketStart, \
    HandlePacketEnd, \
    CopyOutputStart, \
    CopyOutputEnd, \
    SendFeedbackStart, \
    SendFeedbackEnd, \
    PrrtReturnPackage, \
    PrrtReceivePackage, \
    PrrtDeliver \
56 57 58 59 60 61 62

#define TIMESSTAMP_ID_TO_NAME(id) ts_##id

/*
 * enum containing all timestamp IDs
 */
typedef enum XlapTimestampId {
63 64
    PP_foreach(PP_join_comma, TIMESSTAMP_ID_TO_NAME, TIMESTAMP_ID_LIST),
    ts_count
65 66 67 68 69 70
} XlapTimestampId;

/*
 * enum to distinguish between data and redundancy packet timstamps
 */
typedef enum XlapTimestampPacketKind {
71 72 73
    ts_data_packet = 0,
    ts_any_packet = 0,
    ts_redundancy_packet = 1,
74
    ts_feedback_packet = 2
75 76 77 78 79 80
} XlapTimestampPacketKind;

/*
 * Table that stores timestamps for each timestamp ID
 */
typedef struct XlapTimestampTableRow {
81
    XlapTimestamp time[ts_count];
82 83 84 85 86 87 88 89 90 91 92 93 94
} XlapTimestampTableRow;

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

/*
 * Table that stores timestamp table rows
 */
#ifdef XLAP
95 96 97
typedef struct XlapTimestampTable {
    XlapTimestampTableRow rows[TS_ROWS];
} XlapTimestampTable;
98
#else /* XLAP */
99
typedef char XlapTimestampTable;
100 101 102 103 104 105
#endif

/*
 * Dummy data structure to store a single timestamp table row.
 */
#ifdef XLAP
106 107 108 109
typedef struct XlapTimestampPlaceholder {
    _Atomic(XlapTimestampTable *) tstable[1];
    XlapTimestampTableRow rows[1];
} XlapTimestampPlaceholder;
110
#else /* XLAP */
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
typedef char XlapTimestampPlaceholder;
#endif
/*
 * update the clock value of a timestamp by setting an explicit value
 *
 * This macro will cause a SIGSEGV if the application does not install a
 * timestamp table to the socket.
 */
#ifdef XLAP
#	define XlapTimeStampValue(sck, kind, seqno, id, value) do { \
            atomic_load_explicit(&(sck)->tstable[kind], memory_order_acquire)->rows[(seqno) % TS_ROWS].time[ts_##id].actual.t = value; \
        } while (0)
#else /* XLAP */
#	define XlapTimeStampValue(sck, kind, seqno, id, value) do { \
            (void) (sck); \
            (void) (kind); \
            (void) (seqno); \
            (void) (ts_##id); \
            (void) (value); \
        } while (0)
#endif

/*
 * update the clock value of a cyclestamp by setting an explicit value
 *
 * This macro will cause a SIGSEGV if the application does not install a
 * timestamp table to the socket.
 */

#ifdef XLAP
#	define XlapCycleStampValue(sck, kind, seqno, id, value) do { \
            atomic_load_explicit(&(sck)->tstable[kind], memory_order_acquire)->rows[(seqno) % TS_ROWS].time[ts_##id].actual.c = value; \
        } while (0)
#else /* XLAP */
#	define XlapCycleStampValue(sck, kind, seqno, id, value) do { \
            (void) (sck); \
            (void) (kind); \
            (void) (seqno); \
            (void) (ts_##id); \
            (void) (value); \
        } while (0)
152 153 154 155 156 157 158 159 160 161
#endif

/*
 * 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.
 */
#ifdef XLAP
#	define XlapTimeStampClock(sck, kind, seqno, id) do { \
162 163
            clock_gettime(CLOCK_MONOTONIC, &atomic_load_explicit(&(sck)->tstable[kind], memory_order_acquire)->rows[(seqno) % TS_ROWS].time[ts_##id].actual.t); \
        } while (0)
164 165
#else /* XLAP */
#	define XlapTimeStampClock(sck, kind, seqno, id) do { \
166 167 168 169 170
            (void) (sck); \
            (void) (kind); \
            (void) (seqno); \
            (void) (ts_##id); \
        } while (0)
171 172 173 174 175 176 177 178 179 180 181
#endif


/*
 * 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.
 */
#ifdef XLAP
#	define XlapTimeStampCycle(sck, kind, seqno, id) do { \
182 183
            atomic_load_explicit(&(sck)->tstable[kind], memory_order_acquire)->rows[(seqno) % TS_ROWS].time[ts_##id].actual.c = __builtin_ia32_rdtsc(); \
        } while (0)
184 185
#else /* XLAP */
#	define XlapTimeStampCycle(sck, kind, seqno, id) do { \
186 187 188 189 190
            (void) (sck); \
            (void) (kind); \
            (void) (seqno); \
            (void) (ts_##id); \
        } while (0)
191 192 193 194 195 196 197 198
#endif


/*
 * install a time stamp table to a socket
 */
#ifdef XLAP
#	define XlapTimestampTableInstall(sck, kind, tstp) do { \
199 200 201 202
            XlapTimestampTable *__tstp = (tstp); \
            memset(__tstp, 0, sizeof(XlapTimestampTable)); \
            atomic_store_explicit(&(sck)->tstable[kind], __tstp, memory_order_release); \
        } while (0)
203 204
#else /* XLAP */
#	define XlapTimestampTableInstall(sck, kind, tstp) do { \
205 206 207 208
            (void) (sck); \
            (void) (kind); \
            (void) (tstp); \
        } while (0)
209 210 211 212 213 214 215
#endif


/*
 * print a timestamp dump header
 */
#ifdef XLAP
216
extern void XlapTimestampTableDumpHeader(FILE *);
217 218
#else
#	define XlapTimestampTableDumpHeader(f) do { \
219 220
            (void) (f); \
        } while (0)
221 222 223 224 225 226
#endif

/*
 * dump a timestamp table
 */
#ifdef XLAP
227
extern void XlapTimestampTableDump(FILE *, XlapTimestampPacketKind, XlapTimestampTable *);
228 229
#else
#	define XlapTimestampTableDump(f, k, t) do { \
230 231 232 233
            (void) (f); \
            (void) (k); \
            (void) (t); \
        } while (0)
234 235 236 237 238 239 240
#endif

/*
 * intialize a timestamp table placeholder
 */
#ifdef XLAP
#	define XlapTimestampPlaceholderInitialize(ph) do { \
241 242 243 244
            XlapTimestampPlaceholder *__ph = (ph); \
            atomic_store_explicit(&__ph->tstable[0], (XlapTimestampTable *) &__ph->rows, memory_order_release); \
            memset(&__ph->rows, 0x0, sizeof(XlapTimestampTableRow)); \
        } while (0)
245 246
#else
#	define XlapTimestampPlaceholderInitialize(ph) do { \
247 248
            (void) (ph); \
        } while (0)
249 250 251 252 253 254 255 256 257 258
#endif

/*
 * 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).
 */
#ifdef XLAP
#	define XlapTimestampPlaceholderUse(sck, kind, seqno, ph) do { \
259 260 261 262 263 264 265 266
            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)
267 268
#else
#	define XlapTimestampPlaceholderUse(sck, kind, seqno, ph) do { \
269 270 271 272 273
            (void) (sck); \
            (void) (kind); \
            (void) (seqno); \
            (void) (ph); \
        } while (0)
274 275 276
#endif

#endif // XLAP_H