shithub: riscv

Download patch

ref: 48b0c10681bb4e0785fa9f737d287531d06fecb7
parent: 530a2bc5e99ad83c46ce015544cf30173c145bcc
author: cinap_lenrek <[email protected]>
date: Sun Mar 10 20:48:35 EDT 2013

ape/stdio: make fopen() quasi threadsafe for python

python uses processes sharing memory. it requires at least fopen() to
be called by multiple threads at once so we introduce _IO_newfile()
which allocates the FILE structure slot under a lock.

--- a/sys/src/ape/lib/ap/stdio/_IO_getc.c
+++ b/sys/src/ape/lib/ap/stdio/_IO_getc.c
@@ -8,7 +8,7 @@
 	default:	/* CLOSED, WR, ERR, EOF */
 		return EOF;
 	case OPEN:
-		_IO_setvbuf(f);
+		if(_IO_setvbuf(f)!=0) return EOF;
 	case RDWR:
 	case RD:
 		if(f->flags&STRING) return EOF;
@@ -17,6 +17,7 @@
 		else
 			n = f->bufl;
 		cnt=read(f->fd, f->buf, n);
+		if(f->state==CLOSED) return EOF;
 		switch(cnt){
 		case -1: f->state=ERR; return EOF;
 		case 0: f->state=END; return EOF;
--- /dev/null
+++ b/sys/src/ape/lib/ap/stdio/_IO_newfile.c
@@ -1,0 +1,27 @@
+/*
+ * pANS stdio -- fopen
+ */
+#include "iolib.h"
+
+#define _PLAN9_SOURCE
+#include <lock.h>
+
+FILE *_IO_newfile(void)
+{
+	static FILE *fx=0;
+	static Lock fl;
+	FILE *f;
+	int i;
+
+	lock(&fl);
+	for(i=0; i<FOPEN_MAX; i++){
+		if(fx==0 || ++fx >= &_IO_stream[FOPEN_MAX]) fx=_IO_stream;
+		if(fx->state==CLOSED)
+			break;
+	}
+	f = fx;
+	unlock(&fl);
+	if(f->state!=CLOSED)
+		return NULL;
+	return f;
+}
--- a/sys/src/ape/lib/ap/stdio/_IO_putc.c
+++ b/sys/src/ape/lib/ap/stdio/_IO_putc.c
@@ -19,7 +19,8 @@
 	case CLOSED:
 		return EOF;
 	case OPEN:
-		_IO_setvbuf(f);
+		if(_IO_setvbuf(f)!=0)
+			return EOF;
 		/* fall through */
 	case RDWR:
 	case END:
--- a/sys/src/ape/lib/ap/stdio/fclose.c
+++ b/sys/src/ape/lib/ap/stdio/fclose.c
@@ -3,12 +3,28 @@
  */
 #include "iolib.h"
 int fclose(FILE *f){
-	int error=0;
+	int d, error=0;
+	char *p;
+
 	if(!f) return EOF;
 	if(f->state==CLOSED) return EOF;
 	if(fflush(f)==EOF) error=EOF;
-	if(f->flags&BALLOC) free(f->buf);
-	if(!(f->flags&STRING) && close(f->fd)<0) error=EOF;
+	if(f->flags&BALLOC){
+		if((p = f->buf)!=0){
+			f->buf = 0;
+			f->wp = 0;
+			f->rp = 0;
+			f->lp = 0;
+			free(p);
+		}
+	}
+	if(!(f->flags&STRING)){
+		if((d = f->fd)>=0){
+			f->fd = -1;
+			if(close(d) < 0)
+				error = EOF;
+		}
+	}
 	f->state=CLOSED;
 	f->flags=0;
 	return error;
--- a/sys/src/ape/lib/ap/stdio/fdopen.c
+++ b/sys/src/ape/lib/ap/stdio/fdopen.c
@@ -14,10 +14,8 @@
  */
 FILE *fdopen(const int fd, const char *mode){
 	FILE *f;
-	for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++)
-		if(f->state==CLOSED)
-			break;
-	if(f==&_IO_stream[FOPEN_MAX])
+
+	if((f = _IO_newfile()) == NULL)
 		return NULL;
 	f->fd=fd;
 	if(mode[0]=='a')
--- a/sys/src/ape/lib/ap/stdio/fflush.c
+++ b/sys/src/ape/lib/ap/stdio/fflush.c
@@ -21,7 +21,8 @@
 	case WR:
 		cnt=(f->flags&LINEBUF?f->lp:f->wp)-f->buf;
 		if(cnt && write(f->fd, f->buf, cnt)!=cnt){
-			f->state=ERR;
+			if(f->state!=CLOSED)
+				f->state=ERR;
 			return EOF;
 		}
 		f->rp=f->wp=f->buf;
--- a/sys/src/ape/lib/ap/stdio/fopen.c
+++ b/sys/src/ape/lib/ap/stdio/fopen.c
@@ -2,10 +2,11 @@
  * pANS stdio -- fopen
  */
 #include "iolib.h"
+
 FILE *fopen(const char *name, const char *mode){
 	FILE *f;
-	for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++)
-		if(f->state==CLOSED)
-			return freopen(name, mode, f);
-	return NULL;
+
+	if((f = _IO_newfile()) == NULL)
+		return NULL;
+	return freopen(name, mode, f);
 }
--- a/sys/src/ape/lib/ap/stdio/fread.c
+++ b/sys/src/ape/lib/ap/stdio/fread.c
@@ -12,7 +12,7 @@
 
 	s=(char *)p;
 	n=recl*nrec;
-	while(n>0){
+	while(n>0 && f->state!=CLOSED){
 		d=f->wp-f->rp;
 		if(d>0){
 			if(d>n)
@@ -23,7 +23,8 @@
 			if(f->buf==f->unbuf || (n >= BIGN && f->state==RD && !(f->flags&STRING))){
 				d=read(f->fd, s, n);
 				if(d<=0){
-					f->state=(d==0)?END:ERR;
+					if(f->state!=CLOSED)
+						f->state=(d==0)?END:ERR;
 					goto ret;
 				}
 			}else{
--- a/sys/src/ape/lib/ap/stdio/fwrite.c
+++ b/sys/src/ape/lib/ap/stdio/fwrite.c
@@ -12,7 +12,7 @@
 
 	s=(char *)p;
 	n=recl*nrec;
-	while(n>0){
+	while(n>0 && f->state!=CLOSED){
 		d=f->rp-f->wp;
 		if(d>0){
 			if(d>n)
@@ -26,7 +26,8 @@
 					if(f->flags&APPEND)
 						lseek(f->fd, 0L, SEEK_END);
 					if(write(f->fd, f->buf, d)!=d){
-						f->state=ERR;
+						if(f->state!=CLOSED)
+							f->state=ERR;
 						goto ret;
 					}
 					f->wp=f->rp=f->buf;
@@ -35,7 +36,8 @@
 					lseek(f->fd, 0L, SEEK_END);
 				d=write(f->fd, s, n);
 				if(d<=0){
-					f->state=ERR;
+					if(f->state!=CLOSED)
+						f->state=ERR;
 					goto ret;
 				}
 			} else {
--- a/sys/src/ape/lib/ap/stdio/iolib.h
+++ b/sys/src/ape/lib/ap/stdio/iolib.h
@@ -42,3 +42,4 @@
 FILE *_IO_sopenr(const char*);
 FILE *_IO_sopenw(void);
 char *_IO_sclose(FILE *);
+FILE *_IO_newfile(void);
--- a/sys/src/ape/lib/ap/stdio/mkfile
+++ b/sys/src/ape/lib/ap/stdio/mkfile
@@ -2,6 +2,7 @@
 <$APE/config
 LIB=/$objtype/lib/ape/libap.a
 OFILES=\
+	_IO_newfile.$O\
 	_IO_getc.$O\
 	_IO_putc.$O\
 	_dtoa.$O\
--- a/sys/src/ape/lib/ap/stdio/rdline.c
+++ b/sys/src/ape/lib/ap/stdio/rdline.c
@@ -12,7 +12,8 @@
 	default:	/* CLOSED, WR, ERR, EOF */
 		return NULL;
 	case OPEN:
-		_IO_setvbuf(f);
+		if(_IO_setvbuf(f)!=0)
+			return NULL;
 	case RDWR:
 		f->state=RD;
 	case RD:
@@ -46,6 +47,8 @@
 				break;
 			}
 			cnt=read(f->fd, f->wp, cnt);
+			if(f->state==CLOSED)
+				return NULL;
 			if(cnt==-1){
 				f->state=ERR;
 				return NULL;
--- a/sys/src/ape/lib/ap/stdio/sopenr.c
+++ b/sys/src/ape/lib/ap/stdio/sopenr.c
@@ -6,8 +6,9 @@
 
 FILE *_IO_sopenr(const char *s){
 	FILE *f;
-	for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) if(f->state==CLOSED) break;
-	if(f==&_IO_stream[FOPEN_MAX]) return NULL;
+
+	if((f=_IO_newfile())==NULL)
+		return NULL;
 	f->buf=f->rp=(char *)s;	/* what an annoyance const is */
 	f->bufl=strlen(s);
 	f->wp=f->buf+f->bufl;
--- a/sys/src/ape/lib/ap/stdio/sopenw.c
+++ b/sys/src/ape/lib/ap/stdio/sopenw.c
@@ -5,8 +5,9 @@
 
 FILE *_IO_sopenw(void){
 	FILE *f;
-	for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) if(f->state==CLOSED) break;
-	if(f==&_IO_stream[FOPEN_MAX]) return NULL;
+
+	if((f=_IO_newfile())==NULL)
+		return NULL;
 	f->buf=f->rp=f->wp=0;
 	f->state=OPEN;
 	f->flags=STRING;