};
class buffer::raw_posix_aligned : public buffer::raw {
+ unsigned align;
public:
- raw_posix_aligned(unsigned l) : raw(l) {
+ raw_posix_aligned(unsigned l, unsigned _align) : raw(l) {
+ align = _align;
+ assert((align >= sizeof(void *)) && (align & (align - 1)) == 0);
#ifdef DARWIN
data = (char *) valloc (len);
#else
data = 0;
- int r = ::posix_memalign((void**)(void*)&data, CEPH_PAGE_SIZE, len);
+ int r = ::posix_memalign((void**)(void*)&data, align, len);
if (r)
throw bad_alloc();
#endif /* DARWIN */
if (!data)
throw bad_alloc();
inc_total_alloc(len);
- bdout << "raw_posix_aligned " << this << " alloc " << (void *)data << " " << l << " " << buffer::get_total_alloc() << bendl;
+ bdout << "raw_posix_aligned " << this << " alloc " << (void *)data << " l=" << l << ", align=" << align << " total_alloc=" << buffer::get_total_alloc() << bendl;
}
~raw_posix_aligned() {
::free((void*)data);
bdout << "raw_posix_aligned " << this << " free " << (void *)data << " " << buffer::get_total_alloc() << bendl;
}
raw* clone_empty() {
- return new raw_posix_aligned(len);
+ return new raw_posix_aligned(len, align);
}
};
#endif
#ifdef __CYGWIN__
class buffer::raw_hack_aligned : public buffer::raw {
+ unsigned align;
char *realdata;
public:
- raw_hack_aligned(unsigned l) : raw(l) {
- realdata = new char[len+CEPH_PAGE_SIZE-1];
- unsigned off = ((unsigned)realdata) & ~CEPH_PAGE_MASK;
+ raw_hack_aligned(unsigned l, unsigned _align) : raw(l) {
+ align = _align;
+ realdata = new char[len+align-1];
+ unsigned off = ((unsigned)realdata) & (align-1);
if (off)
- data = realdata + CEPH_PAGE_SIZE - off;
+ data = realdata + align - off;
else
data = realdata;
- inc_total_alloc(len+CEPH_PAGE_SIZE-1);
+ inc_total_alloc(len+align-1);
//cout << "hack aligned " << (unsigned)data
//<< " in raw " << (unsigned)realdata
//<< " off " << off << std::endl;
- assert(((unsigned)data & (CEPH_PAGE_SIZE-1)) == 0);
+ assert(((unsigned)data & (align-1)) == 0);
}
~raw_hack_aligned() {
delete[] realdata;
- dec_total_alloc(len+CEPH_PAGE_SIZE-1);
+ dec_total_alloc(len+align-1);
}
raw* clone_empty() {
- return new raw_hack_aligned(len);
+ return new raw_hack_aligned(len, align);
}
};
#endif
buffer::raw* buffer::create_static(unsigned len, char *buf) {
return new raw_static(buf, len);
}
- buffer::raw* buffer::create_page_aligned(unsigned len) {
+ buffer::raw* buffer::create_aligned(unsigned len, unsigned align) {
#ifndef __CYGWIN__
//return new raw_mmap_pages(len);
- return new raw_posix_aligned(len);
+ return new raw_posix_aligned(len, align);
#else
- return new raw_hack_aligned(len);
+ return new raw_hack_aligned(len, align);
#endif
}
+ buffer::raw* buffer::create_page_aligned(unsigned len) {
+ return create_aligned(len, CEPH_PAGE_SIZE);
+ }
buffer::raw* buffer::create_zero_copy(unsigned len, int fd, int64_t *offset) {
#ifdef CEPH_HAVE_SPLICE
return true;
}
- bool buffer::list::is_page_aligned() const
+ bool buffer::list::is_aligned(unsigned align) const
{
for (std::list<ptr>::const_iterator it = _buffers.begin();
it != _buffers.end();
++it)
- if (!it->is_page_aligned())
+ if (!it->is_aligned(align))
return false;
return true;
}
- bool buffer::list::is_n_page_sized() const
+ bool buffer::list::is_n_align_sized(unsigned align) const
{
for (std::list<ptr>::const_iterator it = _buffers.begin();
it != _buffers.end();
++it)
- if (!it->is_n_page_sized())
+ if (!it->is_n_align_sized(align))
return false;
return true;
}
return &(*_buffers.begin()) == &(*_buffers.rbegin());
}
+ bool buffer::list::is_n_page_sized() const
+ {
+ return is_n_align_sized(CEPH_PAGE_SIZE);
+ }
+
+ bool buffer::list::is_page_aligned() const
+ {
+ return is_aligned(CEPH_PAGE_SIZE);
+ }
+
void buffer::list::rebuild()
{
ptr nb;
_buffers.push_back(nb);
}
-void buffer::list::rebuild_page_aligned()
+void buffer::list::rebuild_aligned(unsigned align)
{
std::list<ptr>::iterator p = _buffers.begin();
while (p != _buffers.end()) {
- // keep anything that's already page sized+aligned
- if (p->is_page_aligned() && p->is_n_page_sized()) {
+ // keep anything that's already align and sized aligned
+ if (p->is_aligned(align) && p->is_n_align_sized(align)) {
/*cout << " segment " << (void*)p->c_str()
- << " offset " << ((unsigned long)p->c_str() & ~CEPH_PAGE_MASK)
+ << " offset " << ((unsigned long)p->c_str() & (align - 1))
<< " length " << p->length()
- << " " << (p->length() & ~CEPH_PAGE_MASK) << " ok" << std::endl;
+ << " " << (p->length() & (align - 1)) << " ok" << std::endl;
*/
++p;
continue;
unsigned offset = 0;
do {
/*cout << " segment " << (void*)p->c_str()
- << " offset " << ((unsigned long)p->c_str() & ~CEPH_PAGE_MASK)
- << " length " << p->length() << " " << (p->length() & ~CEPH_PAGE_MASK)
- << " overall offset " << offset << " " << (offset & ~CEPH_PAGE_MASK)
+ << " offset " << ((unsigned long)p->c_str() & (align - 1))
+ << " length " << p->length() << " " << (p->length() & (align - 1))
+ << " overall offset " << offset << " " << (offset & (align - 1))
<< " not ok" << std::endl;
*/
offset += p->length();
unaligned.push_back(*p);
_buffers.erase(p++);
} while (p != _buffers.end() &&
- (!p->is_page_aligned() ||
- !p->is_n_page_sized() ||
- (offset & ~CEPH_PAGE_MASK)));
- if (!(unaligned.is_contiguous() && unaligned._buffers.front().is_page_aligned())) {
- ptr nb(buffer::create_page_aligned(unaligned._len));
+ (!p->is_aligned(align) ||
+ !p->is_n_align_sized(align) ||
+ (offset & (align-1))));
+ if (!(unaligned.is_contiguous() && unaligned._buffers.front().is_aligned(align))) {
+ ptr nb(buffer::create_aligned(unaligned._len, align));
unaligned.rebuild(nb);
}
_buffers.insert(p, unaligned._buffers.front());
}
}
+void buffer::list::rebuild_page_aligned()
+{
+ rebuild_aligned(CEPH_PAGE_SIZE);
+}
+
// sort-of-like-assignment-op
void buffer::list::claim(list& bl)
{
static raw* create_malloc(unsigned len);
static raw* claim_malloc(unsigned len, char *buf);
static raw* create_static(unsigned len, char *buf);
+ static raw* create_aligned(unsigned len, unsigned align);
static raw* create_page_aligned(unsigned len);
static raw* create_zero_copy(unsigned len, int fd, int64_t *offset);
bool at_buffer_head() const { return _off == 0; }
bool at_buffer_tail() const;
- bool is_page_aligned() const { return ((long)c_str() & ~CEPH_PAGE_MASK) == 0; }
- bool is_n_page_sized() const { return (length() & ~CEPH_PAGE_MASK) == 0; }
+ bool is_aligned(unsigned align) const {
+ return ((long)c_str() & (align-1)) == 0;
+ }
+ bool is_page_aligned() const { return is_aligned(CEPH_PAGE_SIZE); }
+ bool is_n_align_sized(unsigned align) const
+ {
+ return (length() & (align-1)) == 0;
+ }
+ bool is_n_page_sized() const { return is_n_align_sized(CEPH_PAGE_SIZE); }
// accessors
raw *get_raw() const { return _raw; }
bool contents_equal(buffer::list& other);
bool can_zero_copy() const;
+ bool is_aligned(unsigned align) const;
bool is_page_aligned() const;
+ bool is_n_align_sized(unsigned align) const;
bool is_n_page_sized() const;
bool is_zero() const;
bool is_contiguous();
void rebuild();
void rebuild(ptr& nb);
+ void rebuild_aligned(unsigned align);
void rebuild_page_aligned();
// sort-of-like-assignment-op
ASSERT_FALSE(bl1.contents_equal(bl3)); // same length different content
}
+TEST(BufferList, is_aligned) {
+ const int SIMD_ALIGN = 32;
+ {
+ bufferlist bl;
+ EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
+ }
+ {
+ bufferlist bl;
+ bufferptr ptr(buffer::create_aligned(2, SIMD_ALIGN));
+ ptr.set_offset(1);
+ ptr.set_length(1);
+ bl.append(ptr);
+ EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
+ bl.rebuild_aligned(SIMD_ALIGN);
+ EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
+ }
+ {
+ bufferlist bl;
+ bufferptr ptr(buffer::create_aligned(SIMD_ALIGN + 1, SIMD_ALIGN));
+ ptr.set_offset(1);
+ ptr.set_length(SIMD_ALIGN);
+ bl.append(ptr);
+ EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
+ bl.rebuild_aligned(SIMD_ALIGN);
+ EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
+ }
+}
+
+TEST(BufferList, is_n_align_sized) {
+ const int SIMD_ALIGN = 32;
+ {
+ bufferlist bl;
+ EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN));
+ }
+ {
+ bufferlist bl;
+ bl.append_zero(1);
+ EXPECT_FALSE(bl.is_n_align_sized(SIMD_ALIGN));
+ }
+ {
+ bufferlist bl;
+ bl.append_zero(SIMD_ALIGN);
+ EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN));
+ }
+}
+
TEST(BufferList, is_page_aligned) {
{
bufferlist bl;