diff --git a/src/add-ons/kernel/network/stack/net_buffer.cpp b/src/add-ons/kernel/network/stack/net_buffer.cpp index e9fd2f8bee..9bbd8c32dc 100644 --- a/src/add-ons/kernel/network/stack/net_buffer.cpp +++ b/src/add-ons/kernel/network/stack/net_buffer.cpp @@ -10,10 +10,12 @@ #include "utility.h" #include +#include #include #include #include +#include #include #include @@ -63,6 +65,17 @@ struct net_buffer_private : net_buffer { }; +typedef MergedLinkCacheStrategy AreaMergedCacheStrategy; +typedef HashCacheStrategy AreaHashCacheStrategy; + +typedef Cache NetBufferCache; +typedef Cache DataNodeCache; + +static NetBufferCache *sNetBufferCache; +static DataNodeCache *sDataNodeCache; +static benaphore sCachesLock; + + static status_t append_data(net_buffer *buffer, const void *data, size_t size); static status_t trim_data(net_buffer *_buffer, size_t newSize); static status_t remove_header(net_buffer *_buffer, size_t bytes); @@ -87,11 +100,43 @@ dump_buffer(net_buffer *_buffer) #endif +static inline data_header * +allocate_data_header() +{ + BenaphoreLocker _(sCachesLock); + return (data_header *)sDataNodeCache->AllocateObject(CACHE_DONT_SLEEP); +} + + +static inline net_buffer_private * +allocate_net_buffer() +{ + BenaphoreLocker _(sCachesLock); + return (net_buffer_private *)sNetBufferCache->AllocateObject( + CACHE_DONT_SLEEP); +} + + +static inline void +free_data_header(data_header *header) +{ + BenaphoreLocker _(sCachesLock); + sDataNodeCache->ReturnObject(header); +} + + +static inline void +free_net_buffer(net_buffer_private *buffer) +{ + BenaphoreLocker _(sCachesLock); + sNetBufferCache->ReturnObject(buffer); +} + + static data_header * create_data_header(size_t headerSpace) { - // TODO: don't use malloc! - data_header *header = (data_header *)malloc(BUFFER_SIZE); + data_header *header = allocate_data_header(); if (header == NULL) return NULL; @@ -115,7 +160,7 @@ release_data_header(data_header *header) return; TRACE((" free header %p\n", header)); - free(header); + free_data_header(header); } @@ -275,8 +320,7 @@ get_node_at_offset(net_buffer_private *buffer, size_t offset) static net_buffer * create_buffer(size_t headerSpace) { - net_buffer_private *buffer = (net_buffer_private *)malloc( - sizeof(struct net_buffer_private)); + net_buffer_private *buffer = allocate_net_buffer(); if (buffer == NULL) return NULL; @@ -284,7 +328,7 @@ create_buffer(size_t headerSpace) data_header *header = create_data_header(headerSpace); if (header == NULL) { - free(buffer); + free_net_buffer(buffer); return NULL; } @@ -318,7 +362,7 @@ free_buffer(net_buffer *_buffer) remove_data_node(node); } - free(buffer); + free_net_buffer(buffer); } @@ -380,14 +424,13 @@ clone_buffer(net_buffer *_buffer, bool shareFreeSpace) TRACE(("clone_buffer(buffer %p)\n", buffer)); - net_buffer_private *clone = (net_buffer_private *)malloc( - sizeof(struct net_buffer_private)); + net_buffer_private *clone = allocate_net_buffer(); if (clone == NULL) return NULL; data_node *sourceNode = (data_node *)list_get_first_item(&buffer->buffers); if (sourceNode == NULL) { - free(clone); + free_net_buffer(clone); return NULL; } @@ -428,7 +471,7 @@ clone_buffer(net_buffer *_buffer, bool shareFreeSpace) // There was not enough space left for another node in this buffer // TODO: handle this case! panic("clone buffer hits size limit... (fix me)"); - free(clone); + free_net_buffer(clone); return NULL; } } @@ -1136,6 +1179,49 @@ count_iovecs(net_buffer *_buffer) } +status_t +init_net_buffers() +{ + // TODO improve our code a bit so we can add constructors + // and keep around half-constructed buffers in the slab + + status_t status = benaphore_init(&sCachesLock, "net buffer cache lock"); + if (status < B_OK) + return status; + + sNetBufferCache = new (std::nothrow) NetBufferCache("net buffer cache", + sizeof(net_buffer_private), 8, NULL, NULL, NULL); + if (sNetBufferCache == NULL) { + benaphore_destroy(&sCachesLock); + return B_NO_MEMORY; + } + + sDataNodeCache = new (std::nothrow) DataNodeCache("data node cache", + BUFFER_SIZE, 0, NULL, NULL, NULL); + if (sDataNodeCache == NULL) { + benaphore_destroy(&sCachesLock); + delete sNetBufferCache; + return B_NO_MEMORY; + } + + return B_OK; +} + + +status_t +uninit_net_buffers() +{ + benaphore_lock(&sCachesLock); + + delete sNetBufferCache; + delete sDataNodeCache; + + benaphore_destroy(&sCachesLock); + + return B_OK; +} + + static status_t std_ops(int32 op, ...) { diff --git a/src/add-ons/kernel/network/stack/stack.cpp b/src/add-ons/kernel/network/stack/stack.cpp index 55384ec0d6..8ae66b63dd 100644 --- a/src/add-ons/kernel/network/stack/stack.cpp +++ b/src/add-ons/kernel/network/stack/stack.cpp @@ -785,6 +785,10 @@ init_stack() goto err8; } + status = init_net_buffers(); + if (status < B_OK) + goto err9; + sInitialized = true; link_init(); @@ -802,6 +806,8 @@ init_stack() return B_OK; +err9: + hash_uninit(sReceivingProtocolChains); err8: hash_uninit(sDatalinkProtocolChains); err7: @@ -831,6 +837,8 @@ uninit_stack() uninit_interfaces(); uninit_domains(); + uninit_net_buffers(); + benaphore_destroy(&sChainLock); benaphore_destroy(&sInitializeChainLock); diff --git a/src/add-ons/kernel/network/stack/stack_private.h b/src/add-ons/kernel/network/stack/stack_private.h index 6b1d826fa0..838f3aa85d 100644 --- a/src/add-ons/kernel/network/stack/stack_private.h +++ b/src/add-ons/kernel/network/stack/stack_private.h @@ -33,4 +33,8 @@ status_t put_domain_protocols(net_socket *socket); status_t get_domain_datalink_protocols(net_interface *interface); status_t put_domain_datalink_protocols(net_interface *interface); +// net_buffer.cpp +status_t init_net_buffers(); +status_t uninit_net_buffers(); + #endif // STACK_PRIVATE_H