#ifndef _KERNEL_AMD64_SMP_H
#define _KERNEL_AMD64_SMP_H

#include <amd64/gdt.h>
#include <amd64/intr.h>
#include <amd64/tss.h>
#include <aux/compiler.h>
#include <libk/rbtree.h>
#include <libk/std.h>
#include <proc/proc.h>
#include <sync/spin_lock.h>

#define CPUS_MAX 32

struct cpu {
  /* for syscall instruction */
  uintptr_t syscall_user_stack;
  uintptr_t syscall_kernel_stack;
  volatile uint8_t kernel_stack[KSTACK_SIZE] ALIGNED (16);
  volatile uint8_t except_stack[KSTACK_SIZE] ALIGNED (16);
  volatile uint8_t irq_stack[KSTACK_SIZE] ALIGNED (16);
  volatile struct gdt_extended gdt ALIGNED (16);
  volatile struct tss tss;

  uintptr_t lapic_mmio_base;
  uint64_t lapic_ticks;
  uint64_t lapic_id;
  uint32_t id;
  uint32_t acpi_id;

  spin_lock_t lock;

  struct list_node_link* proc_run_q;
  struct proc* proc_current;
  int proc_run_q_count;
};

struct cpu* cpu_make (uint64_t lapic_id, uint64_t acpi_id);
struct cpu* cpu_get (void);
void cpu_request_sched (struct cpu* cpu);
struct cpu* cpu_find_lightest (void);

#define thiscpu (cpu_get ())

#endif // _KERNEL_AMD64_SMP_H
