Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 Oct 2001 07:41:37 -0500 (EST)
From:      Daniel Eischen <eischen@vigrid.com>
To:        Lamont Granquist <lamont@scriptkiddie.org>
Cc:        freebsd-hackers@FreeBSD.ORG
Subject:   Re: MT-Safe wrapper around memcpy()?
Message-ID:  <Pine.SUN.3.91.1011029072107.26899A-100000@pcnet1.pcnet.com>
In-Reply-To: <20011029040255.D27876-100000@coredump.scriptkiddie.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 29 Oct 2001, Lamont Granquist wrote:
> On Mon, 29 Oct 2001, Alfred Perlstein wrote:
> > * Alfred Perlstein <bright@mu.org> [011029 00:53] wrote:
> > > * Lamont Granquist <lamont@scriptkiddie.org> [011029 00:43] wrote:
> > > >
> > > > I'm trying to figure out the best way to write a wrapper around memcpy()
> > > > which can call fprintf() without winding up getting into a recursive
> > > > loop.  The problem is that fprintf() will call memcpy() and around and
> > > > around we go.
> > > >
> > > > I can use a global variable to prevent this, but that usage isn't thread
> > > > safe.  I can make it thread safe by using pthread keys, but then i have to
> > > > link in libc_r, and for non-pthreaded programs i don't want to do that.
> > > >
> > > > Anyone have any suggestions?  Right now I'm almost thinking that I just
> > > > need to directly patch libc and libc_r.  It might be an ugly patch though,
> > > > and I'd rather not have this patch mandate recompiling all of libc.
> > >
> > > Where do you see mem* calling printf?
> >
> > Uh, nevermind. :)
> >
> > Ok, what you want to do is use a nested flag in memcpy so you
> > don't recurse, there's some code in libc that's conditionally
> > compiled when compiling libc_r, _THREAD_SAFE or something is
> > defined, once you find that then just simply use the global
> > for non threaded programs and keys for threaded ones.
> 
> you mean like localtime.c:
> 
> #ifdef _THREAD_SAFE
>         pthread_mutex_lock(&lcl_mutex);
> #endif
> 
> and such?

The _THREAD_SAFE macro has gone away anyways (in -current), and we 
(FreeBSD) shouldn't be conditionally compiling code in libc dependent
on whether libc_r is being built or not.  And I wouldn't recommend it
for user libraries either.

Take a look at how libgcc works (src/contrib/gcc.295/gthr-posix.h).

In your application library, make wrapper functions for whatever
thread routines you need to use in a threaded application.  Then
make weak _references_ to the actual (non-wrapped) pthread
routines.  So you'd have something like:

	/* File mylib_threads.c */
	#pragma weak pthread_mutex_lock
	#pragma weak pthread_mutex_unlock
	#pragma weak pthread_key_create
	#pragma weak pthread_key_delete
	#pragma weak pthread_once
	[add any others you might need]
	#pragma weak pthread_create

	static void app_is_threaded = &pthread_create;

	int mylib_is_threaded(void)
	{
		return (app_is_threaded != NULL);
	}

	int mylib_pthread_mutex_lock(pthread_mutex_t *mutex)
	{
		if (mylib_is_threaded())
			return (pthread_mutex_lock(mutex);
		else
			return (0);
	}

	...

By making the references to pthread_* weak, the linker will not
barf if libc_r isn't linked in, and all references will be NULL.
If the application is threaded (libc_r is linked in), then those
references will be resolved.

Make sure the weak pragmas are localized to the file that actually
implements the wrapper functions.  You don't want them visible to
other files that directly use pthreads.

-- 
Dan Eischen

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.SUN.3.91.1011029072107.26899A-100000>