blob: a200237923f74f7f326a46e49c7b9dda6d473823 [file] [log] [blame]
Willy Tarreauc7e42382012-08-24 19:22:53 +02001/*
2 * Buffer management functions.
3 *
4 * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
William Lallemandbe0efd82012-11-22 18:01:40 +010013#include <ctype.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020014#include <stdio.h>
15#include <string.h>
16
Willy Tarreau4c7e4b72020-05-27 12:58:42 +020017#include <haproxy/api.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +020018#include <haproxy/dynbuf.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020019#include <haproxy/global.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +020020#include <haproxy/list.h>
Willy Tarreaud0ef4392020-06-02 09:38:52 +020021#include <haproxy/pool.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020022
Willy Tarreauff882702021-04-10 17:23:00 +020023struct pool_head *pool_head_buffer __read_mostly;
Willy Tarreau9b28e032012-10-12 23:49:43 +020024
Willy Tarreau9b28e032012-10-12 23:49:43 +020025/* perform minimal intializations, report 0 in case of error, 1 if OK. */
26int init_buffer()
27{
Willy Tarreaua24adf02014-11-27 01:11:56 +010028 void *buffer;
Willy Tarreaue8e50912021-02-20 11:38:56 +010029 int thr;
Willy Tarreaua5b229d2021-04-15 19:24:12 +020030 int done;
Willy Tarreaua24adf02014-11-27 01:11:56 +010031
Willy Tarreauc9fa0482018-07-10 17:43:27 +020032 pool_head_buffer = create_pool("buffer", global.tune.bufsize, MEM_F_SHARED|MEM_F_EXACT);
Willy Tarreaubafbe012017-11-24 17:34:44 +010033 if (!pool_head_buffer)
Willy Tarreaua24adf02014-11-27 01:11:56 +010034 return 0;
35
Willy Tarreaue8e50912021-02-20 11:38:56 +010036 for (thr = 0; thr < MAX_THREADS; thr++)
Willy Tarreau90f366b2021-02-20 11:49:49 +010037 LIST_INIT(&ha_thread_info[thr].buffer_wq);
Willy Tarreaue8e50912021-02-20 11:38:56 +010038
39
Willy Tarreaua24adf02014-11-27 01:11:56 +010040 /* The reserved buffer is what we leave behind us. Thus we always need
41 * at least one extra buffer in minavail otherwise we'll end up waking
42 * up tasks with no memory available, causing a lot of useless wakeups.
43 * That means that we always want to have at least 3 buffers available
44 * (2 for current session, one for next session that might be needed to
45 * release a server connection).
46 */
Willy Tarreaubafbe012017-11-24 17:34:44 +010047 pool_head_buffer->minavail = MAX(global.tune.reserved_bufs, 3);
Willy Tarreau33cb0652014-12-23 22:52:37 +010048 if (global.tune.buf_limit)
Willy Tarreaubafbe012017-11-24 17:34:44 +010049 pool_head_buffer->limit = global.tune.buf_limit;
Willy Tarreaua24adf02014-11-27 01:11:56 +010050
Willy Tarreaua5b229d2021-04-15 19:24:12 +020051 for (done = 0; done < pool_head_buffer->minavail - 1; done++) {
Willy Tarreau8fe726f2021-04-15 18:20:12 +020052 buffer = pool_alloc_nocache(pool_head_buffer);
Willy Tarreaua5b229d2021-04-15 19:24:12 +020053 if (!buffer)
54 return 0;
55 pool_free(pool_head_buffer, buffer);
56 }
Willy Tarreaua24adf02014-11-27 01:11:56 +010057 return 1;
Willy Tarreau9b28e032012-10-12 23:49:43 +020058}
59
Willy Tarreauaf819352012-08-27 22:08:00 +020060/*
Willy Tarreauc7e42382012-08-24 19:22:53 +020061 * Dumps part or all of a buffer.
62 */
63void buffer_dump(FILE *o, struct buffer *b, int from, int to)
64{
65 fprintf(o, "Dumping buffer %p\n", b);
Willy Tarreau81521ed2018-06-19 07:48:13 +020066 fprintf(o, " orig=%p size=%u head=%u tail=%u data=%u\n",
67 b_orig(b), (unsigned int)b_size(b), (unsigned int)b_head_ofs(b), (unsigned int)b_tail_ofs(b), (unsigned int)b_data(b));
Willy Tarreauc7e42382012-08-24 19:22:53 +020068
69 fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
William Lallemandbe0efd82012-11-22 18:01:40 +010070 fprintf(o, " 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
71 /* dump hexa */
72 while (from < to) {
73 int i;
74
75 fprintf(o, " %04x: ", from);
76 for (i = 0; ((from + i) < to) && (i < 16) ; i++) {
Willy Tarreau81521ed2018-06-19 07:48:13 +020077 fprintf(o, "%02x ", (unsigned char)b_orig(b)[from + i]);
William Lallemand7e7765a2021-08-09 19:37:16 +020078 if (i == 7)
William Lallemandbe0efd82012-11-22 18:01:40 +010079 fprintf(o, "- ");
80 }
Godbachc08057c2013-11-14 10:15:20 +080081 if (to - from < 16) {
Godbachc3916a72013-11-21 10:21:22 +080082 int j = 0;
83
Godbachc08057c2013-11-14 10:15:20 +080084 for (j = 0; j < from + 16 - to; j++)
85 fprintf(o, " ");
Godbachc3916a72013-11-21 10:21:22 +080086 if (j > 8)
87 fprintf(o, " ");
Godbachc08057c2013-11-14 10:15:20 +080088 }
William Lallemandbe0efd82012-11-22 18:01:40 +010089 fprintf(o, " ");
90 for (i = 0; (from + i < to) && (i < 16) ; i++) {
Willy Tarreau90807112020-02-25 08:16:33 +010091 fprintf(o, "%c", isprint((unsigned char)b_orig(b)[from + i]) ? b_orig(b)[from + i] : '.') ;
William Lallemand7e7765a2021-08-09 19:37:16 +020092 if ((i == 15) && ((from + i) != to-1))
William Lallemandbe0efd82012-11-22 18:01:40 +010093 fprintf(o, "\n");
94 }
95 from += i;
Willy Tarreauc7e42382012-08-24 19:22:53 +020096 }
97 fprintf(o, "\n--\n");
William Lallemandbe0efd82012-11-22 18:01:40 +010098 fflush(o);
Willy Tarreauc7e42382012-08-24 19:22:53 +020099}
100
Willy Tarreau4d77bbf2021-02-20 12:02:46 +0100101/* see offer_buffers() for details */
102void __offer_buffers(void *from, unsigned int count)
Christopher Fauleta73e59b2016-12-09 17:30:18 +0100103{
Willy Tarreau90f366b2021-02-20 11:49:49 +0100104 struct buffer_wait *wait, *wait_back;
Christopher Fauleta73e59b2016-12-09 17:30:18 +0100105
106 /* For now, we consider that all objects need 1 buffer, so we can stop
107 * waking up them once we have enough of them to eat all the available
108 * buffers. Note that we don't really know if they are streams or just
109 * other tasks, but that's a rough estimate. Similarly, for each cached
Willy Tarreau4d77bbf2021-02-20 12:02:46 +0100110 * event we'll need 1 buffer.
Christopher Fauleta73e59b2016-12-09 17:30:18 +0100111 */
Willy Tarreau90f366b2021-02-20 11:49:49 +0100112 list_for_each_entry_safe(wait, wait_back, &ti->buffer_wq, list) {
Willy Tarreau4d77bbf2021-02-20 12:02:46 +0100113 if (!count)
Christopher Fauleta73e59b2016-12-09 17:30:18 +0100114 break;
115
116 if (wait->target == from || !wait->wakeup_cb(wait->target))
117 continue;
118
Willy Tarreau90f366b2021-02-20 11:49:49 +0100119 LIST_DEL_INIT(&wait->list);
Willy Tarreau4d77bbf2021-02-20 12:02:46 +0100120 count--;
Christopher Fauleta73e59b2016-12-09 17:30:18 +0100121 }
122}
Willy Tarreauc7e42382012-08-24 19:22:53 +0200123
124/*
125 * Local variables:
126 * c-indent-level: 8
127 * c-basic-offset: 8
128 * End:
129 */