#include <compiler.h>
#include <debug.h>
#include <string.h>
#include <platform.h>
#include <kernel/heap.h>
#include <kernel/thread.h>
#include <kernel/timer.h>

extern void *__ctor_list;
extern void *__ctor_end;
extern int __bss_start;
extern int _end;

static int bootstrap2(void *arg);

static void call_constructors(void)
{
	void **ctor;
   
	ctor = &__ctor_list;
	while(ctor != &__ctor_end) {
		void (*func)(void);

		func = (void (*)())*ctor;

		func();
		ctor++;
	}
}

static void clear_bss()
{
	memset(&__bss_start, 0, (size_t)&_end - (size_t)&__bss_start);
}

/* called from crt0.S */
void kmain(void) __NO_RETURN;
void kmain(void)
{
	// clear the bss
	clear_bss();

	// do any super early platform initialization
	platform_early_init();

	dprintf("welcome to lk\n\n");
	
	// deal with any static constructors
	dprintf("calling constructors\n");
	call_constructors();

	// boot level initializers
//	ModuleList::Instance()->SetInitLevel(Module::LEVEL_BOOT);

	// bring up the kernel heap
	dprintf("initializing heap\n");
	heap_init();

	// initialize the threading system
	dprintf("initializing threads\n");
	thread_init();

	// initialize kernel timers
	timer_init();

	// create a thread to complete system initialization
	thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));

	// enable interrupts
	exit_critical_section();

	// exit this thread, which should switch us to bootstrap2
	thread_exit(0);
}

static int sleep_thread(void *arg)
{
	for(;;) {
		dprintf("sleeper %p\n", current_thread);
		thread_sleep(rand() % 500);
	}
}

static int bootstrap2(void *arg)
{
	dprintf("top of bootstrap2()\n");

	// initialize the rest of the platform
	platform_init();

	int i;
	for(i=0; i < 16; i++)
		thread_resume(thread_create("sleeper", &sleep_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));

	thread_exit(0);
	return 0;
}
