DragonFly submit List (threaded) for 2005-05
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
[
Date Index][
Thread Index]
[PATCH] libc FILE locking
Please test attached patch, I want to make sure it does not break
anything.
David Xu
Index: include/stdio.h
===================================================================
RCS file: /cvs/src/include/stdio.h,v
retrieving revision 1.6
diff -u -u -r1.6 stdio.h
--- include/stdio.h 31 Jan 2005 22:28:58 -0000 1.6
+++ include/stdio.h 7 May 2005 05:43:43 -0000
@@ -118,7 +118,7 @@
/* separate buffer for long sequences of ungetc() */
struct __sbuf _ub; /* ungetc buffer */
- unsigned char *_up; /* saved _p when _p is doing ungetc data */
+ struct __sFILEX *_extra;
int _ur; /* saved _r when _r is counting ungetc data */
/* tricks to meet minimum requirements even when malloc() fails */
Index: lib/libc/gen/_pthread_stubs.c
===================================================================
RCS file: /cvs/src/lib/libc/gen/_pthread_stubs.c,v
retrieving revision 1.3
diff -u -u -r1.3 _pthread_stubs.c
--- lib/libc/gen/_pthread_stubs.c 26 Apr 2005 10:05:08 -0000 1.3
+++ lib/libc/gen/_pthread_stubs.c 7 May 2005 05:44:00 -0000
@@ -44,6 +44,12 @@
int _pthread_once_stub(pthread_once_t *, void (*)(void));
int _pthread_setspecific_stub(pthread_key_t, const void *);
+/* define a null pthread structure just to satisfy _pthread_self */
+struct pthread {
+};
+
+static struct pthread main_thread;
+
/*
* Weak symbols: All libc internal usage of these functions should
* use the weak symbol versions (_pthread_XXX). If libpthread is
@@ -66,6 +72,7 @@
__weak_reference(_pthread_mutexattr_settype_stub,_pthread_mutexattr_settype);
__weak_reference(_pthread_once_stub,_pthread_once);
__weak_reference(_pthread_setspecific_stub,_pthread_setspecific);
+__weak_reference(_pthread_self_stub,_pthread_self);
void *
_pthread_getspecific_stub(pthread_key_t key __unused)
@@ -143,6 +150,11 @@
return (0);
}
+struct pthread *
+_pthread_self_stub(void)
+{
+ return (&main_thread);
+}
int
_pthread_setspecific_stub(pthread_key_t key __unused,
const void *value __unused)
Index: lib/libc/stdio/_flock_stub.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/_flock_stub.c,v
retrieving revision 1.6
diff -u -u -r1.6 _flock_stub.c
--- lib/libc/stdio/_flock_stub.c 2 Feb 2005 04:57:15 -0000 1.6
+++ lib/libc/stdio/_flock_stub.c 7 May 2005 05:44:08 -0000
@@ -34,7 +34,12 @@
*
*/
+#include "namespace.h"
#include <stdio.h>
+#include <pthread.h>
+#include "un-namespace.h"
+
+#include "local.h"
/* Don't build this in libc_r, just libc: */
/*
@@ -55,11 +60,34 @@
void funlockfile(FILE *);
/*
+ * We need to retain binary compatibility for a while. So pretend
+ * that _lock is part of FILE * even though it is dereferenced off
+ * _extra now. When we stop encoding the size of FILE into binaries
+ * this can be changed in stdio.h. This will reduce the amount of
+ * code that has to change in the future (just remove this comment
+ * and #define).
+ */
+#define _lock _extra
+
+/*
* This function is a stub for the _flockfile function in libpthread.
*/
void
_flockfile_stub(FILE *fp)
{
+ pthread_t curthread = _pthread_self();
+
+ if (fp->_lock->fl_owner == curthread)
+ fp->_lock->fl_count++;
+ else {
+ /*
+ * Make sure this mutex is treated as a private
+ * internal mutex:
+ */
+ _pthread_mutex_lock(&fp->_lock->fl_mutex);
+ fp->_lock->fl_owner = curthread;
+ fp->_lock->fl_count = 1;
+ }
}
/*
@@ -68,6 +96,7 @@
void
_flockfile_debug_stub(FILE *fp, char *fname, int lineno)
{
+ _flockfile(fp);
}
/*
@@ -76,7 +105,22 @@
int
_ftrylockfile_stub(FILE *fp)
{
- return(0);
+ pthread_t curthread = _pthread_self();
+ int ret = 0;
+
+ if (fp->_lock->fl_owner == curthread)
+ fp->_lock->fl_count++;
+ /*
+ * Make sure this mutex is treated as a private
+ * internal mutex:
+ */
+ else if (_pthread_mutex_trylock(&fp->_lock->fl_mutex) == 0) {
+ fp->_lock->fl_owner = curthread;
+ fp->_lock->fl_count = 1;
+ }
+ else
+ ret = -1;
+ return (ret);
}
/*
@@ -85,4 +129,31 @@
void
_funlockfile_stub(FILE *fp)
{
+ pthread_t curthread = _pthread_self();
+
+ /*
+ * Check if this file is owned by the current thread:
+ */
+ if (fp->_lock->fl_owner == curthread) {
+ /*
+ * Check if this thread has locked the FILE
+ * more than once:
+ */
+ if (fp->_lock->fl_count > 1)
+ /*
+ * Decrement the count of the number of
+ * times the running thread has locked this
+ * file:
+ */
+ fp->_lock->fl_count--;
+ else {
+ /*
+ * The running thread will release the
+ * lock now:
+ */
+ fp->_lock->fl_count = 0;
+ fp->_lock->fl_owner = NULL;
+ _pthread_mutex_unlock(&fp->_lock->fl_mutex);
+ }
+ }
}
Index: lib/libc/stdio/asprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/asprintf.c,v
retrieving revision 1.4
diff -u -u -r1.4 asprintf.c
--- lib/libc/stdio/asprintf.c 7 Jun 2004 17:59:42 -0000 1.4
+++ lib/libc/stdio/asprintf.c 7 May 2005 05:44:12 -0000
@@ -35,12 +35,15 @@
#include <errno.h>
#include <stdarg.h>
+#include "local.h"
+
int
asprintf(char **str, char const *fmt, ...)
{
int ret;
va_list ap;
FILE f;
+ struct __sFILEX ext;
f._file = -1;
f._flags = __SWR | __SSTR | __SALC;
@@ -51,8 +54,10 @@
return (-1);
}
f._bf._size = f._w = 127; /* Leave room for the NUL */
+ f._extra = &ext;
+ INITEXTRA(&f);
va_start(ap, fmt);
- ret = vfprintf(&f, fmt, ap);
+ ret = __vfprintf(&f, fmt, ap); /* Use unlocked __vfprintf */
va_end(ap);
if (ret < 0) {
free(f._bf._base);
Index: lib/libc/stdio/findfp.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/findfp.c,v
retrieving revision 1.6
diff -u -u -r1.6 findfp.c
--- lib/libc/stdio/findfp.c 31 Jan 2005 22:29:40 -0000 1.6
+++ lib/libc/stdio/findfp.c 7 May 2005 05:44:12 -0000
@@ -56,13 +56,18 @@
#define NDYNAMIC 10 /* add ten more whenever necessary */
#define std(flags, file) \
- {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite}
+ {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
+ {0}, __sFX + file}
/* p r w flags file _bf z cookie close read seek write */
+/* _ub _extra */
/* the usual - (stdin + stdout + stderr) */
static FILE usual[FOPEN_MAX - 3];
+static struct __sFILEX usual_extra[FOPEN_MAX - 3];
static struct glue uglue = { NULL, FOPEN_MAX - 3, usual };
+static struct __sFILEX __sFX[3];
+
FILE __sF[3] = {
std(__SRD, STDIN_FILENO), /* stdin */
std(__SWR, STDOUT_FILENO), /* stdout */
@@ -103,18 +108,26 @@
moreglue(int n)
{
struct glue *g;
- FILE *p;
static FILE empty;
+ static struct __sFILEX emptyx;
+ FILE *p;
+ struct __sFILEX *fx;
- g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE));
+ g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE) +
+ n * sizeof(struct __sFILEX));
if (g == NULL)
return (NULL);
p = (FILE *)ALIGN(g + 1);
+ fx = (struct __sFILEX *)&p[n];
g->next = NULL;
g->niobs = n;
g->iobs = p;
- while (--n >= 0)
- *p++ = empty;
+ while (--n >= 0) {
+ *p = empty;
+ p->_extra = fx;
+ *p->_extra = emptyx;
+ p++, fx++;
+ }
return (g);
}
@@ -214,7 +227,17 @@
void
__sinit(void)
{
- /* make sure we clean up on exit */
- __cleanup = _cleanup; /* conservative */
- __sdidinit = 1;
+ int i;
+
+ THREAD_LOCK();
+ if (__sdidinit == 0) {
+ /* Set _extra for the usual suspects. */
+ for (i = 0; i < FOPEN_MAX - 3; i++)
+ usual[i]._extra = &usual_extra[i];
+
+ /* Make sure we clean up on exit. */
+ __cleanup = _cleanup; /* conservative */
+ __sdidinit = 1;
+ }
+ THREAD_UNLOCK();
}
Index: lib/libc/stdio/fseek.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/fseek.c,v
retrieving revision 1.6
diff -u -u -r1.6 fseek.c
--- lib/libc/stdio/fseek.c 31 Jan 2005 22:29:40 -0000 1.6
+++ lib/libc/stdio/fseek.c 7 May 2005 05:44:13 -0000
@@ -195,7 +195,7 @@
*/
if (HASUB(fp)) {
curoff += fp->_r; /* kill off ungetc */
- n = fp->_up - fp->_bf._base;
+ n = fp->_extra->_up - fp->_bf._base;
curoff -= n;
n += fp->_ur;
} else {
Index: lib/libc/stdio/local.h
===================================================================
RCS file: /cvs/src/lib/libc/stdio/local.h,v
retrieving revision 1.5
diff -u -u -r1.5 local.h
--- lib/libc/stdio/local.h 31 Jan 2005 22:29:40 -0000 1.5
+++ lib/libc/stdio/local.h 7 May 2005 05:44:13 -0000
@@ -40,6 +40,7 @@
*/
#include <sys/types.h> /* for off_t */
+#include <pthread.h>
#ifndef _MACHINE_STDINT_H_
#include <machine/stdint.h> /* __size_t */
@@ -65,9 +66,18 @@
extern int _fwalk (int (*)(FILE *));
extern int __swsetup (FILE *);
extern int __sflags (const char *, int *);
+extern int __vfprintf(FILE *, const char *, __va_list);
extern int __sdidinit;
+/* hold a buncha junk that would grow the ABI */
+struct __sFILEX {
+ unsigned char *_up; /* saved _p when _p is doing ungetc data */
+ pthread_mutex_t fl_mutex; /* used for MT-safety */
+ pthread_t fl_owner; /* current owner */
+ int fl_count; /* recursive lock count */
+};
+
/*
* Return true iff the given FILE cannot be written now.
*/
@@ -94,3 +104,11 @@
free((char *)(fp)->_lb._base); \
(fp)->_lb._base = NULL; \
}
+
+#define INITEXTRA(fp) { \
+ (fp)->_extra->_up = NULL; \
+ (fp)->_extra->fl_mutex = PTHREAD_MUTEX_INITIALIZER; \
+ (fp)->_extra->fl_owner = NULL; \
+ (fp)->_extra->fl_count = 0; \
+}
+
Index: lib/libc/stdio/refill.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/refill.c,v
retrieving revision 1.6
diff -u -u -r1.6 refill.c
--- lib/libc/stdio/refill.c 31 Jan 2005 22:29:40 -0000 1.6
+++ lib/libc/stdio/refill.c 7 May 2005 05:44:14 -0000
@@ -99,7 +99,7 @@
if (HASUB(fp)) {
FREEUB(fp);
if ((fp->_r = fp->_ur) != 0) {
- fp->_p = fp->_up;
+ fp->_p = fp->_extra->_up;
return (0);
}
}
Index: lib/libc/stdio/snprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/snprintf.c,v
retrieving revision 1.3
diff -u -u -r1.3 snprintf.c
--- lib/libc/stdio/snprintf.c 7 Jun 2004 20:35:41 -0000 1.3
+++ lib/libc/stdio/snprintf.c 7 May 2005 05:44:14 -0000
@@ -42,6 +42,8 @@
#include <stdio.h>
#include <stdarg.h>
+#include "local.h"
+
int
snprintf(char *str, size_t n, char const *fmt, ...)
{
@@ -49,6 +51,7 @@
int ret;
va_list ap;
FILE f;
+ struct __sFILEX ext;
on = n;
if (n != 0)
@@ -60,7 +63,9 @@
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = n;
- ret = vfprintf(&f, fmt, ap);
+ f._extra = &ext;
+ INITEXTRA(&f);
+ ret = __vfprintf(&f, fmt, ap); /* Use unlocked __vfprintf */
if (on > 0)
*f._p = '\0';
va_end(ap);
Index: lib/libc/stdio/sprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/sprintf.c,v
retrieving revision 1.3
diff -u -u -r1.3 sprintf.c
--- lib/libc/stdio/sprintf.c 7 Jun 2004 20:35:41 -0000 1.3
+++ lib/libc/stdio/sprintf.c 7 May 2005 05:44:14 -0000
@@ -49,13 +49,16 @@
int ret;
va_list ap;
FILE f;
+ struct __sFILEX ext;
f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = INT_MAX;
+ f._extra = &ext;
+ INITEXTRA(&f);
va_start(ap, fmt);
- ret = vfprintf(&f, fmt, ap);
+ ret = __vfprintf(&f, fmt, ap); /* Use unlocked __vfprintf */
va_end(ap);
*f._p = 0;
return (ret);
Index: lib/libc/stdio/sscanf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/sscanf.c,v
retrieving revision 1.4
diff -u -u -r1.4 sscanf.c
--- lib/libc/stdio/sscanf.c 7 Jun 2004 20:35:41 -0000 1.4
+++ lib/libc/stdio/sscanf.c 7 May 2005 05:44:14 -0000
@@ -59,6 +59,7 @@
int ret;
va_list ap;
FILE f;
+ struct __sFILEX ext;
f._file = -1;
f._flags = __SRD;
@@ -67,6 +68,8 @@
f._read = eofread;
f._ub._base = NULL;
f._lb._base = NULL;
+ f._extra = &ext;
+ INITEXTRA(&f);
va_start(ap, fmt);
ret = __svfscanf(&f, fmt, ap);
va_end(ap);
Index: lib/libc/stdio/ungetc.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/ungetc.c,v
retrieving revision 1.4
diff -u -u -r1.4 ungetc.c
--- lib/libc/stdio/ungetc.c 31 Jan 2005 22:29:40 -0000 1.4
+++ lib/libc/stdio/ungetc.c 7 May 2005 05:44:18 -0000
@@ -163,7 +163,7 @@
* Initially, we will use the `reserve' buffer.
*/
fp->_ur = fp->_r;
- fp->_up = fp->_p;
+ fp->_extra->_up = fp->_p;
fp->_ub._base = fp->_ubuf;
fp->_ub._size = sizeof(fp->_ubuf);
fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
Index: lib/libc/stdio/vasprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/vasprintf.c,v
retrieving revision 1.4
diff -u -u -r1.4 vasprintf.c
--- lib/libc/stdio/vasprintf.c 31 Jan 2005 22:29:40 -0000 1.4
+++ lib/libc/stdio/vasprintf.c 7 May 2005 05:44:18 -0000
@@ -41,6 +41,7 @@
{
int ret;
FILE f;
+ struct __sFILEX ext;
f._file = -1;
f._flags = __SWR | __SSTR | __SALC;
@@ -51,6 +52,8 @@
return (-1);
}
f._bf._size = f._w = 127; /* Leave room for the NULL */
+ f._extra = &ext;
+ INITEXTRA(&f);
ret = __vfprintf(&f, fmt, ap);
*f._p = '\0';
f._bf._base = reallocf(f._bf._base, f._bf._size + 1);
Index: lib/libc/stdio/vfprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/vfprintf.c,v
retrieving revision 1.8
diff -u -u -r1.8 vfprintf.c
--- lib/libc/stdio/vfprintf.c 21 Apr 2005 16:36:35 -0000 1.8
+++ lib/libc/stdio/vfprintf.c 7 May 2005 05:44:29 -0000
@@ -158,6 +158,7 @@
fake._file = fp->_file;
fake._cookie = fp->_cookie;
fake._write = fp->_write;
+ fake._extra = fp->_extra;
/* set up the buffer */
fake._bf._base = fake._p = buf;
Index: lib/libc/stdio/vsnprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/vsnprintf.c,v
retrieving revision 1.4
diff -u -u -r1.4 vsnprintf.c
--- lib/libc/stdio/vsnprintf.c 31 Jan 2005 22:29:40 -0000 1.4
+++ lib/libc/stdio/vsnprintf.c 7 May 2005 05:44:29 -0000
@@ -50,6 +50,7 @@
int ret;
char dummy;
FILE f;
+ struct __sFILEX ext;
on = n;
if (n != 0)
@@ -65,6 +66,8 @@
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = n;
+ f._extra = &ext;
+ INITEXTRA(&f);
ret = __vfprintf(&f, fmt, ap);
if (on > 0)
*f._p = '\0';
Index: lib/libc/stdio/vsprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/vsprintf.c,v
retrieving revision 1.4
diff -u -u -r1.4 vsprintf.c
--- lib/libc/stdio/vsprintf.c 31 Jan 2005 22:29:40 -0000 1.4
+++ lib/libc/stdio/vsprintf.c 7 May 2005 05:44:31 -0000
@@ -48,11 +48,14 @@
{
int ret;
FILE f;
+ struct __sFILEX ext;
f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = INT_MAX;
+ f._extra = &ext;
+ INITEXTRA(&f);
ret = __vfprintf(&f, fmt, ap);
*f._p = 0;
return (ret);
Index: lib/libc/stdio/vsscanf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/vsscanf.c,v
retrieving revision 1.5
diff -u -u -r1.5 vsscanf.c
--- lib/libc/stdio/vsscanf.c 7 Jun 2004 20:35:41 -0000 1.5
+++ lib/libc/stdio/vsscanf.c 7 May 2005 05:44:31 -0000
@@ -41,6 +41,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#include "local.h"
static int
eofread (void *, char *, int);
@@ -57,6 +58,7 @@
vsscanf(const char *str, const char *fmt, va_list ap)
{
FILE f;
+ struct __sFILEX ext;
f._file = -1;
f._flags = __SRD;
@@ -65,5 +67,7 @@
f._read = eofread;
f._ub._base = NULL;
f._lb._base = NULL;
+ f._extra = &ext;
+ INITEXTRA(&f);
return (__svfscanf(&f, fmt, ap));
}
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
[
Date Index][
Thread Index]