Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 1 | /* |
Willy Tarreau | 2741c8c | 2020-06-02 11:28:02 +0200 | [diff] [blame] | 2 | * include/haproxy/dynbuf.h |
| 3 | * Buffer management functions. |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 4 | * |
Willy Tarreau | 2741c8c | 2020-06-02 11:28:02 +0200 | [diff] [blame] | 5 | * Copyright (C) 2000-2020 Willy Tarreau - w@1wt.eu |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 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 | */ |
| 21 | |
Willy Tarreau | 2741c8c | 2020-06-02 11:28:02 +0200 | [diff] [blame] | 22 | #ifndef _HAPROXY_DYNBUF_H |
| 23 | #define _HAPROXY_DYNBUF_H |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 24 | |
| 25 | #include <stdio.h> |
| 26 | #include <stdlib.h> |
| 27 | #include <string.h> |
| 28 | |
Willy Tarreau | 2741c8c | 2020-06-02 11:28:02 +0200 | [diff] [blame] | 29 | #include <import/ist.h> |
| 30 | #include <haproxy/activity.h> |
Willy Tarreau | 4c7e4b7 | 2020-05-27 12:58:42 +0200 | [diff] [blame] | 31 | #include <haproxy/api.h> |
Willy Tarreau | 8dabda7 | 2020-05-27 17:22:10 +0200 | [diff] [blame] | 32 | #include <haproxy/buf.h> |
Willy Tarreau | c13ed53 | 2020-06-02 10:22:45 +0200 | [diff] [blame] | 33 | #include <haproxy/chunk.h> |
Willy Tarreau | 2741c8c | 2020-06-02 11:28:02 +0200 | [diff] [blame] | 34 | #include <haproxy/dynbuf-t.h> |
Willy Tarreau | d0ef439 | 2020-06-02 09:38:52 +0200 | [diff] [blame] | 35 | #include <haproxy/pool.h> |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 36 | |
Willy Tarreau | bafbe01 | 2017-11-24 17:34:44 +0100 | [diff] [blame] | 37 | extern struct pool_head *pool_head_buffer; |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 38 | |
Willy Tarreau | 9b28e03 | 2012-10-12 23:49:43 +0200 | [diff] [blame] | 39 | int init_buffer(); |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 40 | void buffer_dump(FILE *o, struct buffer *b, int from, int to); |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 41 | |
| 42 | /*****************************************************************/ |
| 43 | /* These functions are used to compute various buffer area sizes */ |
| 44 | /*****************************************************************/ |
| 45 | |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 46 | /* Return 1 if the buffer has less than 1/4 of its capacity free, otherwise 0 */ |
| 47 | static inline int buffer_almost_full(const struct buffer *buf) |
| 48 | { |
Willy Tarreau | c9fa048 | 2018-07-10 17:43:27 +0200 | [diff] [blame] | 49 | if (b_is_null(buf)) |
Willy Tarreau | 4428a29 | 2014-11-28 20:54:13 +0100 | [diff] [blame] | 50 | return 0; |
| 51 | |
Willy Tarreau | bbc68df | 2018-06-06 14:30:50 +0200 | [diff] [blame] | 52 | return b_almost_full(buf); |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 53 | } |
| 54 | |
Willy Tarreau | 7b04cc4 | 2018-07-10 10:35:02 +0200 | [diff] [blame] | 55 | /**************************************************/ |
| 56 | /* Functions below are used for buffer allocation */ |
| 57 | /**************************************************/ |
Willy Tarreau | af81935 | 2012-08-27 22:08:00 +0200 | [diff] [blame] | 58 | |
Willy Tarreau | 766b6cf | 2021-03-22 16:10:22 +0100 | [diff] [blame] | 59 | /* Ensures that <buf> is allocated, or allocates it. If no memory is available, |
| 60 | * ((char *)1) is assigned instead with a zero size. The allocated buffer is |
Willy Tarreau | c9fa048 | 2018-07-10 17:43:27 +0200 | [diff] [blame] | 61 | * returned, or NULL in case no memory is available. |
Willy Tarreau | e583ea5 | 2014-11-24 11:30:16 +0100 | [diff] [blame] | 62 | */ |
Willy Tarreau | c9fa048 | 2018-07-10 17:43:27 +0200 | [diff] [blame] | 63 | static inline struct buffer *b_alloc(struct buffer *buf) |
Willy Tarreau | e583ea5 | 2014-11-24 11:30:16 +0100 | [diff] [blame] | 64 | { |
Willy Tarreau | c9fa048 | 2018-07-10 17:43:27 +0200 | [diff] [blame] | 65 | char *area; |
Willy Tarreau | f2f7d6b | 2014-11-24 11:55:08 +0100 | [diff] [blame] | 66 | |
Willy Tarreau | 766b6cf | 2021-03-22 16:10:22 +0100 | [diff] [blame] | 67 | if (buf->size) |
| 68 | return buf; |
| 69 | |
Willy Tarreau | c9fa048 | 2018-07-10 17:43:27 +0200 | [diff] [blame] | 70 | *buf = BUF_WANTED; |
Willy Tarreau | de749a9 | 2021-03-22 20:54:15 +0100 | [diff] [blame] | 71 | area = __pool_alloc(pool_head_buffer, POOL_F_NO_POISON); |
Willy Tarreau | a8b2ce0 | 2019-05-28 17:04:16 +0200 | [diff] [blame] | 72 | if (unlikely(!area)) { |
| 73 | activity[tid].buf_wait++; |
Willy Tarreau | c9fa048 | 2018-07-10 17:43:27 +0200 | [diff] [blame] | 74 | return NULL; |
Willy Tarreau | a8b2ce0 | 2019-05-28 17:04:16 +0200 | [diff] [blame] | 75 | } |
Willy Tarreau | c9fa048 | 2018-07-10 17:43:27 +0200 | [diff] [blame] | 76 | |
| 77 | buf->area = area; |
| 78 | buf->size = pool_head_buffer->size; |
| 79 | return buf; |
Willy Tarreau | e583ea5 | 2014-11-24 11:30:16 +0100 | [diff] [blame] | 80 | } |
| 81 | |
Willy Tarreau | 3b091f8 | 2019-08-08 07:53:20 +0200 | [diff] [blame] | 82 | /* Releases buffer <buf> (no check of emptiness). The buffer's head is marked |
| 83 | * empty. |
| 84 | */ |
Willy Tarreau | e0d0b40 | 2019-08-08 08:06:27 +0200 | [diff] [blame] | 85 | static inline void __b_free(struct buffer *buf) |
Willy Tarreau | 7dfca9d | 2014-11-25 19:45:11 +0100 | [diff] [blame] | 86 | { |
Willy Tarreau | 3b091f8 | 2019-08-08 07:53:20 +0200 | [diff] [blame] | 87 | char *area = buf->area; |
| 88 | |
| 89 | /* let's first clear the area to save an occasional "show sess all" |
| 90 | * glancing over our shoulder from getting a dangling pointer. |
| 91 | */ |
| 92 | *buf = BUF_NULL; |
| 93 | __ha_barrier_store(); |
| 94 | pool_free(pool_head_buffer, area); |
Willy Tarreau | 7dfca9d | 2014-11-25 19:45:11 +0100 | [diff] [blame] | 95 | } |
| 96 | |
Willy Tarreau | 3b091f8 | 2019-08-08 07:53:20 +0200 | [diff] [blame] | 97 | /* Releases buffer <buf> if allocated, and marks it empty. */ |
Willy Tarreau | c9fa048 | 2018-07-10 17:43:27 +0200 | [diff] [blame] | 98 | static inline void b_free(struct buffer *buf) |
Willy Tarreau | 2a4b543 | 2014-11-24 11:39:34 +0100 | [diff] [blame] | 99 | { |
Willy Tarreau | e0d0b40 | 2019-08-08 08:06:27 +0200 | [diff] [blame] | 100 | if (buf->size) |
| 101 | __b_free(buf); |
Willy Tarreau | 2a4b543 | 2014-11-24 11:39:34 +0100 | [diff] [blame] | 102 | } |
| 103 | |
Willy Tarreau | 4d77bbf | 2021-02-20 12:02:46 +0100 | [diff] [blame] | 104 | /* Offer one or multiple buffer currently belonging to target <from> to whoever |
| 105 | * needs one. Any pointer is valid for <from>, including NULL. Its purpose is |
| 106 | * to avoid passing a buffer to oneself in case of failed allocations (e.g. |
| 107 | * need two buffers, get one, fail, release it and wake up self again). In case |
| 108 | * of normal buffer release where it is expected that the caller is not waiting |
Willy Tarreau | e8e5091 | 2021-02-20 11:38:56 +0100 | [diff] [blame] | 109 | * for a buffer, NULL is fine. It will wake waiters on the current thread only. |
Willy Tarreau | c41b3e8 | 2018-03-02 10:27:12 +0100 | [diff] [blame] | 110 | */ |
Willy Tarreau | 4d77bbf | 2021-02-20 12:02:46 +0100 | [diff] [blame] | 111 | void __offer_buffers(void *from, unsigned int count); |
Christopher Faulet | a73e59b | 2016-12-09 17:30:18 +0100 | [diff] [blame] | 112 | |
Willy Tarreau | 4d77bbf | 2021-02-20 12:02:46 +0100 | [diff] [blame] | 113 | static inline void offer_buffers(void *from, unsigned int count) |
Christopher Faulet | a73e59b | 2016-12-09 17:30:18 +0100 | [diff] [blame] | 114 | { |
Willy Tarreau | 90f366b | 2021-02-20 11:49:49 +0100 | [diff] [blame] | 115 | if (!LIST_ISEMPTY(&ti->buffer_wq)) |
Willy Tarreau | 4d77bbf | 2021-02-20 12:02:46 +0100 | [diff] [blame] | 116 | __offer_buffers(from, count); |
Christopher Faulet | a73e59b | 2016-12-09 17:30:18 +0100 | [diff] [blame] | 117 | } |
| 118 | |
Willy Tarreau | e5676e7 | 2017-09-22 15:47:51 +0200 | [diff] [blame] | 119 | |
Willy Tarreau | 2741c8c | 2020-06-02 11:28:02 +0200 | [diff] [blame] | 120 | #endif /* _HAPROXY_DYNBUF_H */ |
Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame] | 121 | |
| 122 | /* |
| 123 | * Local variables: |
| 124 | * c-indent-level: 8 |
| 125 | * c-basic-offset: 8 |
| 126 | * End: |
| 127 | */ |