intfree_process( process* proc ) { // we set the status to ZOMBIE, but cannot destruct its vm space immediately. // since proc can be current process, and its user kernel stack is currently in use! // but for proxy kernel, it (memory leaking) may NOT be a really serious issue, // as it is different from regular OS, which needs to run 7x24. proc->status = ZOMBIE; remove_from_blocked_queue(proc); remove_from_ready_queue(proc);
return0; }
// syscall.c longdo_syscall(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7){ insert_to_ready_queue(current); }
// sched.c voidschedule() { // 检查父进程等待的子进程是否已经zombie,如果是,则将父进程重新投入运行(重置waiting_pid, status) if (blocked_queue_head){ for(process* p = blocked_queue_head; p != NULL; p = p->queue_next){ if(procs[p->waiting_pid].status == ZOMBIE){ p->waiting_pid = -1; from_blocked_to_ready(p); } } }
if ( !ready_queue_head ){ int should_shutdown = 1;
for( int i=0; i<NPROC; i++ ) if( (procs[i].status != FREE) && (procs[i].status != ZOMBIE) ){ should_shutdown = 0; sprint( "ready queue empty, but process %d is not in free/zombie state:%d\n", i, procs[i].status ); }
if( should_shutdown ){ sprint( "no more ready processes, system shutdown now.\n" ); shutdown( 0 ); }else{ panic( "Not handled: we should let system wait for unfinished processes.\n" ); } }
// split the path, and retrieves a token at a time. // note: strtok() uses a static (local) variable to store the input path // string at the first time it is called. thus it can out a token each time. // for example, when input path is: /RAMDISK0/test_dir/ramfile2 // strtok() outputs three tokens: 1)RAMDISK0, 2)test_dir and 3)ramfile2 // at its three continuous invocations. int flag = 0; char *token = strtok(path_copy, "/"); structdentry* this = *parent; structdentry* cwd =NULL; if(current[hartid] != NULL){ cwd = current[hartid]->pfiles->cwd; }
while (token != NULL) { if(strcmp(token, "..") == 0){ if(cwd == NULL){ panic("lookup_final_dentry: proc not init\n"); returnNULL; } if(flag == 0){ if(cwd == vfs_root_dentry){ panic("already in root\n"); returnNULL; } (*parent) = cwd->parent; flag = 1; }else{ if((*parent) == vfs_root_dentry){ panic("already in root\n"); returnNULL; } (*parent) = (*parent)->parent; } this = (*parent); }elseif(strcmp(token, ".") == 0){ if(cwd == NULL){ panic("lookup_final_dentry: proc not init\n"); returnNULL; } if(flag == 0){ (*parent) = cwd; flag = 1; } this = (*parent); }else{ // function return subdir's dentry this = hash_get_dentry((*parent), token);
if (this == NULL) { // function return subdir's dentry this = alloc_vfs_dentry(token, NULL, *parent);
// get subdir's vinode structvinode *found_vinode = viop_lookup((*parent)->dentry_inode, this);
// dentry not in hash && vinode not in disk // return miss if (found_vinode == NULL) { // not found in both hash table and directory file on disk. free_page(this); strcpy(miss_name, token); returnNULL; }
// dentry not in hash && vinode in disk // ensure dentry and vinode in hash structvinode *same_inode = hash_get_vinode(found_vinode->sb, found_vinode->inum); if (same_inode != NULL) { // the vinode is already in the hash table (i.e. we are opening another hard link) this->dentry_inode = same_inode; same_inode->ref++; free_page(found_vinode); } else { // the vinode is not in the hash table this->dentry_inode = found_vinode; found_vinode->ref++; hash_put_vinode(found_vinode); } hash_put_dentry(this); } flag = 1; *parent = this; }
// get next token token = strtok(NULL, "/"); } return this; }