Linux RCU and double linked list - c

I'm reading about Read-copy-update (RCU). I'm not sure if I understood it correctly in case of SMP. As far as I know RCU ensures that Update is executed atomically. In case for example single linked list it is obvious that exchanging old element with the new one can be done in one operation, because it is done by changing pointer. But how to ensure that RCU will still be atomically executed in case of doubly-linked list? There are two pointers points to given element (next and prev), so every change on this element needs to change those two pointers.
How to ensure that changing those two pointers will be done as atomic operation?
How it is done in Linux?

I was asking myself the same question, and a quick search brought a reply to a comment, extracted from an introduction article to RCU by Paul McKenney (who, from what I gather, is one of the multiple concurrent inventors of the ideas behind RCU).
The question:
I'm wondering whether the omission of the backlinks in the examples is a
good thing. The omission makes the technique trivial, since publishing
only involves one replacing one pointer.
What about the second, back, one? Without support for atomic two-pointer
updates, how can both the p->prev->next = q and p->next->prev = q updates
be performed without risking clients to see an inconsistent view of the
doubly linked list? Or is that not a problem in practice?
Thanks for the article, though. Looking forward to the next installment!
The answer:
Glad you liked the article, and thank you for the excellent question! I could give any number of answers, including:
In production systems, trivial techniques are a very good thing.
Show me an example where it is useful to traverse the ->prev pointers under RCU protection. Given several such examples, we could work out how best to support this.
Consistency is grossly overrated. (Not everyone agrees with me on this, though!)
Even with atomic two-pointer updates, consider the following sequence of events: (1) task 1 does p=p->next (2) task 2 inserts a new element between the two that task 1 just dealt with (3) task 1 does p=p->prev and fails to end up where it started! Even double-pointer atomic update fails to banish inconsistency! ;-)
If you need consistency, use locks.
Given the example above, we could support a level of consistency equivalent to the double-pointer atomic update simply by assigning the pointers in sequence -- just remove the prev-pointer poisoning from list_del_rcu(), for example. But doing this would sacrifice the ability to catch those bugs that pointer-poisoning currently catches.
So, there might well come a time when the Linux kernel permits RCU-protected traversal of linked lists in both directions, but we need to see a compelling need for this before implementing it.
So basically, Linux "disallows" backwards traversal in both directions when doing RCU. As mentioned in the comment, you could use some newer hardware mechanisms like Double Compare And Swap, but they're not available everywhere, and as mentioned, you can still get memory consistency issues.

Related

dynamically resized array based queues in C - are they used in practice?

I'm working on a self-resizing queue in C using arrays with structs and int pointers.
I wanted to be able to dynamically resize it (double it as needed) using realloc and of course still preserve the priority or "queueness". I'm struggling to do that last part cleanly. I've got it working as a queue of static size, which I know is the most common use of circular buffers, and I can realloc that block. I just can't find the best way to put humpty dumpty back together. I know I can implement a queue easily as a linked list. I just wanted to make a good attempt for learning purposes but I don't see many people asking this particular question.
There was one person who asked about it here with respect to Java, but I don't know that language. So anyway my question is: is there any point or advantage to making queues with arrays if you know you'll have to resize them later? It seems overly complicated and wasteful regarding time and space complexity, so do people always them and just go wtih linked lists or other methods in the field?
Edit: When I say priority above, I'm not referring to priority queues, but general queue FIFO ordering.

Solution for the consumer / producer task

I have been assigned a piece of coursework to implement a solution for the consumer/producer problem that uses a single producer, a single consumer, and a circular buffer. This should be written in C.
Unfortunately, we have been provided with no learning material and are somehow meant to implement this with no help from the lecturer.
the requirement is as follows:
Requirement: You are asked to implement a solution for the consumer/producer problem that uses asingle producer, a single consumer, and a circular bounded buffer (i.e. of a fixed size containing, e.g.,integer values). Both the producer and consumer generate/consume an unlimited number of items(e.g. integers). I.e., they can be executed in an infinite loop, assuming that the code runs indefinitely.You are free to choose how to implement this approach, however, it may be recommended to usesemaphores. A successful implementation has:
A circular buffer of which the size is fixed and configurable (e.g. using a define statement)
Counters that keeps track of the number of items that have been produced/consumed so far(you ignore wrap-arounds of ints/longs)
An identification number for every item produced, e.g. its index in the sequence of produceditems
A simple visualisation that demonstrates how the number of items in the buffer evolves overtime. This can be as simple as printing a number of stars every time an item isproduced/consumed, with each star representing one element currently in the buffer
Correct synchronisation of any critical sections that may be present, and only where it is strictly necessary to do so
If anyone can help me out with how to approach this requirement it would be extremely grateful
While I can't provide you with complete solution (neither should I), it is possible to lead you into a good path towards the solution.
The Consumer / Producer problem is a classic problem that involves synchronization, avoiding "hunger" or deadlocks. It is an important problem in Computer Science, given that the solution is really fundamental to, for instance, Operating Systems.
It is a great thing to a CS Student learn, but it may require some time and attention. There is a lot of great sources to study this problem. Here's some.
Wikipedia https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem
CS MTU https://www.cs.mtu.edu/~shene/NSF-3/e-Book/SEMA/TM-example-buffer.html
Also, there is a great load of videos about it:
https://www.youtube.com/results?search_query=producer+consumer+problem
Remember: these sources are of great use when you try to understand it, but copying code without comprehending what is happening is a very bad habit that will do nothing but waste your time as a student.
Lastly, as bad as your teacher may be, don't be afraid to contact him and ask for help. Showing interest can really motivate an apparently unmotivated teacher.
So go out there, do a thorough research and dedicate a good time to study this problem and when you start to code and problems starts to appear don't be afraid to ask again about this issue. With your better grasp at the question and a piece of code, it is much easier to help you out.
Hope this helps, though. =)

Is it okay to use functions to stay organized in C?

I'm a relatively new C programmer, and I've noticed that many conventions from other higher-level OOP languages don't exactly hold true on C.
Is it okay to use short functions to have your coding stay organized (even though it will likely be called only once)? An example of this would be 10-15 lines in something like void init_file(void), then calling it first in main().
I would have to say, not only is it OK, but it's generally encouraged. Just don't overly fragment the train of thought by creating myriads of tiny functions. Try to ensure that each function performs a single cohesive, well... function, with a clean interface (too many parameters can be a hint that the function is performing work which is not sufficiently separate from it's caller).
Furthermore, well-named functions can serve to replace comments that would otherwise be needed. As well as providing re-use, functions can also (or instead) provide a means to organize the code and break it down into smaller units which can be more readily understood. Using functions in this way is very much like creating packages and classes/modules, though at a more fine-grained level.
Yes. Please. Don't write long functions. Write short ones that do one thing and do it well. The fact that they may only be called once is fine. One benefit is that if you name your function well, you can avoid writing comments that will get out of sync with the code over time.
If I can take the liberty to do some quoting from Code Complete:
(These reason details have been abbreviated and in spots paraphrased, for the full explanation see the complete text.)
Valid Reasons to Create a Routine
Note the reasons overlap and are not intended to be independent of each other.
Reduce complexity - The single most important reason to create a routine is to reduce a program's complexity (hide away details so you don't need to think about them).
Introduce an intermediate, understandable abstraction - Putting a section of code int o a well-named routine is one of the best ways to document its purpose.
Avoid duplicate code - The most popular reason for creating a routine. Saves space and is easier to maintain (only have to check and/or modify one place).
Hide sequences - It's a good idea to hide the order in which events happen to be processed.
Hide pointer operations - Pointer operations tend to be hard to read and error prone. Isolating them into routines shifts focus to the intent of the operation instead of the mechanics of pointer manipulation.
Improve portability - Use routines to isolate nonportable capabilities.
Simplify complicated boolean tests - Putting complicated boolean tests into a function makes the code more readable because the details of the test are out of the way and a descriptive function name summarizes the purpose of the tests.
Improve performance - You can optimize the code in one place instead of several.
To ensure all routines are small? - No. With so many good reasons for putting code into a routine, this one is unnecessary. (This is the one thrown into the list to make sure you are paying attention!)
And one final quote from the text (Chapter 7: High-Quality Routines)
One of the strongest mental blocks to
creating effective routines is a
reluctance to create a simple routine
for a simple purpose. Constructing a
whole routine to contain two or three
lines of code might seem like
overkill, but experience shows how
helpful a good small routine can be.
If a group of statements can be thought of as a thing - then make them a function
i think it is more than OK, I would recommend it! short easy to prove correct functions with well thought out names lead to code which is more self documenting than long complex functions.
Any compiler worth using will be able to inline these calls to generate efficient code if needed.
Functions are absolutely necessary to stay organized. You need to first design the problem, and then depending on the different functionality you need to split them into functions. Some segment of code which is used multiple times, probably needs to be written in a function.
I think first thinking about what problem you have in hand, break down the components and for each component try writing a function. When writing the function see if there are some code segment doing the same thing, then break it into a sub function, or if there is a sub module then it is also a candidate for another function. But at some time this breaking job should stop, and it depends on you. Generally, do not make many too big functions and not many too small functions.
When construction the function please consider the design to have high cohesion and low coupling.
EDIT1::
you might want to also consider separate modules. For example if you need to use a stack or queue for some application. Make it separate modules whose functions could be called from other functions. This way you can save re-coding commonly used modules by programming them as a group of functions stored separately.
Yes
I follow a few guidelines:
DRY (aka DIE)
Keep Cyclomatic Complexity low
Functions should fit in a Terminal window
Each one of these principles at some point will require that a function be broken up, although I suppose #2 could imply that two functions with straight-line code should be combined. It's somewhat more common to do what is called method extraction than actually splitting a function into a top and bottom half, because the usual reason is to extract common code to be called more than once.
#1 is quite useful as a decision aid. It's the same thing as saying, as I do, "never copy code".
#2 gives you a good reason to break up a function even if there is no repeated code. If the decision logic passes a certain complexity threshold, we break it up into more functions that make fewer decisions.
It is indeed a good practice to refactor code into functions, irrespective of the language being used. Even if your code is short, it will make it more readable.
If your function is quite short, you can consider inlining it.
IBM Publib article on inlining

How can I implement cooperative lightweight threading with C on Mac OS X?

I'm trying to find a lightweight cooperative threading solution to try implementing an actor model.
As far as I know, the only solution is setcontext/getcontext,
but the functionality is deprecated(?) by Apple. I'm confused by why they did this; however, I'm finding replacement for this.
Pthreads are not an option because I need cooperative model instead of preemptive model to control context switching timing precisely/manually without expensive locking.
-- edit --
Reason of avoiding pthreads:
Because pthreads are not cooperative/deterministic and too expensive. I need actor model for game logic code, so thousand of execution context are required at minimal. Hardware threading requires MB of memory and expense to create/destruct. And parallelism is not important. In fact, I just need concurrent execution of many functions. This can be implemented with many divided functions and some kind of object model, but my goal is reducing those overheads.
If I know something wrong, please correct me. It'll be very appreciated.
The obvious 'lightweight' solution is to avoid complex nested calling except for limited situations where the execution time will be tightly bounded, then store an explicit state structure for each "thread" and implement the main program logic as a state machine that's easily suspendable/resumable at most points. Then you can simply swap out the pointer to the state structure for 'context switch'. Basically this technique amounts to keeping all of your important state variables, including what would conventionally be local variables, in the state structure.
Whether this is worthwhile probably depends on your reason for avoiding pthreads. If your reason is to be portable to non-POSIX systems, or if you really need deterministic program flow, then it may be worthwhile. But if you're just worried about performance overhead and memory synchronization issues, I think you should use pthreads and manage these issues. If you avoid unnecessary locking, use fine-grained locks, and minimize the amount of time locks are held, performance should not suffer.
Edit: Based on your further details posted in the comments on the main question, I think the solution I've proposed is the right one. Each actor should have their own context in which you store the state of the actor's action/thinking/etc. You would have a run_actor function which would take an actor context and a number of "ticks" to advance the actor's state by, and a run_all_actors function which would iterate over a list of active actors and call run_actor for each with the specified number of ticks.
Further, note that this solution still allows you to use real threads to take advantage of SMP/multicore machines. You simply divide the actors up between threads. You may need some degree of locking if one actor needs to examine another's context (e.g. for collision detection).
I was researching this question as well, and I ran across GNU Pth (not to be confused with Pthreads). See http://www.gnu.org/software/pth/
It aims to be a portable solution for cooperative threads. It does mention it is implemented via setcontext/getcontext if available (so it may not be on Mac OSX). Otherwise it says it uses longjmp/setjmp, but it's not clear to me how that works.
Hope this is helpful to anyone who searches for this question.
I have discovered the some of required functionalities from setcontext/getcontext are implemented in libunwind.
Unfortunately the library won't be compiled on Mac OS X because of deprecation of the setcontext/getcontext. Anyway Apple has implemented their own libunwind which is compatible with GNU's implementation at source level. The library is exist on Mac OS X 10.6, 10.7, and iOS. (I don't know exact version in case of iOS)
This library is not documented, but I could find the headers from these locations.
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/include/libunwind.h
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/usr/include/libunwind.h
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/usr/include/libunwind.h
/Developer/SDKs/MacOSX10.6.sdk/usr/include/libunwind.h
/Developer/SDKs/MacOSX10.7.sdk/usr/include/libunwind.h
There was a note in the header file that to go GNU libunwind site for documentation.
I'll bet on the library.

Link list usage in system programming

in spite of having so many efficient data structures, why is only linked list used
so heavily in systems programming? Is it because it allows least usage of heap/less buggy code?
Regards,
Pwn
Linked List is a very efficient data structure to use for something like a queue or stack where you want to add something at the end or remove it from the beginning. Systems programming deals a lot with queues and stacks.
I'm guessing because it's just extremely simple to implement and understand. And it has an extremely small overhead.
The kernel has access to copious amounts of memory (it's in charge of it, after all) and mainly has to control lists of things (rather than associative structures that connect one thing with another).
So it's just a good match. There is no (or rarely) any need to complicate it further.
Linked lists are quite efficient for many systems-level tasks:
Queues (for scheduling)
Collections where your main operation is to visit every single thing in the collection, e.g., gather information about every active process
Memory blocks (for first-fit allocation)
Collections where you add or remove one element at a time
It's quite rare in systems programming to have a collection where you have to look things up by key, or to have to take the union of two sets. Except of course in filesystems, where you will find that more sophisticated data structures are used.
Is it because it allows least usage of heap/less buggy code?
No. In many cases, a linked list is the most appropriate data structure for the job.
Linked lists provide an easy implementation for several important abstract data structures, including stacks, queues, hash tables, symbolic expressions, and skip lists.
Its partly because efficent datastructures tend to have overheads that are relatively large when dealing with small numbers of entries, and partly because a lot of OS data-structures are FIFOs which linked-lists are good for.
Usually it is because you need a list of stuff - that is, you often pretty much just need something you can add/remove easily at either end or remove/insert at a node pointer you already have and iterate over.
There's plenty of areas where you don't need random access or search capabilities - or the space you need to search is so small that a linked list is anyway faster than more "fancy" data structures.
Sometimes though, it's also because linked lists are easiy to implement.
There's no good answer, because you're making wrong assumptions. It's not true that only linked list is used heavily. It's used when there are many things which need to be traversed in sequence - like free memory segments list, queue-like structures, etc.
There are many places where you need exactly such structure. There are other places where you don't need it.
Linked lists can easily be tied-in with other data-structures, (such as hash-tables for example). Also they can be translated easily to arrays and there are different ways of implementing them, for example one or two way linked list.

Resources