arch/mips/kernel/sync-r4k.c

Source file repositories/reference/linux-study-clean/arch/mips/kernel/sync-r4k.c

File Facts

System
Linux kernel
Corpus path
arch/mips/kernel/sync-r4k.c
Extension
.c
Size
5914 bytes
Lines
246
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (unlikely(!(i & 7))) {
			if (now > end || i > 10000000)
				break;
			cpu_relax();
			touch_nmi_watchdog();
		}
		/*
		 * Outside the critical section we can now see whether
		 * we saw a time-warp of the counter going backwards:
		 */
		if (unlikely(prev > now)) {
			arch_spin_lock(&sync_lock);
			max_warp = max(max_warp, prev - now);
			cur_max_warp = max_warp;
			/*
			 * Check whether this bounces back and forth. Only
			 * one CPU should observe time going backwards.
			 */
			if (cur_warps != nr_warps)
				random_warps++;
			nr_warps++;
			cur_warps = nr_warps;
			arch_spin_unlock(&sync_lock);
		}
	}
	WARN(!(now-start),
		"Warning: zero counter calibration delta: %d [max: %d]\n",
			now-start, end-start);
	return cur_max_warp;
}

/*
 * The freshly booted CPU initiates this via an async SMP function call.
 */
static void check_counter_sync_source(void *__cpu)
{
	unsigned int cpu = (unsigned long)__cpu;
	int cpus = 2;

	atomic_set(&test_runs, NR_LOOPS);
retry:
	/* Wait for the target to start. */
	while (atomic_read(&start_count) != cpus - 1)
		cpu_relax();

	/*
	 * Trigger the target to continue into the measurement too:
	 */
	atomic_inc(&start_count);

	check_counter_warp();

	while (atomic_read(&stop_count) != cpus-1)
		cpu_relax();

	/*
	 * If the test was successful set the number of runs to zero and
	 * stop. If not, decrement the number of runs an check if we can
	 * retry. In case of random warps no retry is attempted.
	 */
	if (!nr_warps) {
		atomic_set(&test_runs, 0);

		pr_info("Counter synchronization [CPU#%d -> CPU#%u]: passed\n",
			smp_processor_id(), cpu);
	} else if (atomic_dec_and_test(&test_runs) || random_warps) {
		/* Force it to 0 if random warps brought us here */
		atomic_set(&test_runs, 0);

		pr_info("Counter synchronization [CPU#%d -> CPU#%u]:\n",
			smp_processor_id(), cpu);
		pr_info("Measured %d cycles counter warp between CPUs", max_warp);
		if (random_warps)
			pr_warn("Counter warped randomly between CPUs\n");
	}

	/*
	 * Reset it - just in case we boot another CPU later:
	 */
	atomic_set(&start_count, 0);
	random_warps = 0;
	nr_warps = 0;
	max_warp = 0;
	last_counter = 0;

	/*
	 * Let the target continue with the bootup:
	 */
	atomic_inc(&stop_count);

Annotation

Implementation Notes