Example #1
0
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;
    }

}
Example #2
0
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;

}
Example #3
0
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;

}
Example #4
0
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();

}