On 15/03/2012 06:01, Jens Bauer wrote:
Hi Jon and Ian,
On Wed, 14 Mar 2012 19:54:48 -0700, Ian Lance Taylor wrote:
Jonathan Andrews<jon@xxxxxxxxxxxxxxx> writes:
Would it be possible to add a warning to gcc C when code in an
signal handler (alarm) uses non thread safe calls.
Your request for a warning is reasonable, I just don't see a way
to implement it such that it is useful.
I like that idea. When compiling applications on Apple's Mac OS X,
they have keywords to inform about "deprecated" functions at
compile-time. A similar solution might be possible, providing that
the authors of the libraries and functions being called, mark those
as "thread_safe" or "interrupt_safe". Ofcourse, a compiler might be
able to recursively go through functions and hunt for things that
identifies whether or not a function is thread-safe, a'la the
optimizer, however at present, this might be too complex.
It would, for instance be a bit difficult to see whether a function
that writes to a shared memory location is thread-safe, because
writing to this location *could* be a semaphore or behind a
semaphore.
Note: Remember there's a difference between thread-safe and
interrupt-safe. Whether or not I should mention 'reentry-safe' or
not, I don't know.. Well, hereby done. ;)
Your final paragraph here gives some hints about the size of this idea -
both in its potential usefulness, and in the work required to implement
it. Trying to implement some sort of checking for "signal handler safe"
or "thread safe" or "interrupt safe" functions is a waste of effort. It
would have to be much more general to be effective - then "interrupt
safe" or "signal handler safe" would simply be a specialisation of the
concept.
What you need here is a way of tagging the compilation state with some
sort of attributes, and a way of having functions and other parts of the
code check those attributes for particular features. These features
must be definable in the user code, not just in the compiler, so they
should probably have string names and integer values. So then you'd
have things like this:
__require_tag("gotLock1")
void foo(void) { ... code assuming lock1 is acquired .... }
void bar(void) {
getLock(lock1);
__set_tag("gotLock1");
foo();
__unset_tag("gotLock1");
releaseLock(lock1);
}
Trying to call "foo" from code that has not set the "gotLock1" tag will
give an error or warning.
Once you have this idea, there are all sorts of possibilities. Some of
these include:
Alternative paths in functions depending on the tags (if you have the
"interruptsDisabled" tag on a single-processor system, then you can take
short-cuts when accessing "atomic" data). Or the "foo" function could
be made to acquire and release the lock if needed. This would be
particularly efficient in inline functions.
Functions could affect the tags of their callers - "getLock" could set a
tag on return.
You could use tags to say that "lock1" was always needed before getting
"lock2" - thus spotting ordering errors that could lead to deadlocks.
You could have "unsafe" functions, that may only be called by code that
sets the "unsafe" tag. This could easily be combined with code
development policies, such as requiring extra code reviews for anything
"unsafe".
Code that must be run on a particular cpu in an SMP system could be tagged.
There are lots of uses for embedded systems and odd processors. For
example, on the msp430, gcc disables interrupts whenever it needs to use
the hardware multiplier. With an "interruptsDisabled" tag, it could
generate smaller and faster code in some situations.
The potential for such a tag system is enormous, both for enhancing
warning and error checking, and thus code quality, and for generating
smaller and faster object code. But it would also take a great deal of
effort to come up with a flexible, consistent and workable syntax for
the system.
As for implementation, I think it would be possible to come a long way
by using a pre-preprocessor, as I think it would all be handled in a
single compilation unit at a time. In particular, any tag requirements
for a function or code would be specified in the function declaration,
not the definition.
mvh.,
David