Skip to content

Commit

Permalink
werid bug
Browse files Browse the repository at this point in the history
  • Loading branch information
flaneur2020 committed Feb 28, 2011
1 parent 7ca7924 commit 234a304
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 55 deletions.
3 changes: 1 addition & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,8 @@ end

# ----------------------------------------------------------------------

usr_cfiles = %w{
usr_cfiles = Dir['usr/test_*.c'] + %w{
usr/hello.c
usr/test_fork.c
}
usr_ofiles = usr_cfiles.map{|fn| 'bin/usr/'+File.basename(fn).ext('o') }
usr_efiles = usr_cfiles.map{|fn| 'bin/usr/'+File.basename(fn).ext('') }
Expand Down
7 changes: 5 additions & 2 deletions src/inc/proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ struct proc {
uint p_ruid; /* real uid */
uint p_rgid; /* real gid */
uint p_umask; /* umask for files */
uint p_error; /* return error code */
uint p_sig; /* a bitmap of the recieved signals of current proc */
uint p_sig; /* a bitmap of the recieved signals */
uint p_sigmask; /* a bitmap of the blocked(masked) signals */
uint p_cursig; /* the current signal to be delivered */
char p_ret; /* the exit code */
uint p_error; /* the returned error code from a syscall. */
struct sigaction p_sigact[NSIG]; /* signal handlers */
struct inode *p_wdir; /* current working dir */
struct inode *p_iroot; /* the root dir */
Expand Down
4 changes: 2 additions & 2 deletions src/inc/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ void lldt(uint n);
void ljmp(ushort seg, uint offset);

// kern/exec.c
uint upush(uint *esp, char *buf, int len);
uint upush_argv(uint *esp, char **argv);
int upush(uint *esp, char *buf, int len);
int upush_argv(uint *esp, char **argv);

// mm/vm.c
int vm_clone(struct vm *to);
Expand Down
1 change: 1 addition & 0 deletions src/inc/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ struct sigaction{

#define NSIG 32

/* the list of signals */
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
Expand Down
3 changes: 3 additions & 0 deletions src/inc/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ enum {
NR_getpid,
NR_setuid,
NR_chdir,
NR_exec,
// on fs
NR_access,
NR_chown,
Expand Down Expand Up @@ -107,6 +108,7 @@ int sys_debug (struct trap *);
int sys_getpid (struct trap *);
int sys_open (struct trap *);
int sys_write (struct trap *);
int sys_exec (struct trap *);

static inline _SYS1(int, debug, int);
static inline _SYS1(int, close, int);
Expand All @@ -120,5 +122,6 @@ static inline _SYS0(int, getpid);
static inline _SYS2(int, access, char*, int);
static inline _SYS3(int, write, int, char*, int);
static inline _SYS3(int, open, char*, int, int);
static inline _SYS2(int, exec, char*, char**);

#endif
18 changes: 13 additions & 5 deletions src/kern/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ int do_exec(char *path, char **argv){
esp = VM_STACK;
argv0 = upush(&esp, path, strlen(path)+1);
argc = upush_argv(&esp, argv) + 1;
if (argc<0) {
panic("exec(): bad mem");
}
uargv = upush(&esp, &argv0, sizeof(uint));
upush(&esp, &uargv, sizeof(uint));
upush(&esp, &argc, sizeof(uint));
Expand All @@ -119,9 +122,9 @@ int do_exec(char *path, char **argv){

/* push strings and one array into user stack, returns a count of
* argv. */
uint upush_argv(uint *esp, char **argv){
int upush_argv(uint *esp, char **argv){
uint arglen, argc;
int i;
int i,r;
char *str, **uargv;

if (argv==NULL) {
Expand All @@ -134,7 +137,10 @@ uint upush_argv(uint *esp, char **argv){
argc++;
}
arglen += sizeof(char*) * argc;
vm_verify(*esp-arglen, arglen);
if (vm_verify(*esp-arglen, arglen) < 0){
syserr(EINVAL);
return -1;
}
uargv = *esp - arglen;
for (i=argc-1; i>=0; i--){
str = argv[i];
Expand All @@ -146,9 +152,11 @@ uint upush_argv(uint *esp, char **argv){
}

/* push one string into the user stack. returns the new esp */
uint upush(uint *esp, char *buf, int len){
int upush(uint *esp, char *buf, int len){
uint tmp = *esp; // take care, *esp may overlaps *buf
vm_verify(tmp-=len, len);
if (vm_verify(tmp-=len, len) < 0) {
panic("upush(): bad mem");
}
memcpy(tmp, buf, len);
return (*esp=tmp);
}
Expand Down
18 changes: 14 additions & 4 deletions src/kern/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,21 @@ int do_fork(struct trap *tf){
/* terminate the currenct proccess into ZOMBIE.
* TODO:
* */
int do_exit(int err){
int do_exit(int ret){
struct file *fp;
uint fd;

cu->p_error = err;
struct proc *p;
uint fd, nr;

cu->p_ret = ret;
// make this process Zombie, give all the children to proc[1]
// and tell its parent
cu->p_stat = SZOMB;
for (nr=0; nr<NPROC; nr++) {
if ((p=proc[nr]) && (p->p_ppid==cu->p_pid)) {
p->p_ppid = 1;
sigsend(1, SIGCHLD);
}
}
// close all the opened files, and iput the directories.
for (fd=0; fd<NOFILE; fd++){
fp = cu->p_ofile[fd];
Expand Down
2 changes: 1 addition & 1 deletion src/kern/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void init(){
do_fcntl(0, F_SETFD, 0); // turn off FD_CLOEXEC
do_fcntl(1, F_SETFD, 0);
do_fcntl(2, F_SETFD, 0);
do_exec("/bin/test_fork", argv);
do_exec("/bin/test_exec", NULL);

for(;;);
}
Expand Down
47 changes: 29 additions & 18 deletions src/kern/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,24 @@

/* ----------------------------------------------------- */

/* returns a signal number, or returns 0 on no signal */
int signum(){
/* returns true if the current process has got a signal.
* on delivering the signal, clear the bit in cu->p_sig.
* */
int issig(){
uint n, sig;
struct sigaction sa;

sig = cu->p_sig;
if (sig==0)
if (sig==0)
return 0;
for (n=0; n<32; n++) {
if (sig & (1<<n))
if (sig & (1<<n)) {
cu->p_sig &= ~(1<<n);
if (cu->p_sigact[n].sa_handler == SIG_IGN)
return 0;
cu->p_cursig = n;
return n;
}
}

/* returns true if the current process has got a signal. */
int issig(){
uint n, sig;
struct sigaction sa;

sig = signum();
if (cu->p_sigact[sig].sa_handler != SIG_IGN){
return sig;
}
}
return 0;
}
Expand All @@ -50,8 +47,10 @@ void psig(){
uint n, ufunc, esp;
struct trap *tf;

n = signum();
cu->p_sig &= ~(1<<n);
n = cu->p_cursig;
if (n==0)
return;
cu->p_cursig = 0;
if ((ufunc=cu->p_sigact[n].sa_handler) != SIG_DFL) {
tf = cu->p_trap;
esp = tf->esp;
Expand All @@ -61,13 +60,25 @@ void psig(){
_retsys(cu->p_trap);
return;
}
// on default
// on SIG_DFL
do_exit(1);
}

/* ----------------------------------------------------- */

int sigsend(int pid, int sig){
struct proc *p;

p = proc[pid];
if (p==NULL || sig<0 || sig>=NSIG)
return -1;
if (p->p_sigact[sig].sa_handler != SIG_IGN) {
p->p_sig |= (1<<sig);
if (p->p_stat == SWAIT) {
setrun(p);
}
}
return 0;
}

/* ----------------------------------------------------- */
Expand Down
11 changes: 11 additions & 0 deletions src/kern/sys1.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,20 @@ int sys_fork(struct trap *tf){
}

int sys_exit(struct trap *tf){
int code = (int)tf->ebx;
return do_exit(code);
}

/* exec(char *path, char **argv) */
int sys_exec(struct trap *tf){
int r;
char *path = (char*)tf->ebx;
char **argv = (char**)tf->ecx;

if (vm_verify(path, strlen(path)+1)<0 || vm_verify(argv, 1)<0) {
syserr(EINVAL);
}
return do_exec(path, argv);
}

int sys_brk(struct trap *tf){
Expand Down
1 change: 1 addition & 0 deletions src/kern/sysent.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ static uint sys_routines[NSYSC] = {
[NR_getpid] = &sys_getpid,
[NR_open] = &sys_open,
[NR_write] = &sys_write,
[NR_exec] = &sys_exec,
&nosys,
};

Expand Down
32 changes: 22 additions & 10 deletions src/mm/pte.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct pte* find_pte(uint vaddr, uint creat){
struct pde *pde, *pgd;
struct pte *pt;
struct page *pg;
uint pn;

if (vaddr < KMEM_END) {
panic("find_pte(): don't touch kernel's address space.");
Expand All @@ -59,7 +60,10 @@ struct pte* find_pte(uint vaddr, uint creat){
pde->pd_flag = PTE_P | PTE_U | PTE_W;
pde->pd_off = pg->pg_num;
pt = (struct pte*)(pde->pd_off << 12);
memset(pt, 0, PAGE);
for (pn=0; pn<1024; pn++) {
pt[pn].pt_off = 0;
pt[pn].pt_flag = 0;
}
flmmu();
}
pt = (struct pte*)(pde->pd_off << 12);
Expand Down Expand Up @@ -108,12 +112,14 @@ int pt_copy(struct pde *pgd, uint base, uint size, uint flag){
pgd[pdn].pd_off = PPN(new_pt);
pgd[pdn].pd_flag = PTE_U | PTE_W | PTE_P;
for(pn=0; pn<1024; pn++) {
new_pt[pn].pt_off = old_pt[pn].pt_off;
new_pt[pn].pt_flag = flag;
old_pt[pn].pt_flag = flag; // note: old PTE is also modified.
// increase this page's ref count
pg = pgfind(old_pt[pn].pt_off);
pg->pg_count++;
if (old_pt[pn].pt_flag & PTE_P) {
new_pt[pn].pt_off = old_pt[pn].pt_off;
new_pt[pn].pt_flag = flag;
old_pt[pn].pt_flag = flag; // note: old PTE is also modified.
// increase this page's ref count
pg = pgfind(old_pt[pn].pt_off);
pg->pg_count++;
}
}
}
}
Expand All @@ -127,15 +133,21 @@ int pt_free(struct pde *pgd, uint base, uint size){
struct page *pg;
uint pdn, pn;

if (base<KMEM_END) {
panic("pt_free(): bad memory");
}
//
for (pdn=PPN(base)/1024; pdn<PPN(base+size)/1024; pdn++) {
pde = &pgd[pdn];
if (pde->pd_flag & PTE_P) {
pt = (struct pte*)(pde->pd_off * PAGE);
for(pn=0; pn<1024; pn++) {
pte = &pt[pn];
pte->pt_flag &= ~PTE_P;
pg = pgfind(pte->pt_off);
pgfree(pg); // decrease each page's reference count.
if (pte->pt_flag & PTE_P) {
pte->pt_flag &= ~PTE_P;
pg = pgfind(pte->pt_off);
pgfree(pg); // decrease each page's reference count.
}
}
kfree(pt, PAGE);
}
Expand Down
13 changes: 8 additions & 5 deletions src/mm/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ int vm_clone(struct vm *to){
return 0;
}

/* free all the pages used in this process, deallocate all the
* page tables,
/* free all the pages used in this process, deallocate all the page tables,
* this routine is called on freeing one task in do_exit(), or overlapping
* a proc's address space on do_exec() is being called.
* note: this routine will *NOT* free the pgd.
* */
int vm_clear(struct vm *vm){
Expand All @@ -53,7 +54,7 @@ int vm_clear(struct vm *vm){
for (i=0; i<NVMA; i++) {
vp = &vm->vm_area[i];
if (vp->v_flag != 0) {
pt_free(vm->vm_pgd, vp->v_base, vp->v_size);
pt_free(vm->vm_pgd, PG_ADDR(vp->v_base), vp->v_size);
if (vp->v_ino)
iput(vp->v_ino);
vp->v_ino = NULL;
Expand All @@ -69,17 +70,19 @@ int vm_clear(struct vm *vm){
* pointer, on writing a write protected page, x86 do not raise
* a page fault in ring0, so simulate a write only access as
* what mmu does if nessary.
* note: do not verify kernel memory.
* note: only use this routine before writing, be aware that do
* not touch kernel memory.
* */
int vm_verify(uint vaddr, uint size){
struct pde *pgd;
struct pte *pte;
struct page *pg;
uint page;

if (vaddr<KMEM_END || size<=0) {
if (vaddr<KMEM_END || size<0) {
return -1;
}
// special case on checking string.
for (page=PG_ADDR(vaddr); page<=PG_ADDR(vaddr+size-1); page+=PAGE) {
pte = find_pte(page, 1);
if ((pte->pt_flag & PTE_P)==0) {
Expand Down
1 change: 1 addition & 0 deletions tool/user.ld
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ SECTIONS {
bin/usr/entry.o(.text) *(.text)
*(.rodata .gnu.linkonce.*)
. = ALIGN(0x1000);
__text_end__ = .;
}
.data : {
__data__ = .;
Expand Down
6 changes: 3 additions & 3 deletions usr/hello.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ int strlen(char *str) {

int main(int argc, char **argv) {
int fd;
char str[] = "hello, world\n";
char str[] = "/bin/hello, world\n";

fd = 1;
for (i=0; i<argc;i++) {
write(1, str, sizeof(str));
for (i=0; i<argc; i++) {
write(fd, "\n", 1);
write(fd, argv[i], strlen(argv[i]));
}
Expand Down
Loading

0 comments on commit 234a304

Please sign in to comment.