// Exit the current process. Does not return. // An exited process remains in the zombie state // until its parent calls wait() to find out it exited. void exit(void) { struct proc *p; int fd; if(proc == initproc) panic("init exiting"); // Close all open files. for(fd = 0; fd < NOFILE; fd++) { if(proc->ofile[fd]) { fileclose(proc->ofile[fd]); proc->ofile[fd] = 0; } } begin_op(); iput(proc->cwd); end_op(); proc->cwd = 0; acquire(&ptable.lock); // Parent might be sleeping in wait(). wakeup1(proc->parent); for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { if(p->parent == proc && p->is_thread == 1) { p->killed = 1; if(p->state == SLEEPING) { p->state = RUNNABLE; } } } for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { if(p->parent == proc) { if (p->state == ZOMBIE) { p->killed = 1; } join(p->pid); } } for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { if(p->parent == proc) { p->parent = initproc; if(p->state == ZOMBIE) wakeup1(initproc); } } // Jump into the scheduler, never to return. proc->state = ZOMBIE; sched(); panic("zombie exit"); }
// Close file f. (Decrement ref count, close when reaches 0.) void fileclose(struct file *f) { struct file ff; acquire(&ftable.lock); if(f->ref < 1) panic("fileclose"); if(--f->ref > 0){ release(&ftable.lock); return; } ff = *f; f->ref = 0; f->type = FD_NONE; release(&ftable.lock); if(ff.type == FD_PIPE) pipeclose(ff.pipe, ff.writable); else if(ff.type == FD_INODE){ begin_op(); iput(ff.ip); end_op(); } }
// Exit the current process. Does not return. // An exited process remains in the zombie state // until its parent calls wait() to find out it exited. void exit(void) { struct proc *p; int fd; if(proc == initproc) panic("init exiting"); // Close all open files. for(fd = 0; fd < NOFILE; fd++){ if(proc->ofile[fd]){ fileclose(proc->ofile[fd]); proc->ofile[fd] = 0; } } #ifndef SELECTION_NONE #ifdef VERBOSE_PRINT_TRUE char* state; if(proc->state >= 0 && proc->state < NELEM(states) && states[proc->state]) state = states[proc->state]; else state = "???"; print_proc_data(proc, state); cprintf("\n"); #endif free_proc_pgmd(proc,1); //remove swap file and pages metadata #endif begin_op(); iput(proc->cwd); end_op(); proc->cwd = 0; acquire(&ptable.lock); // Parent might be sleeping in wait(). wakeup1(proc->parent); // Pass abandoned children to init. for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent == proc){ p->parent = initproc; if(p->state == ZOMBIE) wakeup1(initproc); } } // Jump into the scheduler, never to return. proc->state = ZOMBIE; sched(); panic("zombie exit"); }
// Exit the current process. Does not return. // An exited process remains in the zombie state // until its parent calls wait() to find out it exited. void exit(void) { struct proc *p; int fd; if(proc == initproc) panic("init exiting"); // Close all open files. for(fd = 0; fd < NOFILE; fd++){ if(proc->ofile[fd] && proc->thread == 0){ fileclose(proc->ofile[fd]); proc->ofile[fd] = 0; } } begin_op(); iput(proc->cwd); end_op(); proc->cwd = 0; acquire(&ptable.lock); // Parent might be sleeping in wait(). wakeup1(proc->parent); // Pass abandoned children to init. for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->thread == 1 && p->parent == proc){ p->killed = 1; if(p->state == SLEEPING) // Wake process from sleep if necessary p->state = RUNNABLE; release(&ptable.lock); join(p->pid); acquire(&ptable.lock); p->parent = initproc; if(p->state == ZOMBIE) wakeup1(initproc); } else if(p->parent == proc){ p->parent = initproc; if(p->state == ZOMBIE) wakeup1(initproc); } } // Jump into the scheduler, never to return. proc->state = ZOMBIE; sched(); panic("zombie exit"); }
static int load_proc(char *path, struct proc *p) { int i; struct proc np; //an inode describes a single unnamed file struct inode *ip; begin_op(); if ((ip = namei(path)) == 0) { end_op(); return -1; } ilock(ip); if((np.pgdir = setupkvm()) == 0) return -1; if((np.sz = allocuvm(np.pgdir, 0, p->sz)) == 0) return -1; for(i = 0; i < p->sz; i+=PGSIZE) { if(loaduvm(np.pgdir, (void *)i, ip, sizeof(struct proc) + i,PGSIZE) < 0) return -1; } iunlockput(ip); end_op(); ip = 0; np.tf->eax = proc->pid; np.tf->eip = p->tf->eip; np.tf->esp = p->tf->esp; np.tf->ebp = p->tf->ebp; proc->pgdir = np.pgdir; proc->sz = PGROUNDUP(np.sz); *proc->tf = *np.tf; switchuvm(proc); return 0; }
//PAGEBREAK! // Write to file f. int filewrite(struct file *f, char *addr, int n) { int r; if(f->writable == 0) { return -9; } if(f->type == FD_PIPE) { return pipewrite(f->pipe, addr, n); } if(f->type == FD_INODE) { // write a few blocks at a time to avoid exceeding // the maximum log transaction size, including // i-node, indirect block, allocation blocks, // and 2 blocks of slop for non-aligned writes. // this really belongs lower down, since writei() // might be writing a device like the console. int max = ((LOGSIZE - 1 - 1 - 2) / 2) * 512; int i = 0; while(i < n) { int n1 = n - i; if(n1 > max) { n1 = max; } begin_op(); ilock(f->ip); if ((r = writei(f->ip, addr + i, f->off, n1)) > 0) { f->off += r; } iunlock(f->ip); end_op(); if(r < 0) { break; } if(r != n1) { panic("short filewrite"); } i += r; } return i == n ? n : -11; } panic("filewrite"); }
// Exit the current process. Does not return. // An exited process remains in the zombie state // until its parent calls wait() to find out it exited. void exit(void) { struct proc *p; int fd; cprintf("Exiting process. System free pages is %d, replacement count is %d\n",kfreepagecount(),replacementcount()); if(proc == initproc) panic("init exiting"); // Close all open files. for(fd = 0; fd < NOFILE; fd++){ if(proc->ofile[fd]){ fileclose(proc->ofile[fd]); proc->ofile[fd] = 0; } } begin_op(); iput(proc->cwd); end_op(); proc->cwd = 0; acquire(&ptable.lock); // Parent might be sleeping in wait(). wakeup1(proc->parent); // Pass abandoned children to init. for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent == proc){ p->parent = initproc; if(p->state == ZOMBIE) wakeup1(initproc); } } // Jump into the scheduler, never to return. proc->state = ZOMBIE; sched(); panic("zombie exit"); }
// Exit the current process. Does not return. // An exited process remains in the zombie state // until its parent calls wait() to find out it exited. void exit(void) { struct proc *curproc = myproc(); struct proc *p; int fd; if(curproc == initproc) panic("init exiting"); // Close all open files. for(fd = 0; fd < NOFILE; fd++){ if(curproc->ofile[fd]){ fileclose(curproc->ofile[fd]); curproc->ofile[fd] = 0; } } begin_op(); iput(curproc->cwd); end_op(); curproc->cwd = 0; acquire(&ptable.lock); // Parent might be sleeping in wait(). wakeup1(curproc->parent); // Pass abandoned children to init. for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->parent == curproc){ p->parent = initproc; if(p->state == ZOMBIE) wakeup1(initproc); } } // Jump into the scheduler, never to return. curproc->state = ZOMBIE; sched(); panic("zombie exit"); }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; begin_op(); if((ip = namei(path)) == 0){ end_op(); return -1; } ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); end_op(); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip){ iunlockput(ip); end_op(); } return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; // namei converts given path into inode begin_op(); if((ip = namei(path)) == 0){ end_op(); return -1; } ilock(ip); pgdir = 0; // Check ELF header // if the file is smaller than the size of an elf header, // then it doesn't hold an elf header. (ERROR) if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. // do this for each section of the elf file (chunk size dlineated // by sizeof program header) // allocate user virtual memory // load program into user virtual memory // in linux, run readelf -a /bin/ls and see the the offset and size // column program section header being loaded sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); end_op(); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); // This is macro function that jumps to the next page boundary if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; // this makes the inaccessible page clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. // This code is building the stack frame of the application. // since argc is not passed into this function, to find the max // num of args, we need to step through the argv string until the // item returned is NULL or the end of the string. // This means that we have found all of the arguments. // Next, we need to copy each argument into the stack and keep // references to it in a local stack. Once this is done, we can // set the stack pointer to point to the first argument on the stack. // now, we can put the return value and the total number of args onto our // local stack. Then, we must prepare local stack for the copy into the // real stack. Next, we adjust the real stack pointer to make // room for our local stack and then we copy our stack that contains // pointers to each argument onto the stack. // We need this for quick lookup of each argument -- without the poitners // we can't efficiently get the args back. we also need the // the total number of arguments to make sure that we are growing the // stack properly. // think about this: int main(int argc, char **argv); // this code defends why we need a double pointer to a char. // we are giving an array of char *. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; // explain of ~3 in following line: // to make memory align with 4 bits, we the two lower order bit // which are the oly two bits that aren't divisibile by 4. // this is to keep the compiler aligned with the system sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; // This is getting the real stack ready for the copy // of the local stack, ustack[] ustack[2] = sp - (argc+1)*4; // argv pointer // this is moving the stack pointer to the location of first argument. sp -= (3+argc+1) * 4; // This is copying the ustack[] into the real stack if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // done buildng the stack frame // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip){ iunlockput(ip); end_op(); } return -1; }
int main(int argc, char **argv) { read_args(argc, argv); struct counters timer; start_measure(timer); // declarations float tab_var = 1.0; float *ioB = &tab_var; ioBuffer = cl::sycl::buffer<float,2>(cl::sycl::range<2> {M, N}); ioABuffer = cl::sycl::buffer<float,2>(cl::sycl::range<2> {M, N}); ioBBuffer = cl::sycl::buffer<float,1>(ioB, cl::sycl::range<1> {1}); #if DEBUG_STENCIL float *a_test = (float *) malloc(sizeof(float)*M*N); float *b_test = (float *) malloc(sizeof(float)*M*N); #endif // initialization for (size_t i = 0; i < M; ++i){ for (size_t j = 0; j < N; ++j){ float value = ((float) i*(j+2) + 10) / N; cl::sycl::id<2> id = {i, j}; ioBuffer.get_access<cl::sycl::access::mode::write, cl::sycl::access::target::host_buffer>()[id] = value; ioABuffer.get_access<cl::sycl::access::mode::write, cl::sycl::access::target::host_buffer>()[id] = value; #if DEBUG_STENCIL a_test[i*N+j] = value; b_test[i*N+j] = value; #endif } } // our work coef_var2D<0, 0> c1; coef_var2D<1, 0> c2; coef_var2D<0, 1> c3; coef_var2D<-1, 0> c4; coef_var2D<0, -1> c5; auto st = c1+c2+c3+c4+c5; input_var2D<float, &ioABuffer, &ioBBuffer, &fdl_in, &fac> work_in; output_2D<float, &ioBuffer, &fdl_out> work_out; auto op_work = work_out << st << work_in; auto st_id = c1.toStencil(); input_var2D<float, &ioBuffer, &ioBBuffer, &fdl_in, &fac_id> copy_in; output_2D<float, &ioABuffer, &fdl_out> copy_out; auto op_copy = copy_out << st_id << copy_in; end_init(timer); struct op_time time_op; begin_op(time_op); // compute result with "gpu" { cl::sycl::queue myQueue; for (unsigned int i = 0; i < NB_ITER; ++i){ //op_work.doComputation(myQueue); op_work.doLocalComputation(myQueue); op_copy.doComputation(myQueue); } } end_op(time_op, timer.stencil_time); // loading time is not watched end_measure(timer); #if DEBUG_STENCIL // get the gpu result auto C = (ioABuffer).get_access<cl::sycl::access::mode::read, cl::sycl::access::target::host_buffer>(); ute_and_are(a_test,b_test,C); free(a_test); free(b_test); #endif return 0; }