Your OS will need a scheduler, a task manager, and code to start multiple cores before you need to worry about spinlocks and multicore.
I started my OS project when the 386 processor was new, and multicore was not a topic. For synchronization with interrupt code, I used cli/sti. When I many years later wanted a multicore OS, I had to replace all cli/sti occurrences with spinlocks (among other things). This was a major problem that required several complete reverts before I had a stable multicore OS.
So, if you plan to eventually support multicore operation, you should try to mark-up or centralize cli/sti code, perhaps even providing an API for it that can be extended to a spinlock. A spinlock requires a variable. Then you might just place cli in the "acquire" call and sti in the "release" for now. Later, when you want multicore operation, you can add real spinlocks. Actually, I support both variants depending on number of active cores.
I think your first task is to implement threads & a scheduler on single core. If you have enough of the basic functionality (memory manager, interrupt handlers, fault handlers), that is.
When you can start threads & schedule them, you need synchronization primitives. I have critical sections and a signal/wait-for-signal API. Signal can be called from IRQs to wake-up threads. The synchronization primitives should be in place early, because you should not write lots of code without thinking of the code being shared by multiple threads, because this is not easily fixed later.