[init] Make lk_init_level re-entrant

Change api to pass in a range of levels to call, instead of just the
last level.
Allows secondary init hooks to run in parallel on multiple cpus.

Change-Id: I7447547818a35d475631b3e7fa8315ff7f80ba4f
This commit is contained in:
Arve Hjønnevåg
2015-03-18 20:30:46 -07:00
parent 1e912a133c
commit 2ff3f126e2
3 changed files with 29 additions and 58 deletions

View File

@@ -7,10 +7,6 @@
* LK's init system
*/
int lk_init_level(uint level);
void lk_secondary_cpu_reset_init_level(void);
int lk_secondary_cpu_init_level(uint level);
typedef void (*lk_init_hook)(uint level);
enum lk_init_level {
@@ -37,6 +33,15 @@ enum lk_init_flags {
LK_INIT_FLAG_ALL_CPUS = LK_INIT_FLAG_PRIMARY_CPU | LK_INIT_FLAG_SECONDARY_CPUS,
};
void lk_init_level(enum lk_init_flags flags, uint start_level, uint stop_level);
static inline void lk_primary_cpu_init_level(uint start_level, uint stop_level) {
lk_init_level(LK_INIT_FLAG_PRIMARY_CPU, start_level, stop_level);
}
static inline void lk_init_level_all(enum lk_init_flags flags) {
lk_init_level(flags, LK_INIT_LEVEL_EARLIEST, LK_INIT_LEVEL_LAST);
}
struct lk_init_struct {
uint level;

View File

@@ -29,6 +29,7 @@
#include <arch/ops.h>
#include <lk/init.h>
#include <assert.h>
#include <compiler.h>
#include <debug.h>
#include <trace.h>
@@ -39,20 +40,13 @@
extern const struct lk_init_struct __lk_init[];
extern const struct lk_init_struct __lk_init_end[];
enum init_level_type {
INIT_LEVEL_TYPE_PRIMARY_CPU,
INIT_LEVEL_TYPE_SECONDARY_CPUS,
INIT_LEVEL_TYPE_COUNT
};
static uint last_init_level[INIT_LEVEL_TYPE_COUNT];
int lk_init_level_common(uint level, enum init_level_type type)
void lk_init_level(enum lk_init_flags required_flag, uint start_level, uint stop_level)
{
LTRACEF("level %#x, last_init_level %#x\n", level, last_init_level[type]);
LTRACEF("flags %#x, start_level %#x, stop_level %#x\n",
required_flag, start_level, stop_level);
uint required_flag = (type == INIT_LEVEL_TYPE_PRIMARY_CPU) ?
LK_INIT_FLAG_PRIMARY_CPU : LK_INIT_FLAG_SECONDARY_CPUS;
uint last_called_level = last_init_level[type];
ASSERT(start_level > 0);
uint last_called_level = start_level - 1;
const struct lk_init_struct *last = NULL;
for (;;) {
/* search for the lowest uncalled hook to call */
@@ -69,7 +63,7 @@ int lk_init_level_common(uint level, enum init_level_type type)
/* reject the easy ones */
if (!(ptr->flags & required_flag))
continue;
if (ptr->level > level)
if (ptr->level > stop_level)
continue;
if (ptr->level < last_called_level)
continue;
@@ -77,7 +71,7 @@ int lk_init_level_common(uint level, enum init_level_type type)
continue;
/* keep the lowest one we haven't called yet */
if (ptr->level > last_init_level[type] && ptr->level > last_called_level) {
if (ptr->level >= start_level && ptr->level > last_called_level) {
found = ptr;
continue;
}
@@ -103,29 +97,6 @@ int lk_init_level_common(uint level, enum init_level_type type)
last_called_level = found->level;
last = found;
}
last_init_level[type] = level;
return 0;
}
int lk_init_level(uint level)
{
return lk_init_level_common(level, INIT_LEVEL_TYPE_PRIMARY_CPU);
}
/* Since there may be multiple secondary CPUs, we allow reseting the
* last_init_level for secondary CPUs so that we can call the same handlers
* on all secondary CPUs without having a separate last_init_level for each CPU.
*/
void lk_secondary_cpu_reset_init_level(void)
{
last_init_level[INIT_LEVEL_TYPE_SECONDARY_CPUS] = 0;
}
int lk_secondary_cpu_init_level(uint level)
{
return lk_init_level_common(level, INIT_LEVEL_TYPE_SECONDARY_CPUS);
}
#if 0

View File

@@ -83,15 +83,15 @@ void lk_main(ulong arg0, ulong arg1, ulong arg2, ulong arg3)
thread_init_early();
// early arch stuff
lk_init_level(LK_INIT_LEVEL_ARCH_EARLY - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_EARLIEST, LK_INIT_LEVEL_ARCH_EARLY - 1);
arch_early_init();
// do any super early platform initialization
lk_init_level(LK_INIT_LEVEL_PLATFORM_EARLY - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_ARCH_EARLY, LK_INIT_LEVEL_PLATFORM_EARLY - 1);
platform_early_init();
// do any super early target initialization
lk_init_level(LK_INIT_LEVEL_TARGET_EARLY - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_PLATFORM_EARLY, LK_INIT_LEVEL_TARGET_EARLY - 1);
target_early_init();
dprintf(INFO, "welcome to lk\n\n");
@@ -104,14 +104,14 @@ void lk_main(ulong arg0, ulong arg1, ulong arg2, ulong arg3)
// bring up the kernel heap
dprintf(SPEW, "initializing heap\n");
lk_init_level(LK_INIT_LEVEL_HEAP - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_TARGET_EARLY, LK_INIT_LEVEL_HEAP - 1);
heap_init();
// initialize the kernel
lk_init_level(LK_INIT_LEVEL_KERNEL - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_HEAP, LK_INIT_LEVEL_KERNEL - 1);
kernel_init();
lk_init_level(LK_INIT_LEVEL_THREADING - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_KERNEL, LK_INIT_LEVEL_THREADING - 1);
// create a thread to complete system initialization
dprintf(SPEW, "creating bootstrap completion thread\n");
@@ -128,24 +128,24 @@ static int bootstrap2(void *arg)
{
dprintf(SPEW, "top of bootstrap2()\n");
lk_init_level(LK_INIT_LEVEL_ARCH - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_THREADING, LK_INIT_LEVEL_ARCH - 1);
arch_init();
// initialize the rest of the platform
dprintf(SPEW, "initializing platform\n");
lk_init_level(LK_INIT_LEVEL_PLATFORM - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_ARCH, LK_INIT_LEVEL_PLATFORM - 1);
platform_init();
// initialize the target
dprintf(SPEW, "initializing target\n");
lk_init_level(LK_INIT_LEVEL_TARGET - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_PLATFORM, LK_INIT_LEVEL_TARGET - 1);
target_init();
dprintf(SPEW, "calling apps_init()\n");
lk_init_level(LK_INIT_LEVEL_APPS - 1);
lk_primary_cpu_init_level(LK_INIT_LEVEL_TARGET, LK_INIT_LEVEL_APPS - 1);
apps_init();
lk_init_level(LK_INIT_LEVEL_LAST);
lk_primary_cpu_init_level(LK_INIT_LEVEL_APPS, LK_INIT_LEVEL_LAST);
return 0;
}
@@ -170,12 +170,7 @@ void lk_secondary_cpu_entry(void)
static int secondary_cpu_bootstrap2(void *arg)
{
static mutex_t lock = MUTEX_INITIAL_VALUE(lock);
mutex_acquire(&lock);
lk_secondary_cpu_reset_init_level();
lk_secondary_cpu_init_level(LK_INIT_LEVEL_LAST);
mutex_release(&lock);
lk_init_level_all(LK_INIT_FLAG_SECONDARY_CPUS);
return 0;
}