cpu.c 16.2 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
11
12
/* CPU control.
 * (C) 2001, 2002, 2003, 2004 Rusty Russell
 *
 * This code is licenced under the GPL.
 */
#include <linux/proc_fs.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/notifier.h>
#include <linux/sched.h>
#include <linux/unistd.h>
#include <linux/cpu.h>
13
#include <linux/export.h>
Linus Torvalds's avatar
Linus Torvalds committed
14
15
#include <linux/kthread.h>
#include <linux/stop_machine.h>
16
#include <linux/mutex.h>
17
#include <linux/gfp.h>
18
#include <linux/suspend.h>
Linus Torvalds's avatar
Linus Torvalds committed
19

20
#ifdef CONFIG_SMP
21
/* Serializes the updates to cpu_online_mask, cpu_present_mask */
22
static DEFINE_MUTEX(cpu_add_remove_lock);
Linus Torvalds's avatar
Linus Torvalds committed
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * The following two API's must be used when attempting
 * to serialize the updates to cpu_online_mask, cpu_present_mask.
 */
void cpu_maps_update_begin(void)
{
	mutex_lock(&cpu_add_remove_lock);
}

void cpu_maps_update_done(void)
{
	mutex_unlock(&cpu_add_remove_lock);
}

38
static RAW_NOTIFIER_HEAD(cpu_chain);
Linus Torvalds's avatar
Linus Torvalds committed
39

40
41
42
43
44
/* If set, cpu_up and cpu_down will return -EBUSY and do nothing.
 * Should always be manipulated under cpu_add_remove_lock
 */
static int cpu_hotplug_disabled;

45
46
#ifdef CONFIG_HOTPLUG_CPU

47
48
49
50
51
52
53
54
static struct {
	struct task_struct *active_writer;
	struct mutex lock; /* Synchronizes accesses to refcount, */
	/*
	 * Also blocks the new readers during
	 * an ongoing cpu hotplug operation.
	 */
	int refcount;
55
56
57
58
59
} cpu_hotplug = {
	.active_writer = NULL,
	.lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
	.refcount = 0,
};
60

61
void get_online_cpus(void)
62
{
63
64
	might_sleep();
	if (cpu_hotplug.active_writer == current)
65
		return;
66
67
68
69
	mutex_lock(&cpu_hotplug.lock);
	cpu_hotplug.refcount++;
	mutex_unlock(&cpu_hotplug.lock);

70
}
71
EXPORT_SYMBOL_GPL(get_online_cpus);
72

73
void put_online_cpus(void)
74
{
75
	if (cpu_hotplug.active_writer == current)
76
		return;
77
	mutex_lock(&cpu_hotplug.lock);
78
79
	if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer))
		wake_up_process(cpu_hotplug.active_writer);
80
81
	mutex_unlock(&cpu_hotplug.lock);

82
}
83
EXPORT_SYMBOL_GPL(put_online_cpus);
84

85
86
87
88
89
90
91
/*
 * This ensures that the hotplug operation can begin only when the
 * refcount goes to zero.
 *
 * Note that during a cpu-hotplug operation, the new readers, if any,
 * will be blocked by the cpu_hotplug.lock
 *
92
93
 * Since cpu_hotplug_begin() is always called after invoking
 * cpu_maps_update_begin(), we can be sure that only one writer is active.
94
95
96
97
98
99
100
101
102
103
 *
 * Note that theoretically, there is a possibility of a livelock:
 * - Refcount goes to zero, last reader wakes up the sleeping
 *   writer.
 * - Last reader unlocks the cpu_hotplug.lock.
 * - A new reader arrives at this moment, bumps up the refcount.
 * - The writer acquires the cpu_hotplug.lock finds the refcount
 *   non zero and goes to sleep again.
 *
 * However, this is very difficult to achieve in practice since
104
 * get_online_cpus() not an api which is called all that often.
105
106
107
108
109
 *
 */
static void cpu_hotplug_begin(void)
{
	cpu_hotplug.active_writer = current;
110
111
112
113
114
115

	for (;;) {
		mutex_lock(&cpu_hotplug.lock);
		if (likely(!cpu_hotplug.refcount))
			break;
		__set_current_state(TASK_UNINTERRUPTIBLE);
116
117
118
119
120
121
122
123
124
125
		mutex_unlock(&cpu_hotplug.lock);
		schedule();
	}
}

static void cpu_hotplug_done(void)
{
	cpu_hotplug.active_writer = NULL;
	mutex_unlock(&cpu_hotplug.lock);
}
126
127
128
129

#else /* #if CONFIG_HOTPLUG_CPU */
static void cpu_hotplug_begin(void) {}
static void cpu_hotplug_done(void) {}
Lucas De Marchi's avatar
Lucas De Marchi committed
130
#endif	/* #else #if CONFIG_HOTPLUG_CPU */
131

Linus Torvalds's avatar
Linus Torvalds committed
132
/* Need to know about CPUs going up/down? */
133
int __ref register_cpu_notifier(struct notifier_block *nb)
Linus Torvalds's avatar
Linus Torvalds committed
134
{
135
	int ret;
136
	cpu_maps_update_begin();
137
	ret = raw_notifier_chain_register(&cpu_chain, nb);
138
	cpu_maps_update_done();
139
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
140
}
141

142
143
144
static int __cpu_notify(unsigned long val, void *v, int nr_to_call,
			int *nr_calls)
{
145
146
147
	int ret;

	ret = __raw_notifier_call_chain(&cpu_chain, val, v, nr_to_call,
148
					nr_calls);
149
150

	return notifier_to_errno(ret);
151
152
153
154
155
156
157
}

static int cpu_notify(unsigned long val, void *v)
{
	return __cpu_notify(val, v, -1, NULL);
}

158
159
#ifdef CONFIG_HOTPLUG_CPU

160
161
static void cpu_notify_nofail(unsigned long val, void *v)
{
162
	BUG_ON(cpu_notify(val, v));
163
}
Linus Torvalds's avatar
Linus Torvalds committed
164
165
EXPORT_SYMBOL(register_cpu_notifier);

166
void __ref unregister_cpu_notifier(struct notifier_block *nb)
Linus Torvalds's avatar
Linus Torvalds committed
167
{
168
	cpu_maps_update_begin();
169
	raw_notifier_chain_unregister(&cpu_chain, nb);
170
	cpu_maps_update_done();
Linus Torvalds's avatar
Linus Torvalds committed
171
172
173
174
175
176
177
178
179
}
EXPORT_SYMBOL(unregister_cpu_notifier);

static inline void check_for_tasks(int cpu)
{
	struct task_struct *p;

	write_lock_irq(&tasklist_lock);
	for_each_process(p) {
180
		if (task_cpu(p) == cpu && p->state == TASK_RUNNING &&
181
		    (p->utime || p->stime))
182
183
184
185
			printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d "
				"(state = %ld, flags = %x)\n",
				p->comm, task_pid_nr(p), cpu,
				p->state, p->flags);
Linus Torvalds's avatar
Linus Torvalds committed
186
187
188
189
	}
	write_unlock_irq(&tasklist_lock);
}

Avi Kivity's avatar
Avi Kivity committed
190
191
192
193
194
struct take_cpu_down_param {
	unsigned long mod;
	void *hcpu;
};

Linus Torvalds's avatar
Linus Torvalds committed
195
/* Take this CPU down. */
196
static int __ref take_cpu_down(void *_param)
Linus Torvalds's avatar
Linus Torvalds committed
197
{
Avi Kivity's avatar
Avi Kivity committed
198
	struct take_cpu_down_param *param = _param;
Linus Torvalds's avatar
Linus Torvalds committed
199
200
201
202
203
	int err;

	/* Ensure this CPU doesn't handle any more interrupts. */
	err = __cpu_disable();
	if (err < 0)
Zwane Mwaikambo's avatar
Zwane Mwaikambo committed
204
		return err;
Linus Torvalds's avatar
Linus Torvalds committed
205

206
	cpu_notify(CPU_DYING | param->mod, param->hcpu);
Zwane Mwaikambo's avatar
Zwane Mwaikambo committed
207
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
208
209
}

210
/* Requires cpu_add_remove_lock to be held */
211
static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
Linus Torvalds's avatar
Linus Torvalds committed
212
{
213
214
	int err, nr_calls = 0;
	void *hcpu = (void *)(long)cpu;
215
	unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
Avi Kivity's avatar
Avi Kivity committed
216
217
218
219
	struct take_cpu_down_param tcd_param = {
		.mod = mod,
		.hcpu = hcpu,
	};
Linus Torvalds's avatar
Linus Torvalds committed
220

221
222
	if (num_online_cpus() == 1)
		return -EBUSY;
Linus Torvalds's avatar
Linus Torvalds committed
223

224
225
	if (!cpu_online(cpu))
		return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
226

227
	cpu_hotplug_begin();
228

229
	err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls);
230
	if (err) {
231
		nr_calls--;
232
		__cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
233
		printk("%s: attempt to take down CPU %u failed\n",
234
				__func__, cpu);
235
		goto out_release;
Linus Torvalds's avatar
Linus Torvalds committed
236
237
	}

Rusty Russell's avatar
Rusty Russell committed
238
	err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
239
	if (err) {
Linus Torvalds's avatar
Linus Torvalds committed
240
		/* CPU didn't die: tell everyone.  Can't complain. */
241
		cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu);
Linus Torvalds's avatar
Linus Torvalds committed
242

243
		goto out_release;
244
	}
245
	BUG_ON(cpu_online(cpu));
Linus Torvalds's avatar
Linus Torvalds committed
246

247
248
249
250
	/*
	 * The migration_call() CPU_DYING callback will have removed all
	 * runnable tasks from the cpu, there's only the idle task left now
	 * that the migration thread is done doing the stop_machine thing.
Peter Zijlstra's avatar
Peter Zijlstra committed
251
252
	 *
	 * Wait for the stop thread to go away.
253
	 */
Peter Zijlstra's avatar
Peter Zijlstra committed
254
255
	while (!idle_cpu(cpu))
		cpu_relax();
Linus Torvalds's avatar
Linus Torvalds committed
256
257
258
259
260

	/* This actually kills the CPU. */
	__cpu_die(cpu);

	/* CPU is completely dead: tell everyone.  Too late to complain. */
261
	cpu_notify_nofail(CPU_DEAD | mod, hcpu);
Linus Torvalds's avatar
Linus Torvalds committed
262
263
264

	check_for_tasks(cpu);

265
out_release:
266
	cpu_hotplug_done();
267
268
	if (!err)
		cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu);
269
270
271
	return err;
}

272
int __ref cpu_down(unsigned int cpu)
273
{
274
	int err;
275

276
	cpu_maps_update_begin();
277
278

	if (cpu_hotplug_disabled) {
279
		err = -EBUSY;
280
281
282
283
		goto out;
	}

	err = _cpu_down(cpu, 0);
284

285
out:
286
	cpu_maps_update_done();
Linus Torvalds's avatar
Linus Torvalds committed
287
288
	return err;
}
289
EXPORT_SYMBOL(cpu_down);
Linus Torvalds's avatar
Linus Torvalds committed
290
291
#endif /*CONFIG_HOTPLUG_CPU*/

292
/* Requires cpu_add_remove_lock to be held */
293
static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
Linus Torvalds's avatar
Linus Torvalds committed
294
{
295
	int ret, nr_calls = 0;
Linus Torvalds's avatar
Linus Torvalds committed
296
	void *hcpu = (void *)(long)cpu;
297
	unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
Linus Torvalds's avatar
Linus Torvalds committed
298

299
300
	if (cpu_online(cpu) || !cpu_present(cpu))
		return -EINVAL;
301

302
	cpu_hotplug_begin();
303
	ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls);
304
	if (ret) {
305
		nr_calls--;
306
		printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n",
307
				__func__, cpu);
Linus Torvalds's avatar
Linus Torvalds committed
308
309
310
311
312
313
314
		goto out_notify;
	}

	/* Arch-specific enabling code. */
	ret = __cpu_up(cpu);
	if (ret != 0)
		goto out_notify;
315
	BUG_ON(!cpu_online(cpu));
Linus Torvalds's avatar
Linus Torvalds committed
316
317

	/* Now call notifier in preparation. */
318
	cpu_notify(CPU_ONLINE | mod, hcpu);
Linus Torvalds's avatar
Linus Torvalds committed
319
320
321

out_notify:
	if (ret != 0)
322
		__cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);
323
	cpu_hotplug_done();
324
325
326
327

	return ret;
}

328
int __cpuinit cpu_up(unsigned int cpu)
329
330
{
	int err = 0;
331
332
333
334
335
336

#ifdef	CONFIG_MEMORY_HOTPLUG
	int nid;
	pg_data_t	*pgdat;
#endif

Rusty Russell's avatar
Rusty Russell committed
337
	if (!cpu_possible(cpu)) {
338
339
		printk(KERN_ERR "can't online cpu %d because it is not "
			"configured as may-hotadd at boot time\n", cpu);
340
#if defined(CONFIG_IA64)
341
342
343
344
345
		printk(KERN_ERR "please check additional_cpus= boot "
				"parameter\n");
#endif
		return -EINVAL;
	}
346

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
#ifdef	CONFIG_MEMORY_HOTPLUG
	nid = cpu_to_node(cpu);
	if (!node_online(nid)) {
		err = mem_online_node(nid);
		if (err)
			return err;
	}

	pgdat = NODE_DATA(nid);
	if (!pgdat) {
		printk(KERN_ERR
			"Can't online cpu %d due to NULL pgdat\n", cpu);
		return -ENOMEM;
	}

362
363
	if (pgdat->node_zonelists->_zonerefs->zone == NULL) {
		mutex_lock(&zonelists_mutex);
364
		build_all_zonelists(NULL);
365
366
		mutex_unlock(&zonelists_mutex);
	}
367
368
#endif

369
	cpu_maps_update_begin();
370
371

	if (cpu_hotplug_disabled) {
372
		err = -EBUSY;
373
374
375
376
377
378
		goto out;
	}

	err = _cpu_up(cpu, 0);

out:
379
	cpu_maps_update_done();
380
381
	return err;
}
Paul E. McKenney's avatar
Paul E. McKenney committed
382
EXPORT_SYMBOL_GPL(cpu_up);
383

384
#ifdef CONFIG_PM_SLEEP_SMP
Rusty Russell's avatar
Rusty Russell committed
385
static cpumask_var_t frozen_cpus;
386

387
388
389
390
391
392
393
394
void __weak arch_disable_nonboot_cpus_begin(void)
{
}

void __weak arch_disable_nonboot_cpus_end(void)
{
}

395
396
int disable_nonboot_cpus(void)
{
397
	int cpu, first_cpu, error = 0;
398

399
	cpu_maps_update_begin();
Rusty Russell's avatar
Rusty Russell committed
400
	first_cpu = cpumask_first(cpu_online_mask);
401
402
	/*
	 * We take down all of the non-boot CPUs in one shot to avoid races
403
404
	 * with the userspace trying to use the CPU hotplug at the same time
	 */
Rusty Russell's avatar
Rusty Russell committed
405
	cpumask_clear(frozen_cpus);
406
	arch_disable_nonboot_cpus_begin();
407

408
409
410
411
	printk("Disabling non-boot CPUs ...\n");
	for_each_online_cpu(cpu) {
		if (cpu == first_cpu)
			continue;
412
		error = _cpu_down(cpu, 1);
413
		if (!error)
Rusty Russell's avatar
Rusty Russell committed
414
			cpumask_set_cpu(cpu, frozen_cpus);
415
		else {
416
417
418
419
420
			printk(KERN_ERR "Error taking CPU%d down: %d\n",
				cpu, error);
			break;
		}
	}
421

422
423
	arch_disable_nonboot_cpus_end();

424
425
426
427
428
	if (!error) {
		BUG_ON(num_online_cpus() > 1);
		/* Make sure the CPUs won't be enabled by someone else */
		cpu_hotplug_disabled = 1;
	} else {
429
		printk(KERN_ERR "Non-boot CPUs are not disabled\n");
430
	}
431
	cpu_maps_update_done();
432
433
434
	return error;
}

435
436
437
438
439
440
441
442
void __weak arch_enable_nonboot_cpus_begin(void)
{
}

void __weak arch_enable_nonboot_cpus_end(void)
{
}

443
void __ref enable_nonboot_cpus(void)
444
445
446
447
{
	int cpu, error;

	/* Allow everyone to use the CPU hotplug again */
448
	cpu_maps_update_begin();
449
	cpu_hotplug_disabled = 0;
Rusty Russell's avatar
Rusty Russell committed
450
	if (cpumask_empty(frozen_cpus))
451
		goto out;
452

453
	printk(KERN_INFO "Enabling non-boot CPUs ...\n");
454
455
456

	arch_enable_nonboot_cpus_begin();

Rusty Russell's avatar
Rusty Russell committed
457
	for_each_cpu(cpu, frozen_cpus) {
458
		error = _cpu_up(cpu, 1);
459
		if (!error) {
460
			printk(KERN_INFO "CPU%d is up\n", cpu);
461
462
			continue;
		}
463
		printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error);
464
	}
465
466
467

	arch_enable_nonboot_cpus_end();

Rusty Russell's avatar
Rusty Russell committed
468
	cpumask_clear(frozen_cpus);
469
out:
470
	cpu_maps_update_done();
Linus Torvalds's avatar
Linus Torvalds committed
471
}
Rusty Russell's avatar
Rusty Russell committed
472

473
static int __init alloc_frozen_cpus(void)
Rusty Russell's avatar
Rusty Russell committed
474
475
476
477
478
479
{
	if (!alloc_cpumask_var(&frozen_cpus, GFP_KERNEL|__GFP_ZERO))
		return -ENOMEM;
	return 0;
}
core_initcall(alloc_frozen_cpus);
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545

/*
 * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU
 * hotplug when tasks are about to be frozen. Also, don't allow the freezer
 * to continue until any currently running CPU hotplug operation gets
 * completed.
 * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the
 * 'cpu_add_remove_lock'. And this same lock is also taken by the regular
 * CPU hotplug path and released only after it is complete. Thus, we
 * (and hence the freezer) will block here until any currently running CPU
 * hotplug operation gets completed.
 */
void cpu_hotplug_disable_before_freeze(void)
{
	cpu_maps_update_begin();
	cpu_hotplug_disabled = 1;
	cpu_maps_update_done();
}


/*
 * When tasks have been thawed, re-enable regular CPU hotplug (which had been
 * disabled while beginning to freeze tasks).
 */
void cpu_hotplug_enable_after_thaw(void)
{
	cpu_maps_update_begin();
	cpu_hotplug_disabled = 0;
	cpu_maps_update_done();
}

/*
 * When callbacks for CPU hotplug notifications are being executed, we must
 * ensure that the state of the system with respect to the tasks being frozen
 * or not, as reported by the notification, remains unchanged *throughout the
 * duration* of the execution of the callbacks.
 * Hence we need to prevent the freezer from racing with regular CPU hotplug.
 *
 * This synchronization is implemented by mutually excluding regular CPU
 * hotplug and Suspend/Hibernate call paths by hooking onto the Suspend/
 * Hibernate notifications.
 */
static int
cpu_hotplug_pm_callback(struct notifier_block *nb,
			unsigned long action, void *ptr)
{
	switch (action) {

	case PM_SUSPEND_PREPARE:
	case PM_HIBERNATION_PREPARE:
		cpu_hotplug_disable_before_freeze();
		break;

	case PM_POST_SUSPEND:
	case PM_POST_HIBERNATION:
		cpu_hotplug_enable_after_thaw();
		break;

	default:
		return NOTIFY_DONE;
	}

	return NOTIFY_OK;
}


546
static int __init cpu_hotplug_pm_sync_init(void)
547
548
549
550
551
552
{
	pm_notifier(cpu_hotplug_pm_callback, 0);
	return 0;
}
core_initcall(cpu_hotplug_pm_sync_init);

553
#endif /* CONFIG_PM_SLEEP_SMP */
554

555
556
557
558
559
560
561
562
/**
 * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers
 * @cpu: cpu that just started
 *
 * This function calls the cpu_chain notifiers with CPU_STARTING.
 * It must be called by the arch code on the new cpu, before the new cpu
 * enables interrupts and before the "boot" cpu returns from __cpu_up().
 */
Al Viro's avatar
Al Viro committed
563
void __cpuinit notify_cpu_starting(unsigned int cpu)
564
565
566
567
{
	unsigned long val = CPU_STARTING;

#ifdef CONFIG_PM_SLEEP_SMP
Rusty Russell's avatar
Rusty Russell committed
568
	if (frozen_cpus != NULL && cpumask_test_cpu(cpu, frozen_cpus))
569
570
		val = CPU_STARTING_FROZEN;
#endif /* CONFIG_PM_SLEEP_SMP */
571
	cpu_notify(val, (void *)(long)cpu);
572
573
}

574
#endif /* CONFIG_SMP */
575

576
577
578
579
/*
 * cpu_bit_bitmap[] is a special, "compressed" data structure that
 * represents all NR_CPUS bits binary values of 1<<nr.
 *
Rusty Russell's avatar
Rusty Russell committed
580
 * It is used by cpumask_of() to get a constant address to a CPU
581
582
 * mask value that has a single bit set only.
 */
583

584
/* cpu_bit_bitmap[0] is empty - so we can back into it */
585
#define MASK_DECLARE_1(x)	[x+1][0] = (1UL << (x))
586
587
588
#define MASK_DECLARE_2(x)	MASK_DECLARE_1(x), MASK_DECLARE_1(x+1)
#define MASK_DECLARE_4(x)	MASK_DECLARE_2(x), MASK_DECLARE_2(x+2)
#define MASK_DECLARE_8(x)	MASK_DECLARE_4(x), MASK_DECLARE_4(x+4)
589

590
591
592
593
594
595
596
const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {

	MASK_DECLARE_8(0),	MASK_DECLARE_8(8),
	MASK_DECLARE_8(16),	MASK_DECLARE_8(24),
#if BITS_PER_LONG > 32
	MASK_DECLARE_8(32),	MASK_DECLARE_8(40),
	MASK_DECLARE_8(48),	MASK_DECLARE_8(56),
597
598
#endif
};
599
EXPORT_SYMBOL_GPL(cpu_bit_bitmap);
600
601
602

const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL;
EXPORT_SYMBOL(cpu_all_bits);
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

#ifdef CONFIG_INIT_ALL_POSSIBLE
static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly
	= CPU_BITS_ALL;
#else
static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly;
#endif
const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
EXPORT_SYMBOL(cpu_possible_mask);

static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly;
const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);
EXPORT_SYMBOL(cpu_online_mask);

static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly;
const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits);
EXPORT_SYMBOL(cpu_present_mask);

static DECLARE_BITMAP(cpu_active_bits, CONFIG_NR_CPUS) __read_mostly;
const struct cpumask *const cpu_active_mask = to_cpumask(cpu_active_bits);
EXPORT_SYMBOL(cpu_active_mask);
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670

void set_cpu_possible(unsigned int cpu, bool possible)
{
	if (possible)
		cpumask_set_cpu(cpu, to_cpumask(cpu_possible_bits));
	else
		cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits));
}

void set_cpu_present(unsigned int cpu, bool present)
{
	if (present)
		cpumask_set_cpu(cpu, to_cpumask(cpu_present_bits));
	else
		cpumask_clear_cpu(cpu, to_cpumask(cpu_present_bits));
}

void set_cpu_online(unsigned int cpu, bool online)
{
	if (online)
		cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
	else
		cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
}

void set_cpu_active(unsigned int cpu, bool active)
{
	if (active)
		cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits));
	else
		cpumask_clear_cpu(cpu, to_cpumask(cpu_active_bits));
}

void init_cpu_present(const struct cpumask *src)
{
	cpumask_copy(to_cpumask(cpu_present_bits), src);
}

void init_cpu_possible(const struct cpumask *src)
{
	cpumask_copy(to_cpumask(cpu_possible_bits), src);
}

void init_cpu_online(const struct cpumask *src)
{
	cpumask_copy(to_cpumask(cpu_online_bits), src);
}
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690

static ATOMIC_NOTIFIER_HEAD(idle_notifier);

void idle_notifier_register(struct notifier_block *n)
{
	atomic_notifier_chain_register(&idle_notifier, n);
}
EXPORT_SYMBOL_GPL(idle_notifier_register);

void idle_notifier_unregister(struct notifier_block *n)
{
	atomic_notifier_chain_unregister(&idle_notifier, n);
}
EXPORT_SYMBOL_GPL(idle_notifier_unregister);

void idle_notifier_call_chain(unsigned long val)
{
	atomic_notifier_call_chain(&idle_notifier, val, NULL);
}
EXPORT_SYMBOL_GPL(idle_notifier_call_chain);