diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cf3a331..831b1f7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCE_FILES manipulate_debug_flags.c cleanup_swiftnet.c make_response.c + memory_cleanup_background_service.c make_request.c internal/get_mtu.c internal/get_default_interface_and_mac.c diff --git a/src/cleanup_swiftnet.c b/src/cleanup_swiftnet.c index c3cb606..7774eac 100644 --- a/src/cleanup_swiftnet.c +++ b/src/cleanup_swiftnet.c @@ -1,5 +1,6 @@ #include "internal/internal.h" #include "swift_net.h" +#include #include #include @@ -22,6 +23,12 @@ static inline void close_listeners() { vector_destroy(&listeners); } +static inline void close_background_service() { + atomic_store_explicit(&swiftnet_closing, true, memory_order_release); + + pthread_join(memory_cleanup_thread, NULL); +} + void swiftnet_cleanup() { allocator_destroy(&packet_queue_node_memory_allocator); allocator_destroy(&packet_callback_queue_node_memory_allocator); @@ -45,4 +52,6 @@ void swiftnet_cleanup() { #ifdef SWIFT_NET_INTERNAL_TESTING printf("Bytes leaked: %d\nItems leaked: %d\n", bytes_leaked, items_leaked); #endif + + close_background_service(); } diff --git a/src/initialize_swiftnet.c b/src/initialize_swiftnet.c index 5daf8eb..b10e7b5 100644 --- a/src/initialize_swiftnet.c +++ b/src/initialize_swiftnet.c @@ -41,6 +41,10 @@ struct SwiftNetMemoryAllocator listener_memory_allocator; struct SwiftNetVector listeners; +pthread_t memory_cleanup_thread; + +_Atomic bool swiftnet_closing; + static inline void initialize_allocators() { packet_queue_node_memory_allocator = allocator_create(sizeof(struct PacketQueueNode), 100); packet_callback_queue_node_memory_allocator = allocator_create(sizeof(struct PacketCallbackQueueNode), 100); @@ -50,9 +54,28 @@ static inline void initialize_allocators() { server_memory_allocator = allocator_create(sizeof(struct SwiftNetServer), 10); client_connection_memory_allocator = allocator_create(sizeof(struct SwiftNetClientConnection), 10); listener_memory_allocator = allocator_create(sizeof(struct Listener), 100); + + #ifdef SWIFT_NET_REQUESTS + requests_sent_memory_allocator = allocator_create(sizeof(struct RequestSent), 100); + #endif + +} + +static inline void initialize_vectors() { + #ifdef SWIFT_NET_REQUESTS + requests_sent = vector_create(100); + #endif + + listeners = vector_create(10); +} + +static inline void initialize_memory_cleanup_thread() { + pthread_create(&memory_cleanup_thread, NULL, memory_cleanup_background_service, NULL); } void swiftnet_initialize() { + atomic_store_explicit(&swiftnet_closing, false, memory_order_release); + const int temp_socket = socket(AF_INET, SOCK_DGRAM, 0); if (temp_socket < 0) { PRINT_ERROR("Failed to create temp socket"); @@ -98,14 +121,9 @@ void swiftnet_initialize() { close(temp_socket); initialize_allocators(); + initialize_vectors(); - #ifdef SWIFT_NET_REQUESTS - requests_sent_memory_allocator = allocator_create(sizeof(struct RequestSent), 100); - - requests_sent = vector_create(100); - #endif - - listeners = vector_create(10); + initialize_memory_cleanup_thread(); return; } diff --git a/src/internal/internal.h b/src/internal/internal.h index 7c7d6b3..85dec02 100644 --- a/src/internal/internal.h +++ b/src/internal/internal.h @@ -47,6 +47,8 @@ typedef enum { #define SIZEOF_FIELD(type, field) sizeof(((type *)0)->field) +#define PACKET_HISTORY_STORE_TIME 5 + #define PRINT_ERROR(fmt, ...) \ do { fprintf(stderr, fmt " | function: %s | line: %d\n", ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0) @@ -125,6 +127,11 @@ enum ConnectionType { extern struct SwiftNetVector listeners; +extern pthread_t memory_cleanup_thread; +extern _Atomic bool swiftnet_closing; + +extern void* memory_cleanup_background_service(); + extern int get_default_interface_and_mac(char *restrict interface_name, uint32_t interface_name_length, uint8_t mac_out[6], int sockfd); extern const uint32_t get_mtu(const char* restrict const interface, const int sockfd); extern int get_bpf_device(); diff --git a/src/memory_cleanup_background_service.c b/src/memory_cleanup_background_service.c new file mode 100644 index 0000000..b8068af --- /dev/null +++ b/src/memory_cleanup_background_service.c @@ -0,0 +1,71 @@ +#include "swift_net.h" +#include "internal/internal.h" +#include +#include +#include + +static inline void cleanup_packets_completed(struct SwiftNetVector* packets_completed, struct SwiftNetMemoryAllocator* const packets_completed_allocator) { + vector_lock(packets_completed); + + for (uint32_t i = 0; i < packets_completed->size; i++) { + struct SwiftNetPacketCompleted* const current_packet_completed = vector_get(packets_completed, i); + + if (current_packet_completed->marked_cleanup == true) { + vector_remove(packets_completed, i); + + allocator_free(packets_completed_allocator, current_packet_completed); + } else { + current_packet_completed->marked_cleanup = true; + } + } + + vector_unlock(packets_completed); +} + +void* memory_cleanup_background_service() { + while(atomic_load_explicit(&swiftnet_closing, memory_order_acquire) == false) { + struct timeval start, end; + gettimeofday(&start, NULL); + + vector_lock(&listeners); + + for (uint32_t i = 0; i < listeners.size; i++) { + struct Listener* const current_listener = vector_get(&listeners, i); + + struct SwiftNetVector* const client_connections = ¤t_listener->client_connections; + struct SwiftNetVector* const servers = ¤t_listener->servers; + + vector_lock(servers); + vector_lock(client_connections); + + for (uint32_t client_connection_index = 0; client_connection_index < client_connections->size; client_connection_index++) { + struct SwiftNetClientConnection* const current_con = vector_get(client_connections, client_connection_index); + + cleanup_packets_completed(¤t_con->packets_completed, ¤t_con->packets_completed_memory_allocator); + } + + for (uint32_t server_index = 0; server_index < servers->size; server_index++) { + struct SwiftNetServer* const current_server = vector_get(servers, server_index); + + cleanup_packets_completed(¤t_server->packets_completed, ¤t_server->packets_completed_memory_allocator); + } + + vector_unlock(client_connections); + vector_unlock(servers); + } + + vector_unlock(&listeners); + + gettimeofday(&end, NULL); + + uint32_t diff_us = (uint32_t)((end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec)); + + if (diff_us > PACKET_HISTORY_STORE_TIME * 1000000) { + continue; + } + + usleep((PACKET_HISTORY_STORE_TIME * 1000000) - diff_us); + } + + return NULL; +} diff --git a/src/process_packets.c b/src/process_packets.c index 28f1586..e41145e 100644 --- a/src/process_packets.c +++ b/src/process_packets.c @@ -85,6 +85,7 @@ static inline const uint32_t return_lost_chunk_indexes(const uint8_t* const chun static inline void packet_completed(const uint16_t packet_id, struct SwiftNetVector* const packets_completed_history, struct SwiftNetMemoryAllocator* const packets_completed_history_memory_allocator) { struct SwiftNetPacketCompleted* const new_packet_completed = allocator_allocate(packets_completed_history_memory_allocator); new_packet_completed->packet_id = packet_id; + new_packet_completed->marked_cleanup = false; vector_lock(packets_completed_history); diff --git a/src/swift_net.h b/src/swift_net.h index aa21eb3..44f7456 100644 --- a/src/swift_net.h +++ b/src/swift_net.h @@ -137,6 +137,7 @@ struct SwiftNetPacketSending { struct SwiftNetPacketCompleted { uint16_t packet_id; + bool marked_cleanup; }; struct SwiftNetPacketBuffer { diff --git a/tests/integration_tests/output/run_tests b/tests/integration_tests/output/run_tests index c318c2f..3f114af 100755 Binary files a/tests/integration_tests/output/run_tests and b/tests/integration_tests/output/run_tests differ diff --git a/tests/performance_tests/output/run_tests b/tests/performance_tests/output/run_tests index 6999639..cd9b63d 100755 Binary files a/tests/performance_tests/output/run_tests and b/tests/performance_tests/output/run_tests differ