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:
parent
530a2bc5e9
commit
48b0c10681
|
@ -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;
|
||||
|
|
27
sys/src/ape/lib/ap/stdio/_IO_newfile.c
Normal file
27
sys/src/ape/lib/ap/stdio/_IO_newfile.c
Normal 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;
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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\
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue