Running a UMDF driver on dual core systems

I’m debugging my UMDF driver, which operates correctly on single-core systems, and fails, at some occasions, on dual-core systems.
That’s why I assume that it has something to do with synchronizing and mutual-exclusion.
My question is, what kind of precautions should I add to the driver to avoid this?
For instance, I have OnRead and OnCompletion methods. They run on different threads which can run on different cores. They have originated from the same class (CMyReadWriteQueue), so they have common data (the data members in the class). Should I perform mutual exclusion every time I enter one of these functions, so the other won’t change the data at the same time? Or would it do unnecessary performance reduction?
Are there any mutual-exclusion, data protection and synchronizing mechanisms already built-in in the driver which I can rely on, or should I assume nothing and add them myself?
If so, what are the most appropriate for a UMDF driver? Are SDK mechanisms such as ::EnterCriticalSection(&CRITICAL_SECTION) enough?
What other precautions should be taken when running drivers on dual-core systems (that if not taken, can run perfectly on single-core but fail on dual core)?

If I understand your problem correctly, one option is to use AcquireLock and ReleaseLock (IWdfObject interfaces) on the device or queue in the OnCompletion callback. If you are using Device Level locking, anyway (you do this at OnDeviceAdd callback using IWdfDeviceInitialize::SetLockingConstraint).

You can also uses synchronization events, mutexes, or critical sections- since the device lock is there, it’s at least an option. For that matter, you may be able to get by with interlocked operations and no thread blocking mechanisms-knowing which to select is dependent upon the details of your situation.

Performance impact analysis needs similar level of detail to give any reasonable answer. But from what you’ve said, you definitely are in need of some sort of synchronization (not just dual cores- hyperthreaded single-core and multiprocessor machines will also exhibit these problems if you don’t synchronize, and single-threaded single processor machines usually show them eventually [but it can take a while, and usually requires stress testing]).