3 ms·
My experience is to the contrary. Every spin lock I have seen uses more than one pause instruction. Some may start with one and then execute more. They all invo
by eloff 8y ago
My experience is to the contrary. Every spin lock I have seen uses more than one pause instruction. Some may start with one and then execute more. They all involve a loop over pause instruction(s). I don't think that's the problem per se. The problem is more likely the back-off logic.
- cesarb 8y agoAt least the Linux kernel spinlocks do a single pause instruction (which it calls cpu_relax()) before checking again to see whether the lock is free; it's a loop over the pause instruction, but the loop condition checks the lock value. I'd expect most spinlock implementations to do the same.
- eloff 8y agoThey basically all do that. I've seen some with multiple pause instructions in the loop body, and others with a switch or if/else if/else block where it starts off with one pause instruction, then goes to multiple, then moves to more drastic back-off techniques like giving up the thread time slice or micro sleeping.
- acqq 8y ago> I've seen some Then please quote at least one actually used in Linux kernel, including where it is used.
- __s 8y agoThere exist spink locks outside of the Linux kernel
- cesarb 8y agoYes, but the Linux kernel is the one I'm more familiar with. So I looked for another example: glibc's pthread_mutex_lock. The code is at nptl/pthread_mutex_lock.c and the "pause" instruction here is called atomic_spin_nop() (or BUSY_WAIT_NOP on older versions), defined by sysdeps/x86_64/atomic-machine.h. Yet again, it does a single "pause" instruction in the loop, and the loop condition tests the lock.
- senozhatsky 8y agoThe kernel does use PAUSE // f390 objdump -d vmlinux.o | grep -c "f3 90" 245 e.g. 00000000000683a0 <__task_rq_lock>: 683a0: e8 00 00 00 00 callq 683a5 <__task_rq_lock+0x5> 683a5: 55 push %rbp 683a6: 48 89 e5 mov %rsp,%rbp 683a9: 41 56 push %r14 683ab: 49 c7 c6 00 00 00 00 mov $0x0,%r14 683b2: 41 55 push %r13 683b4: 49 89 fd mov %rdi,%r13 683b7: 41 54 push %r12 683b9: 53 push %rbx 683ba: 48 c7 c3 00 00 00 00 mov $0x0,%rbx 683c1: 41 8b 45 3c mov 0x3c(%r13),%eax 683c5: 4d 8b 24 c6 mov (%r14,%rax,8),%r12 683c9: 49 01 dc add %rbx,%r12 683cc: 4c 89 e7 mov %r12,%rdi 683cf: e8 00 00 00 00 callq 683d4 <__task_rq_lock+0x34> 683d4: 41 8b 45 3c mov 0x3c(%r13),%eax 683d8: 49 8b 14 c6 mov (%r14,%rax,8),%rdx 683dc: 48 01 da add %rbx,%rdx 683df: 49 39 d4 cmp %rdx,%r12 683e2: 75 13 jne 683f7 <__task_rq_lock+0x57> 683e4: 41 83 7d 60 02 cmpl $0x2,0x60(%r13) 683e9: 74 0c je 683f7 <__task_rq_lock+0x57> 683eb: 5b pop %rbx 683ec: 4c 89 e0 mov %r12,%rax 683ef: 41 5c pop %r12 683f1: 41 5d pop %r13 683f3: 41 5e pop %r14 683f5: 5d pop %rbp 683f6: c3 retq 683f7: 4c 89 e7 mov %r12,%rdi 683fa: e8 00 00 00 00 callq 683ff <__task_rq_lock+0x5f> 683ff: 41 83 7d 60 02 cmpl $0x2,0x60(%r13) 68404: 75 bb jne 683c1 <__task_rq_lock+0x21> 68406: f3 90 pause 68408: 41 83 7d 60 02 cmpl $0x2,0x60(%r13) 6840d: 75 b2 jne 683c1 <__task_rq_lock+0x21> 6840f: eb f5 jmp 68406 <__task_rq_lock+0x66> 68411: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 68416: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 6841d: 00 00 00 that pause should be: while (unlikely(task_on_rq_migrating(p))) cpu_relax(); -ss
- acqq 8y ago
- eloff 8y agoI didn't say I've seen those in the kernel. I haven't ever looked at the spin lock(s) in the kernel.
- acqq 8y agoAnd your claims are still completely unsupported, at least here in this discussion. You don't give even a single example of some other publicly known code that does what .NET does. And the way you formulated your previous claim appeared to claim that the Linux kernel contains such a kind of code. I'd still appreciate even a single verifiable example of all that "some" that you've apparently "seen".