an io library shouldnt have race conditions
This commit is contained in:
parent
648e03c165
commit
7610f5f448
@ -1,2 +0,0 @@
|
|||||||
libio.o: libio.c libio.h
|
|
||||||
$(CC) -c -o libio.o libio.c
|
|
@ -1,97 +0,0 @@
|
|||||||
#include <unistd.h>
|
|
||||||
#include "libio.h"
|
|
||||||
|
|
||||||
/* Backups of standard library systems for the odd scenario where there is no
|
|
||||||
* standard library but there is the write(2) system call. */
|
|
||||||
|
|
||||||
#if defined USE_SYSTEM_STRING_H
|
|
||||||
# include <string.h>
|
|
||||||
# define _strlen strlen
|
|
||||||
#else
|
|
||||||
/* Normally in <string.h> */
|
|
||||||
static int
|
|
||||||
_strlen(char *s){
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; s[i] != '\0'; ++i);
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined USE_SYSTEM_CTYPE_H
|
|
||||||
# include <ctype.h>
|
|
||||||
# define _isdigit isdigit
|
|
||||||
#else
|
|
||||||
/* Normally in <ctype.h> */
|
|
||||||
static int
|
|
||||||
_isdigit(int c){
|
|
||||||
return c >= '0' && c <= '9';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Wrappers around write(2) */
|
|
||||||
static int _write(int fd, char *s, int n);
|
|
||||||
static int _write1(int fd, int c);
|
|
||||||
|
|
||||||
/* Wrapper around write(2) - keeps re-running write(2) until the operation
|
|
||||||
* succeeds in full. Usually unnecessary but still good. */
|
|
||||||
static int
|
|
||||||
_write(int fd, char *s, int n){
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(
|
|
||||||
i = 0;
|
|
||||||
i < n;
|
|
||||||
i += write(fd, s+i, n-i)
|
|
||||||
);
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For writing a single character. To optimize for speed, functions should
|
|
||||||
* allocate a buffer and add to that buffer before write(2)ing the buffer out
|
|
||||||
* in a single system call. However sometimes cheap tricks are as effective. */
|
|
||||||
static int
|
|
||||||
_write1(int fd, int c){
|
|
||||||
while(write(fd, &c, 1) != 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
fdprint(int fd, char *s){
|
|
||||||
return _write(fd, s, _strlen(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
fdputs(int fd, char *s){
|
|
||||||
int i;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
i = _strlen(s);
|
|
||||||
|
|
||||||
/* RACE CONDITION */
|
|
||||||
/* This leaves s as an invalid string while the write(2) syscall is
|
|
||||||
* performed, which can take a non-trivial amount of time. This
|
|
||||||
* implementation is unsuitable when s is shared between threads or
|
|
||||||
* whatever the CS term for that is. */
|
|
||||||
s[i] = '\n';
|
|
||||||
r = _write(fd, s, i + 1);
|
|
||||||
s[i] = '\0';
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Another possible implementation would take char **s and leave *s at the next
|
|
||||||
* non-digit. But that's less simple; just while(isdigit(*s)) ++s;. */
|
|
||||||
unsigned int
|
|
||||||
parse_uint(char *s){
|
|
||||||
unsigned int r;
|
|
||||||
for(
|
|
||||||
r = 0;
|
|
||||||
_isdigit(*s);
|
|
||||||
r = r * 10 + *s - '0',
|
|
||||||
++s
|
|
||||||
);
|
|
||||||
return r;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
#ifndef _LIBIO_H
|
|
||||||
# define _LIBIO_H
|
|
||||||
int fdprint(int fd, char *s);
|
|
||||||
int fdputd(int fd, int d);
|
|
||||||
int fdputs(int fd, char *s);
|
|
||||||
unsigned int parse_uint(char *s);
|
|
||||||
#endif /* ifndef _LIBIO_H */
|
|
Loading…
Reference in New Issue
Block a user