2014-01-04 08:35:03 +08:00
|
|
|
#include "test/jemalloc_test.h"
|
|
|
|
|
2017-04-11 08:06:53 +08:00
|
|
|
#include "jemalloc/internal/qr.h"
|
|
|
|
|
2014-01-04 08:35:03 +08:00
|
|
|
/* Number of ring entries, in [2..26]. */
|
2017-01-20 13:41:41 +08:00
|
|
|
#define NENTRIES 9
|
2014-01-04 08:35:03 +08:00
|
|
|
/* Split index, in [1..NENTRIES). */
|
2017-01-20 13:41:41 +08:00
|
|
|
#define SPLIT_INDEX 5
|
2014-01-04 08:35:03 +08:00
|
|
|
|
|
|
|
typedef struct ring_s ring_t;
|
|
|
|
|
|
|
|
struct ring_s {
|
|
|
|
qr(ring_t) link;
|
|
|
|
char id;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2017-01-16 08:56:30 +08:00
|
|
|
init_entries(ring_t *entries) {
|
2014-01-04 08:35:03 +08:00
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
qr_new(&entries[i], link);
|
|
|
|
entries[i].id = 'a' + i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-01-16 08:56:30 +08:00
|
|
|
test_independent_entries(ring_t *entries) {
|
2014-01-04 08:35:03 +08:00
|
|
|
ring_t *t;
|
|
|
|
unsigned i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
j = 0;
|
|
|
|
qr_foreach(t, &entries[i], link) {
|
|
|
|
j++;
|
|
|
|
}
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_u_eq(j, 1,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Iteration over single-element ring should visit precisely "
|
|
|
|
"one element");
|
|
|
|
}
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
j = 0;
|
|
|
|
qr_reverse_foreach(t, &entries[i], link) {
|
|
|
|
j++;
|
|
|
|
}
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_u_eq(j, 1,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Iteration over single-element ring should visit precisely "
|
|
|
|
"one element");
|
|
|
|
}
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
t = qr_next(&entries[i], link);
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_ptr_eq(t, &entries[i],
|
2014-01-04 08:35:03 +08:00
|
|
|
"Next element in single-element ring should be same as "
|
|
|
|
"current element");
|
|
|
|
}
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
t = qr_prev(&entries[i], link);
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_ptr_eq(t, &entries[i],
|
2014-01-04 08:35:03 +08:00
|
|
|
"Previous element in single-element ring should be same as "
|
|
|
|
"current element");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-16 08:56:30 +08:00
|
|
|
TEST_BEGIN(test_qr_one) {
|
2014-01-04 08:35:03 +08:00
|
|
|
ring_t entries[NENTRIES];
|
|
|
|
|
|
|
|
init_entries(entries);
|
|
|
|
test_independent_entries(entries);
|
|
|
|
}
|
|
|
|
TEST_END
|
|
|
|
|
|
|
|
static void
|
2017-01-16 08:56:30 +08:00
|
|
|
test_entries_ring(ring_t *entries) {
|
2014-01-04 08:35:03 +08:00
|
|
|
ring_t *t;
|
|
|
|
unsigned i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
j = 0;
|
|
|
|
qr_foreach(t, &entries[i], link) {
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[(i+j) % NENTRIES].id,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Element id mismatch");
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
j = 0;
|
|
|
|
qr_reverse_foreach(t, &entries[i], link) {
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[(NENTRIES+i-j-1) %
|
2014-01-04 08:35:03 +08:00
|
|
|
NENTRIES].id, "Element id mismatch");
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
t = qr_next(&entries[i], link);
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[(i+1) % NENTRIES].id,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Element id mismatch");
|
|
|
|
}
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
t = qr_prev(&entries[i], link);
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[(NENTRIES+i-1) % NENTRIES].id,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Element id mismatch");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-16 08:56:30 +08:00
|
|
|
TEST_BEGIN(test_qr_after_insert) {
|
2014-01-04 08:35:03 +08:00
|
|
|
ring_t entries[NENTRIES];
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
init_entries(entries);
|
2017-01-16 08:56:30 +08:00
|
|
|
for (i = 1; i < NENTRIES; i++) {
|
2014-01-04 08:35:03 +08:00
|
|
|
qr_after_insert(&entries[i - 1], &entries[i], link);
|
2017-01-16 08:56:30 +08:00
|
|
|
}
|
2014-01-04 08:35:03 +08:00
|
|
|
test_entries_ring(entries);
|
|
|
|
}
|
|
|
|
TEST_END
|
|
|
|
|
2017-01-16 08:56:30 +08:00
|
|
|
TEST_BEGIN(test_qr_remove) {
|
2014-01-04 08:35:03 +08:00
|
|
|
ring_t entries[NENTRIES];
|
|
|
|
ring_t *t;
|
|
|
|
unsigned i, j;
|
|
|
|
|
|
|
|
init_entries(entries);
|
2017-01-16 08:56:30 +08:00
|
|
|
for (i = 1; i < NENTRIES; i++) {
|
2014-01-04 08:35:03 +08:00
|
|
|
qr_after_insert(&entries[i - 1], &entries[i], link);
|
2017-01-16 08:56:30 +08:00
|
|
|
}
|
2014-01-04 08:35:03 +08:00
|
|
|
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
j = 0;
|
|
|
|
qr_foreach(t, &entries[i], link) {
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[i+j].id,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Element id mismatch");
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
j = 0;
|
|
|
|
qr_reverse_foreach(t, &entries[i], link) {
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[NENTRIES - 1 - j].id,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Element id mismatch");
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
qr_remove(&entries[i], link);
|
|
|
|
}
|
|
|
|
test_independent_entries(entries);
|
|
|
|
}
|
|
|
|
TEST_END
|
|
|
|
|
2017-01-16 08:56:30 +08:00
|
|
|
TEST_BEGIN(test_qr_before_insert) {
|
2014-01-04 08:35:03 +08:00
|
|
|
ring_t entries[NENTRIES];
|
|
|
|
ring_t *t;
|
|
|
|
unsigned i, j;
|
|
|
|
|
|
|
|
init_entries(entries);
|
2017-01-16 08:56:30 +08:00
|
|
|
for (i = 1; i < NENTRIES; i++) {
|
2014-01-04 08:35:03 +08:00
|
|
|
qr_before_insert(&entries[i - 1], &entries[i], link);
|
2017-01-16 08:56:30 +08:00
|
|
|
}
|
2014-01-04 08:35:03 +08:00
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
j = 0;
|
|
|
|
qr_foreach(t, &entries[i], link) {
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[(NENTRIES+i-j) %
|
2014-01-04 08:35:03 +08:00
|
|
|
NENTRIES].id, "Element id mismatch");
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
j = 0;
|
|
|
|
qr_reverse_foreach(t, &entries[i], link) {
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[(i+j+1) % NENTRIES].id,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Element id mismatch");
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
t = qr_next(&entries[i], link);
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[(NENTRIES+i-1) % NENTRIES].id,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Element id mismatch");
|
|
|
|
}
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
t = qr_prev(&entries[i], link);
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[(i+1) % NENTRIES].id,
|
2014-01-04 08:35:03 +08:00
|
|
|
"Element id mismatch");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TEST_END
|
|
|
|
|
|
|
|
static void
|
2017-01-16 08:56:30 +08:00
|
|
|
test_split_entries(ring_t *entries) {
|
2014-01-04 08:35:03 +08:00
|
|
|
ring_t *t;
|
|
|
|
unsigned i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < NENTRIES; i++) {
|
|
|
|
j = 0;
|
|
|
|
qr_foreach(t, &entries[i], link) {
|
|
|
|
if (i < SPLIT_INDEX) {
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id,
|
2014-01-04 08:35:03 +08:00
|
|
|
entries[(i+j) % SPLIT_INDEX].id,
|
|
|
|
"Element id mismatch");
|
|
|
|
} else {
|
2020-02-19 06:39:06 +08:00
|
|
|
expect_c_eq(t->id, entries[(i+j-SPLIT_INDEX) %
|
2014-01-04 08:35:03 +08:00
|
|
|
(NENTRIES-SPLIT_INDEX) + SPLIT_INDEX].id,
|
|
|
|
"Element id mismatch");
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-16 08:56:30 +08:00
|
|
|
TEST_BEGIN(test_qr_meld_split) {
|
2014-01-04 08:35:03 +08:00
|
|
|
ring_t entries[NENTRIES];
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
init_entries(entries);
|
2017-01-16 08:56:30 +08:00
|
|
|
for (i = 1; i < NENTRIES; i++) {
|
2014-01-04 08:35:03 +08:00
|
|
|
qr_after_insert(&entries[i - 1], &entries[i], link);
|
2017-01-16 08:56:30 +08:00
|
|
|
}
|
2014-01-04 08:35:03 +08:00
|
|
|
|
Optimize meld in qr module
The goal of `qr_meld()` is to change the following four fields
`(a->prev, a->prev->next, b->prev, b->prev->next)` from the values
`(a->prev, a, b->prev, b)` to `(b->prev, b, a->prev, a)`.
This commit changes
```
a->prev->next = b;
b->prev->next = a;
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
```
to
```
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
a->prev->next = a;
b->prev->next = b;
```
The benefit is that we can use `b->prev->next` for `temp`, and so
there's no need to pass in `a_type`.
The restriction is that `b` cannot be a `qr_next()` macro, so users
of `qr_meld()` must pay attention. (Before this change, neither `a`
nor `b` could be a `qr_next()` macro.)
2020-04-02 06:04:24 +08:00
|
|
|
qr_split(&entries[0], &entries[SPLIT_INDEX], link);
|
2014-01-04 08:35:03 +08:00
|
|
|
test_split_entries(entries);
|
|
|
|
|
Optimize meld in qr module
The goal of `qr_meld()` is to change the following four fields
`(a->prev, a->prev->next, b->prev, b->prev->next)` from the values
`(a->prev, a, b->prev, b)` to `(b->prev, b, a->prev, a)`.
This commit changes
```
a->prev->next = b;
b->prev->next = a;
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
```
to
```
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
a->prev->next = a;
b->prev->next = b;
```
The benefit is that we can use `b->prev->next` for `temp`, and so
there's no need to pass in `a_type`.
The restriction is that `b` cannot be a `qr_next()` macro, so users
of `qr_meld()` must pay attention. (Before this change, neither `a`
nor `b` could be a `qr_next()` macro.)
2020-04-02 06:04:24 +08:00
|
|
|
qr_meld(&entries[0], &entries[SPLIT_INDEX], link);
|
2014-01-04 08:35:03 +08:00
|
|
|
test_entries_ring(entries);
|
|
|
|
|
Optimize meld in qr module
The goal of `qr_meld()` is to change the following four fields
`(a->prev, a->prev->next, b->prev, b->prev->next)` from the values
`(a->prev, a, b->prev, b)` to `(b->prev, b, a->prev, a)`.
This commit changes
```
a->prev->next = b;
b->prev->next = a;
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
```
to
```
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
a->prev->next = a;
b->prev->next = b;
```
The benefit is that we can use `b->prev->next` for `temp`, and so
there's no need to pass in `a_type`.
The restriction is that `b` cannot be a `qr_next()` macro, so users
of `qr_meld()` must pay attention. (Before this change, neither `a`
nor `b` could be a `qr_next()` macro.)
2020-04-02 06:04:24 +08:00
|
|
|
qr_meld(&entries[0], &entries[SPLIT_INDEX], link);
|
2014-01-04 08:35:03 +08:00
|
|
|
test_split_entries(entries);
|
|
|
|
|
Optimize meld in qr module
The goal of `qr_meld()` is to change the following four fields
`(a->prev, a->prev->next, b->prev, b->prev->next)` from the values
`(a->prev, a, b->prev, b)` to `(b->prev, b, a->prev, a)`.
This commit changes
```
a->prev->next = b;
b->prev->next = a;
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
```
to
```
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
a->prev->next = a;
b->prev->next = b;
```
The benefit is that we can use `b->prev->next` for `temp`, and so
there's no need to pass in `a_type`.
The restriction is that `b` cannot be a `qr_next()` macro, so users
of `qr_meld()` must pay attention. (Before this change, neither `a`
nor `b` could be a `qr_next()` macro.)
2020-04-02 06:04:24 +08:00
|
|
|
qr_split(&entries[0], &entries[SPLIT_INDEX], link);
|
2014-01-04 08:35:03 +08:00
|
|
|
test_entries_ring(entries);
|
|
|
|
|
Optimize meld in qr module
The goal of `qr_meld()` is to change the following four fields
`(a->prev, a->prev->next, b->prev, b->prev->next)` from the values
`(a->prev, a, b->prev, b)` to `(b->prev, b, a->prev, a)`.
This commit changes
```
a->prev->next = b;
b->prev->next = a;
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
```
to
```
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
a->prev->next = a;
b->prev->next = b;
```
The benefit is that we can use `b->prev->next` for `temp`, and so
there's no need to pass in `a_type`.
The restriction is that `b` cannot be a `qr_next()` macro, so users
of `qr_meld()` must pay attention. (Before this change, neither `a`
nor `b` could be a `qr_next()` macro.)
2020-04-02 06:04:24 +08:00
|
|
|
qr_split(&entries[0], &entries[0], link);
|
2014-01-04 08:35:03 +08:00
|
|
|
test_entries_ring(entries);
|
|
|
|
|
Optimize meld in qr module
The goal of `qr_meld()` is to change the following four fields
`(a->prev, a->prev->next, b->prev, b->prev->next)` from the values
`(a->prev, a, b->prev, b)` to `(b->prev, b, a->prev, a)`.
This commit changes
```
a->prev->next = b;
b->prev->next = a;
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
```
to
```
temp = a->prev;
a->prev = b->prev;
b->prev = temp;
a->prev->next = a;
b->prev->next = b;
```
The benefit is that we can use `b->prev->next` for `temp`, and so
there's no need to pass in `a_type`.
The restriction is that `b` cannot be a `qr_next()` macro, so users
of `qr_meld()` must pay attention. (Before this change, neither `a`
nor `b` could be a `qr_next()` macro.)
2020-04-02 06:04:24 +08:00
|
|
|
qr_meld(&entries[0], &entries[0], link);
|
2014-01-04 08:35:03 +08:00
|
|
|
test_entries_ring(entries);
|
|
|
|
}
|
|
|
|
TEST_END
|
|
|
|
|
|
|
|
int
|
2017-01-16 08:56:30 +08:00
|
|
|
main(void) {
|
2017-01-20 10:15:45 +08:00
|
|
|
return test(
|
2014-01-04 08:35:03 +08:00
|
|
|
test_qr_one,
|
|
|
|
test_qr_after_insert,
|
|
|
|
test_qr_remove,
|
|
|
|
test_qr_before_insert,
|
2017-01-20 10:15:45 +08:00
|
|
|
test_qr_meld_split);
|
2014-01-04 08:35:03 +08:00
|
|
|
}
|