aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/sched.c22
-rw-r--r--mm/percpu.c30
2 files changed, 28 insertions, 24 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index e88689522e66..a455dca884a6 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1564,11 +1564,7 @@ static unsigned long cpu_avg_load_per_task(int cpu)
1564 1564
1565#ifdef CONFIG_FAIR_GROUP_SCHED 1565#ifdef CONFIG_FAIR_GROUP_SCHED
1566 1566
1567struct update_shares_data { 1567static __read_mostly unsigned long *update_shares_data;
1568 unsigned long rq_weight[NR_CPUS];
1569};
1570
1571static DEFINE_PER_CPU(struct update_shares_data, update_shares_data);
1572 1568
1573static void __set_se_shares(struct sched_entity *se, unsigned long shares); 1569static void __set_se_shares(struct sched_entity *se, unsigned long shares);
1574 1570
@@ -1578,12 +1574,12 @@ static void __set_se_shares(struct sched_entity *se, unsigned long shares);
1578static void update_group_shares_cpu(struct task_group *tg, int cpu, 1574static void update_group_shares_cpu(struct task_group *tg, int cpu,
1579 unsigned long sd_shares, 1575 unsigned long sd_shares,
1580 unsigned long sd_rq_weight, 1576 unsigned long sd_rq_weight,
1581 struct update_shares_data *usd) 1577 unsigned long *usd_rq_weight)
1582{ 1578{
1583 unsigned long shares, rq_weight; 1579 unsigned long shares, rq_weight;
1584 int boost = 0; 1580 int boost = 0;
1585 1581
1586 rq_weight = usd->rq_weight[cpu]; 1582 rq_weight = usd_rq_weight[cpu];
1587 if (!rq_weight) { 1583 if (!rq_weight) {
1588 boost = 1; 1584 boost = 1;
1589 rq_weight = NICE_0_LOAD; 1585 rq_weight = NICE_0_LOAD;
@@ -1618,7 +1614,7 @@ static void update_group_shares_cpu(struct task_group *tg, int cpu,
1618static int tg_shares_up(struct task_group *tg, void *data) 1614static int tg_shares_up(struct task_group *tg, void *data)
1619{ 1615{
1620 unsigned long weight, rq_weight = 0, shares = 0; 1616 unsigned long weight, rq_weight = 0, shares = 0;
1621 struct update_shares_data *usd; 1617 unsigned long *usd_rq_weight;
1622 struct sched_domain *sd = data; 1618 struct sched_domain *sd = data;
1623 unsigned long flags; 1619 unsigned long flags;
1624 int i; 1620 int i;
@@ -1627,11 +1623,11 @@ static int tg_shares_up(struct task_group *tg, void *data)
1627 return 0; 1623 return 0;
1628 1624
1629 local_irq_save(flags); 1625 local_irq_save(flags);
1630 usd = &__get_cpu_var(update_shares_data); 1626 usd_rq_weight = per_cpu_ptr(update_shares_data, smp_processor_id());
1631 1627
1632 for_each_cpu(i, sched_domain_span(sd)) { 1628 for_each_cpu(i, sched_domain_span(sd)) {
1633 weight = tg->cfs_rq[i]->load.weight; 1629 weight = tg->cfs_rq[i]->load.weight;
1634 usd->rq_weight[i] = weight; 1630 usd_rq_weight[i] = weight;
1635 1631
1636 /* 1632 /*
1637 * If there are currently no tasks on the cpu pretend there 1633 * If there are currently no tasks on the cpu pretend there
@@ -1652,7 +1648,7 @@ static int tg_shares_up(struct task_group *tg, void *data)
1652 shares = tg->shares; 1648 shares = tg->shares;
1653 1649
1654 for_each_cpu(i, sched_domain_span(sd)) 1650 for_each_cpu(i, sched_domain_span(sd))
1655 update_group_shares_cpu(tg, i, shares, rq_weight, usd); 1651 update_group_shares_cpu(tg, i, shares, rq_weight, usd_rq_weight);
1656 1652
1657 local_irq_restore(flags); 1653 local_irq_restore(flags);
1658 1654
@@ -9407,6 +9403,10 @@ void __init sched_init(void)
9407#endif /* CONFIG_USER_SCHED */ 9403#endif /* CONFIG_USER_SCHED */
9408#endif /* CONFIG_GROUP_SCHED */ 9404#endif /* CONFIG_GROUP_SCHED */
9409 9405
9406#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP
9407 update_shares_data = __alloc_percpu(nr_cpu_ids * sizeof(unsigned long),
9408 __alignof__(unsigned long));
9409#endif
9410 for_each_possible_cpu(i) { 9410 for_each_possible_cpu(i) {
9411 struct rq *rq; 9411 struct rq *rq;
9412 9412
diff --git a/mm/percpu.c b/mm/percpu.c
index 6af78c1ee704..d90797160c2a 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -153,7 +153,10 @@ static int pcpu_reserved_chunk_limit;
153 * 153 *
154 * During allocation, pcpu_alloc_mutex is kept locked all the time and 154 * During allocation, pcpu_alloc_mutex is kept locked all the time and
155 * pcpu_lock is grabbed and released as necessary. All actual memory 155 * pcpu_lock is grabbed and released as necessary. All actual memory
156 * allocations are done using GFP_KERNEL with pcpu_lock released. 156 * allocations are done using GFP_KERNEL with pcpu_lock released. In
157 * general, percpu memory can't be allocated with irq off but
158 * irqsave/restore are still used in alloc path so that it can be used
159 * from early init path - sched_init() specifically.
157 * 160 *
158 * Free path accesses and alters only the index data structures, so it 161 * Free path accesses and alters only the index data structures, so it
159 * can be safely called from atomic context. When memory needs to be 162 * can be safely called from atomic context. When memory needs to be
@@ -366,7 +369,7 @@ static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr)
366 * RETURNS: 369 * RETURNS:
367 * 0 if noop, 1 if successfully extended, -errno on failure. 370 * 0 if noop, 1 if successfully extended, -errno on failure.
368 */ 371 */
369static int pcpu_extend_area_map(struct pcpu_chunk *chunk) 372static int pcpu_extend_area_map(struct pcpu_chunk *chunk, unsigned long *flags)
370{ 373{
371 int new_alloc; 374 int new_alloc;
372 int *new; 375 int *new;
@@ -376,7 +379,7 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk)
376 if (chunk->map_alloc >= chunk->map_used + 2) 379 if (chunk->map_alloc >= chunk->map_used + 2)
377 return 0; 380 return 0;
378 381
379 spin_unlock_irq(&pcpu_lock); 382 spin_unlock_irqrestore(&pcpu_lock, *flags);
380 383
381 new_alloc = PCPU_DFL_MAP_ALLOC; 384 new_alloc = PCPU_DFL_MAP_ALLOC;
382 while (new_alloc < chunk->map_used + 2) 385 while (new_alloc < chunk->map_used + 2)
@@ -384,7 +387,7 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk)
384 387
385 new = pcpu_mem_alloc(new_alloc * sizeof(new[0])); 388 new = pcpu_mem_alloc(new_alloc * sizeof(new[0]));
386 if (!new) { 389 if (!new) {
387 spin_lock_irq(&pcpu_lock); 390 spin_lock_irqsave(&pcpu_lock, *flags);
388 return -ENOMEM; 391 return -ENOMEM;
389 } 392 }
390 393
@@ -393,7 +396,7 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk)
393 * could have happened inbetween, so map_used couldn't have 396 * could have happened inbetween, so map_used couldn't have
394 * grown. 397 * grown.
395 */ 398 */
396 spin_lock_irq(&pcpu_lock); 399 spin_lock_irqsave(&pcpu_lock, *flags);
397 BUG_ON(new_alloc < chunk->map_used + 2); 400 BUG_ON(new_alloc < chunk->map_used + 2);
398 401
399 size = chunk->map_alloc * sizeof(chunk->map[0]); 402 size = chunk->map_alloc * sizeof(chunk->map[0]);
@@ -1047,6 +1050,7 @@ static void *pcpu_alloc(size_t size, size_t align, bool reserved)
1047 struct pcpu_chunk *chunk; 1050 struct pcpu_chunk *chunk;
1048 const char *err; 1051 const char *err;
1049 int slot, off; 1052 int slot, off;
1053 unsigned long flags;
1050 1054
1051 if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) { 1055 if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) {
1052 WARN(true, "illegal size (%zu) or align (%zu) for " 1056 WARN(true, "illegal size (%zu) or align (%zu) for "
@@ -1055,13 +1059,13 @@ static void *pcpu_alloc(size_t size, size_t align, bool reserved)
1055 } 1059 }
1056 1060
1057 mutex_lock(&pcpu_alloc_mutex); 1061 mutex_lock(&pcpu_alloc_mutex);
1058 spin_lock_irq(&pcpu_lock); 1062 spin_lock_irqsave(&pcpu_lock, flags);
1059 1063
1060 /* serve reserved allocations from the reserved chunk if available */ 1064 /* serve reserved allocations from the reserved chunk if available */
1061 if (reserved && pcpu_reserved_chunk) { 1065 if (reserved && pcpu_reserved_chunk) {
1062 chunk = pcpu_reserved_chunk; 1066 chunk = pcpu_reserved_chunk;
1063 if (size > chunk->contig_hint || 1067 if (size > chunk->contig_hint ||
1064 pcpu_extend_area_map(chunk) < 0) { 1068 pcpu_extend_area_map(chunk, &flags) < 0) {
1065 err = "failed to extend area map of reserved chunk"; 1069 err = "failed to extend area map of reserved chunk";
1066 goto fail_unlock; 1070 goto fail_unlock;
1067 } 1071 }
@@ -1079,7 +1083,7 @@ restart:
1079 if (size > chunk->contig_hint) 1083 if (size > chunk->contig_hint)
1080 continue; 1084 continue;
1081 1085
1082 switch (pcpu_extend_area_map(chunk)) { 1086 switch (pcpu_extend_area_map(chunk, &flags)) {
1083 case 0: 1087 case 0:
1084 break; 1088 break;
1085 case 1: 1089 case 1:
@@ -1096,7 +1100,7 @@ restart:
1096 } 1100 }
1097 1101
1098 /* hmmm... no space left, create a new chunk */ 1102 /* hmmm... no space left, create a new chunk */
1099 spin_unlock_irq(&pcpu_lock); 1103 spin_unlock_irqrestore(&pcpu_lock, flags);
1100 1104
1101 chunk = alloc_pcpu_chunk(); 1105 chunk = alloc_pcpu_chunk();
1102 if (!chunk) { 1106 if (!chunk) {
@@ -1104,16 +1108,16 @@ restart:
1104 goto fail_unlock_mutex; 1108 goto fail_unlock_mutex;
1105 } 1109 }
1106 1110
1107 spin_lock_irq(&pcpu_lock); 1111 spin_lock_irqsave(&pcpu_lock, flags);
1108 pcpu_chunk_relocate(chunk, -1); 1112 pcpu_chunk_relocate(chunk, -1);
1109 goto restart; 1113 goto restart;
1110 1114
1111area_found: 1115area_found:
1112 spin_unlock_irq(&pcpu_lock); 1116 spin_unlock_irqrestore(&pcpu_lock, flags);
1113 1117
1114 /* populate, map and clear the area */ 1118 /* populate, map and clear the area */
1115 if (pcpu_populate_chunk(chunk, off, size)) { 1119 if (pcpu_populate_chunk(chunk, off, size)) {
1116 spin_lock_irq(&pcpu_lock); 1120 spin_lock_irqsave(&pcpu_lock, flags);
1117 pcpu_free_area(chunk, off); 1121 pcpu_free_area(chunk, off);
1118 err = "failed to populate"; 1122 err = "failed to populate";
1119 goto fail_unlock; 1123 goto fail_unlock;
@@ -1125,7 +1129,7 @@ area_found:
1125 return __addr_to_pcpu_ptr(chunk->base_addr + off); 1129 return __addr_to_pcpu_ptr(chunk->base_addr + off);
1126 1130
1127fail_unlock: 1131fail_unlock:
1128 spin_unlock_irq(&pcpu_lock); 1132 spin_unlock_irqrestore(&pcpu_lock, flags);
1129fail_unlock_mutex: 1133fail_unlock_mutex:
1130 mutex_unlock(&pcpu_alloc_mutex); 1134 mutex_unlock(&pcpu_alloc_mutex);
1131 if (warn_limit) { 1135 if (warn_limit) {