/*
 * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
 * Distributed under the terms of the NewOS License.
 */
 
 
#include "paging/X86VMTranslationMap.h"
 
#include <thread.h>
#include <smp.h>
 
#include "paging/X86PagingStructures.h"
 
 
//#define TRACE_X86_VM_TRANSLATION_MAP
#ifdef TRACE_X86_VM_TRANSLATION_MAP
#	define TRACE(x...) dprintf(x)
#else
#	define TRACE(x...) ;
#endif
 
 
X86VMTranslationMap::X86VMTranslationMap()
	:
	fPageMapper(NULL),
	fInvalidPagesCount(0)
{
}
 
 
X86VMTranslationMap::~X86VMTranslationMap()
{
}
 
 
status_t
X86VMTranslationMap::Init(bool kernel)
{
	fIsKernelMap = kernel;
	return B_OK;
}
 
 
/*!	Acquires the map's recursive lock, and resets the invalidate pages counter
	in case it's the first locking recursion.
*/
bool
X86VMTranslationMap::Lock()
{
	TRACE("%p->X86VMTranslationMap::Lock()\n", this);
 
	recursive_lock_lock(&fLock);
	if (recursive_lock_get_recursion(&fLock) == 1) {
		// we were the first one to grab the lock
		TRACE("clearing invalidated page count\n");
		fInvalidPagesCount = 0;
	}
 
	return true;
}
 
 
/*!	Unlocks the map, and, if we are actually losing the recursive lock,
	flush all pending changes of this map (ie. flush TLB caches as
	needed).
*/
void
X86VMTranslationMap::Unlock()
{
	TRACE("%p->X86VMTranslationMap::Unlock()\n", this);
 
	if (recursive_lock_get_recursion(&fLock) == 1) {
		// we're about to release it for the last time
		Flush();
	}
 
	recursive_lock_unlock(&fLock);
}
 
 
addr_t
X86VMTranslationMap::MappedSize() const
{
	return fMapCount;
}
 
 
void
X86VMTranslationMap::Flush()
{
	if (fInvalidPagesCount <= 0)
		return;
 
	Thread* thread = thread_get_current_thread();
	thread_pin_to_current_cpu(thread);
 
	if (fInvalidPagesCount > PAGE_INVALIDATE_CACHE_SIZE) {
		// invalidate all pages
		TRACE("flush_tmap: %d pages to invalidate, invalidate all\n",
			fInvalidPagesCount);
 
		if (fIsKernelMap) {
			arch_cpu_global_TLB_invalidate();
			smp_send_broadcast_ici(SMP_MSG_GLOBAL_INVALIDATE_PAGES, 0, 0, 0,
				NULL, SMP_MSG_FLAG_SYNC);
		} else {
			cpu_status state = disable_interrupts();
			arch_cpu_user_TLB_invalidate();
			restore_interrupts(state);
 
			int cpu = smp_get_current_cpu();
			CPUSet cpuMask = PagingStructures()->active_on_cpus;
			cpuMask.ClearBit(cpu);
 
			if (!cpuMask.IsEmpty()) {
				smp_send_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES,
					0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
			}
		}
	} else {
		TRACE("flush_tmap: %d pages to invalidate, invalidate list\n",
			fInvalidPagesCount);
 
		arch_cpu_invalidate_TLB_list(fInvalidPages, fInvalidPagesCount);
 
		if (fIsKernelMap) {
			smp_send_broadcast_ici(SMP_MSG_INVALIDATE_PAGE_LIST,
				(addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL,
				SMP_MSG_FLAG_SYNC);
		} else {
			int cpu = smp_get_current_cpu();
			CPUSet cpuMask = PagingStructures()->active_on_cpus;
			cpuMask.ClearBit(cpu);
 
			if (!cpuMask.IsEmpty()) {
				smp_send_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST,
					(addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL,
					SMP_MSG_FLAG_SYNC);
			}
		}
	}
	fInvalidPagesCount = 0;
 
	thread_unpin_from_current_cpu(thread);
}

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: fInvalidPages, fIsKernelMap.