-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core: Atomic counters #2321
core: Atomic counters #2321
Conversation
int atomic_inc(int *val) | ||
{ | ||
int old_val; | ||
dINT(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be a pair of state=disableIRQ()/restoreIRQ(state)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not check if the msp430 platform was up to date with regards to IRQ functions, since the above atomic_set_return also used eINT/dINT.
I will change this to match the Cortex-M0 implementation.
The 'naive' implementation looks like a good candidate for a generic fallback implementation that could be used whenever an architecture doesn't define an optimized version. Could you do something like, |
@kaspar030 I get the feeling that your suggested |
@gebart Well, I prefer one That way, if any problem shows up, it's also easy to disable any specialized function by commenting out the define... |
a29b0f8
to
809faad
Compare
@kaspar030 I updated the PR according to your suggestions. I also removed copies of the generic Missing is an implementation for x86 ( |
should I remove the API CHANGE label? This PR only adds functions to the core API. |
I just stumbled upon a use case, where you need to increment/decrement a value atomically by a given number (e.g. inc by 3). What is your opinion for including this into the proposed API, say something like int atomic_arch_inc(int *val, int howmuch); ? |
@haukepetersen What is your use case? Maybe we should introduce @Kijewski 's suggestion of Compare And Swap? Then you would write: atomic_cas(&val, val, val+3); My first use case is: Atomic counter as a counting semaphore to introduce inhibiting of low power modes when modules are using hardware devices which need the CPU to stay alive. i.e. a reference count on power modes. In this case we only need up/down counting in steps of 1. |
My use case is a simple usage counter, that keeps track of the number of threads that are being passed a (read-)pointer to a data structure. If a thread is done reading from it, it decrements the counter again (atomically, of course). If I send this pointer to 4 different threads, I have to increment it (atomically) 4 times before sending. This would be best looking with such function... I like @Kijewski 's suggestion, works very well for me. Does it even make sense to just have this one function, as you can do everything we need with it? |
@haukepetersen , @Kijewski , it does make sense to implement I would be leaving |
+1 for implementing But I would really think of slimming the interface down to this one function, for the sake of resource efficiency. This is a kernel function that is normally only used by people who know what they are doing, it's not an everyday interface as e.g. threading or mutexes... |
@haukepetersen Well, if you need more than one line to do atomic_inc, something's wrong with the API. When we're touching this, we should think about introducing special types for atomic values. |
@haukepetersen I liked the |
ok, I guess you convinced me... |
@kaspar030 how do you propose these atomic types would be used? |
simply doing the following will not warn if passed a regular typedef int atomic_int_t; How can I enforce strict type checking in C? Should I change atomic_int_t into a union instead? |
d26d8c0
to
c461171
Compare
Rebased and updated with a generic atomic_cas function for all atomic operations as per @Kijewski 's suggestion. TODO (in a separate PR): Update mutex.c etc to use atomic_int_t and atomic_set/clear instead of old atomic_set_return. |
int atomic_cas(atomic_int_t *var, int old, int now) | ||
{ | ||
unsigned int mask = disableIRQ(); | ||
if (var->val != old) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you need to restore the IRQs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, updated the PR accordingly.
#ifndef _ARM_CPU_H | ||
#define _ARM_CPU_H | ||
#ifndef ARM_CPU_H_ | ||
#define ARM_CPU_H_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%s,#endif // _ARM_CPU_H,#endif /* ARM_CPU_H_ */,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
But for my last comment the PR should be ready to merge. |
759cd6b
to
f8f86d3
Compare
@kaspar030 ACK still holds? OK to squash? |
Yes! |
f8f86d3
to
83c735a
Compare
- Move generic implementation of atomic_set_return to core/atomic.c - Generic implementation of atomic compare and swap in core/atomic.c - atomic_cas is used to implement atomic counters in core/include/atomic.h - atomic_int_t is an atomic integer type - ATOMIC_INIT can be used as an initializer for atomic_int_t - ATOMIC_VALUE gets a reference to the value of an atomic integer
The removed implementation is the same as the generic implementation in core/atomic.c
83c735a
to
f15fc17
Compare
Squashed and rebased, waiting for Travis. |
Travis fell asleep for arm7 build tests. Kicked it. |
ACK and go. |
This PR adds
atomic_inc
andatomic_dec
as discussed in #2302I have created basic implementations for some of the CPUs as an example.