This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
[PATCH]: Thread safe FILE allocation [WAS: Re: [RFC]: Thread safetyin __sfp and atexit]
- From: Thomas Pfaff <thomas dot pfaff at gmx dot net>
- To: Jeff Johnston <jjohnstn at redhat dot com>
- Cc: newlib at sources dot redhat dot com
- Date: Thu, 22 Jan 2004 21:40:51 +0100
- Subject: [PATCH]: Thread safe FILE allocation [WAS: Re: [RFC]: Thread safetyin __sfp and atexit]
- References: <400C46CA.6000605@gmx.net> <400C544F.7050002@redhat.com>
Jeff Johnston wrote:
Thomas Pfaff wrote:
The list operations in __sfp and atexit are not thread safe AFAICS.
This could be avoided by using a mutex or atomic instructions when a
FILE pointer is acquired or an atexit function is added.
The problem hereby is that such a mutex should be created on newlib
initialization (_REENT_INIT on the _impure_ptr for example), but there
might be better locations.
Doing list insert with atomic instructions on the other hand is easy
on i86 (i486 and above) but might be a problem on other platfomrs.
Comments are welcome.
Thomas
You can't assume atomic instructions exist for all platforms. I think
something akin to the ENV_LOCK. MALLOC_LOCK methods used by the getenv
and malloc family routines would be appropriate.
-- Jeff J.
Attached is what i think would be appropriate.
It protects the FILE pointer list by using __LOCK_INIT, __lock_acquire
and __lock_release.
Thomas
2004-01-22 Thomas Pfaff <tpfaff@gmx.net>
* libc/stdio/findfp.c (__sfp): Protect global FILE pointer list
by a lock when newlib is multithreaded.
--- findfp.c.org 2004-01-22 13:52:35.135137600 +0100
+++ findfp.c 2004-01-22 13:53:31.976872000 +0100
@@ -86,6 +86,12 @@ __sfp (d)
int n;
struct _glue *g;
+#ifndef __SINGLE_THREAD__
+ __LOCK_INIT(static, lock);
+
+ __lock_acquire(lock);
+#endif
+
if (!_GLOBAL_REENT->__sdidinit)
__sinit (_GLOBAL_REENT);
for (g = &_GLOBAL_REENT->__sglue;; g = g->_next)
@@ -97,11 +103,17 @@ __sfp (d)
(g->_next = __sfmoreglue (d, NDYNAMIC)) == NULL)
break;
}
+#ifndef __SINGLE_THREAD__
+ __lock_release(lock);
+#endif
d->_errno = ENOMEM;
return NULL;
found:
fp->_flags = 1; /* reserve this slot; caller sets real flags */
+#ifndef __SINGLE_THREAD__
+ __lock_release(lock);
+#endif
fp->_p = NULL; /* no current pointer */
fp->_w = 0; /* nothing to read or write */
fp->_r = 0;