Beispiel #1
0
static int
dump_info(int argc, char **argv)
{
	kprintf("kernel build: %s %s (gcc%d %s)\n", __DATE__, __TIME__, __GNUC__,
		__VERSION__);
	kprintf("revision: %s\n\n", get_haiku_revision());

	kprintf("cpu count: %" B_PRId32 "\n", smp_get_num_cpus());

	for (int32 i = 0; i < smp_get_num_cpus(); i++)
		kprintf("  [%" B_PRId32 "] active time: %10" B_PRId64 ", interrupt"
			" time: %10" B_PRId64 ", irq time: %10" B_PRId64 "\n", i + 1,
			gCPU[i].active_time, gCPU[i].interrupt_time, gCPU[i].irq_time);

	// ToDo: Add page_faults
	kprintf("pages:\t\t%" B_PRIuPHYSADDR " (%" B_PRIuPHYSADDR " max)\n",
		vm_page_num_pages() - vm_page_num_free_pages(), vm_page_num_pages());

	kprintf("sems:\t\t%" B_PRId32 " (%" B_PRId32 " max)\n", sem_used_sems(),
		sem_max_sems());
	kprintf("ports:\t\t%" B_PRId32 " (%" B_PRId32 " max)\n", port_used_ports(),
			port_max_ports());
	kprintf("threads:\t%" B_PRId32 " (%" B_PRId32 " max)\n",
		thread_used_threads(), thread_max_threads());
	kprintf("teams:\t\t%" B_PRId32 " (%" B_PRId32 " max)\n", team_used_teams(),
		team_max_teams());

	return 0;
}
Beispiel #2
0
status_t
_user_set_cpu_enabled(int32 cpu, bool enabled)
{
	status_t status = B_OK;
	cpu_status state;
	int32 i, count;

	if (cpu < 0 || cpu >= smp_get_num_cpus())
		return B_BAD_VALUE;

	// We need to lock here to make sure that no one can disable
	// the last CPU

	state = disable_interrupts();
	acquire_spinlock(&sSetCpuLock);

	if (!enabled) {
		// check if this is the last CPU to be disabled
		for (i = 0, count = 0; i < smp_get_num_cpus(); i++) {
			if (!gCPU[i].disabled)
				count++;
		}

		if (count == 1)
			status = B_NOT_ALLOWED;
	}

	if (status == B_OK)
		gCPU[cpu].disabled = !enabled;

	release_spinlock(&sSetCpuLock);
	restore_interrupts(state);
	return status;
}
Beispiel #3
0
BaseDepot::BaseDepot()
	: fFull(NULL), fEmpty(NULL), fFullCount(0), fEmptyCount(0)
{
	// benaphore_init(...)
	fStores = new (std::nothrow) CPUStore[smp_get_num_cpus()];

	if (fStores) {
		for (int i = 0; i < smp_get_num_cpus(); i++) {
			// benaphore_init(...)
			fStores[i].loaded = fStores[i].previous = NULL;
		}
	}
}
Beispiel #4
0
status_t
get_system_info(system_info* info)
{
	memset(info, 0, sizeof(system_info));

	info->boot_time = rtc_boot_time();
	info->cpu_count = smp_get_num_cpus();

	vm_page_get_stats(info);
	vm_get_info(info);

	info->used_threads = thread_used_threads();
	info->max_threads = thread_max_threads();
	info->used_teams = team_used_teams();
	info->max_teams = team_max_teams();
	info->used_ports = port_used_ports();
	info->max_ports = port_max_ports();
	info->used_sems = sem_used_sems();
	info->max_sems = sem_max_sems();

	info->kernel_version = kKernelVersion;
	strlcpy(info->kernel_name, kKernelName, B_FILE_NAME_LENGTH);
	strlcpy(info->kernel_build_date, __DATE__, B_OS_NAME_LENGTH);
	strlcpy(info->kernel_build_time, __TIME__, B_OS_NAME_LENGTH);
	info->abi = B_HAIKU_ABI;

	return B_OK;
}
Beispiel #5
0
void
scheduler_init(void)
{
	int32 cpuCount = smp_get_num_cpus();
	dprintf("scheduler_init: found %ld logical cpu%s\n", cpuCount,
		cpuCount != 1 ? "s" : "");

	if (cpuCount > 1) {
#if 0
		dprintf("scheduler_init: using affine scheduler\n");
		scheduler_affine_init();
#else
		dprintf("scheduler_init: using simple SMP scheduler\n");
		scheduler_simple_smp_init();
#endif
	} else {
		dprintf("scheduler_init: using simple scheduler\n");
		scheduler_simple_init();
	}

	// Disable rescheduling until the basic kernel initialization is done and
	// CPUs are ready to enable interrupts.
	sRescheduleFunction = gScheduler->reschedule;
	gScheduler->reschedule = scheduler_reschedule_no_op;

#if SCHEDULER_TRACING
	add_debugger_command_etc("scheduler", &cmd_scheduler,
		"Analyze scheduler tracing information",
		"<thread>\n"
		"Analyzes scheduler tracing information for a given thread.\n"
		"  <thread>  - ID of the thread.\n", 0);
#endif
}
Beispiel #6
0
bool
object_depot_contains_object(object_depot* depot, void* object)
{
	WriteLocker writeLocker(depot->outer_lock);

	int cpuCount = smp_get_num_cpus();
	for (int i = 0; i < cpuCount; i++) {
		depot_cpu_store& store = depot->stores[i];

		if (store.loaded != NULL && !store.loaded->IsEmpty()) {
			if (store.loaded->ContainsObject(object))
				return true;
		}

		if (store.previous != NULL && !store.previous->IsEmpty()) {
			if (store.previous->ContainsObject(object))
				return true;
		}
	}

	for (DepotMagazine* magazine = depot->full; magazine != NULL;
			magazine = magazine->next) {
		if (magazine->ContainsObject(object))
			return true;
	}

	return false;
}
Beispiel #7
0
status_t
object_depot_init(object_depot* depot, size_t capacity, size_t maxCount,
	uint32 flags, void* cookie, void (*return_object)(object_depot* depot,
		void* cookie, void* object, uint32 flags))
{
	depot->full = NULL;
	depot->empty = NULL;
	depot->full_count = depot->empty_count = 0;
	depot->max_count = maxCount;
	depot->magazine_capacity = capacity;

	rw_lock_init(&depot->outer_lock, "object depot");
	B_INITIALIZE_SPINLOCK(&depot->inner_lock);

	int cpuCount = smp_get_num_cpus();
	depot->stores = (depot_cpu_store*)slab_internal_alloc(
		sizeof(depot_cpu_store) * cpuCount, flags);
	if (depot->stores == NULL) {
		rw_lock_destroy(&depot->outer_lock);
		return B_NO_MEMORY;
	}

	for (int i = 0; i < cpuCount; i++) {
		depot->stores[i].loaded = NULL;
		depot->stores[i].previous = NULL;
	}

	depot->cookie = cookie;
	depot->return_object = return_object;

	return B_OK;
}
Beispiel #8
0
bool
_user_cpu_enabled(int32 cpu)
{
	if (cpu < 0 || cpu >= smp_get_num_cpus())
		return false;

	return !gCPU[cpu].disabled;
}
Beispiel #9
0
static status_t
acpi_processor_init(acpi_cpuidle_driver_info *device)
{
	// get the CPU index
	dprintf("get acpi processor @%p\n", device->acpi_cookie);

	acpi_data buffer;
	buffer.pointer = NULL;
	buffer.length = ACPI_ALLOCATE_BUFFER;
	status_t status = device->acpi->evaluate_method(device->acpi_cookie, NULL,
		NULL, &buffer);
	if (status != B_OK) {
		dprintf("failed to get processor obj\n");
		return status;
	}

	acpi_object_type *object = (acpi_object_type *)buffer.pointer;
	dprintf("acpi cpu%" B_PRId32 ": P_BLK at %#x/%lu\n",
		object->data.processor.cpu_id,
		object->data.processor.pblk_address,
		object->data.processor.pblk_length);

	int32 cpuIndex = object->data.processor.cpu_id;
	free(buffer.pointer);

	if (cpuIndex < 0 || cpuIndex >= smp_get_num_cpus())
		return B_ERROR;

	device->cpuIndex = cpuIndex;
	sAcpiProcessor[cpuIndex] = device;

	// If nodes for all processors have been registered, init the idle callback.
	for (int32 i = smp_get_num_cpus() - 1; i >= 0; i--) {
		if (sAcpiProcessor[i] == NULL)
			return B_OK;
	}

	if (intel_cpuidle_init() == B_OK)
		return B_OK;

	status = acpi_cpuidle_init();
	if (status != B_OK)
		sAcpiProcessor[cpuIndex] = NULL;

	return status;
}
Beispiel #10
0
status_t
get_cpu_info(uint32 firstCPU, uint32 cpuCount, cpu_info* info)
{
	if (firstCPU >= (uint32)smp_get_num_cpus())
		return B_BAD_VALUE;
	if (cpuCount == 0)
		return B_OK;

	uint32 count = std::min(cpuCount, smp_get_num_cpus() - firstCPU);

	memset(info, 0, sizeof(cpu_info) * count);
	for (uint32 i = 0; i < count; i++) {
		info[i].active_time = cpu_get_active_time(firstCPU + i);
		info[i].enabled = !gCPU[firstCPU + i].disabled;
	}

	return B_OK;
}
Beispiel #11
0
static bool
all_cpus_have_feature(enum x86_feature_type type, int feature)
{
	int i;
	int cpuCount = smp_get_num_cpus();

	for (i = 0; i < cpuCount; i++) {
		if (!(gCPU[i].arch.feature[type] & feature))
			return false;
	}

	return true;
}
Beispiel #12
0
bigtime_t
cpu_get_active_time(int32 cpu)
{
	if (cpu < 0 || cpu > smp_get_num_cpus())
		return 0;

	// We need to grab the scheduler lock here, because the thread activity
	// time is not maintained atomically (because there is no need to).

	InterruptsSpinLocker schedulerLocker(gSchedulerLock);

	return gCPU[cpu].active_time;
}
Beispiel #13
0
status_t
_user_get_cpu_info(uint32 firstCPU, uint32 cpuCount, cpu_info* userInfo)
{
	if (userInfo == NULL || !IS_USER_ADDRESS(userInfo))
		return B_BAD_ADDRESS;
	if (firstCPU >= (uint32)smp_get_num_cpus())
		return B_BAD_VALUE;
	if (cpuCount == 0)
		return B_OK;

	uint32 count = std::min(cpuCount, smp_get_num_cpus() - firstCPU);

	cpu_info* cpuInfos = new(std::nothrow) cpu_info[count];
	if (cpuInfos == NULL)
		return B_NO_MEMORY;
	ArrayDeleter<cpu_info> _(cpuInfos);

	status_t error = get_cpu_info(firstCPU, count, cpuInfos);
	if (error != B_OK)
		return error;

	return user_memcpy(userInfo, cpuInfos, sizeof(cpu_info) * count);
}
Beispiel #14
0
static status_t
acpi_cpuidle_init(void)
{
	dprintf("acpi_cpuidle_init\n");

	for (int32 i = 0; i < smp_get_num_cpus(); i++)
		if (acpi_cpuidle_setup(sAcpiProcessor[i]) != B_OK)
			return B_ERROR;

	status_t status = gIdle->AddDevice(&sAcpiDevice);
	if (status == B_OK)
		dprintf("using acpi idle\n");
	return status;
}
Beispiel #15
0
void
dump_object_depot(object_depot* depot)
{
	kprintf("  full:     %p, count %lu\n", depot->full, depot->full_count);
	kprintf("  empty:    %p, count %lu\n", depot->empty, depot->empty_count);
	kprintf("  max full: %lu\n", depot->max_count);
	kprintf("  capacity: %lu\n", depot->magazine_capacity);
	kprintf("  stores:\n");

	int cpuCount = smp_get_num_cpus();

	for (int i = 0; i < cpuCount; i++) {
		kprintf("  [%d] loaded:   %p\n", i, depot->stores[i].loaded);
		kprintf("      previous: %p\n", depot->stores[i].previous);
	}
}
Beispiel #16
0
/*!	Starts/stops the timer as necessary, if it is active.

	Called whenever threads of the team whose CPU time is referred to by the
	timer are scheduled or unscheduled (or leave the team), or when the timer
	was just set. Schedules a kernel timer for the remaining time, respectively
	cancels it.

	The caller must hold \c time_lock and \c sUserTimerLock.

	\param unscheduledThread If not \c NULL, this is the thread that is
		currently running and which is in the process of being unscheduled.
*/
void
TeamTimeUserTimer::Update(Thread* unscheduledThread)
{
	if (fTeam == NULL)
		return;

	// determine how many of the team's threads are currently running
	fRunningThreads = 0;
	int32 cpuCount = smp_get_num_cpus();
	for (int32 i = 0; i < cpuCount; i++) {
		Thread* thread = gCPU[i].running_thread;
		if (thread != unscheduledThread && thread->team == fTeam)
			fRunningThreads++;
	}

	_Update(unscheduledThread != NULL);
}
Beispiel #17
0
void
BaseDepot::MakeEmpty()
{
	for (int i = 0; i < smp_get_num_cpus(); i++) {
		if (fStores[i].loaded)
			_EmptyMagazine(fStores[i].loaded);
		if (fStores[i].previous)
			_EmptyMagazine(fStores[i].previous);
		fStores[i].loaded = fStores[i].previous = NULL;
	}

	while (fFull)
		_EmptyMagazine(SListPop(fFull));

	while (fEmpty)
		_EmptyMagazine(SListPop(fEmpty));
}
Beispiel #18
0
void
object_depot_make_empty(object_depot* depot, uint32 flags)
{
	WriteLocker writeLocker(depot->outer_lock);

	// collect the store magazines

	DepotMagazine* storeMagazines = NULL;

	int cpuCount = smp_get_num_cpus();
	for (int i = 0; i < cpuCount; i++) {
		depot_cpu_store& store = depot->stores[i];

		if (store.loaded) {
			_push(storeMagazines, store.loaded);
			store.loaded = NULL;
		}

		if (store.previous) {
			_push(storeMagazines, store.previous);
			store.previous = NULL;
		}
	}

	// detach the depot's full and empty magazines

	DepotMagazine* fullMagazines = depot->full;
	depot->full = NULL;

	DepotMagazine* emptyMagazines = depot->empty;
	depot->empty = NULL;

	writeLocker.Unlock();

	// free all magazines

	while (storeMagazines != NULL)
		empty_magazine(depot, _pop(storeMagazines), flags);

	while (fullMagazines != NULL)
		empty_magazine(depot, _pop(fullMagazines), flags);

	while (emptyMagazines)
		free_magazine(_pop(emptyMagazines), flags);
}
void
call_all_cpus_sync(void (*func)(void*, int), void* cookie)
{
	cpu_status state = disable_interrupts();
	
	// if inter-CPU communication is not yet enabled, use the early mechanism
	if (!sICIEnabled) {
		call_all_cpus_early(func, cookie);
		restore_interrupts(state);
		return;
	}

	if (smp_get_num_cpus() > 1) {
		smp_send_broadcast_ici(SMP_MSG_CALL_FUNCTION, (addr_t)cookie,
			0, 0, (void*)func, SMP_MSG_FLAG_SYNC);
	}

	// we need to call this function ourselves as well
	func(cookie, smp_get_current_cpu());

	restore_interrupts(state);
}
status_t
SystemProfiler::Init()
{
	// clone the user area
	void* areaBase;
	fKernelArea = clone_area("profiling samples", &areaBase,
		B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA,
		fUserArea);
	if (fKernelArea < 0)
		return fKernelArea;

	// we need the memory locked
	status_t error = lock_memory(areaBase, fAreaSize, B_READ_DEVICE);
	if (error != B_OK) {
		delete_area(fKernelArea);
		fKernelArea = -1;
		return error;
	}

	// the buffer is ready for use
	fHeader = (system_profiler_buffer_header*)areaBase;
	fBufferBase = (uint8*)(fHeader + 1);
	fBufferCapacity = fAreaSize - (fBufferBase - (uint8*)areaBase);
	fHeader->start = 0;
	fHeader->size = 0;

	// allocate the wait object buffer and init the hash table
	if (fWaitObjectCount > 0) {
		fWaitObjectBuffer = new(std::nothrow) WaitObject[fWaitObjectCount];
		if (fWaitObjectBuffer == NULL)
			return B_NO_MEMORY;

		for (int32 i = 0; i < fWaitObjectCount; i++)
			fFreeWaitObjects.Add(fWaitObjectBuffer + i);

		error = fWaitObjectTable.Init(fWaitObjectCount * 3 / 2);
		if (error != B_OK)
			return error;
	}

	// start listening for notifications

	// teams
	NotificationManager& notificationManager
		= NotificationManager::Manager();
	if ((fFlags & B_SYSTEM_PROFILER_TEAM_EVENTS) != 0) {
		error = notificationManager.AddListener("teams",
			TEAM_ADDED | TEAM_REMOVED | TEAM_EXEC, *this);
		if (error != B_OK)
			return error;
		fTeamNotificationsRequested = true;
	}

	// threads
	if ((fFlags & B_SYSTEM_PROFILER_THREAD_EVENTS) != 0) {
		error = notificationManager.AddListener("threads",
			THREAD_ADDED | THREAD_REMOVED, *this);
		if (error != B_OK)
			return error;
		fThreadNotificationsRequested = true;
	}

	// images
	if ((fFlags & B_SYSTEM_PROFILER_IMAGE_EVENTS) != 0) {
		error = notificationManager.AddListener("images",
			IMAGE_ADDED | IMAGE_REMOVED, *this);
		if (error != B_OK)
			return error;
		fImageNotificationsRequested = true;
	}

	// I/O events
	if ((fFlags & B_SYSTEM_PROFILER_IO_SCHEDULING_EVENTS) != 0) {
		error = notificationManager.AddListener("I/O",
			IO_SCHEDULER_ADDED | IO_SCHEDULER_REMOVED
				| IO_SCHEDULER_REQUEST_SCHEDULED | IO_SCHEDULER_REQUEST_FINISHED
				| IO_SCHEDULER_OPERATION_STARTED
				| IO_SCHEDULER_OPERATION_FINISHED,
			*this);
		if (error != B_OK)
			return error;
		fIONotificationsRequested = true;
	}

	// We need to fill the buffer with the initial state of teams, threads,
	// and images.

	// teams
	if ((fFlags & B_SYSTEM_PROFILER_TEAM_EVENTS) != 0) {
		InterruptsSpinLocker locker(fLock);

		TeamListIterator iterator;
		while (Team* team = iterator.Next()) {
			locker.Unlock();

			bool added = _TeamAdded(team);

			// release the reference returned by the iterator
			team->ReleaseReference();

			if (!added)
				return B_BUFFER_OVERFLOW;

			locker.Lock();
		}

		fTeamNotificationsEnabled = true;
	}

	// images
	if ((fFlags & B_SYSTEM_PROFILER_IMAGE_EVENTS) != 0) {
		if (image_iterate_through_images(&_InitialImageIterator, this) != NULL)
			return B_BUFFER_OVERFLOW;
	}

	// threads
	if ((fFlags & B_SYSTEM_PROFILER_THREAD_EVENTS) != 0) {
		InterruptsSpinLocker locker(fLock);

		ThreadListIterator iterator;
		while (Thread* thread = iterator.Next()) {
			locker.Unlock();

			bool added = _ThreadAdded(thread);

			// release the reference returned by the iterator
			thread->ReleaseReference();

			if (!added)
				return B_BUFFER_OVERFLOW;

			locker.Lock();
		}

		fThreadNotificationsEnabled = true;
	}

	fProfilingActive = true;

	// start scheduler and wait object listening
	if ((fFlags & B_SYSTEM_PROFILER_SCHEDULING_EVENTS) != 0) {
		scheduler_add_listener(this);
		fSchedulerNotificationsRequested = true;

		InterruptsSpinLocker waitObjectLocker(gWaitObjectListenerLock);
		add_wait_object_listener(this);
		fWaitObjectNotificationsRequested = true;
		waitObjectLocker.Unlock();

		// fake schedule events for the initially running threads
		int32 cpuCount = smp_get_num_cpus();
		for (int32 i = 0; i < cpuCount; i++) {
			Thread* thread = gCPU[i].running_thread;
			if (thread != NULL)
				ThreadScheduled(thread, thread);
		}
	}

	// I/O scheduling
	if ((fFlags & B_SYSTEM_PROFILER_IO_SCHEDULING_EVENTS) != 0) {
		IOSchedulerRoster* roster = IOSchedulerRoster::Default();
		AutoLocker<IOSchedulerRoster> rosterLocker(roster);

		for (IOSchedulerList::ConstIterator it
				= roster->SchedulerList().GetIterator();
			IOScheduler* scheduler = it.Next();) {
			_IOSchedulerAdded(scheduler);
		}

		fIONotificationsEnabled = true;
	}

	// activate the profiling timers on all CPUs
	if ((fFlags & B_SYSTEM_PROFILER_SAMPLING_EVENTS) != 0)
		call_all_cpus(_InitTimers, this);

	return B_OK;
}
Beispiel #21
0
RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
{
    return idCpu < smp_get_num_cpus()
        /* FIXME: && !CPU_ABSENT(idCpu)*/;
}
Beispiel #22
0
RTDECL(RTCPUID) RTMpGetCount(void)
{
    return smp_get_num_cpus();
}
Beispiel #23
0
RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
{
    return smp_get_num_cpus() - 1;
}
Beispiel #24
0
RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
{
    return (unsigned)iCpu < smp_get_num_cpus() ? (RTCPUID)iCpu : NIL_RTCPUID;
}
Beispiel #25
0
RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
{
    return idCpu < smp_get_num_cpus() ? (int)idCpu : -1;
}
RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
{
    return idCpu < smp_get_num_cpus();
    /** @todo: FixMe && !CPU_ABSENT(idCpu) */
}
Beispiel #27
0
status_t
ObjectCache::Init(const char* name, size_t objectSize, size_t alignment,
	size_t maximum, size_t magazineCapacity, size_t maxMagazineCount,
	uint32 flags, void* cookie, object_cache_constructor constructor,
	object_cache_destructor destructor, object_cache_reclaimer reclaimer)
{
	strlcpy(this->name, name, sizeof(this->name));

	mutex_init(&lock, this->name);

	if (objectSize < sizeof(object_link))
		objectSize = sizeof(object_link);

	if (alignment > 0 && (objectSize & (alignment - 1)))
		object_size = objectSize + alignment - (objectSize & (alignment - 1));
	else
		object_size = objectSize;

	TRACE_CACHE(this, "init %lu, %lu -> %lu", objectSize, alignment,
		object_size);

	cache_color_cycle = 0;
	total_objects = 0;
	used_count = 0;
	empty_count = 0;
	pressure = 0;
	min_object_reserve = 0;

	maintenance_pending = false;
	maintenance_in_progress = false;
	maintenance_resize = false;
	maintenance_delete = false;

	usage = 0;
	this->maximum = maximum;

	this->flags = flags;

	resize_request = NULL;
	resize_entry_can_wait = NULL;
	resize_entry_dont_wait = NULL;

	// no gain in using the depot in single cpu setups
	if (smp_get_num_cpus() == 1)
		this->flags |= CACHE_NO_DEPOT;

	if (!(this->flags & CACHE_NO_DEPOT)) {
		// Determine usable magazine configuration values if none had been given
		if (magazineCapacity == 0) {
			magazineCapacity = objectSize < 256
				? 32 : (objectSize < 512 ? 16 : 8);
		}
		if (maxMagazineCount == 0)
			maxMagazineCount = magazineCapacity / 2;

		status_t status = object_depot_init(&depot, magazineCapacity,
			maxMagazineCount, flags, this, object_cache_return_object_wrapper);
		if (status != B_OK) {
			mutex_destroy(&lock);
			return status;
		}
	}

	this->cookie = cookie;
	this->constructor = constructor;
	this->destructor = destructor;
	this->reclaimer = reclaimer;

	return B_OK;
}
Beispiel #28
0
RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
{
    return idCpu < smp_get_num_cpus();
}