File indexing completed on 2025-11-19 09:50:45
0001
0002 #ifndef Py_INTERNAL_BACKOFF_H
0003 #define Py_INTERNAL_BACKOFF_H
0004 #ifdef __cplusplus
0005 extern "C" {
0006 #endif
0007
0008 #ifndef Py_BUILD_CORE
0009 # error "this header requires Py_BUILD_CORE define"
0010 #endif
0011
0012 #include <assert.h>
0013 #include <stdbool.h>
0014 #include <stdint.h>
0015
0016
0017 typedef struct {
0018 union {
0019 struct {
0020 uint16_t backoff : 4;
0021 uint16_t value : 12;
0022 };
0023 uint16_t as_counter;
0024 };
0025 } _Py_BackoffCounter;
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #define UNREACHABLE_BACKOFF 0xFFFF
0047
0048 static inline bool
0049 is_unreachable_backoff_counter(_Py_BackoffCounter counter)
0050 {
0051 return counter.as_counter == UNREACHABLE_BACKOFF;
0052 }
0053
0054 static inline _Py_BackoffCounter
0055 make_backoff_counter(uint16_t value, uint16_t backoff)
0056 {
0057 assert(backoff <= 15);
0058 assert(value <= 0xFFF);
0059 _Py_BackoffCounter result;
0060 result.value = value;
0061 result.backoff = backoff;
0062 return result;
0063 }
0064
0065 static inline _Py_BackoffCounter
0066 forge_backoff_counter(uint16_t counter)
0067 {
0068 _Py_BackoffCounter result;
0069 result.as_counter = counter;
0070 return result;
0071 }
0072
0073 static inline _Py_BackoffCounter
0074 restart_backoff_counter(_Py_BackoffCounter counter)
0075 {
0076 assert(!is_unreachable_backoff_counter(counter));
0077 if (counter.backoff < 12) {
0078 return make_backoff_counter((1 << (counter.backoff + 1)) - 1, counter.backoff + 1);
0079 }
0080 else {
0081 return make_backoff_counter((1 << 12) - 1, 12);
0082 }
0083 }
0084
0085 static inline _Py_BackoffCounter
0086 pause_backoff_counter(_Py_BackoffCounter counter)
0087 {
0088 return make_backoff_counter(counter.value | 1, counter.backoff);
0089 }
0090
0091 static inline _Py_BackoffCounter
0092 advance_backoff_counter(_Py_BackoffCounter counter)
0093 {
0094 if (!is_unreachable_backoff_counter(counter)) {
0095 return make_backoff_counter((counter.value - 1) & 0xFFF, counter.backoff);
0096 }
0097 else {
0098 return counter;
0099 }
0100 }
0101
0102 static inline bool
0103 backoff_counter_triggers(_Py_BackoffCounter counter)
0104 {
0105 return counter.value == 0;
0106 }
0107
0108
0109
0110
0111 #define JUMP_BACKWARD_INITIAL_VALUE 16
0112 #define JUMP_BACKWARD_INITIAL_BACKOFF 4
0113 static inline _Py_BackoffCounter
0114 initial_jump_backoff_counter(void)
0115 {
0116 return make_backoff_counter(JUMP_BACKWARD_INITIAL_VALUE,
0117 JUMP_BACKWARD_INITIAL_BACKOFF);
0118 }
0119
0120
0121
0122
0123
0124
0125 #define COLD_EXIT_INITIAL_VALUE 64
0126 #define COLD_EXIT_INITIAL_BACKOFF 6
0127
0128 static inline _Py_BackoffCounter
0129 initial_temperature_backoff_counter(void)
0130 {
0131 return make_backoff_counter(COLD_EXIT_INITIAL_VALUE,
0132 COLD_EXIT_INITIAL_BACKOFF);
0133 }
0134
0135
0136 static inline _Py_BackoffCounter
0137 initial_unreachable_backoff_counter(void)
0138 {
0139 return forge_backoff_counter(UNREACHABLE_BACKOFF);
0140 }
0141
0142 #ifdef __cplusplus
0143 }
0144 #endif
0145 #endif