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.
This commit is contained in:
cinap_lenrek 2013-03-11 00:48:35 +01:00
parent 530a2bc5e9
commit 48b0c10681
14 changed files with 79 additions and 24 deletions

View file

@ -8,7 +8,7 @@ int _IO_getc(FILE *f){
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 @@ int _IO_getc(FILE *f){
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;

View file

@ -0,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;
}

View file

@ -19,7 +19,8 @@ int _IO_putc(int c, FILE *f){
case CLOSED:
return EOF;
case OPEN:
_IO_setvbuf(f);
if(_IO_setvbuf(f)!=0)
return EOF;
/* fall through */
case RDWR:
case END:

View file

@ -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;

View file

@ -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')

View file

@ -21,7 +21,8 @@ int fflush(FILE *f){
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;

View file

@ -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);
}

View file

@ -12,7 +12,7 @@ size_t fread(void *p, size_t recl, size_t nrec, FILE *f){
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 @@ size_t fread(void *p, size_t recl, size_t nrec, FILE *f){
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{

View file

@ -12,7 +12,7 @@ size_t fwrite(const void *p, size_t recl, size_t nrec, FILE *f){
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 @@ size_t fwrite(const void *p, size_t recl, size_t nrec, FILE *f){
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 @@ size_t fwrite(const void *p, size_t recl, size_t nrec, FILE *f){
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 {

View file

@ -42,3 +42,4 @@ int _IO_setvbuf(FILE *);
FILE *_IO_sopenr(const char*);
FILE *_IO_sopenw(void);
char *_IO_sclose(FILE *);
FILE *_IO_newfile(void);

View file

@ -2,6 +2,7 @@ APE=/sys/src/ape
<$APE/config
LIB=/$objtype/lib/ape/libap.a
OFILES=\
_IO_newfile.$O\
_IO_getc.$O\
_IO_putc.$O\
_dtoa.$O\

View file

@ -12,7 +12,8 @@ char *rdline(FILE *f, char **ep){
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 @@ char *rdline(FILE *f, char **ep){
break;
}
cnt=read(f->fd, f->wp, cnt);
if(f->state==CLOSED)
return NULL;
if(cnt==-1){
f->state=ERR;
return NULL;

View file

@ -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;

View file

@ -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;