简体   繁体   中英

Concurrent modification of linked list in C

I've wrote a C application to stress test a DNS server(running on VM), I'm trying to get maximum DNS request rate(throughput) to see how it will behave.
My application runs two threads, sending thread which generates DNS requests(with different query names) and sends them on socket to the server and a receiving thread which receives the DNS responses on the same socket and calculates response time.

Now here comes the use of concurrent linked list(I've implemented), sending thread appends query name and send time(to the end of the list) for each sent request. The receiving thread runs each time from the start, looks for the query name with the relevant send time, calculates response time and removes the object from the list, also every object it traverses it checks whether the send time is within the DNS timeout window I set and if it is not I treat this request as unanswered and remove it from the list.

Now the problem is that I have to lock each time the whole traversing of the list in receiving thread which contains nodes removal as well, it impacts heavily the sending thread which stops sending, waiting a lot of time on the lock to append.

Is there a different way you would suggest to implement the locking in my case? Or maybe is there something more major I can change?

PS: I've tried to use unix dig in a script and implement the same in python scapy but couldn't reach the rates I'm reaching in C app(sending without locking was up to 10 Mbit), this is why I chose to implement this in C.

Thank you!

You probably don't need to lock the whole list while the receiving thread scans it. The sending thread will only ever modify the current last node (to append a new node), and it does not need to examine any other node as long as it maintains a pointer to the current tail. For its part, the receiving thread can then remove any node other than the current tail without any impact on the sending thread. Therefore only the tail node needs to be locked.

It may be a bit trickier to maintain a moving lock on the current tail, because you need to know which node that is, but I don't think it would be too hard. For instance, you might provide a shared atomic pointer to the tail, which the sender updates before sending each request and the receiver reads upon receiving a response. The receiver does not need to consider any subsequent requests (for they had not yet been sent when the current response was received).

The receiver may occasionally need to wait for the sender to append at least one request, so that the erstwhile tail can be removed, but I would expect that to be rare. Otherwise, I don't see how your list can now be getting so long that holding the whole thing locked while scanning it is too time-consuming.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM