daemon_funcs.c (7914B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2024 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file src/mhd2/daemon_funcs.c 41 * @brief The implementation of internal daemon-related functions 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 #include "mhd_sys_options.h" 46 47 #include "daemon_funcs.h" 48 49 #include "sys_base_types.h" 50 #include "sys_malloc.h" 51 52 #include "mhd_assert.h" 53 #include "mhd_itc.h" 54 #include "mhd_daemon.h" 55 #include "daemon_logger.h" 56 57 58 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 59 MHD_FN_MUST_CHECK_RESULT_ struct MHD_Daemon * 60 mhd_daemon_get_master_daemon (struct MHD_Daemon *restrict d) 61 { 62 #ifdef MHD_SUPPORT_THREADS 63 if (mhd_D_HAS_MASTER (d)) 64 return d->threading.hier.master; 65 #endif /* MHD_SUPPORT_THREADS */ 66 return d; 67 } 68 69 70 #ifdef MHD_SUPPORT_THREADS 71 72 MHD_INTERNAL bool 73 mhd_daemon_trigger_itc (struct MHD_Daemon *restrict d) 74 { 75 mhd_assert (mhd_ITC_IS_VALID (d->threading.itc)); 76 if (! mhd_itc_activate (d->threading.itc)) 77 { 78 mhd_LOG_MSG (d, MHD_SC_ITC_USE_FAILED, \ 79 "Failed to communicate by ITC with the daemon thread."); 80 return false; 81 } 82 return true; 83 } 84 85 86 #endif /* MHD_SUPPORT_THREADS */ 87 88 89 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 90 MHD_FN_MUST_CHECK_RESULT_ bool 91 mhd_daemon_claim_lbuf (struct MHD_Daemon *restrict d, 92 size_t requested_size) 93 { 94 bool ret; 95 struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d); 96 mhd_assert (0 != requested_size); 97 if (0 == masterd->req_cfg.large_buf.space_left) 98 return false; /* Shortcut for typical use without large buffer */ 99 100 ret = false; 101 mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock)); 102 if (masterd->req_cfg.large_buf.space_left >= requested_size) 103 { 104 masterd->req_cfg.large_buf.space_left -= requested_size; 105 ret = true; 106 } 107 mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock)); 108 return ret; 109 } 110 111 112 static MHD_FN_PAR_NONNULL_ALL_ 113 MHD_FN_MUST_CHECK_RESULT_ size_t 114 mhd_daemon_claim_lbuf_up_to (struct MHD_Daemon *d, 115 size_t requested_size) 116 { 117 size_t ret; 118 struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d); 119 mhd_assert (0 != requested_size); 120 if (0 == masterd->req_cfg.large_buf.space_left) 121 return false; /* Shortcut for typical use without large buffer */ 122 123 mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock)); 124 if (masterd->req_cfg.large_buf.space_left >= requested_size) 125 { 126 ret = requested_size; 127 masterd->req_cfg.large_buf.space_left -= requested_size; 128 } 129 else 130 { 131 ret = masterd->req_cfg.large_buf.space_left; 132 masterd->req_cfg.large_buf.space_left = 0; 133 } 134 mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock)); 135 return ret; 136 } 137 138 139 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void 140 mhd_daemon_reclaim_lbuf (struct MHD_Daemon *restrict d, 141 size_t reclaimed_size) 142 { 143 struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d); 144 mhd_assert (0 != reclaimed_size); 145 mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock)); 146 masterd->req_cfg.large_buf.space_left += reclaimed_size; 147 mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock)); 148 } 149 150 151 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ 152 MHD_FN_PAR_OUT_ (3) bool 153 mhd_daemon_get_lbuf (struct MHD_Daemon *restrict d, 154 size_t requested_size, 155 struct mhd_Buffer *restrict buf) 156 { 157 if (! mhd_daemon_claim_lbuf (d, requested_size)) 158 { 159 buf->size = 0; 160 buf->data = NULL; 161 return false; 162 } 163 buf->data = (char *) malloc (requested_size); 164 if (NULL == buf->data) 165 { 166 buf->size = 0; 167 mhd_daemon_reclaim_lbuf (d, requested_size); 168 return false; 169 } 170 buf->size = requested_size; 171 return true; 172 } 173 174 175 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ 176 MHD_FN_PAR_INOUT_ (3) bool 177 mhd_daemon_grow_lbuf (struct MHD_Daemon *restrict d, 178 size_t grow_size, 179 struct mhd_Buffer *restrict buf) 180 { 181 void *new_alloc; 182 mhd_assert (NULL != buf->data || 0 == buf->size); 183 mhd_assert (0 != buf->size || NULL == buf->data); 184 185 if (! mhd_daemon_claim_lbuf (d, grow_size)) 186 return false; 187 188 if (NULL == buf->data) 189 new_alloc = malloc (grow_size); 190 else 191 new_alloc = realloc (buf->data, buf->size + grow_size); 192 if (NULL == new_alloc) 193 { 194 mhd_daemon_reclaim_lbuf (d, grow_size); 195 return false; 196 } 197 198 buf->data = (char *) new_alloc; 199 buf->size += grow_size; 200 201 return true; 202 } 203 204 205 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ 206 MHD_FN_PAR_INOUT_ (3) size_t 207 mhd_daemon_extend_lbuf_up_to (struct MHD_Daemon *restrict d, 208 size_t desired_grow_size, 209 struct mhd_Buffer *restrict buf) 210 { 211 void *new_alloc; 212 size_t grow_size; 213 mhd_assert (NULL != buf->data || 0 == buf->size); 214 mhd_assert (0 != buf->size || NULL == buf->data); 215 mhd_assert (0 != desired_grow_size); 216 217 grow_size = mhd_daemon_claim_lbuf_up_to (d, desired_grow_size); 218 219 new_alloc = NULL; 220 if (NULL == buf->data) 221 { 222 while ((0 != grow_size) && 223 (NULL == (new_alloc = malloc (grow_size)))) 224 { 225 size_t reduce = grow_size / 2; 226 if (sizeof(void *) >= (grow_size - reduce)) 227 reduce = grow_size; 228 mhd_daemon_reclaim_lbuf (d, 229 reduce); 230 grow_size -= reduce; 231 } 232 } 233 else 234 { 235 while ((0 != grow_size) && 236 (NULL == (new_alloc = realloc (buf->data, 237 buf->size + grow_size)))) 238 { 239 size_t reduce = grow_size / 2; 240 if (sizeof(void *) >= (grow_size - reduce)) 241 reduce = grow_size; 242 mhd_daemon_reclaim_lbuf (d, 243 reduce); 244 grow_size -= reduce; 245 } 246 } 247 248 if (NULL != new_alloc) 249 { 250 mhd_assert (0 != grow_size); 251 buf->data = (char *) new_alloc; 252 buf->size += grow_size; 253 } 254 255 return grow_size; 256 } 257 258 259 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 260 MHD_FN_PAR_INOUT_ (2) void 261 mhd_daemon_free_lbuf (struct MHD_Daemon *restrict d, 262 struct mhd_Buffer *restrict buf) 263 { 264 if (0 == buf->size) 265 { 266 mhd_assert (NULL == buf->data); 267 return; 268 } 269 free (buf->data); 270 buf->data = NULL; 271 mhd_daemon_reclaim_lbuf (d, buf->size); 272 buf->size = 0; 273 }