#include <debug.h>
#include <err.h>
#include <kernel/Scheduler.h>
#include <os/Thread.h>
#include <os/Mutex.h>
#include <os/Module.h>

using namespace OS;

namespace OS {
namespace Test {

	static Mutex *m;
	static volatile unsigned int var = 0;
	static int mutexThreadRoutine()
	{
		int loop_count = 0;
		Thread *t = Thread::GetCurrent();
		dprintf("mutexThreadRoutine %p: start\n", t);

		for(;;) {
			if (loop_count % 1024 == 0)
				dprintf("mutexThreadRoutine %p: loop %d\n", t, loop_count);
			loop_count++;

			Thread::YieldCurrent();

//			dprintf("mutexThreadRoutine %p: acquiring\n", t);
			m->Acquire();

			if (var != 0)
				dprintf("mutex collision, val 0x%x!\n", var);

			Thread::YieldCurrent();

//			dprintf("mutexThreadRoutine %p: setting var (currently contains 0x%x)\n", t, var);
			var = (unsigned int)t;

//			dprintf("mutexThreadRoutine %p: yielding\n", t);
			Thread::YieldCurrent();

//			dprintf("mutexThreadRoutine %p: clearing var (currently contains 0x%x)\n", t, var);
			var = 0;

//			dprintf("mutexThreadRoutine %p: releasing\n", t);
			m->Release();
//			dprintf("mutexThreadRoutine %p: released\n", t);
		}	

		return 0;
	}

	static void mutexTest()
	{
		m = new Mutex;

		Thread *t;
		t = new GenericThread(&mutexThreadRoutine); t->SetPriority(Kernel::Scheduler::kHighestPriority); t->Start(false);
		t = new GenericThread(&mutexThreadRoutine); t->SetPriority(Kernel::Scheduler::kHighestPriority); t->Start(false);
		t = new GenericThread(&mutexThreadRoutine); t->SetPriority(Kernel::Scheduler::kHighestPriority); t->Start(false);
		t = new GenericThread(&mutexThreadRoutine); t->SetPriority(Kernel::Scheduler::kHighestPriority); t->Start(false);
	}

	static status_t testInit(Module *)
	{
		TRACE_ENTRY;

		mutexTest();

		return NO_ERROR;
	}

//	Module mutexTestModule("Mutex Test", Module::LEVEL_THREAD, &testInit);
}} // namespace OS::Test

