about summary refs log tree commit diff
path: root/src/stdio
diff options
context:
space:
mode:
Diffstat (limited to 'src/stdio')
-rw-r--r--src/stdio/__fdopen.c8
-rw-r--r--src/stdio/__lockfile.c26
-rw-r--r--src/stdio/fclose.c2
-rw-r--r--src/stdio/fflush.c10
-rw-r--r--src/stdio/fgetc.c5
-rw-r--r--src/stdio/fgetwc.c1
-rw-r--r--src/stdio/flockfile.c6
-rw-r--r--src/stdio/fputc.c5
-rw-r--r--src/stdio/ftell.c6
-rw-r--r--src/stdio/ftrylockfile.c3
-rw-r--r--src/stdio/funlockfile.c2
-rw-r--r--src/stdio/stderr.c2
-rw-r--r--src/stdio/stdin.c2
-rw-r--r--src/stdio/stdout.c5
14 files changed, 44 insertions, 39 deletions
diff --git a/src/stdio/__fdopen.c b/src/stdio/__fdopen.c
index b13318e5..07f966a5 100644
--- a/src/stdio/__fdopen.c
+++ b/src/stdio/__fdopen.c
@@ -39,11 +39,13 @@ FILE *__fdopen(int fd, const char *mode)
 	f->seek = __stdio_seek;
 	f->close = __stdio_close;
 
+	if (!libc.threaded) f->lock = -1;
+
 	/* Add new FILE to open file list */
 	OFLLOCK();
-	f->next = ofl_head;
-	if (ofl_head) ofl_head->prev = f;
-	ofl_head = f;
+	f->next = libc.ofl_head;
+	if (libc.ofl_head) libc.ofl_head->prev = f;
+	libc.ofl_head = f;
 	OFLUNLOCK();
 
 	return f;
diff --git a/src/stdio/__lockfile.c b/src/stdio/__lockfile.c
index 66a4d26d..6ebf6202 100644
--- a/src/stdio/__lockfile.c
+++ b/src/stdio/__lockfile.c
@@ -1,20 +1,18 @@
 #include "stdio_impl.h"
 #include "pthread_impl.h"
 
-void __lockfile(FILE *f)
+int __lockfile(FILE *f)
 {
-	int spins=10000;
-	int tid;
+	int owner, tid = __pthread_self()->tid;
+	if (f->lock == tid)
+		return 0;
+	while ((owner = a_cas(&f->lock, 0, tid)))
+		__wait(&f->lock, &f->waiters, owner, 1);
+	return f->lockcount = 1;
+}
 
-	if (f->lock < 0) return;
-	tid = __pthread_self()->tid;
-	if (f->lock == tid) {
-		while (f->lockcount == INT_MAX);
-		f->lockcount++;
-		return;
-	}
-	while (a_cas(&f->lock, 0, tid))
-		if (spins) spins--, a_spin();
-		else __syscall(SYS_sched_yield);
-	f->lockcount = 1;
+void __unlockfile(FILE *f)
+{
+	a_store(&f->lock, 0);
+	if (f->waiters) __wake(&f->lock, 1, 1);
 }
diff --git a/src/stdio/fclose.c b/src/stdio/fclose.c
index ee772fbb..373a2c76 100644
--- a/src/stdio/fclose.c
+++ b/src/stdio/fclose.c
@@ -9,7 +9,7 @@ int fclose(FILE *f)
 		OFLLOCK();
 		if (f->prev) f->prev->next = f->next;
 		if (f->next) f->next->prev = f->prev;
-		if (ofl_head == f) ofl_head = f->next;
+		if (libc.ofl_head == f) libc.ofl_head = f->next;
 		OFLUNLOCK();
 	}
 
diff --git a/src/stdio/fflush.c b/src/stdio/fflush.c
index cdbd39bc..4c1647b7 100644
--- a/src/stdio/fflush.c
+++ b/src/stdio/fflush.c
@@ -22,8 +22,8 @@ static int __fflush_unlocked(FILE *f)
 }
 
 /* stdout.c will override this if linked */
-static FILE *const __dummy = 0;
-weak_alias(__dummy, __stdout_to_flush);
+static FILE *const dummy = 0;
+weak_alias(dummy, __stdout_used);
 
 int fflush(FILE *f)
 {
@@ -37,13 +37,13 @@ int fflush(FILE *f)
 		return r;
 	}
 
-	r = __stdout_to_flush ? fflush(__stdout_to_flush) : 0;
+	r = __stdout_used ? fflush(__stdout_used) : 0;
 
 	OFLLOCK();
-	for (f=ofl_head; f; f=next) {
+	for (f=libc.ofl_head; f; f=next) {
 		FLOCK(f);
 		//OFLUNLOCK();
-		r |= __fflush_unlocked(f);
+		if (f->wpos > f->wbase) r |= __fflush_unlocked(f);
 		//OFLLOCK();
 		next = f->next;
 		FUNLOCK(f);
diff --git a/src/stdio/fgetc.c b/src/stdio/fgetc.c
index da638684..4d8aca37 100644
--- a/src/stdio/fgetc.c
+++ b/src/stdio/fgetc.c
@@ -3,9 +3,10 @@
 int fgetc(FILE *f)
 {
 	int c;
-	FLOCK(f);
+	if (f->lock < 0 || !__lockfile(f))
+		return getc_unlocked(f);
 	c = getc_unlocked(f);
-	FUNLOCK(f);
+	__unlockfile(f);
 	return c;
 }
 
diff --git a/src/stdio/fgetwc.c b/src/stdio/fgetwc.c
index 5e420594..6f9f9ec2 100644
--- a/src/stdio/fgetwc.c
+++ b/src/stdio/fgetwc.c
@@ -34,7 +34,6 @@ wint_t __fgetwc_unlocked(FILE *f)
 		if (l == -1) return WEOF;
 	}
 
-	FUNLOCK(f);
 	return wc;
 }
 
diff --git a/src/stdio/flockfile.c b/src/stdio/flockfile.c
index 0d4c92c2..a196c1ef 100644
--- a/src/stdio/flockfile.c
+++ b/src/stdio/flockfile.c
@@ -3,6 +3,8 @@
 
 void flockfile(FILE *f)
 {
-	if (!libc.threaded) pthread_self();
-	__lockfile(f);
+	while (ftrylockfile(f)) {
+		int owner = f->lock;
+		if (owner) __wait(&f->lock, &f->waiters, owner, 1);
+	}
 }
diff --git a/src/stdio/fputc.c b/src/stdio/fputc.c
index 98d0a20a..6a144a54 100644
--- a/src/stdio/fputc.c
+++ b/src/stdio/fputc.c
@@ -2,9 +2,10 @@
 
 int fputc(int c, FILE *f)
 {
-	FLOCK(f);
+	if (f->lock < 0 || !__lockfile(f))
+		return putc_unlocked(c, f);
 	c = putc_unlocked(c, f);
-	FUNLOCK(f);
+	__unlockfile(f);
 	return c;
 }
 
diff --git a/src/stdio/ftell.c b/src/stdio/ftell.c
index aa1f5381..3904a1d8 100644
--- a/src/stdio/ftell.c
+++ b/src/stdio/ftell.c
@@ -3,10 +3,8 @@
 off_t __ftello_unlocked(FILE *f)
 {
 	off_t pos = f->seek(f, 0, SEEK_CUR);
-	if (pos < 0) {
-		FUNLOCK(f);
-		return pos;
-	}
+	if (pos < 0) return pos;
+
 	/* Adjust for data in buffer. */
 	return pos - (f->rend - f->rpos) + (f->wpos - f->wbase);
 }
diff --git a/src/stdio/ftrylockfile.c b/src/stdio/ftrylockfile.c
index 0b0e44aa..725c4c3e 100644
--- a/src/stdio/ftrylockfile.c
+++ b/src/stdio/ftrylockfile.c
@@ -5,11 +5,12 @@ int ftrylockfile(FILE *f)
 {
 	int tid = pthread_self()->tid;
 	if (f->lock == tid) {
-		if (f->lockcount == INT_MAX)
+		if (f->lockcount == LONG_MAX)
 			return -1;
 		f->lockcount++;
 		return 0;
 	}
+	if (f->lock < 0) f->lock = 0;
 	if (f->lock || a_cas(&f->lock, 0, tid))
 		return -1;
 	f->lockcount = 1;
diff --git a/src/stdio/funlockfile.c b/src/stdio/funlockfile.c
index d69f68ee..f8a2a071 100644
--- a/src/stdio/funlockfile.c
+++ b/src/stdio/funlockfile.c
@@ -3,5 +3,5 @@
 
 void funlockfile(FILE *f)
 {
-	FUNLOCK(f);
+	if (!--f->lockcount) __unlockfile(f);
 }
diff --git a/src/stdio/stderr.c b/src/stdio/stderr.c
index 9a70700c..3fd8f81d 100644
--- a/src/stdio/stderr.c
+++ b/src/stdio/stderr.c
@@ -10,5 +10,7 @@ static FILE f = {
 	.write = __stdio_write,
 	.seek = __stdio_seek,
 	.close = __stdio_close,
+	.lock = -1,
 };
 FILE *const stderr = &f;
+FILE *const __stderr_used = &f;
diff --git a/src/stdio/stdin.c b/src/stdio/stdin.c
index 51c99232..476dc708 100644
--- a/src/stdio/stdin.c
+++ b/src/stdio/stdin.c
@@ -9,5 +9,7 @@ static FILE f = {
 	.read = __stdio_read,
 	.seek = __stdio_seek,
 	.close = __stdio_close,
+	.lock = -1,
 };
 FILE *const stdin = &f;
+FILE *const __stdin_used = &f;
diff --git a/src/stdio/stdout.c b/src/stdio/stdout.c
index 552d729e..3855dd0b 100644
--- a/src/stdio/stdout.c
+++ b/src/stdio/stdout.c
@@ -10,8 +10,7 @@ static FILE f = {
 	.write = __stdout_write,
 	.seek = __stdio_seek,
 	.close = __stdio_close,
+	.lock = -1,
 };
 FILE *const stdout = &f;
-
-/* overrides symbol in fflush.c, used for flushing NULL */
-FILE *const __stdout_to_flush = &f;
+FILE *const __stdout_used = &f;