|
@@ -18,7 +18,6 @@
|
|
|
#include <linux/mm.h>
|
|
|
#include <linux/swap.h>
|
|
|
#include <linux/interrupt.h>
|
|
|
-#include <linux/rwsem.h>
|
|
|
#include <linux/pagemap.h>
|
|
|
#include <linux/jiffies.h>
|
|
|
#include <linux/bootmem.h>
|
|
@@ -1060,7 +1059,15 @@ static void __init deferred_free_range(struct page *page,
|
|
|
__free_pages_boot_core(page, pfn, 0);
|
|
|
}
|
|
|
|
|
|
-static __initdata DECLARE_RWSEM(pgdat_init_rwsem);
|
|
|
+/* Completion tracking for deferred_init_memmap() threads */
|
|
|
+static atomic_t pgdat_init_n_undone __initdata;
|
|
|
+static __initdata DECLARE_COMPLETION(pgdat_init_all_done_comp);
|
|
|
+
|
|
|
+static inline void __init pgdat_init_report_one_done(void)
|
|
|
+{
|
|
|
+ if (atomic_dec_and_test(&pgdat_init_n_undone))
|
|
|
+ complete(&pgdat_init_all_done_comp);
|
|
|
+}
|
|
|
|
|
|
/* Initialise remaining memory on a node */
|
|
|
static int __init deferred_init_memmap(void *data)
|
|
@@ -1077,7 +1084,7 @@ static int __init deferred_init_memmap(void *data)
|
|
|
const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
|
|
|
|
|
|
if (first_init_pfn == ULONG_MAX) {
|
|
|
- up_read(&pgdat_init_rwsem);
|
|
|
+ pgdat_init_report_one_done();
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1177,7 +1184,8 @@ free_range:
|
|
|
|
|
|
pr_info("node %d initialised, %lu pages in %ums\n", nid, nr_pages,
|
|
|
jiffies_to_msecs(jiffies - start));
|
|
|
- up_read(&pgdat_init_rwsem);
|
|
|
+
|
|
|
+ pgdat_init_report_one_done();
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1185,14 +1193,14 @@ void __init page_alloc_init_late(void)
|
|
|
{
|
|
|
int nid;
|
|
|
|
|
|
+ /* There will be num_node_state(N_MEMORY) threads */
|
|
|
+ atomic_set(&pgdat_init_n_undone, num_node_state(N_MEMORY));
|
|
|
for_each_node_state(nid, N_MEMORY) {
|
|
|
- down_read(&pgdat_init_rwsem);
|
|
|
kthread_run(deferred_init_memmap, NODE_DATA(nid), "pgdatinit%d", nid);
|
|
|
}
|
|
|
|
|
|
/* Block until all are initialised */
|
|
|
- down_write(&pgdat_init_rwsem);
|
|
|
- up_write(&pgdat_init_rwsem);
|
|
|
+ wait_for_completion(&pgdat_init_all_done_comp);
|
|
|
}
|
|
|
#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
|
|
|
|