diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-03-06 20:52:32 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-03-07 07:52:26 -0500 |
commit | 3d331ad74fa33f0b14a46cf0de8358012d3c1500 (patch) | |
tree | 17b8d8615001e4de1a7a3a1e86418485fd4179d1 /mm/percpu.c | |
parent | 723ad1d90b5663ab623bb3bfba3e4ee7101795d7 (diff) |
percpu: speed alloc_pcpu_area() up
If we know that first N areas are all in use, we can obviously skip
them when searching for a free one. And that kind of hint is very
easy to maintain.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'mm/percpu.c')
-rw-r--r-- | mm/percpu.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/mm/percpu.c b/mm/percpu.c index 49dfccf9169c..c7206d06f8de 100644 --- a/mm/percpu.c +++ b/mm/percpu.c | |||
@@ -106,6 +106,7 @@ struct pcpu_chunk { | |||
106 | int map_alloc; /* # of map entries allocated */ | 106 | int map_alloc; /* # of map entries allocated */ |
107 | int *map; /* allocation map */ | 107 | int *map; /* allocation map */ |
108 | void *data; /* chunk data */ | 108 | void *data; /* chunk data */ |
109 | int first_free; /* no free below this */ | ||
109 | bool immutable; /* no [de]population allowed */ | 110 | bool immutable; /* no [de]population allowed */ |
110 | unsigned long populated[]; /* populated bitmap */ | 111 | unsigned long populated[]; /* populated bitmap */ |
111 | }; | 112 | }; |
@@ -441,9 +442,10 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align) | |||
441 | int oslot = pcpu_chunk_slot(chunk); | 442 | int oslot = pcpu_chunk_slot(chunk); |
442 | int max_contig = 0; | 443 | int max_contig = 0; |
443 | int i, off; | 444 | int i, off; |
445 | bool seen_free = false; | ||
444 | int *p; | 446 | int *p; |
445 | 447 | ||
446 | for (i = 0, p = chunk->map; i < chunk->map_used; i++, p++) { | 448 | for (i = chunk->first_free, p = chunk->map + i; i < chunk->map_used; i++, p++) { |
447 | int head, tail; | 449 | int head, tail; |
448 | int this_size; | 450 | int this_size; |
449 | 451 | ||
@@ -456,6 +458,10 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align) | |||
456 | 458 | ||
457 | this_size = (p[1] & ~1) - off; | 459 | this_size = (p[1] & ~1) - off; |
458 | if (this_size < head + size) { | 460 | if (this_size < head + size) { |
461 | if (!seen_free) { | ||
462 | chunk->first_free = i; | ||
463 | seen_free = true; | ||
464 | } | ||
459 | max_contig = max(this_size, max_contig); | 465 | max_contig = max(this_size, max_contig); |
460 | continue; | 466 | continue; |
461 | } | 467 | } |
@@ -491,6 +497,10 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align) | |||
491 | chunk->map_used += nr_extra; | 497 | chunk->map_used += nr_extra; |
492 | 498 | ||
493 | if (head) { | 499 | if (head) { |
500 | if (!seen_free) { | ||
501 | chunk->first_free = i; | ||
502 | seen_free = true; | ||
503 | } | ||
494 | *++p = off += head; | 504 | *++p = off += head; |
495 | ++i; | 505 | ++i; |
496 | max_contig = max(head, max_contig); | 506 | max_contig = max(head, max_contig); |
@@ -501,6 +511,9 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align) | |||
501 | } | 511 | } |
502 | } | 512 | } |
503 | 513 | ||
514 | if (!seen_free) | ||
515 | chunk->first_free = i + 1; | ||
516 | |||
504 | /* update hint and mark allocated */ | 517 | /* update hint and mark allocated */ |
505 | if (i + 1 == chunk->map_used) | 518 | if (i + 1 == chunk->map_used) |
506 | chunk->contig_hint = max_contig; /* fully scanned */ | 519 | chunk->contig_hint = max_contig; /* fully scanned */ |
@@ -558,6 +571,9 @@ static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme) | |||
558 | } | 571 | } |
559 | BUG_ON(off != freeme); | 572 | BUG_ON(off != freeme); |
560 | 573 | ||
574 | if (i < chunk->first_free) | ||
575 | chunk->first_free = i; | ||
576 | |||
561 | p = chunk->map + i; | 577 | p = chunk->map + i; |
562 | *p = off &= ~1; | 578 | *p = off &= ~1; |
563 | chunk->free_size += (p[1] & ~1) - off; | 579 | chunk->free_size += (p[1] & ~1) - off; |