1717
1818// #define DEBUG
1919// #undef NO_DEBUG
20- #include < debug>
21- #include < cassert>
2220#if !defined(__MACH__)
2321#include < malloc.h>
2422#else
@@ -27,26 +25,33 @@ extern void *memalign(size_t, size_t);
2725#include < net/buffer_store.hpp>
2826#include < kernel/syscalls.hpp>
2927#include < common>
28+ #include < debug>
29+ #include < info>
30+ #include < cassert>
3031#include < smp>
3132#define PAGE_SIZE 0x1000
3233
34+ #define ENABLE_BUFFERSTORE_CHAIN
35+ #define BS_CHAIN_ALLOC_PACKETS 2048
36+
3337namespace net {
3438
3539 bool BufferStore::smp_enabled_ = false ;
3640
3741 BufferStore::BufferStore (size_t num, size_t bufsize) :
3842 poolsize_ {num * bufsize},
39- bufsize_ {bufsize}
43+ bufsize_ {bufsize},
44+ next_ (nullptr )
4045 {
4146 assert (num != 0 );
4247 assert (bufsize != 0 );
4348 const size_t DATA_SIZE = poolsize_;
4449
45- this ->pool_ = (buffer_t ) memalign (PAGE_SIZE, DATA_SIZE);
50+ this ->pool_ = (uint8_t * ) memalign (PAGE_SIZE, DATA_SIZE);
4651 assert (this ->pool_ );
4752
4853 available_.reserve (num);
49- for (buffer_t b = pool_end ()-bufsize; b >= pool_begin (); b -= bufsize) {
54+ for (uint8_t * b = pool_end ()-bufsize; b >= pool_begin (); b -= bufsize) {
5055 available_.push_back (b);
5156 }
5257 assert (available () == num);
@@ -61,9 +66,33 @@ namespace net {
6166 }
6267
6368 BufferStore::~BufferStore () {
69+ delete this ->next_ ;
6470 free (this ->pool_ );
6571 }
6672
73+ BufferStore* BufferStore::get_next_bufstore ()
74+ {
75+ #ifdef ENABLE_BUFFERSTORE_CHAIN
76+ BufferStore* parent = this ;
77+ while (parent->next_ != nullptr ) {
78+ parent = parent->next_ ;
79+ if (parent->available () != 0 ) return parent;
80+ }
81+ INFO (" BufferStore" , " Allocating %u new packets" , BS_CHAIN_ALLOC_PACKETS);
82+ parent->next_ = new BufferStore (BS_CHAIN_ALLOC_PACKETS, bufsize ());
83+ return parent->next_ ;
84+ #else
85+ return nullptr ;
86+ #endif
87+ }
88+
89+ BufferStore::buffer_t BufferStore::get_buffer_directly () noexcept
90+ {
91+ auto addr = available_.back ();
92+ available_.pop_back ();
93+ return { this , addr };
94+ }
95+
6796 BufferStore::buffer_t BufferStore::get_buffer ()
6897 {
6998#ifndef INCLUDEOS_SINGLE_THREADED
@@ -78,7 +107,11 @@ namespace net {
78107#ifndef INCLUDEOS_SINGLE_THREADED
79108 if (is_locked) unlock (plock);
80109#endif
81- panic (" <BufferStore> Storage pool full! Don't know how to increase pool size yet.\n " );
110+ #ifdef ENABLE_BUFFERSTORE_CHAIN
111+ return get_next_bufstore ()->get_buffer_directly ();
112+ #else
113+ panic (" <BufferStore> Buffer pool empty! Not configured to increase pool size.\n " );
114+ #endif
82115 }
83116
84117 auto addr = available_.back ();
@@ -87,12 +120,12 @@ namespace net {
87120#ifndef INCLUDEOS_SINGLE_THREADED
88121 if (is_locked) unlock (plock);
89122#endif
90- return addr;
123+ return { this , addr } ;
91124 }
92125
93126 void BufferStore::release (void * addr)
94127 {
95- buffer_t buff = (buffer_t ) addr;
128+ auto * buff = (uint8_t * ) addr;
96129 debug (" Release %p -> " , buff);
97130
98131#ifndef INCLUDEOS_SINGLE_THREADED
@@ -111,6 +144,18 @@ namespace net {
111144 debug (" released\n " );
112145 return ;
113146 }
147+ #ifdef ENABLE_BUFFERSTORE_CHAIN
148+ // try to release buffer on linked bufferstore
149+ BufferStore* ptr = next_;
150+ while (ptr != nullptr ) {
151+ if (ptr->is_from_pool (buff)) {
152+ debug (" released on other bufferstore\n " );
153+ ptr->release_directly (buff);
154+ return ;
155+ }
156+ ptr = ptr->next_ ;
157+ }
158+ #endif
114159 // buffer not owned by bufferstore, so just delete it?
115160 debug (" deleted\n " );
116161 delete[] buff;
@@ -119,6 +164,11 @@ namespace net {
119164#endif
120165 }
121166
167+ void BufferStore::release_directly (uint8_t * buffer)
168+ {
169+ available_.push_back (buffer);
170+ }
171+
122172 void BufferStore::move_to_this_cpu () noexcept
123173 {
124174 this ->cpu = SMP::cpu_id ();
0 commit comments