Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 1 | /* |
Willy Tarreau | c2f7c58 | 2020-06-02 18:15:32 +0200 | [diff] [blame] | 2 | * include/haproxy/ticks.h |
| 3 | * Functions and macros for manipulation of expiration timers |
| 4 | * |
| 5 | * Copyright (C) 2000-2020 Willy Tarreau - w@1wt.eu |
| 6 | * |
| 7 | * This library is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU Lesser General Public |
| 9 | * License as published by the Free Software Foundation, version 2.1 |
| 10 | * exclusively. |
| 11 | * |
| 12 | * This library is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 | * Lesser General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU Lesser General Public |
| 18 | * License along with this library; if not, write to the Free Software |
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 | */ |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 21 | |
| 22 | /* |
| 23 | * Using a mix of milliseconds and timeval for internal timers is expensive and |
| 24 | * overkill, because we don't need such a precision to compute timeouts. |
Willy Tarreau | d0a201b | 2009-03-08 15:53:06 +0100 | [diff] [blame] | 25 | * So we're converting them to "ticks". |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 26 | * |
Willy Tarreau | d0a201b | 2009-03-08 15:53:06 +0100 | [diff] [blame] | 27 | * A tick is a representation of a date relative to another one, and is |
| 28 | * measured in milliseconds. The natural usage is to represent an absolute date |
| 29 | * relative to the current date. Since it is not practical to update all values |
| 30 | * each time the current date changes, instead we use the absolute date rounded |
| 31 | * down to fit in a tick. We then have to compare a tick to the current date to |
| 32 | * know whether it is in the future or in the past. If a tick is below the |
| 33 | * current date, it is in the past. If it is above, it is in the future. The |
| 34 | * values will wrap so we can't compare that easily, instead we check the sign |
| 35 | * of the difference between a tick and the current date. |
| 36 | * |
| 37 | * Proceeding like this allows us to manipulate dates that are stored in |
| 38 | * scalars with enough precision and range. For this reason, we store ticks in |
| 39 | * 32-bit integers. This is enough to handle dates that are between 24.85 days |
| 40 | * in the past and as much in the future. |
| 41 | * |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 42 | * We must both support absolute dates (well in fact, dates relative to now+/- |
Willy Tarreau | e35c94a | 2009-03-21 10:01:42 +0100 | [diff] [blame] | 43 | * 24 days), and intervals (for timeouts). Both types need an "eternity" magic |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 44 | * value. For optimal code generation, we'll use zero as the magic value |
| 45 | * indicating that an expiration timer or a timeout is not set. We have to |
| 46 | * check that we don't return this value when adding timeouts to <now>. If a |
| 47 | * computation returns 0, we must increase it to 1 (which will push the timeout |
Willy Tarreau | d0a201b | 2009-03-08 15:53:06 +0100 | [diff] [blame] | 48 | * 1 ms further). For this reason, timeouts must not be added by hand but via |
| 49 | * the dedicated tick_add() function. |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 50 | */ |
| 51 | |
Willy Tarreau | c2f7c58 | 2020-06-02 18:15:32 +0200 | [diff] [blame] | 52 | #ifndef _HAPROXY_TICKS_H |
| 53 | #define _HAPROXY_TICKS_H |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 54 | |
Willy Tarreau | 4c7e4b7 | 2020-05-27 12:58:42 +0200 | [diff] [blame] | 55 | #include <haproxy/api.h> |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 56 | |
| 57 | #define TICK_ETERNITY 0 |
| 58 | |
| 59 | /* right now, ticks are milliseconds. Both negative ms and negative ticks |
| 60 | * indicate eternity. |
| 61 | */ |
| 62 | #define MS_TO_TICKS(ms) (ms) |
| 63 | #define TICKS_TO_MS(tk) (tk) |
| 64 | |
| 65 | /* return 1 if tick is set, otherwise 0 */ |
| 66 | static inline int tick_isset(int expire) |
| 67 | { |
| 68 | return expire != 0; |
| 69 | } |
| 70 | |
| 71 | /* Add <timeout> to <now>, and return the resulting expiration date. |
| 72 | * <timeout> will not be checked for null values. |
| 73 | */ |
| 74 | static inline int tick_add(int now, int timeout) |
| 75 | { |
| 76 | now += timeout; |
| 77 | if (unlikely(!now)) |
| 78 | now++; /* unfortunate value */ |
| 79 | return now; |
| 80 | } |
| 81 | |
| 82 | /* add <timeout> to <now> if it is set, otherwise set it to eternity. |
| 83 | * Return the resulting expiration date. |
| 84 | */ |
| 85 | static inline int tick_add_ifset(int now, int timeout) |
| 86 | { |
| 87 | if (!timeout) |
| 88 | return TICK_ETERNITY; |
| 89 | return tick_add(now, timeout); |
| 90 | } |
| 91 | |
Willy Tarreau | e35c94a | 2009-03-21 10:01:42 +0100 | [diff] [blame] | 92 | /* return 1 if timer <t1> is before <t2>, none of which can be infinite. */ |
| 93 | static inline int tick_is_lt(int t1, int t2) |
| 94 | { |
| 95 | return (t1 - t2) < 0; |
| 96 | } |
| 97 | |
| 98 | /* return 1 if timer <t1> is before or equal to <t2>, none of which can be infinite. */ |
| 99 | static inline int tick_is_le(int t1, int t2) |
| 100 | { |
| 101 | return (t1 - t2) <= 0; |
| 102 | } |
| 103 | |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 104 | /* return 1 if timer <timer> is expired at date <now>, otherwise zero */ |
| 105 | static inline int tick_is_expired(int timer, int now) |
| 106 | { |
Willy Tarreau | 534c5a2 | 2008-09-04 09:00:24 +0200 | [diff] [blame] | 107 | if (unlikely(!tick_isset(timer))) |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 108 | return 0; |
Willy Tarreau | 534c5a2 | 2008-09-04 09:00:24 +0200 | [diff] [blame] | 109 | if (unlikely((timer - now) <= 0)) |
| 110 | return 1; |
| 111 | return 0; |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | /* return the first one of the two timers, both of which may be infinite */ |
| 115 | static inline int tick_first(int t1, int t2) |
| 116 | { |
| 117 | if (!tick_isset(t1)) |
| 118 | return t2; |
| 119 | if (!tick_isset(t2)) |
| 120 | return t1; |
| 121 | if ((t1 - t2) <= 0) |
| 122 | return t1; |
| 123 | else |
| 124 | return t2; |
| 125 | } |
| 126 | |
Willy Tarreau | 531cf0c | 2009-03-08 16:35:27 +0100 | [diff] [blame] | 127 | /* return the first one of the two timers, where only the first one may be infinite */ |
| 128 | static inline int tick_first_2nz(int t1, int t2) |
| 129 | { |
| 130 | if (!tick_isset(t1)) |
| 131 | return t2; |
| 132 | if ((t1 - t2) <= 0) |
| 133 | return t1; |
| 134 | else |
| 135 | return t2; |
| 136 | } |
| 137 | |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 138 | /* return the number of ticks remaining from <now> to <exp>, or zero if expired */ |
| 139 | static inline int tick_remain(int now, int exp) |
| 140 | { |
| 141 | if (tick_is_expired(exp, now)) |
| 142 | return 0; |
| 143 | return exp - now; |
| 144 | } |
| 145 | |
Willy Tarreau | c2f7c58 | 2020-06-02 18:15:32 +0200 | [diff] [blame] | 146 | #endif /* _HAPROXY_TICKS_H */ |
Willy Tarreau | 0c303ee | 2008-07-07 00:09:58 +0200 | [diff] [blame] | 147 | |
| 148 | /* |
| 149 | * Local variables: |
| 150 | * c-indent-level: 8 |
| 151 | * c-basic-offset: 8 |
| 152 | * End: |
| 153 | */ |