This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
mutex in frame code
- To: egcs at cygnus dot com
- Subject: mutex in frame code
- From: Ulrich Drepper <drepper at cygnus dot com>
- Date: 25 Jan 1999 14:44:38 -0800
- Cc: drepper at cygnus dot com
- Reply-To: drepper at cygnus dot com (Ulrich Drepper)
We've recently adding to the frame installation functions in frame.c
code to protect the installation of the frame element to a global list
by an semaphore. E.g., the __register_frame_info is
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
__register_frame_info (void *begin, struct object *ob)
{
ob->fde_begin = begin;
ob->pc_begin = ob->pc_end = 0;
ob->fde_array = 0;
ob->count = 0;
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
ob->next = objects;
objects = ob;
__gthread_mutex_unlock (&object_mutex);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There is a major flaw in this code. It could use the thread functions
before the thread library is initialized. E.g., a simple program
using pthreads could would use the libraries libpthread.so and
libc.so. Due to the dependencies the C library is initialized first.
Part of the initialization is registration of a frame. But now the C
library initialization will use the thread library though it is not
yet initialized.
This so far lead to no problems since in most thread implementations
the mutex functions do not need special initialization but others do.
In fact, I found this problem because the library I'm writing has this
problem.
Looking at the code one can see that the lock is used to insert into a
single-linked list. This can be done safely without locks with an
compare & exchange instruction:
do
{
struct object *last = objects;
ob->next = objects;
}
while (compxchg (ob, last, ob) != 0);
with an appropriate compxchg function. This function would be very
system-specific so Jason proposed to have a __builtin_cmpxchg function
and put the system specific bits into the .md files.
Now there is the problem that not all processors have such an opcode.
This is where the problems start. E.g., the i386 processor has no
such opcode while i486 and up do. I think this is the situation for
some other processor families as well. Using the opcode nevertheless
would mean that there is not anymore full backward compatibility.
I.e., a gcc compiled for i486 will not work on i386 anymore. I don't
think this is a problem personally. We already have similar
restrictions (i686 code cannot be used on earlier processors) and i386
are also not anymore the commonly found platform.
One way to work around not having a compare & exchange opcode is using
spinlocks. This works in most situations so at least one can assume
these processors still be supported. The only situations where this
fails is with threads of different priority (priority inversion).
What I suggest is to add the __builtin_cmpxchg code. It will be using
the asm opcode if allowed and fall back to a spinlock implementations
in the case where there is no such opcode. If compiled without thread
support the opcode even compiles to no code at all.
Comments?
--
---------------. drepper at gnu.org ,-. 1325 Chesapeake Terrace
Ulrich Drepper \ ,-------------------' \ Sunnyvale, CA 94089 USA
Cygnus Solutions `--' drepper at cygnus.com `------------------------