Yes, if IRQs are disabled, the timer interrupt is disabled and task scheduling no longer occurs. The unsafe part is the “if”: if you’re relying on disabled IRQs, you need to be absolutely sure that all the code you run with IRQs disabled respects that. That can be quite difficult in the kernel since spinlocks disable and enable pre-emption themselves (along with IRQs in some cases), and many pieces of code use locks, including
printk (to ensure that log messages don’t get mixed up). Any time a lock is released, you risk a reschedule (to run code that was waiting on the lock), even if IRQs are disabled:
preempt_enable() explicitly calls
__preempt_schedule() when its counter reaches zero, so no timer interrupt is required.
It’s thus safer to use the proper pre-emption support functions, especially in terms of future-proofing: you might be well aware of the constraints in the code you’re writing now, but someone else changing it won’t (and “someone else” includes “you in six months’ time”).