[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:
@@ -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;
|
||||
|
||||
45
top/init.c
45
top/init.c
@@ -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
|
||||
|
||||
29
top/main.c
29
top/main.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user