File: SyncChecker.h

package info (click to toggle)
spring 0.81.2.1%2Bdfsg1-6
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 28,496 kB
  • ctags: 37,096
  • sloc: cpp: 238,659; ansic: 13,784; java: 12,175; awk: 3,428; python: 1,159; xml: 738; perl: 405; sh: 297; makefile: 267; pascal: 228; objc: 192
file content (142 lines) | stat: -rw-r--r-- 4,328 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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
/* Author: Tobi Vollebregt */

#ifndef SYNCCHECKER_H
#define SYNCCHECKER_H

#ifdef SYNCCHECK

#include <assert.h>
#include <deque>
#include <vector>

#ifdef TRACE_SYNC
#include "SyncTracer.h"
#endif

#include <boost/cstdint.hpp> /* Replace with <stdint.h> if appropriate */

#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const boost::uint16_t *) (d)))
#endif

#if !defined (get16bits)
#define get16bits(d) ((((boost::uint32_t)(((const boost::uint8_t *)(d))[1])) << 8)\
	+(boost::uint32_t)(((const boost::uint8_t *)(d))[0]) )
#endif


/**
 * @brief sync checker class
 *
 * Lightweight sync debugger that just keeps a running checksum over all
 * assignments to synced variables.
 */
class CSyncChecker {

	public:

		static unsigned GetChecksum() { return g_checksum; }
		static void NewFrame() { g_checksum = 0xfade1eaf; }

                /** @brief a fast hash function
                 *
                 * This hash function is roughly 4x as fast as CRC32, but even that is too slow.
                 * We use a very simplistic add/xor feedback scheme when not debugging. */
                static inline boost::uint32_t HsiehHash (const char * data, int len, boost::uint32_t hash) {
                        boost::uint32_t tmp;
                        int rem;

                        if (len <= 0 || data == NULL) return 0;

                        rem = len & 3;
                        len >>= 2;

                        /* Main loop */
                        for (;len > 0; len--) {
                                hash  += get16bits (data);
                                tmp    = (get16bits (data+2) << 11) ^ hash;
                                hash   = (hash << 16) ^ tmp;
                                data  += 2*sizeof (boost::uint16_t);
                                hash  += hash >> 11;
                        }

                        /* Handle end cases */
                        switch (rem) {
                        case 3: hash += get16bits (data);
                                hash ^= hash << 16;
                                hash ^= data[sizeof (boost::uint16_t)] << 18;
                                hash += hash >> 11;
                                break;
                        case 2: hash += get16bits (data);
                                hash ^= hash << 11;
                                hash += hash >> 17;
                                break;
                        case 1: hash += *data;
                                hash ^= hash << 10;
                                hash += hash >> 1;
                        }

                        /* Force "avalanching" of final 127 bits */
                        hash ^= hash << 3;
                        hash += hash >> 5;
                        hash ^= hash << 4;
                        hash += hash >> 17;
                        hash ^= hash << 25;
                        hash += hash >> 6;

                        return hash;
                }

	private:

		static unsigned g_checksum;

		static inline void Sync(void* p, unsigned size) {
			// most common cases first, make it easy for compiler to optimize for it
			// simple xor is not enough to detect multiple zeroes, e.g.
#ifdef TRACE_SYNC_HEAVY
			g_checksum = HsiehHash((char*)p, size, g_checksum);
#else
			switch(size) {
			case 1:
				g_checksum += *(unsigned char*)p;
				g_checksum ^= g_checksum << 10;
				g_checksum += g_checksum >> 1;
				break;
			case 2:
				g_checksum += *(unsigned short*)(char*)p;
				g_checksum ^= g_checksum << 11;
				g_checksum += g_checksum >> 17;
				break;
			case 4:
				g_checksum += *(unsigned int*)(char*)p;
				g_checksum ^= g_checksum << 16;
				g_checksum += g_checksum >> 11;
				break;
			default:
			{
				unsigned i = 0;
				for (; i < (size & ~3); i += 4) {
					g_checksum += *(unsigned int*)(char*)p + i;
					g_checksum ^= g_checksum << 16;
					g_checksum += g_checksum >> 11;
				}
				for (; i < size; ++i) {
					g_checksum += *(unsigned char*)p + i;
					g_checksum ^= g_checksum << 10;
					g_checksum += g_checksum >> 1;
				}
				break;
			}
			}
#endif
		}

		friend class CSyncedPrimitiveBase;
};

#endif // SYNCDEBUG

#endif // SYNCDEBUGGER_H