tinyproxy/src/sblist.c

81 lines
1.7 KiB
C
Raw Normal View History

simplify codebase by using one thread/conn, instead of preforked procs the existing codebase used an elaborate and complex approach for its parallelism: 5 different config file options, namely - MaxClients - MinSpareServers - MaxSpareServers - StartServers - MaxRequestsPerChild were used to steer how (and how many) parallel processes tinyproxy would spin up at start, how many processes at each point needed to be idle, etc. it seems all preforked processes would listen on the server port and compete with each other about who would get assigned the new incoming connections. since some data needs to be shared across those processes, a half- baked "shared memory" implementation was provided for this purpose. that implementation used to use files in the filesystem, and since it had a big FIXME comment, the author was well aware of how hackish that approach was. this entire complexity is now removed. the main thread enters a loop which polls on the listening fds, then spins up a new thread per connection, until the maximum number of connections (MaxClients) is hit. this is the only of the 5 config options left after this cleanup. since threads share the same address space, the code necessary for shared memory access has been removed. this means that the other 4 mentioned config option will now produce a parse error, when encountered. currently each thread uses a hardcoded default of 256KB per thread for the thread stack size, which is quite lavish and should be sufficient for even the worst C libraries, but people may want to tweak this value to the bare minimum, thus we may provide a new config option for this purpose in the future. i suspect that on heavily optimized C libraries such a musl, a stack size of 8-16 KB per thread could be sufficient. since the existing list implementation in vector.c did not provide a way to remove a single item from an existing list, i added my own list implementation from my libulz library which offers this functionality, rather than trying to add an ad-hoc, and perhaps buggy implementation to the vector_t list code. the sblist code is contained in an 80 line C file and as simple as it can get, while offering good performance and is proven bugfree due to years of use in other projects.
2018-12-16 16:23:09 -08:00
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#include "sblist.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#define MY_PAGE_SIZE 4096
sblist* sblist_new(size_t itemsize, size_t blockitems) {
sblist* ret = (sblist*) malloc(sizeof(sblist));
sblist_init(ret, itemsize, blockitems);
return ret;
}
static void sblist_clear(sblist* l) {
l->items = NULL;
l->capa = 0;
l->count = 0;
}
void sblist_init(sblist* l, size_t itemsize, size_t blockitems) {
if(l) {
l->blockitems = blockitems ? blockitems : MY_PAGE_SIZE / itemsize;
l->itemsize = itemsize;
sblist_clear(l);
}
}
void sblist_free_items(sblist* l) {
if(l) {
if(l->items) free(l->items);
sblist_clear(l);
}
}
void sblist_free(sblist* l) {
if(l) {
sblist_free_items(l);
free(l);
}
}
char* sblist_item_from_index(sblist* l, size_t idx) {
return l->items + (idx * l->itemsize);
}
void* sblist_get(sblist* l, size_t item) {
if(item < l->count) return (void*) sblist_item_from_index(l, item);
return NULL;
}
int sblist_set(sblist* l, void* item, size_t pos) {
if(pos >= l->count) return 0;
memcpy(sblist_item_from_index(l, pos), item, l->itemsize);
return 1;
}
int sblist_grow_if_needed(sblist* l) {
char* temp;
if(l->count == l->capa) {
temp = realloc(l->items, (l->capa + l->blockitems) * l->itemsize);
if(!temp) return 0;
l->capa += l->blockitems;
l->items = temp;
}
return 1;
}
int sblist_add(sblist* l, void* item) {
if(!sblist_grow_if_needed(l)) return 0;
l->count++;
return sblist_set(l, item, l->count - 1);
}
void sblist_delete(sblist* l, size_t item) {
if (l->count && item < l->count) {
memmove(sblist_item_from_index(l, item), sblist_item_from_index(l, item + 1), (sblist_getsize(l) - (item + 1)) * l->itemsize);
l->count--;
}
}