Preemptive multitasking replaced cooperative multitasking. There are two big advantages to it: 1) your code doesn't need to worry about multitasking and 2) bad code or a crashing program can't lock up the entire system (or at least, not quite as easily).
With cooperative multitasking, each program has to play nice (aka cooperate) to allow multitasking to happen. To do this, your code has to tell the operating system when to multitask, so you had to write your loops something like this (pseudo-code):
while running {
do_a_thing();
os.multitask();
}
the call to os.multitask() would tell the operating system to switch to the next task and run it until it makes a call to os.multitask, etc etc, until it gets back to running another iteration of your loop.
This approach has many pitfalls. A couple of big ones:
If I forget to include that call to os.multitask in my loop, the entire system locks up for the duration of my loop.
Another issue is that if one iteration of my loop isn't very expensive then my code might run slower than it could due to unnecessary task swaps. So I don't want to call os.multitask too often.
Preemtive multitasking solves these problems by having the OS kernel take charge of which task is running at any particular moment. Rather than letting one task run until it yields control back to the OS, a preemptive kernel allows one task to run for a (small) amount of time, then the kernel interrupts - pre-empts - it, and switches to let another task run for a little bit of time.
But that doesn't have anything to do with your mouse pointer locking up. An example of how that can happen is that the kernel can still get stuck waiting for some IO or whatever, even if it's preemptive.
HTH :)