Implementation of lock-free queue Design Based on Sliding Window

Source: Internet
Author: User

Message Queue is the cornerstone of communication on some platforms. The communication between tasks is based on message queues. The processing speed of message queues often affects the performance of the entire system. To avoid multi-task processing of message queues at the same time, A lock is usually required for mutually exclusive access when a task is processing a queue.

1: assume that each module has its own message queue. Any module can send messages to this module, but only this module can process the messages from the message queue, as shown in, a message queue may write multiple tasks at the same time and read one task.

2: in order to avoid the efficiency bottom line caused by lock when processing multiple tasks, we can use the lock-free design to implement queue operations, see the http://www.cnblogs.com/chencheng/p/3527692.html

3: The above design is highly efficient for joining multiple tasks, but the problem is that if the element in the queue is readable, but the element in the header is never ready, the tout task keeps polling and cannot process the elements that are prepared later.

4: In order to improve the task message processing efficiency, A Message Queue Based on the sliding window mechanism can be designed to process outbound operations, avoiding polling.

1) The task processing team Header element. If the team Header element is readable, read the team Header element operation immediately:

2) The task processing team Header element. If the team Header element is not readable but there is a readable message in the queue, set the processing window to the space from the current team end to the team header, extract the readable data from the window in sequence for processing until all data processing in the window is completed:

3) after processing the current window, move the head of the team and construct the next sliding window to process the data.

5: The above design can improve the speed of Message Processing and avoid polling and waiting.

6: postscript, problem locating

  • If you want to perform the modulo operation by yourself, we can find that the values in the occasionally CAS (& (g_que.rear), g_que.rear, g_que.rear % maxlen) & (g_que.rear) addresses are not equal to g_que.rear.

1: gcc-lpthread-g-o freelockqueue. C compiled with the-G Option

2: objdump-s freelockqueue Disassembly

3: CAS (& (g_que.rear), maxlen, 0 );
40079f: B8 D0 07 00 00 mov $0x7d0, % eax
4007a4: BA 00 00 00 mov $0x0, % edX
4007a9: F0 0f B1 15 53 D4 20 lock cmpxchg % edX, 0x20d453 (% rip) #60dc04 <g_que + 0xbb84>

4: CAS (& (g_que.rear), g_que.rear, g_que.rear % maxlen );
40079f: 8B 0d 5f D4 20 00 mov 0x20d45f (% rip), % ECx #60dc04 <g_que + 0xbb84>
4007a5: BA D3 4D 62 10 mov $0x000024dd3, % edX
4007aa: 89 C8 mov % ECx, % eax
4007ac: F7 EA imul % edX
4007ae: C1 fa 07 SAR $0x7, % edX
4007b1: 89 C8 mov % ECx, % eax
4007b3: C1 F8 1f SAR $ 0x1f, % eax
4007b6: 29 C2 sub % eax, % edX
4007b8: 89 D0 mov % edX, % eax
4007ba: 69 C0 D0 07 00 00 imul $0x7d0, % eax, % eax
4007c0: 29 C1 sub % eax, % ECx
4007c2: 89 C8 mov % ECx, % eax
4007c4: 89 C2 mov % eax, % edX
4007c6: 8B 05 38 D4 20 00 mov 0x20d438 (% rip), % eax #60dc04 <g_que + 0xbb84>
4007cc: F0 0f B1 15 30 D4 20 lock cmpxchg % edX, 0x20d430 (% rip) #60dc04 <g_que + 0xbb84>

5: CAS (& (g_que.rear), g_que.rear, g_que.rear % maxlen) parameter calculation from the perspective of Assembly multiple commands, not atomic, atomic operations are comparison and exchange itself, if the value of g_que.rear is moved into the register, thread switching occurs, and another thread modifies the value of g_que.rear, after switching back, & (g_que.rear) the value in the address is different from the value saved in the register.

Conclusion: The atomic operation is only for the operation itself, and careful parameter solving may lead to switching.

  • G_que.readablecnt --; the Assembly command is as follows,

400bd4: 8B 05 32 D0 20 00 mov 0x20d032 (% rip), % eax # 60dc0c <g_que + 0xbb8c>
400bda: 83 E8 01 Sub $0x1, % eax
400bdd: 89 05 29 D0 20 00 mov % eax, 0x20d029 (% rip) # 60dc0c <g_que + 0xbb8c>

1: first get the value in the address to the register, then subtract one from the value in the Register, and finally store the value in the address. You can see that if the value is switched out after the first command is executed, if other threads operate readablecnt and then switch back, the value will go wrong.
2: g_que.readablecnt: the initial value is 1. Run g_que.readablecnt --
3: After the command 1 is executed, it is switched out. At this moment, the value of eax is 1,
4: another thread operates g_que.readablecn + 1 and is switched back.
5: Execute Command 2. The value of eax is 0.
6: Execute Command 3, save 0 back to g_que.readablecn, and finally g_que.readablecn is 0.
7: It is inconsistent with our expected value 1. Therefore, we should use the Fas (& (g_que.readablecnt), 1) atomic operation to ensure consistency.

Reprinted please indicate the original source: http://www.cnblogs.com/chencheng/p/3961263.html

Implementation of lock-free queue Design Based on Sliding Window

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.