Question regarding SOCKOPS_WRAP macros
Apologies if this has been asked before. I performed a search and didn't see this question asked before.
In kernels 2.3.15 through 2.6.32 (according to LXR), there were macros designed to wrap socket driver callback functions. SOCKOPS_WRAPPED and SOCKOPS_WRAP would automatically wrap socket driver functions in the big kernel lock, preventing race conditions at the expense of concurrency.
As a part of cleanup work to get rid of the big kernel lock, these macros were removed in kernel 2.6.33, and the lock itself was removed in kernel 2.6.39. I already know how to code drivers to not need these mechanisms (sock_lock(), private mutexes, etc.) I am also aware of the fact that in 2.6.32, most drivers had already migrated away from the SOCKOPS_WRAP macros anyway. This is not my question.
As a part of my job, I'm working on updating third-party software designed for use with the 2.6.27 kernel. It has drivers that use the SOCKOPS_WRAPPED macros. As a part of the update process (to 2.6.34 and to be compatible with future kernels) I've removed these macros and added proper locking mechanisms to the code.
As a part of understanding this code, however, a question arose. On non-SMP kernels, the SOCKOPS_WRAPPED macros have empty definitions. So a wrapped driver compiled for a non-SMP kernel has no locking.
This seems like it should be fine for the 2.4-series of kernels, where kernel threads are not preemptable. I don't understand how this can work on a 2.6 kernel, where kernel threads are preemptable. It seems to me that the same race conditions that occur on SMP systems should also be possible (although less likely) on non-SMP systems, as a result of kernel thread preemption.
If these NULL-implementation macros were insufficient to prevent race conditions, then I assume the kernel developers would have discovered and fixed the bug long ago, and probably before the release of 2.6. I just don't understand why.
Is there some other mechanism taking place that I don't know about? Does the socket framework disable time-slicing when executing driver code? Are there other locks being taken that are sufficient? Is there a guarantee that all socket threads run at the same priority (and therefore, I think, can't preempt each other.)? Or is it something else that I haven't thought of yet?