1 | /* |
2 | This file is part of Mtproto-proxy Library. |
3 | |
4 | Mtproto-proxy Library is free software: you can redistribute it and/or modify |
5 | it under the terms of the GNU Lesser General Public License as published by |
6 | the Free Software Foundation, either version 2 of the License, or |
7 | (at your option) any later version. |
8 | |
9 | Mtproto-proxy Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | GNU Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public License |
15 | along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | Copyright 2012-2013 Vkontakte Ltd |
18 | 2012-2013 Nikolai Durov |
19 | 2012-2013 Andrey Lopatin |
20 | |
21 | Copyright 2014-2016 Telegram Messenger Inc |
22 | 2015-2016 Vitaly Valtman |
23 | */ |
24 | |
25 | #pragma once |
26 | |
27 | #include <assert.h> |
28 | #include "common/mp-queue.h" |
29 | |
30 | #define MSG_STD_BUFFER 2048 |
31 | #define MSG_SMALL_BUFFER 512 |
32 | #define MSG_TINY_BUFFER 48 |
33 | |
34 | #define MSG_BUFFERS_CHUNK_SIZE ((1L << 21) - 64) |
35 | |
36 | #define MSG_DEFAULT_MAX_ALLOCATED_BYTES (1L << 28) |
37 | |
38 | #ifdef _LP64 |
39 | #define MSG_MAX_ALLOCATED_BYTES (1L << 40) |
40 | #else |
41 | #define MSG_MAX_ALLOCATED_BYTES (1L << 30) |
42 | #endif |
43 | |
44 | #define MSG_BUFFER_FREE_MAGIC 0x4abdc351 |
45 | #define MSG_BUFFER_USED_MAGIC 0x72e39317 |
46 | #define MSG_BUFFER_SPECIAL_MAGIC 0x683caad3 |
47 | |
48 | #define MSG_CHUNK_USED_MAGIC 0x5c75e681 |
49 | #define MSG_CHUNK_USED_LOCKED_MAGIC (~MSG_CHUNK_USED_MAGIC) |
50 | #define MSG_CHUNK_HEAD_MAGIC 0x2dfecca3 |
51 | #define MSG_CHUNK_HEAD_LOCKED_MAGIC (~MSG_CHUNK_HEAD_MAGIC) |
52 | |
53 | #define MAX_BUFFER_SIZE_VALUES 16 |
54 | |
55 | #define BUFF_HD_BYTES (offsetof (struct msg_buffer, data)) |
56 | |
57 | struct msg_buffer { |
58 | struct msg_buffers_chunk *chunk; |
59 | #ifndef _LP64 |
60 | int resvd; |
61 | #endif |
62 | int refcnt; |
63 | int magic; |
64 | char data[0]; |
65 | }; |
66 | |
67 | struct msg_buffers_chunk { |
68 | int magic; |
69 | int buffer_size; |
70 | int (*free_buffer)(struct msg_buffers_chunk *C, struct msg_buffer *B); |
71 | struct msg_buffers_chunk *ch_next, *ch_prev; |
72 | struct msg_buffers_chunk *ch_head; |
73 | struct msg_buffer *first_buffer; |
74 | int two_power; /* least two-power >= tot_buffers */ |
75 | int tot_buffers; |
76 | int bs_inverse; |
77 | int bs_shift; |
78 | struct mp_queue *free_block_queue; |
79 | int thread_class; |
80 | int thread_subclass; |
81 | int refcnt; |
82 | union { |
83 | struct { |
84 | int tot_chunks; |
85 | int free_buffers; |
86 | }; |
87 | unsigned short free_cnt[0]; |
88 | }; |
89 | }; |
90 | |
91 | struct buffers_stat { |
92 | long long total_used_buffers_size; |
93 | long long allocated_buffer_bytes; |
94 | long long buffer_chunk_alloc_ops; |
95 | int total_used_buffers; |
96 | int allocated_buffer_chunks, max_allocated_buffer_chunks, max_buffer_chunks; |
97 | long long max_allocated_buffer_bytes; |
98 | }; |
99 | |
100 | void fetch_buffers_stat (struct buffers_stat *bs); |
101 | |
102 | int free_msg_buffer (struct msg_buffer *X); |
103 | static inline void msg_buffer_decref (struct msg_buffer *buffer) { |
104 | if (buffer->refcnt == 1 || __sync_fetch_and_add (&buffer->refcnt, -1) == 1) { |
105 | buffer->refcnt = 0; |
106 | free_msg_buffer (buffer); |
107 | } |
108 | } |
109 | |
110 | |
111 | int init_msg_buffers (long max_buffer_bytes); |
112 | |
113 | struct msg_buffer *alloc_msg_buffer (struct msg_buffer *neighbor, int size_hint); |
114 | |
115 | int free_msg_buffer (struct msg_buffer *buffer); |
116 | int msg_buffer_reach_limit (double ratio); |
117 | double msg_buffer_usage (void); |
118 | |
119 | extern long long max_allocated_buffer_bytes; |
120 | extern int allocated_buffer_chunks, max_allocated_buffer_chunks; |
121 | |