@@ -15,13 +15,7 @@ extern "C" {
15
15
16
16
17
17
typedef struct {
18
- union {
19
- struct {
20
- uint16_t backoff : 4 ;
21
- uint16_t value : 12 ;
22
- };
23
- uint16_t as_counter ; // For printf("%#x", ...)
24
- };
18
+ uint16_t value_and_backoff ;
25
19
} _Py_BackoffCounter ;
26
20
27
21
@@ -38,17 +32,19 @@ typedef struct {
38
32
and a 4-bit 'backoff' field. When resetting the counter, the
39
33
backoff field is incremented (until it reaches a limit) and the
40
34
value is set to a bit mask representing the value 2**backoff - 1.
41
- The maximum backoff is 12 (the number of value bits).
35
+ The maximum backoff is 12 (the number of bits in the value ).
42
36
43
37
There is an exceptional value which must not be updated, 0xFFFF.
44
38
*/
45
39
46
- #define UNREACHABLE_BACKOFF 0xFFFF
40
+ #define BACKOFF_BITS 4
41
+ #define MAX_BACKOFF 12
42
+ #define UNREACHABLE_BACKOFF 15
47
43
48
44
static inline bool
49
45
is_unreachable_backoff_counter (_Py_BackoffCounter counter )
50
46
{
51
- return counter .as_counter == UNREACHABLE_BACKOFF ;
47
+ return counter .value_and_backoff == UNREACHABLE_BACKOFF ;
52
48
}
53
49
54
50
static inline _Py_BackoffCounter
@@ -57,52 +53,52 @@ make_backoff_counter(uint16_t value, uint16_t backoff)
57
53
assert (backoff <= 15 );
58
54
assert (value <= 0xFFF );
59
55
_Py_BackoffCounter result ;
60
- result .value = value ;
61
- result .backoff = backoff ;
56
+ result .value_and_backoff = (value << BACKOFF_BITS ) | backoff ;
62
57
return result ;
63
58
}
64
59
65
60
static inline _Py_BackoffCounter
66
61
forge_backoff_counter (uint16_t counter )
67
62
{
68
63
_Py_BackoffCounter result ;
69
- result .as_counter = counter ;
64
+ result .value_and_backoff = counter ;
70
65
return result ;
71
66
}
72
67
73
68
static inline _Py_BackoffCounter
74
69
restart_backoff_counter (_Py_BackoffCounter counter )
75
70
{
76
71
assert (!is_unreachable_backoff_counter (counter ));
77
- if (counter .backoff < 12 ) {
78
- return make_backoff_counter ((1 << (counter .backoff + 1 )) - 1 , counter .backoff + 1 );
72
+ int backoff = counter .value_and_backoff & 15 ;
73
+ if (backoff < MAX_BACKOFF ) {
74
+ return make_backoff_counter ((1 << (backoff + 1 )) - 1 , backoff + 1 );
79
75
}
80
76
else {
81
- return make_backoff_counter ((1 << 12 ) - 1 , 12 );
77
+ return make_backoff_counter ((1 << MAX_BACKOFF ) - 1 , MAX_BACKOFF );
82
78
}
83
79
}
84
80
85
81
static inline _Py_BackoffCounter
86
82
pause_backoff_counter (_Py_BackoffCounter counter )
87
83
{
88
- return make_backoff_counter (counter .value | 1 , counter .backoff );
84
+ _Py_BackoffCounter result ;
85
+ result .value_and_backoff = counter .value_and_backoff | (1 << BACKOFF_BITS );
86
+ return result ;
89
87
}
90
88
91
89
static inline _Py_BackoffCounter
92
90
advance_backoff_counter (_Py_BackoffCounter counter )
93
91
{
94
- if (!is_unreachable_backoff_counter (counter )) {
95
- return make_backoff_counter ((counter .value - 1 ) & 0xFFF , counter .backoff );
96
- }
97
- else {
98
- return counter ;
99
- }
92
+ _Py_BackoffCounter result ;
93
+ result .value_and_backoff = counter .value_and_backoff - (1 << BACKOFF_BITS );
94
+ return result ;
100
95
}
101
96
102
97
static inline bool
103
98
backoff_counter_triggers (_Py_BackoffCounter counter )
104
99
{
105
- return counter .value == 0 ;
100
+ /* Test whether the value is zero and the backoff is not UNREACHABLE_BACKOFF */
101
+ return counter .value_and_backoff < UNREACHABLE_BACKOFF ;
106
102
}
107
103
108
104
/* Initial JUMP_BACKWARD counter.
@@ -136,7 +132,7 @@ initial_temperature_backoff_counter(void)
136
132
static inline _Py_BackoffCounter
137
133
initial_unreachable_backoff_counter (void )
138
134
{
139
- return forge_backoff_counter ( UNREACHABLE_BACKOFF );
135
+ return make_backoff_counter ( 0 , UNREACHABLE_BACKOFF );
140
136
}
141
137
142
138
#ifdef __cplusplus
0 commit comments