/* * Iterates over all chunks to find the max nr_alloc entries.
*/ staticint find_max_nr_alloc(void)
{ struct pcpu_chunk *chunk; int slot, max_nr_alloc;
/* * Prints out chunk state. Fragmentation is considered between * the beginning of the chunk to the last allocation. * * All statistics are in bytes unless stated otherwise.
*/ staticvoid chunk_map_stats(struct seq_file *m, struct pcpu_chunk *chunk, int *buffer)
{ struct pcpu_block_md *chunk_md = &chunk->chunk_md; int i, last_alloc, as_len, start, end; int *alloc_sizes, *p; /* statistics */ int sum_frag = 0, max_frag = 0; int cur_min_alloc = 0, cur_med_alloc = 0, cur_max_alloc = 0;
alloc_sizes = buffer;
/* * find_last_bit returns the start value if nothing found. * Therefore, we must determine if it is a failure of find_last_bit * and set the appropriate value.
*/
last_alloc = find_last_bit(chunk->alloc_map,
pcpu_chunk_map_bits(chunk) -
chunk->end_offset / PCPU_MIN_ALLOC_SIZE - 1);
last_alloc = test_bit(last_alloc, chunk->alloc_map) ?
last_alloc + 1 : 0;
/* * If a bit is set in the allocation map, the bound_map identifies * where the allocation ends. If the allocation is not set, the * bound_map does not identify free areas as it is only kept accurate * on allocation, not free. * * Positive values are allocations and negative values are free * fragments.
*/ while (start < last_alloc) { if (test_bit(start, chunk->alloc_map)) {
end = find_next_bit(chunk->bound_map, last_alloc,
start + 1);
alloc_sizes[as_len] = 1;
} else {
end = find_next_bit(chunk->alloc_map, last_alloc,
start + 1);
alloc_sizes[as_len] = -1;
}
/* * The negative values are free fragments and thus sorting gives the * free fragments at the beginning in largest first order.
*/ if (as_len > 0) {
sort(alloc_sizes, as_len, sizeof(int), cmpint, NULL);
/* iterate through the unallocated fragments */ for (i = 0, p = alloc_sizes; *p < 0 && i < as_len; i++, p++) {
sum_frag -= *p;
max_frag = max(max_frag, -1 * (*p));
}
/* there can be at most this many free and allocated fragments */
buffer = vmalloc_array(2 * max_nr_alloc + 1, sizeof(int)); if (!buffer) return -ENOMEM;
spin_lock_irq(&pcpu_lock);
/* if the buffer allocated earlier is too small */ if (max_nr_alloc < find_max_nr_alloc()) {
spin_unlock_irq(&pcpu_lock);
vfree(buffer); goto alloc_buffer;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.