user-level malloc (untested)

nit in sbrk
indirect block
fix dup to share fd struct
This commit is contained in:
kaashoek 2006-08-24 02:44:41 +00:00
parent 8b58e81077
commit ea2909b6b5
10 changed files with 210 additions and 52 deletions

View file

@ -57,7 +57,7 @@ kernel : $(OBJS) bootother.S init
vectors.S : vectors.pl vectors.S : vectors.pl
perl vectors.pl > vectors.S perl vectors.pl > vectors.S
ULIB = ulib.o usys.o printf.o ULIB = ulib.o usys.o printf.o umalloc.o
user1 : user1.o $(ULIB) user1 : user1.o $(ULIB)
$(LD) -N -e main -Ttext 0 -o user1 user1.o $(ULIB) $(LD) -N -e main -Ttext 0 -o user1 user1.o $(ULIB)

2
defs.h
View file

@ -16,7 +16,7 @@ struct jmpbuf;
void setupsegs(struct proc *); void setupsegs(struct proc *);
struct proc * copyproc(struct proc*); struct proc * copyproc(struct proc*);
struct spinlock; struct spinlock;
int growproc(int); char *growproc(int);
void sleep(void *, struct spinlock *); void sleep(void *, struct spinlock *);
void wakeup(void *); void wakeup(void *);
void scheduler(void); void scheduler(void);

86
fs.c
View file

@ -231,24 +231,46 @@ uint
bmap(struct inode *ip, uint bn) bmap(struct inode *ip, uint bn)
{ {
unsigned x; unsigned x;
uint *a;
struct buf *inbp;
if(bn >= NDIRECT) if(bn >= MAXFILE)
panic("bmap 1"); panic("bmap 1");
x = ip->addrs[bn]; if (bn < NDIRECT) {
if(x == 0) x = ip->addrs[bn];
panic("bmap 2"); if (x == 0)
panic("bmap 2");
} else {
cprintf("indirect block read\n");
inbp = bread(ip->dev, INDIRECT);
a = (uint *) inbp->data;
x = a[bn - NDIRECT];
brelse(inbp);
if (x == 0)
panic("bmap 3");
}
return x; return x;
} }
void void
iunlink(struct inode *ip) iunlink(struct inode *ip)
{ {
int i; int i, j;
// free inode, its blocks, and remove dir entry // free inode, its blocks, and remove dir entry
for (i = 0; i < NDIRECT; i++) { for (i = 0; i < NADDRS; i++) {
if (ip->addrs[i] != 0) { if (ip->addrs[i] != 0) {
bfree(ip->dev, ip->addrs[i]); if (i == INDIRECT) {
for (j = 0; j < NINDIRECT; j++) {
uint *a = (uint *) (ip->addrs[i]);
if (a[j] != 0) {
bfree(ip->dev, a[j]);
a[j] = 0;
}
}
}
else
bfree(ip->dev, ip->addrs[i]);
ip->addrs[i] = 0; ip->addrs[i] = 0;
} }
} }
@ -332,6 +354,40 @@ readi(struct inode *ip, char *dst, uint off, uint n)
return target - n; return target - n;
} }
int
newblock(struct inode *ip, uint lbn)
{
struct buf *inbp;
uint *inaddrs;
uint b;
if (lbn < NDIRECT) {
if (ip->addrs[lbn] == 0) {
b = balloc(ip->dev);
if (b <= 0) return -1;
ip->addrs[lbn] = b;
}
} else {
cprintf("newblock: use indirect block\n");
if (ip->addrs[INDIRECT] == 0) {
cprintf("newblock: allocate indirect block\n");
b = balloc(ip->dev);
if (b <= 0) return -1;
ip->addrs[INDIRECT] = b;
}
inbp = bread(ip->dev, bmap(ip, INDIRECT));
inaddrs = (uint *) inbp->data;
if (inaddrs[lbn - NDIRECT] == 0) {
b = balloc(ip->dev);
if (b <= 0) return -1;
inaddrs[lbn - NDIRECT] = b;
bwrite(inbp, INDIRECT);
}
brelse(inbp);
}
return 0;
}
int int
writei(struct inode *ip, char *addr, uint off, uint n) writei(struct inode *ip, char *addr, uint off, uint n)
{ {
@ -339,24 +395,22 @@ writei(struct inode *ip, char *addr, uint off, uint n)
if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_write) if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_write)
return -1; return -1;
return devsw[ip->major].d_write (ip->minor, addr, n); return devsw[ip->major].d_write (ip->minor, addr, n);
} else if (ip->type == T_FILE || ip->type == T_DIR) { // XXX dir here too? } else if (ip->type == T_FILE || ip->type == T_DIR) {
struct buf *bp; struct buf *bp;
int r = 0; int r = 0;
int m; int m;
int lbn; int lbn;
uint b;
while (r < n) { while (r < n) {
lbn = off / BSIZE; lbn = off / BSIZE;
if (lbn >= NDIRECT) return r; if (lbn >= MAXFILE) return r;
if (ip->addrs[lbn] == 0) { if (newblock(ip, lbn) < 0) {
b = balloc(ip->dev); cprintf("newblock failed\n");
if (b <= 0) return r; return r;
ip->addrs[lbn] = b;
} }
m = min(BSIZE - off % BSIZE, n-r); m = min(BSIZE - off % BSIZE, n-r);
bp = bread(ip->dev, bmap(ip, off / BSIZE)); bp = bread(ip->dev, bmap(ip, lbn));
memmove (bp->data + off % BSIZE, addr, m); memmove (bp->data + off % BSIZE, addr, m);
bwrite (bp, bmap(ip, off/BSIZE)); bwrite (bp, bmap(ip, lbn));
brelse (bp); brelse (bp);
r += m; r += m;
off += m; off += m;

8
fs.h
View file

@ -9,7 +9,11 @@ struct superblock{
uint ninodes; uint ninodes;
}; };
#define NDIRECT 13 #define NADDRS NDIRECT+1
#define NDIRECT 12
#define INDIRECT 12
#define NINDIRECT (BSIZE / sizeof(uint))
#define MAXFILE (NDIRECT + NINDIRECT)
struct dinode { struct dinode {
short type; short type;
@ -17,7 +21,7 @@ struct dinode {
short minor; short minor;
short nlink; short nlink;
uint size; uint size;
uint addrs[NDIRECT]; uint addrs[NADDRS];
}; };
#define T_DIR 1 #define T_DIR 1

32
mkfs.c
View file

@ -106,6 +106,7 @@ main(int argc, char *argv[])
for(i = 2; i < argc; i++){ for(i = 2; i < argc; i++){
assert(index(argv[i], '/') == 0); assert(index(argv[i], '/') == 0);
if((fd = open(argv[i], 0)) < 0){ if((fd = open(argv[i], 0)) < 0){
perror(argv[i]); perror(argv[i]);
exit(1); exit(1);
@ -234,21 +235,40 @@ iappend(uint inum, void *xp, int n)
uint fbn, off, n1; uint fbn, off, n1;
struct dinode din; struct dinode din;
char buf[512]; char buf[512];
uint indirect[NINDIRECT];
uint x;
rinode(inum, &din); rinode(inum, &din);
off = xint(din.size); off = xint(din.size);
while(n > 0){ while(n > 0){
fbn = off / 512; fbn = off / 512;
assert(fbn < NDIRECT); assert(fbn < MAXFILE);
if(din.addrs[fbn] == 0) { if (fbn < NDIRECT) {
din.addrs[fbn] = xint(freeblock++); if(xint(din.addrs[fbn]) == 0) {
usedblocks++; din.addrs[fbn] = xint(freeblock++);
usedblocks++;
}
x = xint(din.addrs[fbn]);
} else {
if(xint(din.addrs[INDIRECT]) == 0) {
printf("allocate indirect block\n");
din.addrs[INDIRECT] = xint(freeblock++);
usedblocks++;
}
printf("read indirect block\n");
rsect(xint(din.addrs[INDIRECT]), (char *) indirect);
if (indirect[fbn - NDIRECT] == 0) {
indirect[fbn - NDIRECT] = xint(freeblock++);
usedblocks++;
wsect(INDIRECT, (char *) indirect);
}
x = xint(indirect[fbn-NDIRECT]);
} }
n1 = min(n, (fbn + 1) * 512 - off); n1 = min(n, (fbn + 1) * 512 - off);
rsect(xint(din.addrs[fbn]), buf); rsect(x, buf);
bcopy(p, buf + off - (fbn * 512), n1); bcopy(p, buf + off - (fbn * 512), n1);
wsect(xint(din.addrs[fbn]), buf); wsect(x, buf);
n -= n1; n -= n1;
off += n1; off += n1;
p += n1; p += n1;

9
proc.c
View file

@ -138,22 +138,23 @@ copyproc(struct proc* p)
return np; return np;
} }
int char *
growproc(int n) growproc(int n)
{ {
struct proc *cp = curproc[cpu()]; struct proc *cp = curproc[cpu()];
char *newmem, *oldmem; char *newmem, *oldmem;
newmem = kalloc(cp->sz + n); newmem = kalloc(cp->sz + n);
if(newmem == 0) return -1; if(newmem == 0) return (char *) -1;
memmove(newmem, cp->mem, cp->sz); memmove(newmem, cp->mem, cp->sz);
memset(newmem + cp->sz, 0, n); memset(newmem + cp->sz, 0, n);
oldmem = cp->mem; oldmem = cp->mem;
cp->mem = newmem; cp->mem = newmem;
kfree(oldmem, cp->sz); kfree(oldmem, cp->sz);
cp->sz += n; cp->sz += n;
cprintf("growproc: added %d bytes\n", n); cprintf("growproc: added %d bytes starting at address 0x%x\n", n,
return 0; newmem + cp->sz - n);
return newmem + cp->sz - n;
} }
// Per-CPU process scheduler. // Per-CPU process scheduler.

View file

@ -404,7 +404,6 @@ sys_dup(void)
{ {
struct proc *cp = curproc[cpu()]; struct proc *cp = curproc[cpu()];
uint fd, ufd1; uint fd, ufd1;
struct fd *fd1;
if(fetcharg(0, &fd) < 0) if(fetcharg(0, &fd) < 0)
return -1; return -1;
@ -414,25 +413,11 @@ sys_dup(void)
return -1; return -1;
if (cp->fds[fd]->type != FD_PIPE && cp->fds[fd]->type != FD_FILE) if (cp->fds[fd]->type != FD_PIPE && cp->fds[fd]->type != FD_FILE)
return -1; return -1;
if ((fd1 = fd_alloc()) == 0) {
return -1;
}
if ((ufd1 = fd_ualloc()) < 0) { if ((ufd1 = fd_ualloc()) < 0) {
fd_close(fd1);
return -1; return -1;
} }
cp->fds[ufd1] = fd1; cp->fds[ufd1] = cp->fds[fd];
fd1->type = cp->fds[fd]->type; fd_incref(cp->fds[ufd1]);
fd1->readable = cp->fds[fd]->readable;
fd1->writeable = cp->fds[fd]->writeable;
if (cp->fds[fd]->type == FD_FILE) {
fd1->ip = cp->fds[fd]->ip;
iincref(fd1->ip);
} else if (cp->fds[fd]->type == FD_PIPE) {
fd1->pipe = cp->fds[fd]->pipe;
}
fd1->off = cp->fds[fd]->off;
return ufd1; return ufd1;
} }
@ -462,14 +447,15 @@ sys_getpid(void)
int int
sys_sbrk(void) sys_sbrk(void)
{ {
int r, n; char *r;
int n;
struct proc *cp = curproc[cpu()]; struct proc *cp = curproc[cpu()];
if(fetcharg(0, &n) < 0) if(fetcharg(0, &n) < 0)
return -1; return -1;
r = growproc(n); r = growproc(n);
setupsegs(cp); setupsegs(cp);
return r; return (int) r;
} }
int int

90
umalloc.c Normal file
View file

@ -0,0 +1,90 @@
#include "types.h"
#include "stat.h"
#include "user.h"
#include "param.h"
// Memory allocator by Kernighan and Ritchie, The C programming Language,
// 2nd ed. Section 8.7.
typedef long Align;
union header {
struct {
union header *ptr;
uint size;
} s;
Align x;
};
typedef union header Header;
static Header base;
static Header *freep = 0;
void
free(void *ap)
{
Header *bp, *p;
bp = (Header *) ap - 1;
for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
break;
if (bp + bp->s.size == p->s.ptr) {
bp->s.size += p->s.ptr->s.size;
bp->s.ptr = p->s.ptr->s.ptr;
} else
bp->s.ptr = p->s.ptr;
if (p + p->s.size == bp) {
p->s.size += bp->s.size;
p->s.ptr = bp->s.ptr;
} else
p->s.ptr = bp;
freep = p;
}
static Header *
morecore(uint nu)
{
char *cp;
Header *up;
if (nu < PAGE)
nu = PAGE;
cp = sbrk(nu * sizeof(Header));
if (cp == (char *) -1)
return 0;
up = (Header *) cp;
up->s.size = nu;
free((void *)(up + 1));
return freep;
}
void *
malloc(uint nbytes)
{
Header *p, *prevp;
uint nunits;
nunits = (nbytes + sizeof(Header) - 1)/sizeof(Header) + 1;
if ((prevp = freep) == 0) {
base.s.ptr = freep = prevp = &base;
base.s.size = 0;
}
for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr) {
if (p->s.size >= nunits) {
if (p->s.size == nunits)
prevp->s.ptr = p->s.ptr;
else {
p->s.size -= nunits;
p += p->s.size;
p->s.size = nunits;
}
freep = prevp;
return (void *) (p + 1);
}
if (p == freep)
if ((p = morecore(nunits)) == 0)
return 0;
}
}

3
user.h
View file

@ -19,6 +19,7 @@ int mkdir(char *);
int chdir(char *); int chdir(char *);
int dup(int); int dup(int);
int getpid(); int getpid();
char *sbrk(int);
int stat(char *, struct stat *stat); int stat(char *, struct stat *stat);
int puts(char*); int puts(char*);
@ -29,3 +30,5 @@ void printf(int fd, char *fmt, ...);
char *gets(char *, int max); char *gets(char *, int max);
unsigned int strlen(char *); unsigned int strlen(char *);
void * memset(void *dst, int c, unsigned int n); void * memset(void *dst, int c, unsigned int n);
void *mallic(uint);
void free(void *);

View file

@ -21,7 +21,7 @@ main(void)
printf(stdout, "userfs is running\n"); printf(stdout, "userfs is running\n");
if (sbrk(4096) < 0) { if (sbrk(4096) < 0) {
printf(stdout, "sbrk failed\n"); printf(stdout, "sbrk failed\n");
} }
fd = open("echo", 0); fd = open("echo", 0);
@ -46,10 +46,10 @@ main(void)
} }
for (i = 0; i < 100; i++) { for (i = 0; i < 100; i++) {
if (write (fd, "aaaaaaaaaa", 10) != 10) { if (write (fd, "aaaaaaaaaa", 10) != 10) {
printf(stdout, "error: write new file failed\n"); printf(stdout, "error: write aa %d new file failed\n", i);
} }
if (write (fd, "bbbbbbbbbb", 10) != 10) { if (write (fd, "bbbbbbbbbb", 10) != 10) {
printf(stdout, "error: write new file failed\n"); printf(stdout, "error: write bb %d new file failed\n", i);
} }
} }
printf(stdout, "writes done\n"); printf(stdout, "writes done\n");