int32_t fork() { /* Time to... fork! * I had spent a long time preparing for this! * now I am done, it's time to start working on fork(). */ int32_t i; proc_t *newproc; /* create a new process structure: */ newproc = kmalloc(sizeof(proc_t)); if (newproc == NULL) return -1; /* set parent */ newproc->parent = curproc; /* initialize descriptors: */ newproc->plist.proc = newproc; newproc->sched.proc = newproc; newproc->irqd.proc = newproc; newproc->semad.proc = newproc; /* create memory: */ if (umem_init(&(newproc->umem))) { kfree(newproc); return -1; /* error. */ } /* inherit parent's memory: */ if (umem_copy(&(curproc->umem), &(newproc->umem))) { umem_free(&(newproc->umem)); kfree(newproc); return -1; /* error. */ } /* create a new kernel stack. */ newproc->kstack = (unsigned char *) kmalloc(KERNEL_STACK_SIZE); if (newproc->kstack == NULL) { umem_free(&(newproc->umem)); kfree(newproc); return -1; /* error. */ } initproc->phy_stack_bot = arch_vmpage_getAddr(NULL, newproc->kstack); /* initialize kernel stack... * this invokes page faults to allocate memory for * the stack early. */ for (i = 0; i < KERNEL_STACK_SIZE; i++) newproc->kstack[i] = 0; /* copy context from parent's stack to child's stack: */ copy_context(newproc); /* copy the set of file descriptors: */ for (i = 0; i < FD_MAX; i++) { if (curproc->file[i] == NULL) { newproc->file[i] = NULL; } else { curproc->file[i]->fcount++; newproc->file[i] = curproc->file[i]; } } /* inherit the current working directory: */ curproc->cwd->fcount++; newproc->cwd = curproc->cwd; /* set pid: */ newproc->pid = ++last_pid; /* inform the scheduler that this is a just-forked process: */ newproc->after_fork = 1; /* initialize inbox */ newproc->inbox_lock = 0; newproc->blocked_for_msg = 0; linkedlist_init(&(newproc->inbox)); /* children */ newproc->blocked_for_child = 0; /* not blocked */ newproc->blocked = 0; newproc->lock_to_unlock = NULL; /* exit status: */ newproc->terminated = 0; newproc->status = 0; /* add the new process to the list of processes: */ linkedlist_addlast((linkedlist*)&proclist, (linknode*)&(newproc->plist)); /* add to scheduler's queue: */ linkedlist_addlast((linkedlist*)&q_ready, (linknode*)&(newproc->sched)); /* call the scheduler */ scheduler(); /* return */ if (curproc == newproc) { return 0; } else { return newproc->pid; } }
int32_t tmpfs_mknod(inode_t *dir, char *name, int32_t mode, int32_t devid) { /* local variables */ int32_t err; tmpfs_ino_t ino; inode_t *inode; tmpfs_inode_t *dir_tmpfs_inode = (tmpfs_inode_t *) dir->ino; tmpfs_inode_t *nod_tmpfs_inode; char *fsname; tmpfs_dentry_t *p; /* parent must be a directory. */ if ((dir->mode & FT_MASK) != FT_DIR) return ENOTDIR; /* parent is already deleted? */ if (!(dir->ref)) return ENOENT; /* name shouldn't exist. */ err = tmpfs_lookup(dir, name, NULL); if (!err) { return EEXIST; } else if (err != ENOENT) { return err; } /* allocate a new inode: */ ino = (tmpfs_ino_t) kmalloc(sizeof(tmpfs_inode_t)); if (!ino) return ENOSPC; nod_tmpfs_inode = (tmpfs_inode_t *) ino; linkedlist_init(&(nod_tmpfs_inode->u.blocks)); /* get the inode: */ inode = (inode_t *) iget(dir->sb, ino); /* initialize the inode: */ inode->ref = 1; inode->mode = mode; inode->size = 0; inode->devid = devid; tmpfs_update_inode(inode); /* put the inode: */ iput(inode); /* allocate space for name: */ fsname = kmalloc(strlen(name)+1); if (!fsname) return ENOMEM; strcpy(fsname, name); /* look up for an empty entry */ p = dir_tmpfs_inode->u.dentries.first; while(p && (p->inode > 1)) p = p->next; /* no empty entry? allocate a new one! */ if (!p) { if (!(p = kmalloc(sizeof(tmpfs_dentry_t)))) { kfree(fsname); return ENOMEM; } linkedlist_addlast(&(dir_tmpfs_inode->u.dentries), p); tmpfs_update_inode(dir); } /* fill in the entry: */ p->inode = ino; p->name = fsname; /* done */ return ESUCCESS; }
super_block_t *tmpfs_read_super(device_t *dev) { /* local variables */ super_block_t *sb; tmpfs_inode_t *tmpfs_inode; tmpfs_dentry_t *dot; tmpfs_dentry_t *dotdot; /* allocate memory for superblock: */ sb = kmalloc(sizeof(super_block_t)); if (!sb) return NULL; /* initialize superblock: */ sb->fsdriver = &tmpfs_t; sb->dev = dev; sb->icount = 0; sb->mounts = 1; /* allocate root inode: */ tmpfs_inode = kmalloc(sizeof(tmpfs_inode_t)); if (!tmpfs_inode) { kfree(sb); return NULL; } /* initialize the inode: */ tmpfs_inode->ref = 1; tmpfs_inode->mode = FT_DIR; tmpfs_inode->size = 0; tmpfs_inode->devid = 0; linkedlist_init(&(tmpfs_inode->u.blocks)); /* create <.> directory entry: */ dot = kmalloc(sizeof(tmpfs_dentry_t)); if (!dot) { kfree(tmpfs_inode); kfree(sb); return NULL; } dot->inode = (ino_t) tmpfs_inode; dot->name = kmalloc(2); if (!(dot->name)) { kfree(dot); kfree(tmpfs_inode); kfree(sb); return NULL; } dot->name[0] = '.'; dot->name[1] = 0; linkedlist_addlast(&(tmpfs_inode->u.dentries), dot); /* create <..> entry: */ dotdot = kmalloc(sizeof(tmpfs_dentry_t)); if (!dotdot) { kfree(dot->name); kfree(dot); kfree(tmpfs_inode); kfree(sb); return NULL; } dotdot->inode = (ino_t) tmpfs_inode; dotdot->name = kmalloc(3); if (!(dotdot->name)) { kfree(dotdot); kfree(dot->name); kfree(dot); kfree(tmpfs_inode); kfree(sb); return NULL; } dotdot->name[0] = '.'; dotdot->name[1] = '.'; dotdot->name[2] = 0; linkedlist_addlast(&(tmpfs_inode->u.dentries), dotdot); /* Update super block: */ sb->root_ino = (ino_t) tmpfs_inode; /* done: */ return sb; }
void proc_init() { /* Process Manager Initialization */ int32_t i, err = 0; char *initpath = "/bin/init"; /* (I) Initialize linked lists: */ /* ----------------------------- */ linkedlist_init((linkedlist *) &proclist); linkedlist_init((linkedlist *) &q_ready); linkedlist_init((linkedlist *) &q_blocked); /* (II) Create "init" process: */ /* ---------------------------- */ /* Allocate memory for process structures: */ initproc = (proc_t *) kmalloc(sizeof(proc_t)); /* set parent */ initproc->parent = NULL; /* initialize descriptors: */ initproc->plist.proc = initproc; initproc->sched.proc = initproc; initproc->irqd.proc = initproc; /* Set "init" pid <1>: */ initproc->pid = 1; /* Add it to process list: */ linkedlist_addlast((linkedlist *) &proclist, (linknode *) &(initproc->plist)); /* Kernel-mode stack: */ initproc->kstack = kernel_stack; /* User memory: */ umem_init(&(initproc->umem)); /* initialize file descriptors: */ for(i = 0; i < FD_MAX; i++) initproc->file[i] = NULL; /* current working directory: */ file_open("/", 0, &(initproc->cwd)); /* not forked: */ initproc->after_fork = 0; /* initialize inbox */ initproc->inbox_lock = 0; initproc->blocked_for_msg = 0; linkedlist_init(&(initproc->inbox)); /* children */ initproc->blocked_for_child = 0; /* not blocked */ initproc->blocked = 0; /* exit status: */ initproc->terminated = 0; initproc->status = 0; /* (III) Run the "init" process: */ /* ------------------------------ */ curproc = initproc; /* init process is running! */ arch_vmswitch(&(initproc->umem)); /* (IV) Enable multitasking: */ /* -------------------------- */ scheduler_enabled = 1; /* start multitasking! */ /* (V) Open console streams: */ /* -------------------------- */ /* create device file for console: */ mknod("/dev/console", FT_SPECIAL, system_console->devid); /* open console file: */ open("/dev/console", 0); /* this will open the file at fd "0". */ dup(0); /* duplicate at fd "1". */ dup(0); /* duplicate at fd "2". */ /* (VI) Execute "init" program to initialize the operating system: */ /* ---------------------------------------------------------------- */ printk("Executing \"%s\" ...\n\n", initpath); printk("%a", 0x0E); execve(initpath, 0, 0); printk("FATAL: Error happened during execution.\n"); idle(); }