// SPDX-License-Identifier: GPL-2.0
/*
 * A BPF program for testing DSQ operations and peek in particular.
 *
 * Copyright (c) 2025 Meta Platforms, Inc. and affiliates.
 * Copyright (c) 2025 Ryan Newton <ryan.newton@alum.mit.edu>
 */

#include <scx/common.bpf.h>
#include <scx/compat.bpf.h>

char _license[] SEC("license") = "GPL";

UEI_DEFINE(uei); /* Error handling */

#define MAX_SAMPLES 100
#define MAX_CPUS 512
#define DSQ_POOL_SIZE 8
int max_samples = MAX_SAMPLES;
int max_cpus = MAX_CPUS;
int dsq_pool_size = DSQ_POOL_SIZE;

/* Global variables to store test results */
int dsq_peek_result1 = -1;
long dsq_inserted_pid = -1;
int insert_test_cpu = -1; /* Set to the cpu that performs the test */
long dsq_peek_result2 = -1;
long dsq_peek_result2_pid = -1;
long dsq_peek_result2_expected = -1;
int test_dsq_id = 1234; /* Use a simple ID like create_dsq example */
int real_dsq_id = 1235; /* DSQ for normal operation */
int enqueue_count = -1;
int dispatch_count = -1;
bool debug_ksym_exists;

/* DSQ pool for stress testing */
int dsq_pool_base_id = 2000;
int phase1_complete = -1;
long total_peek_attempts = -1;
long successful_peeks = -1;

/* BPF map for sharing peek results with userspace */
struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__uint(max_entries, MAX_SAMPLES);
	__type(key, u32);
	__type(value, long);
} peek_results SEC(".maps");

static int get_random_dsq_id(void)
{
	u64 time = bpf_ktime_get_ns();

	return dsq_pool_base_id + (time % DSQ_POOL_SIZE);
}

static void record_peek_result(long pid)
{
	u32 slot_key;
	long *slot_pid_ptr;
	u32 ix;

	if (pid <= 0)
		return;

	/* Find an empty slot or one with the same PID */
	bpf_for(ix, 0, 10) {
		slot_key = ((u64)pid + ix) % MAX_SAMPLES;
		slot_pid_ptr = bpf_map_lookup_elem(&peek_results, &slot_key);
		if (!slot_pid_ptr)
			continue;

		if (*slot_pid_ptr == -1 || *slot_pid_ptr == pid) {
			*slot_pid_ptr = pid;
			break;
		}
	}
}

/* Scan all DSQs in the pool and try to move a task to local */
static int scan_dsq_pool(void)
{
	struct task_struct *task;
	int moved = 0;
	int i;

	bpf_for(i, 0, DSQ_POOL_SIZE) {
		int dsq_id = dsq_pool_base_id + i;

		total_peek_attempts++;

		task = __COMPAT_scx_bpf_dsq_peek(dsq_id);
		if (task) {
			successful_peeks++;
			record_peek_result(task->pid);

			/* Try to move this task to local */
			if (!moved && scx_bpf_dsq_move_to_local(dsq_id, 0)) {
				moved = 1;
				break;
			}
		}
	}
	return moved;
}

/* Struct_ops scheduler for testing DSQ peek operations */
void BPF_STRUCT_OPS(peek_dsq_enqueue, struct task_struct *p, u64 enq_flags)
{
	struct task_struct *peek_result;
	int last_insert_test_cpu, cpu;

	enqueue_count++;
	cpu = bpf_get_smp_processor_id();
	last_insert_test_cpu = __sync_val_compare_and_swap(&insert_test_cpu, -1, cpu);

	/* Phase 1: Simple insert-then-peek test (only on first task) */
	if (last_insert_test_cpu == -1) {
		bpf_printk("peek_dsq_enqueue beginning phase 1 peek test on cpu %d", cpu);

		/* Test 1: Peek empty DSQ - should return NULL */
		peek_result = __COMPAT_scx_bpf_dsq_peek(test_dsq_id);
		dsq_peek_result1 = (long)peek_result; /* Should be 0 (NULL) */

		/* Test 2: Insert task into test DSQ for testing in dispatch callback */
		dsq_inserted_pid = p->pid;
		scx_bpf_dsq_insert(p, test_dsq_id, 0, enq_flags);
		dsq_peek_result2_expected = (long)p; /* Expected the task we just inserted */
	} else if (!phase1_complete) {
		/* Still in phase 1, use real DSQ */
		scx_bpf_dsq_insert(p, real_dsq_id, 0, enq_flags);
	} else {
		/* Phase 2: Random DSQ insertion for stress testing */
		int random_dsq_id = get_random_dsq_id();

		scx_bpf_dsq_insert(p, random_dsq_id, 0, enq_flags);
	}
}

void BPF_STRUCT_OPS(peek_dsq_dispatch, s32 cpu, struct task_struct *prev)
{
	dispatch_count++;

	/* Phase 1: Complete the simple peek test if we inserted a task but
	 * haven't tested peek yet
	 */
	if (insert_test_cpu == cpu && dsq_peek_result2 == -1) {
		struct task_struct *peek_result;

		bpf_printk("peek_dsq_dispatch completing phase 1 peek test on cpu %d", cpu);

		/* Test 3: Peek DSQ after insert - should return the task we inserted */
		peek_result = __COMPAT_scx_bpf_dsq_peek(test_dsq_id);
		/* Store the PID of the peeked task for comparison */
		dsq_peek_result2 = (long)peek_result;
		dsq_peek_result2_pid = peek_result ? peek_result->pid : -1;

		/* Now consume the task since we've peeked at it */
		scx_bpf_dsq_move_to_local(test_dsq_id, 0);

		/* Mark phase 1 as complete */
		phase1_complete = 1;
		bpf_printk("Phase 1 complete, starting phase 2 stress testing");
	} else if (!phase1_complete) {
		/* Still in phase 1, use real DSQ */
		scx_bpf_dsq_move_to_local(real_dsq_id, 0);
	} else {
		/* Phase 2: Scan all DSQs in the pool and try to move a task */
		if (!scan_dsq_pool()) {
			/* No tasks found in DSQ pool, fall back to real DSQ */
			scx_bpf_dsq_move_to_local(real_dsq_id, 0);
		}
	}
}

s32 BPF_STRUCT_OPS_SLEEPABLE(peek_dsq_init)
{
	s32 err;
	int i;

	/* Always set debug values so we can see which version we're using */
	debug_ksym_exists = bpf_ksym_exists(scx_bpf_dsq_peek) ? 1 : 0;

	/* Initialize state first */
	insert_test_cpu = -1;
	enqueue_count = 0;
	dispatch_count = 0;
	phase1_complete = 0;
	total_peek_attempts = 0;
	successful_peeks = 0;

	/* Create the test and real DSQs */
	err = scx_bpf_create_dsq(test_dsq_id, -1);
	if (err) {
		scx_bpf_error("Failed to create DSQ %d: %d", test_dsq_id, err);
		return err;
	}
	err = scx_bpf_create_dsq(real_dsq_id, -1);
	if (err) {
		scx_bpf_error("Failed to create DSQ %d: %d", real_dsq_id, err);
		return err;
	}

	/* Create the DSQ pool for stress testing */
	bpf_for(i, 0, DSQ_POOL_SIZE) {
		int dsq_id = dsq_pool_base_id + i;

		err = scx_bpf_create_dsq(dsq_id, -1);
		if (err) {
			scx_bpf_error("Failed to create DSQ pool entry %d: %d", dsq_id, err);
			return err;
		}
	}

	/* Initialize the peek results map */
	bpf_for(i, 0, MAX_SAMPLES) {
		u32 key = i;
		long pid = -1;

		bpf_map_update_elem(&peek_results, &key, &pid, BPF_ANY);
	}

	return 0;
}

void BPF_STRUCT_OPS(peek_dsq_exit, struct scx_exit_info *ei)
{
	int i;

	/* Destroy the primary DSQs */
	scx_bpf_destroy_dsq(test_dsq_id);
	scx_bpf_destroy_dsq(real_dsq_id);

	/* Destroy the DSQ pool */
	bpf_for(i, 0, DSQ_POOL_SIZE) {
		int dsq_id = dsq_pool_base_id + i;

		scx_bpf_destroy_dsq(dsq_id);
	}

	UEI_RECORD(uei, ei);
}

SEC(".struct_ops.link")
struct sched_ext_ops peek_dsq_ops = {
	.enqueue = (void *)peek_dsq_enqueue,
	.dispatch = (void *)peek_dsq_dispatch,
	.init = (void *)peek_dsq_init,
	.exit = (void *)peek_dsq_exit,
	.name = "peek_dsq",
};
