Beispiel #1
0
int main(int argc, char *argv[])
{
	int n = 300;
	double **a, **b, **m;
	n = (n/2) * 2;
	a = mm_gen(n); b = mm_gen(n);
	m = mm_mul(n, a, b);
	//fprintf(stderr, "%lf\n", m[n/2][n/2]);
	mm_destroy(n, a); mm_destroy(n, b); mm_destroy(n, m);
	return 0;
}
Beispiel #2
0
static void check_vma_struct(void)
{
	size_t nr_used_pages_store = nr_used_pages();
	size_t slab_allocated_store = slab_allocated();

	struct mm_struct *mm = mm_create();
	assert(mm != NULL);

	int step1 = RB_MIN_MAP_COUNT * 2, step2 = step1 * 10;
//	int step1 = 2, step2 = step1 * 10;

	int i;
	for (i = step1; i >= 1; i--) {
		struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0);
		assert(vma != NULL);
		insert_vma_struct(mm, vma);
	}

	for (i = step1 + 1; i <= step2; i++) {
		struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0);
		assert(vma != NULL);
		insert_vma_struct(mm, vma);
	}

	list_entry_t *le = list_next(&(mm->mmap_list));

	for (i = 1; i <= step2; i++) {
		assert(le != &(mm->mmap_list));
		struct vma_struct *mmap = le2vma(le, list_link);
		assert(mmap->vm_start == i * 5 && mmap->vm_end == i * 5 + 2);
		le = list_next(le);
	}

	for (i = 5; i <= 5 * step2; i+=5) {
		struct vma_struct *vma1 = find_vma(mm, i);
		assert(vma1 != NULL);
		struct vma_struct *vma2 = find_vma(mm, i+1);
		assert(vma2 != NULL);
		struct vma_struct *vma3 = find_vma(mm, i+2);
		assert(vma3 == NULL);
		struct vma_struct *vma4 = find_vma(mm, i+3);
		assert(vma4 == NULL);
		struct vma_struct *vma5 = find_vma(mm, i+4);
		assert(vma5 == NULL);

		assert(vma1->vm_start == i  && vma1->vm_end == i  + 2);
		assert(vma2->vm_start == i  && vma2->vm_end == i  + 2);
	}

	for (i =4; i>=0; i--) {
		struct vma_struct *vma_below_5= find_vma(mm,i);
		assert(vma_below_5 == NULL);
	}
	mm_destroy(mm);

	__CHECK_MEMORY_LEAK();

	kprintf("check_vma_struct() succeeded!\n");
}
Beispiel #3
0
static void
check_vma_struct(void) {
    size_t nr_free_pages_store = nr_free_pages();

    struct mm_struct *mm = mm_create();
    assert(mm != NULL);

    int step1 = 10, step2 = step1 * 10;

    int i;
    for (i = step1; i >= 1; i --) {
        struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0);
        assert(vma != NULL);
        insert_vma_struct(mm, vma);
    }

    for (i = step1 + 1; i <= step2; i ++) {
        struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0);
        assert(vma != NULL);
        insert_vma_struct(mm, vma);
    }

    list_entry_t *le = list_next(&(mm->mmap_list));

    for (i = 1; i <= step2; i ++) {
        assert(le != &(mm->mmap_list));
        struct vma_struct *mmap = le2vma(le, list_link);
        assert(mmap->vm_start == i * 5 && mmap->vm_end == i * 5 + 2);
        le = list_next(le);
    }

    for (i = 5; i <= 5 * step2; i +=5) {
        struct vma_struct *vma1 = find_vma(mm, i);
        assert(vma1 != NULL);
        struct vma_struct *vma2 = find_vma(mm, i+1);
        assert(vma2 != NULL);
        struct vma_struct *vma3 = find_vma(mm, i+2);
        assert(vma3 == NULL);
        struct vma_struct *vma4 = find_vma(mm, i+3);
        assert(vma4 == NULL);
        struct vma_struct *vma5 = find_vma(mm, i+4);
        assert(vma5 == NULL);

        assert(vma1->vm_start == i  && vma1->vm_end == i  + 2);
        assert(vma2->vm_start == i  && vma2->vm_end == i  + 2);
    }

    for (i =4; i>=0; i--) {
        struct vma_struct *vma_below_5= find_vma(mm,i);
        if (vma_below_5 != NULL ) {
           cprintf("vma_below_5: i %x, start %x, end %x\n",i, vma_below_5->vm_start, vma_below_5->vm_end); 
        }
        assert(vma_below_5 == NULL);
    }

    mm_destroy(mm);

    cprintf("check_vma_struct() succeeded!\n");
}
Beispiel #4
0
 inline ~MMSharedMemoryPool()
 {
     if (m_managed_self)
     {
         mm_destroy(m_raw_pool);
     }
     //shm_malloc_destroy( m_mem_block);
 }
Beispiel #5
0
void MM_destroy(void)
{
    if (mm_global == NULL)
        return;
    mm_destroy(mm_global);
    mm_global = NULL;
    return;
}
Beispiel #6
0
 ~STATE() {
     if (this->logFd) {
         close(this->logFd);
     }
     this->logFd = 0;
     delete [] this->mm_file;
     delete [] this->filename;
     mm_destroy(this->mm);
 }
Beispiel #7
0
// copy_mm - process "proc" duplicate OR share process "current"'s mm according clone_flags
//         - if clone_flags & CLONE_VM, then "share" ; else "duplicate"
static int
copy_mm(uint32_t clone_flags, struct proc_struct *proc) {
    struct mm_struct *mm, *oldmm = current->mm;

    /* current is a kernel thread */
    if (oldmm == NULL) {
        return 0;
    }
    if (clone_flags & CLONE_VM) {
        mm = oldmm;
        goto good_mm;
    }

    int ret = -E_NO_MEM;
    if ((mm = mm_create()) == NULL) {
        goto bad_mm;
    }
    if (setup_pgdir(mm) != 0) {
        goto bad_pgdir_cleanup_mm;
    }

    lock_mm(oldmm);
    {
        ret = dup_mmap(mm, oldmm);
    }
    unlock_mm(oldmm);

    if (ret != 0) {
        goto bad_dup_cleanup_mmap;
    }

good_mm:
    if (mm != oldmm) {
        mm->brk_start = oldmm->brk_start;
        mm->brk = oldmm->brk;
        bool intr_flag;
        local_intr_save(intr_flag);
        {
            list_add(&(proc_mm_list), &(mm->proc_mm_link));
        }
        local_intr_restore(intr_flag);
    }
    mm_count_inc(mm);
    proc->mm = mm;
	set_pgdir (proc, mm->pgdir);
    return 0;
bad_dup_cleanup_mmap:
    exit_mmap(mm);
    put_pgdir(mm);
bad_pgdir_cleanup_mm:
    mm_destroy(mm);
bad_mm:
    return ret;
}
Beispiel #8
0
// check_pgfault - check correctness of pgfault handler
static void check_pgfault(void)
{
#ifdef UCONFIG_CHECK_PGFAULT
	kprintf("starting check_pgfault()\n");
	size_t nr_used_pages_store = nr_used_pages();
	size_t slab_allocated_store = slab_allocated();

	check_mm_struct = mm_create();
	assert(check_mm_struct != NULL);

	struct mm_struct *mm = check_mm_struct;
	pgd_t *pgdir = mm->pgdir = init_pgdir_get();
	assert(pgdir[PGX(TEST_PAGE)] == 0);

	struct vma_struct *vma =
	    vma_create(TEST_PAGE, TEST_PAGE + PTSIZE, VM_WRITE);
	assert(vma != NULL);

	insert_vma_struct(mm, vma);
	uintptr_t addr = TEST_PAGE + 0x100;
	assert(find_vma(mm, addr) == vma);

	int i, sum = 0;
	for (i = 0; i < 100; i++) {
		*(char *)(addr + i) = i;
		sum += i;
	}
	for (i = 0; i < 100; i++) {
		sum -= *(char *)(addr + i);
	}
	assert(sum == 0);

	page_remove(pgdir, ROUNDDOWN(addr, PGSIZE));
#if PMXSHIFT != PUXSHIFT
	free_page(pa2page(PMD_ADDR(*get_pmd(pgdir, addr, 0))));
#endif
#if PUXSHIFT != PGXSHIFT
	free_page(pa2page(PUD_ADDR(*get_pud(pgdir, addr, 0))));
#endif
	free_page(pa2page(PGD_ADDR(*get_pgd(pgdir, addr, 0))));
	pgdir[PGX(TEST_PAGE)] = 0;

	mm->pgdir = NULL;
	mm_destroy(mm);
	check_mm_struct = NULL;

	assert(nr_used_pages_store == nr_used_pages());
	assert(slab_allocated_store == slab_allocated());

	kprintf("check_pgfault() succeeded!\n");
#endif
}
Beispiel #9
0
static void
check_vma_struct(void) {
    size_t nr_free_pages_store = nr_free_pages();
    size_t slab_allocated_store = slab_allocated();

    struct mm_struct *mm = mm_create();
    assert(mm != NULL);

    int step1 = RB_MIN_MAP_COUNT * 2, step2 = step1 * 10;

    int i;
    for (i = step1; i >= 0; i --) {
        struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0);
        assert(vma != NULL);
        insert_vma_struct(mm, vma);
    }

    for (i = step1 + 1; i <= step2; i ++) {
        struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0);
        assert(vma != NULL);
        insert_vma_struct(mm, vma);
    }

    list_entry_t *le = list_next(&(mm->mmap_list));

    for (i = 0; i <= step2; i ++) {
        assert(le != &(mm->mmap_list));
        struct vma_struct *mmap = le2vma(le, list_link);
        assert(mmap->vm_start == i * 5 && mmap->vm_end == i * 5 + 2);
        le = list_next(le);
    }

    for (i = 0; i < 5 * step2 + 2; i ++) {
        struct vma_struct *vma = find_vma(mm, i);
        assert(vma != NULL);
        int j = i / 5;
        if (i >= 5 * j + 2) {
            j ++;
        }
        assert(vma->vm_start == j * 5 && vma->vm_end == j * 5 + 2);
    }

    mm_destroy(mm);

    assert(nr_free_pages_store == nr_free_pages());
    assert(slab_allocated_store == slab_allocated());

    cprintf("check_vma_struct() succeeded!\n");
}
Beispiel #10
0
// check_pgfault - check correctness of pgfault handler
static void
check_pgfault(void) {
    size_t nr_free_pages_store = nr_free_pages();
    size_t slab_allocated_store = slab_allocated();

    check_mm_struct = mm_create();
    assert(check_mm_struct != NULL);

    struct mm_struct *mm = check_mm_struct;
    pgd_t *pgdir = mm->pgdir = boot_pgdir;
    assert(pgdir[0] == 0);

    struct vma_struct *vma = vma_create(0, PTSIZE, VM_WRITE);
    assert(vma != NULL);

    insert_vma_struct(mm, vma);

    uintptr_t addr = 0x100;
    assert(find_vma(mm, addr) == vma);

    int i, sum = 0;
    for (i = 0; i < 100; i ++) {
        *(char *)(addr + i) = i;
        sum += i;
    }
    for (i = 0; i < 100; i ++) {
        sum -= *(char *)(addr + i);
    }
    assert(sum == 0);

    page_remove(pgdir, ROUNDDOWN(addr, PGSIZE));
    free_page(pa2page(PMD_ADDR(*get_pmd(pgdir, addr, 0))));
    free_page(pa2page(PUD_ADDR(*get_pud(pgdir, addr, 0))));
    free_page(pa2page(PGD_ADDR(*get_pgd(pgdir, addr, 0))));
    pgdir[0] = 0;

    mm->pgdir = NULL;
    mm_destroy(mm);
    check_mm_struct = NULL;

    assert(nr_free_pages_store == nr_free_pages());
    assert(slab_allocated_store == slab_allocated());

    cprintf("check_pgfault() succeeded!\n");
}
Beispiel #11
0
static int ps_mm_initialize(ps_mm *data, const char *path)
{
	data->owner = getpid();
	data->mm = mm_create(0, path);
	if (!data->mm) {
		return FAILURE;
	}

	data->hash_cnt = 0;
	data->hash_max = 511;
	data->hash = mm_calloc(data->mm, data->hash_max + 1, sizeof(ps_sd *));
	if (!data->hash) {
		mm_destroy(data->mm);
		return FAILURE;
	}

	return SUCCESS;
}
Beispiel #12
0
// check_pgfault - check correctness of pgfault handler
static void
check_pgfault(void) {
    size_t nr_free_pages_store = nr_free_pages();

    check_mm_struct = mm_create();
    assert(check_mm_struct != NULL);

    struct mm_struct *mm = check_mm_struct;
    pde_t *pgdir = mm->pgdir = boot_pgdir;
    assert(pgdir[0] == 0);

    struct vma_struct *vma = vma_create(0, PTSIZE, VM_WRITE);
    assert(vma != NULL);

    insert_vma_struct(mm, vma);

    uintptr_t addr = 0x100;
    assert(find_vma(mm, addr) == vma);

    int i, sum = 0;
    for (i = 0; i < 100; i ++) {
        // cprintf("%d\n", i);
        *(char *)(addr + i) = i;
        sum += i;
    }
    // assert(0);
    for (i = 0; i < 100; i ++) {
        sum -= *(char *)(addr + i);
    }
    assert(sum == 0);

    page_remove(pgdir, ROUNDDOWN(addr, PGSIZE));
    free_page(pde2page(pgdir[0]));
    pgdir[0] = 0;

    mm->pgdir = NULL;
    mm_destroy(mm);
    check_mm_struct = NULL;

    assert(nr_free_pages_store == nr_free_pages());

    cprintf("check_pgfault() succeeded!\n");
}
Beispiel #13
0
static void ps_mm_destroy(ps_mm *data)
{
	int h;
	ps_sd *sd, *next;

	/* This function is called during each module shutdown,
	   but we must not release the shared memory pool, when
	   an Apache child dies! */
	if (data->owner != getpid()) return;

	for (h = 0; h < data->hash_max + 1; h++)
		for (sd = data->hash[h]; sd; sd = next) {
			next = sd->next;
			ps_sd_destroy(data, sd);
		}
	
	mm_free(data->mm, data->hash);
	mm_destroy(data->mm);
	free(data);
}
Beispiel #14
0
/**
 * Free the task's kernel stack, memory context, and close open files.
 * NOTE: Only called when removed from its queue.
 * Leaves the task on in the list of all tasks (only remove when a
 * parent calls cleanup_child).
 */
void task_destroy(struct task_struct *task) {
    int i;
    mm_destroy(task->mm);

    free_page(ALIGN_DOWN(task->kernel_rsp, PAGE_SIZE));

    /* Close any open files */
    for(i = 0; i < TASK_FILES_MAX; i++) {
        struct file *fp = task->files[i];
        if(fp) {
            fp->f_op->close(fp);
            task->files[i] = NULL;
        }
    }

    /* Give terminal control back to the parent */
    if(task->foreground && task->parent) {
        task->parent->foreground = 1;
    }
    task->foreground = 0; /* remove the foreground from the dead task */

    /* If we have children give them to init */
    if(task->chld) {
        /* Give all children to init */
        struct task_struct *prevchld, *nextchld;
        for(prevchld = task->chld; prevchld != NULL; prevchld = nextchld) {
            nextchld = prevchld->sib;
            add_child(init_task, prevchld);
        }
    }

    if(task->parent) {
        /* Notify parent of child's termination */
        if(task->parent->state == TASK_WAITING) {
            task_wakeup(&wait_queue, task->parent);
        }
    } else {
        /* We have no parent so add ourself to init */
        add_child(init_task, task);
    }
}
Beispiel #15
0
int
do_execve(const char *filename, const char **argv, const char **envp) {
    static_assert(EXEC_MAX_ARG_LEN >= FS_MAX_FPATH_LEN);
    
    struct mm_struct *mm = current->mm;

    char local_name[PROC_NAME_LEN + 1];
    memset(local_name, 0, sizeof(local_name));

    char *kargv[EXEC_MAX_ARG_NUM], *kenvp[EXEC_MAX_ENV_NUM];
    const char *path;

    int ret = -E_INVAL;
    lock_mm(mm);
#if 0
    if (name == NULL) {
        snprintf(local_name, sizeof(local_name), "<null> %d", current->pid);
    }
    else {
        if (!copy_string(mm, local_name, name, sizeof(local_name))) {
            unlock_mm(mm);
            return ret;
        }
    }
#endif
    snprintf(local_name, sizeof(local_name), "<null> %d", current->pid);

    int argc = 0, envc = 0;
    if ((ret = copy_kargv(mm, kargv, argv, EXEC_MAX_ARG_NUM, &argc)) != 0) {
      unlock_mm(mm);
      return ret;
    }
    if ((ret = copy_kargv(mm, kenvp, envp, EXEC_MAX_ENV_NUM, &envc)) != 0) {
      unlock_mm(mm);
      put_kargv(argc, kargv);
      return ret;
    }

#if 0
    int i;
    kprintf("## fn %s\n", filename);
    kprintf("## argc %d\n", argc);
    for(i=0;i<argc;i++)
      kprintf("## %08x %s\n", kargv[i], kargv[i]);
    kprintf("## envc %d\n", envc);
    for(i=0;i<envc;i++)
      kprintf("## %08x %s\n", kenvp[i], kenvp[i]);
#endif
    //path = argv[0];
    //copy_from_user (mm, &path, argv, sizeof (char*), 0);
    path = filename;
    unlock_mm(mm);

    /* linux never do this */
    //fs_closeall(current->fs_struct);

    /* sysfile_open will check the first argument path, thus we have to use a user-space pointer, and argv[0] may be incorrect */

    int fd;
    if ((ret = fd = sysfile_open(path, O_RDONLY)) < 0) {
      goto execve_exit;
    }

    if (mm != NULL) {
      mm->lapic = -1;
      mp_set_mm_pagetable(NULL);
      if (mm_count_dec(mm) == 0) {
        exit_mmap(mm);
        put_pgdir(mm);
        bool intr_flag;
        local_intr_save(intr_flag);
        {
          list_del(&(mm->proc_mm_link));
        }
            local_intr_restore(intr_flag);
            mm_destroy(mm);
        }
        current->mm = NULL;
    }
    put_sem_queue(current);

    ret = -E_NO_MEM;
    /* init signal */
    put_sighand(current);
    if ((current->signal_info.sighand = sighand_create()) == NULL) {
      goto execve_exit;
    }
    sighand_count_inc(current->signal_info.sighand);

    put_signal(current);
    if ((current->signal_info.signal = signal_create()) == NULL) {
      goto execve_exit;
    }
    signal_count_inc(current->signal_info.signal);

    if ((current->sem_queue = sem_queue_create()) == NULL) {
      goto execve_exit;
    }
    sem_queue_count_inc(current->sem_queue);

    if ((ret = load_icode(fd, argc, kargv, envc, kenvp)) != 0) {
      goto execve_exit;
    }

    set_proc_name(current, local_name);

	if (do_execve_arch_hook (argc, kargv) < 0)
		goto execve_exit;
	
    put_kargv(argc, kargv);
    return 0;

execve_exit:
    put_kargv(argc, kargv);
    put_kargv(envc, kenvp);
/* exec should return -1 if failed */
    //return ret;
    do_exit(ret);
    panic("already exit: %e.\n", ret);
}
Beispiel #16
0
static int load_icode(int fd, int argc, char **kargv, int envc, char **kenvp)
{
	assert(argc >= 0 && argc <= EXEC_MAX_ARG_NUM);
	assert(envc >= 0 && envc <= EXEC_MAX_ENV_NUM);
	if (current->mm != NULL) {
		panic("load_icode: current->mm must be empty.\n");
	}

	int ret = -E_NO_MEM;

//#ifdef UCONFIG_BIONIC_LIBC
	uint32_t real_entry;
//#endif //UCONFIG_BIONIC_LIBC

	struct mm_struct *mm;
	if ((mm = mm_create()) == NULL) {
		goto bad_mm;
	}

	if (setup_pgdir(mm) != 0) {
		goto bad_pgdir_cleanup_mm;
	}

	mm->brk_start = 0;

	struct Page *page;

	struct elfhdr __elf, *elf = &__elf;
	if ((ret = load_icode_read(fd, elf, sizeof(struct elfhdr), 0)) != 0) {
		goto bad_elf_cleanup_pgdir;
	}

	if (elf->e_magic != ELF_MAGIC) {
		ret = -E_INVAL_ELF;
		goto bad_elf_cleanup_pgdir;
	}
//#ifdef UCONFIG_BIONIC_LIBC
	real_entry = elf->e_entry;

	uint32_t load_address, load_address_flag = 0;
//#endif //UCONFIG_BIONIC_LIBC

	struct proghdr __ph, *ph = &__ph;
	uint32_t vm_flags, phnum;
	pte_perm_t perm = 0;

//#ifdef UCONFIG_BIONIC_LIBC
	uint32_t is_dynamic = 0, interp_idx;
	uint32_t bias = 0;
//#endif //UCONFIG_BIONIC_LIBC
	for (phnum = 0; phnum < elf->e_phnum; phnum++) {
		off_t phoff = elf->e_phoff + sizeof(struct proghdr) * phnum;
		if ((ret =
		     load_icode_read(fd, ph, sizeof(struct proghdr),
				     phoff)) != 0) {
			goto bad_cleanup_mmap;
		}

		if (ph->p_type == ELF_PT_INTERP) {
			is_dynamic = 1;
			interp_idx = phnum;
			continue;
		}

		if (ph->p_type != ELF_PT_LOAD) {
			continue;
		}
		if (ph->p_filesz > ph->p_memsz) {
			ret = -E_INVAL_ELF;
			goto bad_cleanup_mmap;
		}

		if (ph->p_va == 0 && !bias) {
			bias = 0x00008000;
		}

		if ((ret = map_ph(fd, ph, mm, &bias, 0)) != 0) {
			kprintf("load address: 0x%08x size: %d\n", ph->p_va,
				ph->p_memsz);
			goto bad_cleanup_mmap;
		}

		if (load_address_flag == 0)
			load_address = ph->p_va + bias;
		++load_address_flag;

	  /*********************************************/
		/*
		   vm_flags = 0;
		   ptep_set_u_read(&perm);
		   if (ph->p_flags & ELF_PF_X) vm_flags |= VM_EXEC;
		   if (ph->p_flags & ELF_PF_W) vm_flags |= VM_WRITE;
		   if (ph->p_flags & ELF_PF_R) vm_flags |= VM_READ;
		   if (vm_flags & VM_WRITE) ptep_set_u_write(&perm);

		   if ((ret = mm_map(mm, ph->p_va, ph->p_memsz, vm_flags, NULL)) != 0) {
		   goto bad_cleanup_mmap;
		   }

		   if (mm->brk_start < ph->p_va + ph->p_memsz) {
		   mm->brk_start = ph->p_va + ph->p_memsz;
		   }

		   off_t offset = ph->p_offset;
		   size_t off, size;
		   uintptr_t start = ph->p_va, end, la = ROUNDDOWN(start, PGSIZE);

		   end = ph->p_va + ph->p_filesz;
		   while (start < end) {
		   if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) {
		   ret = -E_NO_MEM;
		   goto bad_cleanup_mmap;
		   }
		   off = start - la, size = PGSIZE - off, la += PGSIZE;
		   if (end < la) {
		   size -= la - end;
		   }
		   if ((ret = load_icode_read(fd, page2kva(page) + off, size, offset)) != 0) {
		   goto bad_cleanup_mmap;
		   }
		   start += size, offset += size;
		   }

		   end = ph->p_va + ph->p_memsz;

		   if (start < la) {
		   // ph->p_memsz == ph->p_filesz 
		   if (start == end) {
		   continue ;
		   }
		   off = start + PGSIZE - la, size = PGSIZE - off;
		   if (end < la) {
		   size -= la - end;
		   }
		   memset(page2kva(page) + off, 0, size);
		   start += size;
		   assert((end < la && start == end) || (end >= la && start == la));
		   }

		   while (start < end) {
		   if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) {
		   ret = -E_NO_MEM;
		   goto bad_cleanup_mmap;
		   }
		   off = start - la, size = PGSIZE - off, la += PGSIZE;
		   if (end < la) {
		   size -= la - end;
		   }
		   memset(page2kva(page) + off, 0, size);
		   start += size;
		   }
		 */
	  /**************************************/
	}

	mm->brk_start = mm->brk = ROUNDUP(mm->brk_start, PGSIZE);

	/* setup user stack */
	vm_flags = VM_READ | VM_WRITE | VM_STACK;
	if ((ret =
	     mm_map(mm, USTACKTOP - USTACKSIZE, USTACKSIZE, vm_flags,
		    NULL)) != 0) {
		goto bad_cleanup_mmap;
	}

	if (is_dynamic) {
		elf->e_entry += bias;

		bias = 0;

		off_t phoff =
		    elf->e_phoff + sizeof(struct proghdr) * interp_idx;
		if ((ret =
		     load_icode_read(fd, ph, sizeof(struct proghdr),
				     phoff)) != 0) {
			goto bad_cleanup_mmap;
		}

		char *interp_path = (char *)kmalloc(ph->p_filesz);
		load_icode_read(fd, interp_path, ph->p_filesz, ph->p_offset);

		int interp_fd = sysfile_open(interp_path, O_RDONLY);
		assert(interp_fd >= 0);
		struct elfhdr interp___elf, *interp_elf = &interp___elf;
		assert((ret =
			load_icode_read(interp_fd, interp_elf,
					sizeof(struct elfhdr), 0)) == 0);
		assert(interp_elf->e_magic == ELF_MAGIC);

		struct proghdr interp___ph, *interp_ph = &interp___ph;
		uint32_t interp_phnum;
		uint32_t va_min = 0xffffffff, va_max = 0;
		for (interp_phnum = 0; interp_phnum < interp_elf->e_phnum;
		     ++interp_phnum) {
			off_t interp_phoff =
			    interp_elf->e_phoff +
			    sizeof(struct proghdr) * interp_phnum;
			assert((ret =
				load_icode_read(interp_fd, interp_ph,
						sizeof(struct proghdr),
						interp_phoff)) == 0);
			if (interp_ph->p_type != ELF_PT_LOAD) {
				continue;
			}
			if (va_min > interp_ph->p_va)
				va_min = interp_ph->p_va;
			if (va_max < interp_ph->p_va + interp_ph->p_memsz)
				va_max = interp_ph->p_va + interp_ph->p_memsz;
		}

		bias = get_unmapped_area(mm, va_max - va_min + 1 + PGSIZE);
		bias = ROUNDUP(bias, PGSIZE);

		for (interp_phnum = 0; interp_phnum < interp_elf->e_phnum;
		     ++interp_phnum) {
			off_t interp_phoff =
			    interp_elf->e_phoff +
			    sizeof(struct proghdr) * interp_phnum;
			assert((ret =
				load_icode_read(interp_fd, interp_ph,
						sizeof(struct proghdr),
						interp_phoff)) == 0);
			if (interp_ph->p_type != ELF_PT_LOAD) {
				continue;
			}
			assert((ret =
				map_ph(interp_fd, interp_ph, mm, &bias,
				       1)) == 0);
		}

		real_entry = interp_elf->e_entry + bias;

		sysfile_close(interp_fd);
		kfree(interp_path);
	}

	sysfile_close(fd);

	bool intr_flag;
	local_intr_save(intr_flag);
	{
		list_add(&(proc_mm_list), &(mm->proc_mm_link));
	}
	local_intr_restore(intr_flag);
	mm_count_inc(mm);
	current->mm = mm;
	set_pgdir(current, mm->pgdir);
	mm->cpuid = myid();
	mp_set_mm_pagetable(mm);

	if (!is_dynamic) {
		real_entry += bias;
	}
#ifdef UCONFIG_BIONIC_LIBC
	if (init_new_context_dynamic(current, elf, argc, kargv, envc, kenvp,
				     is_dynamic, real_entry, load_address,
				     bias) < 0)
		goto bad_cleanup_mmap;
#else
	if (init_new_context(current, elf, argc, kargv, envc, kenvp) < 0)
		goto bad_cleanup_mmap;
#endif //UCONFIG_BIONIC_LIBC
	ret = 0;
out:
	return ret;
bad_cleanup_mmap:
	exit_mmap(mm);
bad_elf_cleanup_pgdir:
	put_pgdir(mm);
bad_pgdir_cleanup_mm:
	mm_destroy(mm);
bad_mm:
	goto out;
}
Beispiel #17
0
// __do_exit - cause a thread exit (use do_exit, do_exit_thread instead)
//   1. call exit_mmap & put_pgdir & mm_destroy to free the almost all memory space of process
//   2. set process' state as PROC_ZOMBIE, then call wakeup_proc(parent) to ask parent reclaim itself.
//   3. call scheduler to switch to other process
static int
__do_exit(void) {
    if (current == idleproc) {
        panic("idleproc exit.\n");
    }
    if (current == initproc) {
        panic("initproc exit.\n");
    }

    struct mm_struct *mm = current->mm;
    if (mm != NULL) {
		mm->lapic = -1;
        mp_set_mm_pagetable(NULL);
        if (mm_count_dec(mm) == 0) {
            exit_mmap(mm);
            put_pgdir(mm);
            bool intr_flag;
            local_intr_save(intr_flag);
            {
                list_del(&(mm->proc_mm_link));
            }
            local_intr_restore(intr_flag);
            mm_destroy(mm);
        }
        current->mm = NULL;
    }
    put_sighand(current);
    put_signal(current);
    put_fs(current);
    put_sem_queue(current);
    current->state = PROC_ZOMBIE;

    bool intr_flag;
    struct proc_struct *proc, *parent;
    local_intr_save(intr_flag);
    {
        proc = parent = current->parent;
        do {
            if (proc->wait_state == WT_CHILD) {
                wakeup_proc(proc);
            }
            proc = next_thread(proc);
        } while (proc != parent);

        if ((parent = next_thread(current)) == current) {
            parent = initproc;
        }
        de_thread(current);
        while (current->cptr != NULL) {
            proc = current->cptr;
            current->cptr = proc->optr;

            proc->yptr = NULL;
            if ((proc->optr = parent->cptr) != NULL) {
                parent->cptr->yptr = proc;
            }
            proc->parent = parent;
            parent->cptr = proc;
            if (proc->state == PROC_ZOMBIE) {
                if (parent->wait_state == WT_CHILD) {
                    wakeup_proc(parent);
                }
            }
        }
    }

    wakeup_queue(&(current->event_box.wait_queue), WT_INTERRUPTED, 1);

    local_intr_restore(intr_flag);

    schedule();
    panic("__do_exit will not return!! %d %d.\n", current->pid, current->exit_code);
}
Beispiel #18
0
static int
load_icode(int fd, int argc, char **kargv, int envc, char **kenvp) {
    assert(argc >= 0 && argc <= EXEC_MAX_ARG_NUM);
    assert(envc >= 0 && envc <= EXEC_MAX_ENV_NUM);
    if (current->mm != NULL) {
        panic("load_icode: current->mm must be empty.\n");
    }

    int ret = -E_NO_MEM;

    struct mm_struct *mm;
    if ((mm = mm_create()) == NULL) {
        goto bad_mm;
    }

    if (setup_pgdir(mm) != 0) {
        goto bad_pgdir_cleanup_mm;
    }

    mm->brk_start = 0;

    struct Page *page;

    struct elfhdr __elf, *elf = &__elf;
    if ((ret = load_icode_read(fd, elf, sizeof(struct elfhdr), 0)) != 0) {
        goto bad_elf_cleanup_pgdir;
    }
	
    if (elf->e_magic != ELF_MAGIC) {
        ret = -E_INVAL_ELF;
        goto bad_elf_cleanup_pgdir;
    }

    struct proghdr __ph, *ph = &__ph;
    uint32_t vm_flags, phnum;
    pte_perm_t perm = 0;
    for (phnum = 0; phnum < elf->e_phnum; phnum ++) {
      off_t phoff = elf->e_phoff + sizeof(struct proghdr) * phnum;
      if ((ret = load_icode_read(fd, ph, sizeof(struct proghdr), phoff)) != 0) {
        goto bad_cleanup_mmap;
      }
      if (ph->p_type != ELF_PT_LOAD) {
        continue ;
      }
      if (ph->p_filesz > ph->p_memsz) {
        ret = -E_INVAL_ELF;
        goto bad_cleanup_mmap;
      }
      vm_flags = 0;
      ptep_set_u_read(&perm);
      if (ph->p_flags & ELF_PF_X) vm_flags |= VM_EXEC;
      if (ph->p_flags & ELF_PF_W) vm_flags |= VM_WRITE;
      if (ph->p_flags & ELF_PF_R) vm_flags |= VM_READ;
      if (vm_flags & VM_WRITE) ptep_set_u_write(&perm);

      if ((ret = mm_map(mm, ph->p_va, ph->p_memsz, vm_flags, NULL)) != 0) {
        goto bad_cleanup_mmap;
      }

      if (mm->brk_start < ph->p_va + ph->p_memsz) {
        mm->brk_start = ph->p_va + ph->p_memsz;
      }

      off_t offset = ph->p_offset;
      size_t off, size;
      uintptr_t start = ph->p_va, end, la = ROUNDDOWN(start, PGSIZE);

      end = ph->p_va + ph->p_filesz;
      while (start < end) {
        if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) {
          ret = -E_NO_MEM;
          goto bad_cleanup_mmap;
        }
        off = start - la, size = PGSIZE - off, la += PGSIZE;
        if (end < la) {
          size -= la - end;
        }
        if ((ret = load_icode_read(fd, page2kva(page) + off, size, offset)) != 0) {
          goto bad_cleanup_mmap;
        }
        start += size, offset += size;
      }

      end = ph->p_va + ph->p_memsz;

      if (start < la) {
        /* ph->p_memsz == ph->p_filesz */
        if (start == end) {
          continue ;
        }
        off = start + PGSIZE - la, size = PGSIZE - off;
        if (end < la) {
          size -= la - end;
        }
        memset(page2kva(page) + off, 0, size);
        start += size;
        assert((end < la && start == end) || (end >= la && start == la));
      }

      while (start < end) {
        if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) {
          ret = -E_NO_MEM;
          goto bad_cleanup_mmap;
        }
        off = start - la, size = PGSIZE - off, la += PGSIZE;
        if (end < la) {
          size -= la - end;
        }
        memset(page2kva(page) + off, 0, size);
        start += size;
      }
    }
    sysfile_close(fd);

    mm->brk_start = mm->brk = ROUNDUP(mm->brk_start, PGSIZE);

    /* setup user stack */
    vm_flags = VM_READ | VM_WRITE | VM_STACK;
    if ((ret = mm_map(mm, USTACKTOP - USTACKSIZE, USTACKSIZE, vm_flags, NULL)) != 0) {
      goto bad_cleanup_mmap;
    }

    bool intr_flag;
    local_intr_save(intr_flag);
    {
      list_add(&(proc_mm_list), &(mm->proc_mm_link));
    }
    local_intr_restore(intr_flag);
    mm_count_inc(mm);
    current->mm = mm;
    set_pgdir(current, mm->pgdir);
    mm->lapic = pls_read(lapic_id);
    mp_set_mm_pagetable(mm);

    if (init_new_context (current, elf, argc, kargv, envc, kenvp) < 0)
		goto bad_cleanup_mmap;

    ret = 0;
out:
    return ret;
bad_cleanup_mmap:
    exit_mmap(mm);
bad_elf_cleanup_pgdir:
    put_pgdir(mm);
bad_pgdir_cleanup_mm:
    mm_destroy(mm);
bad_mm:
    goto out;
}
static int ak47_write_proc(struct file *file, const char __user * buffer,
			   unsigned long count, void *data)
{
#define MAX_INPUT_LEN 128
	unsigned char buf[MAX_INPUT_LEN] = { 0 };
	unsigned char bufCMD[MAX_INPUT_LEN] = { 0 };
	int i;
	printk(KERN_ERR "SRT AK47 12.10! \n");
	if (ak47_dev) {
		memset(buf, 0, MAX_INPUT_LEN);
		if (count > 0 && count < MAX_INPUT_LEN) {
			copy_from_user(buf, buffer, count);
			printk(KERN_ERR "SRT AK47 buffer: %s \n", buf);
			unsigned char *sep = strstr(buf, " ");
			if (NULL == sep) {
				printk(KERN_ERR "SRT AK47 error 1! \n");
				return;
			}
			strncpy(bufCMD, buf, sep - buf);
			printk(KERN_ERR "SRT AK47 %s! \n", bufCMD);
			if (strcmp(bufCMD, "plugin") == 0) {

				/*sprd_srt_sdcard_plug(0);*/
			}
			if (strcmp(bufCMD, "plugout") == 0) {
				/*sprd_srt_sdcard_plug(1);*/
			}
			if (strcmp(bufCMD, "emmcpm") == 0) {
				printk(KERN_ERR "SRT do  EMMCPM test! \n");
				char cmd[32] = { 0 };
				strcpy(cmd, sep + 1);
				/*sprd_srt_emmc_test(1,simple_strtol(sep + 1, NULL,10));*/
			}
			if (strcmp(bufCMD, "emmcpmrt") == 0) {
				char cmd[32] = { 0 };
				strcpy(cmd, sep + 1);
				/*sprd_srt_emmc_test(0,simple_strtol(sep + 1, NULL,10));*/
			}
			if (strcmp(bufCMD, "getfreepage") == 0) {
				printk(KERN_ERR "AK47 getfreepage \n");
				void *p = __get_free_page(GFP_KERNEL);
				if (NULL == p) {
					printk(KERN_ERR
					       "AK47 getfreepage [%d] k failed\n",
					       1);
				} else {
					pagec++;
					printk("AK47 getfreepage addr=%x", p);
				}
			}
			if (strcmp(bufCMD, "kmalloc") == 0) {
				printk(KERN_ERR "AK47 kmalloc [%d] k\n",
				       simple_strtol(sep + 1, NULL, 10) * 4);
				void *p =
				    kmalloc(simple_strtol(sep + 1, NULL, 10) *
					    1024 * 4, GFP_KERNEL);
				if (NULL == p) {
					printk(KERN_ERR
					       "AK47 kmalloc [%d] k failed\n",
					       simple_strtol(sep + 1, NULL,
							     10) * 4);
				} else {
					char *pc = (char *)p;
					memset(pc, 0, 255);
					strcpy(pc, "kmallocstring");
					printk("AK47 kmalloc addr=%x,%s", p,
					       pc);
				}
			}
			if (strcmp(bufCMD, "vmalloc") == 0) {
				printk(KERN_ERR "AK47 vmalloc [%d] k\n",
				       simple_strtol(sep + 1, NULL, 10) * 4);
				void *p =
				    vmalloc(simple_strtol(sep + 1, NULL, 10) *
					    1024 * 4);
				if (NULL == p) {
					printk(KERN_ERR
					       "AK47 vmalloc [%d] k failed\n",
					       simple_strtol(sep + 1, NULL,
							     10) * 4);
				} else {
					printk("AK47 vmalloc addr=%x", p);
				}
			}
			if (strcmp(bufCMD, "kstart") == 0) {
				printk(KERN_ERR "AK47 ksatrt [%s] \n", sep + 1);
				int s = simple_strtol(sep + 1, NULL, 10);
				{
					struct task_struct *my_thread = NULL;
					int rc;
					my_thread =
					    kthread_run(thread_func, s,
							"srtkot");
					if (IS_ERR(my_thread)) {
						rc = PTR_ERR(my_thread);
						printk
						    ("AK47 error %d create kthread thread\n",
						     rc);
					} else {
						printk
						    ("AK47 create kthread ok\n");
					}
				}
			}
			if (strcmp(bufCMD, "printk") == 0) {
				printk(KERN_ERR "AK47 printk [%s] \n", sep + 1);
			}
			if (strcmp(bufCMD, "inputkey") == 0) {
				printk(KERN_ERR "AK47 inputkey [%s] \n",
				       sep + 1);
				int param_size = strlen(sep + 1);
				unsigned char *keyBuf = sep + 1;
				for (i = 0; i < param_size; i++) {
					int key = 0;
					if ('u' == keyBuf[i]) {
						key = KEY_VOLUMEUP;
					}
					if ('d' == keyBuf[i]) {
						key = KEY_VOLUMEDOWN;
					}
					input_report_key(ak47_dev, key, 1);
					input_report_key(ak47_dev, key, 0);
					input_sync(ak47_dev);
					printk(KERN_ERR "AK47 inputkey  ok");
				}
			}
			if (strcmp(bufCMD, "slub") == 0) {
				mm_create();
				mm_destroy();
			}
		}
	}
	return count;
}
Beispiel #20
0
// check_swap - check the correctness of swap & page replacement algorithm
static void
check_swap(void) {
    size_t nr_used_pages_store = nr_used_pages();
    size_t slab_allocated_store = slab_allocated();

    size_t offset;
    for (offset = 2; offset < max_swap_offset; offset ++) {
        mem_map[offset] = 1;
    }

    struct mm_struct *mm = mm_create();
    assert(mm != NULL);

    extern struct mm_struct *check_mm_struct;
    assert(check_mm_struct == NULL);

    check_mm_struct = mm;

    pgd_t *pgdir = mm->pgdir = init_pgdir_get();
    assert(pgdir[PGX(TEST_PAGE)] == 0);

    struct vma_struct *vma = vma_create(TEST_PAGE, TEST_PAGE + PTSIZE, VM_WRITE | VM_READ);
    assert(vma != NULL);

    insert_vma_struct(mm, vma);

    struct Page *rp0 = alloc_page(), *rp1 = alloc_page();
    assert(rp0 != NULL && rp1 != NULL);

    pte_perm_t perm;
	ptep_unmap (&perm);
	ptep_set_u_write(&perm);
    int ret = page_insert(pgdir, rp1, TEST_PAGE, perm);
    assert(ret == 0 && page_ref(rp1) == 1);

    page_ref_inc(rp1);
    ret = page_insert(pgdir, rp0, TEST_PAGE, perm);
    assert(ret == 0 && page_ref(rp1) == 1 && page_ref(rp0) == 1);

    // check try_alloc_swap_entry

    swap_entry_t entry = try_alloc_swap_entry();
    assert(swap_offset(entry) == 1);
    mem_map[1] = 1;
    assert(try_alloc_swap_entry() == 0);

    // set rp1, Swap, Active, add to hash_list, active_list

    swap_page_add(rp1, entry);
    swap_active_list_add(rp1);
    assert(PageSwap(rp1));

    mem_map[1] = 0;
    entry = try_alloc_swap_entry();
    assert(swap_offset(entry) == 1);
    assert(!PageSwap(rp1));

    // check swap_remove_entry

    assert(swap_hash_find(entry) == NULL);
    mem_map[1] = 2;
    swap_remove_entry(entry);
    assert(mem_map[1] == 1);

    swap_page_add(rp1, entry);
    swap_inactive_list_add(rp1);
    swap_remove_entry(entry);
    assert(PageSwap(rp1));
    assert(rp1->index == entry && mem_map[1] == 0);

    // check page_launder, move page from inactive_list to active_list

    assert(page_ref(rp1) == 1);
    assert(nr_active_pages == 0 && nr_inactive_pages == 1);
    assert(list_next(&(inactive_list.swap_list)) == &(rp1->swap_link));

    page_launder();
    assert(nr_active_pages == 1 && nr_inactive_pages == 0);
    assert(PageSwap(rp1) && PageActive(rp1));

    entry = try_alloc_swap_entry();
    assert(swap_offset(entry) == 1);
    assert(!PageSwap(rp1) && nr_active_pages == 0);
    assert(list_empty(&(active_list.swap_list)));

    // set rp1 inactive again

    assert(page_ref(rp1) == 1);
    swap_page_add(rp1, 0);
    assert(PageSwap(rp1) && swap_offset(rp1->index) == 1);
    swap_inactive_list_add(rp1);
    mem_map[1] = 1;
    assert(nr_inactive_pages == 1);
    page_ref_dec(rp1);

    size_t count = nr_used_pages();
    swap_remove_entry(entry);
    assert(nr_inactive_pages == 0 && nr_used_pages() == count - 1);

    // check swap_out_mm

    pte_t *ptep0 = get_pte(pgdir, TEST_PAGE, 0), *ptep1;
    assert(ptep0 != NULL && pte2page(*ptep0) == rp0);

    ret = swap_out_mm(mm, 0);
    assert(ret == 0);

    ret = swap_out_mm(mm, 10);
    assert(ret == 1 && mm->swap_address == TEST_PAGE + PGSIZE);

    ret = swap_out_mm(mm, 10);
    assert(ret == 0 && *ptep0 == entry && mem_map[1] == 1);
    assert(PageDirty(rp0) && PageActive(rp0) && page_ref(rp0) == 0);
    assert(nr_active_pages == 1 && list_next(&(active_list.swap_list)) == &(rp0->swap_link));

    // check refill_inactive_scan()

    refill_inactive_scan();
    assert(!PageActive(rp0) && page_ref(rp0) == 0);
    assert(nr_inactive_pages == 1 && list_next(&(inactive_list.swap_list)) == &(rp0->swap_link));

    page_ref_inc(rp0);
    page_launder();
    assert(PageActive(rp0) && page_ref(rp0) == 1);
    assert(nr_active_pages == 1 && list_next(&(active_list.swap_list)) == &(rp0->swap_link));

    page_ref_dec(rp0);
    refill_inactive_scan();
    assert(!PageActive(rp0));

    // save data in rp0

    int i;
    for (i = 0; i < PGSIZE; i ++) {
        ((char *)page2kva(rp0))[i] = (char)i;
    }

    page_launder();
    assert(nr_inactive_pages == 0 && list_empty(&(inactive_list.swap_list)));
    assert(mem_map[1] == 1);

    rp1 = alloc_page();
    assert(rp1 != NULL);
    ret = swapfs_read(entry, rp1);
    assert(ret == 0);

    for (i = 0; i < PGSIZE; i ++) {
        assert(((char *)page2kva(rp1))[i] == (char)i);
    }

    // page fault now

    *(char *)(TEST_PAGE) = 0xEF;

    rp0 = pte2page(*ptep0);
    assert(page_ref(rp0) == 1);
    assert(PageSwap(rp0) && PageActive(rp0));

    entry = try_alloc_swap_entry();
    assert(swap_offset(entry) == 1 && mem_map[1] == SWAP_UNUSED);
    assert(!PageSwap(rp0) && nr_active_pages == 0 && nr_inactive_pages == 0);

    // clear accessed flag

    assert(rp0 == pte2page(*ptep0));
    assert(!PageSwap(rp0));

    ret = swap_out_mm(mm, 10);
    assert(ret == 0);
    assert(!PageSwap(rp0) && ptep_present(ptep0));

    // change page table

    ret = swap_out_mm(mm, 10);
    assert(ret == 1);
    assert(*ptep0 == entry && page_ref(rp0) == 0 && mem_map[1] == 1);

    count = nr_used_pages();
    refill_inactive_scan();
    page_launder();
    assert(count - 1 == nr_used_pages());

    ret = swapfs_read(entry, rp1);
    assert(ret == 0 && *(char *)(page2kva(rp1)) == (char)0xEF);
    free_page(rp1);

    // duplictate *ptep0

    ptep1 = get_pte(pgdir, TEST_PAGE + PGSIZE, 0);
    assert(ptep1 != NULL && ptep_invalid(ptep1));
    swap_duplicate(*ptep0);
	ptep_copy(ptep1, ptep0);
	mp_tlb_invalidate (pgdir, TEST_PAGE + PGSIZE);

    // page fault again
    // update for copy on write

    *(char *)(TEST_PAGE + 1) = 0x88;
    *(char *)(TEST_PAGE + PGSIZE) = 0x8F;
    *(char *)(TEST_PAGE + PGSIZE + 1) = 0xFF;
    assert(pte2page(*ptep0) != pte2page(*ptep1));
    assert(*(char *)(TEST_PAGE) == (char)0xEF);
    assert(*(char *)(TEST_PAGE + 1) == (char)0x88);
    assert(*(char *)(TEST_PAGE + PGSIZE) == (char)0x8F);
    assert(*(char *)(TEST_PAGE + PGSIZE + 1) == (char)0xFF);

    rp0 = pte2page(*ptep0);
    rp1 = pte2page(*ptep1);
    assert(!PageSwap(rp0) && PageSwap(rp1) && PageActive(rp1));

    entry = try_alloc_swap_entry();
    assert(!PageSwap(rp0) && !PageSwap(rp1));
    assert(swap_offset(entry) == 1 && mem_map[1] == SWAP_UNUSED);
    assert(list_empty(&(active_list.swap_list)));
    assert(list_empty(&(inactive_list.swap_list)));

	ptep_set_accessed(&perm);
    page_insert(pgdir, rp0, TEST_PAGE + PGSIZE, perm);

    // check swap_out_mm

    *(char *)(TEST_PAGE) = *(char *)(TEST_PAGE + PGSIZE) = 0xEE;
    mm->swap_address = TEST_PAGE + PGSIZE * 2;
    ret = swap_out_mm(mm, 2);
    assert(ret == 0);
    assert(ptep_present(ptep0) && ! ptep_accessed(ptep0));
    assert(ptep_present(ptep1) && ! ptep_accessed(ptep1));

    ret = swap_out_mm(mm, 2);
    assert(ret == 2);
    assert(mem_map[1] == 2 && page_ref(rp0) == 0);

    refill_inactive_scan();
    page_launder();
    assert(mem_map[1] == 2 && swap_hash_find(entry) == NULL);

    // check copy entry

    swap_remove_entry(entry);
	ptep_unmap(ptep1);
    assert(mem_map[1] == 1);

    swap_entry_t store;
    ret = swap_copy_entry(entry, &store);
    assert(ret == -E_NO_MEM);
    mem_map[2] = SWAP_UNUSED;

    ret = swap_copy_entry(entry, &store);
    assert(ret == 0 && swap_offset(store) == 2 && mem_map[2] == 0);
    mem_map[2] = 1;
	ptep_copy(ptep1, &store);

    assert(*(char *)(TEST_PAGE + PGSIZE) == (char)0xEE && *(char *)(TEST_PAGE + PGSIZE + 1)== (char)0x88);

    *(char *)(TEST_PAGE + PGSIZE) = 1, *(char *)(TEST_PAGE + PGSIZE + 1) = 2;
    assert(*(char *)TEST_PAGE == (char)0xEE && *(char *)(TEST_PAGE + 1) == (char)0x88);

    ret = swap_in_page(entry, &rp0);
    assert(ret == 0);
    ret = swap_in_page(store, &rp1);
    assert(ret == 0);
    assert(rp1 != rp0);

    // free memory

    swap_list_del(rp0), swap_list_del(rp1);
    swap_page_del(rp0), swap_page_del(rp1);

    assert(page_ref(rp0) == 1 && page_ref(rp1) == 1);
    assert(nr_active_pages == 0 && list_empty(&(active_list.swap_list)));
    assert(nr_inactive_pages == 0 && list_empty(&(inactive_list.swap_list)));

    for (i = 0; i < HASH_LIST_SIZE; i ++) {
        assert(list_empty(hash_list + i));
    }

    page_remove(pgdir, TEST_PAGE);
    page_remove(pgdir, (TEST_PAGE + PGSIZE));

#if PMXSHIFT != PUXSHIFT
    free_page(pa2page(PMD_ADDR(*get_pmd(pgdir, TEST_PAGE, 0))));
#endif
#if PUXSHIFT != PGXSHIFT
    free_page(pa2page(PUD_ADDR(*get_pud(pgdir, TEST_PAGE, 0))));
#endif
    free_page(pa2page(PGD_ADDR(*get_pgd(pgdir, TEST_PAGE, 0))));
    pgdir[PGX(TEST_PAGE)] = 0;

    mm->pgdir = NULL;
    mm_destroy(mm);
    check_mm_struct = NULL;

    assert(nr_active_pages == 0 && nr_inactive_pages == 0);
    for (offset = 0; offset < max_swap_offset; offset ++) {
        mem_map[offset] = SWAP_UNUSED;
    }

    assert(nr_used_pages_store == nr_used_pages());
    assert(slab_allocated_store == slab_allocated());

    kprintf("check_swap() succeeded.\n");
}
static void ngx_http_lookaround_destroy()
{
    int ipid = getpid() ;
    fn_v_del_mm_file( MM_BUF_ID , ipid ) ;
    mm_destroy (g_pNLAMM) ;
}
int main( int argc, char** argv )
{
    uint64_t i;

    // pointers for casting
    pq_op_create *op_create;
    pq_op_destroy *op_destroy;
    pq_op_clear *op_clear;
    pq_op_get_key *op_get_key;
    pq_op_get_item *op_get_item;
    pq_op_get_size *op_get_size;
    pq_op_insert *op_insert;
    pq_op_find_min *op_find_min;
    pq_op_delete *op_delete;
    pq_op_delete_min *op_delete_min;
    pq_op_decrease_key *op_decrease_key;
    //pq_op_meld *op_meld;
    pq_op_empty *op_empty;

    // temp dummies for readability
    pq_type *q;//, *r;
    pq_node_type *n;

    if( argc < 2 )
        exit( -1 );

    int trace_file = open( argv[1], O_RDONLY );
    if( trace_file < 0 )
    {
        fprintf( stderr, "Could not open file.\n" );
        return -1;
    }

    pq_trace_header header;
    pq_trace_read_header( trace_file, &header );
    close( trace_file );

    //printf("Header: (%llu,%lu,%lu)\n",header.op_count,header.pq_ids,
    //    header.node_ids);

    pq_op_blank *ops = calloc( MIN( header.op_count, CHUNK_SIZE ),
        sizeof( pq_op_blank ) );
    pq_type **pq_index = calloc( header.pq_ids, sizeof( pq_type* ) );
    pq_node_type **node_index = calloc( header.node_ids,
        sizeof( pq_node_type* ) );
    if( ops == NULL || pq_index == NULL || node_index == NULL )
    {
        fprintf( stderr, "Calloc fail.\n" );
        return -1;
    }

#ifdef USE_QUAKE
    mem_capacities[0] = header.node_ids << 2;
#else
    mem_capacities[0] = header.node_ids;
#endif

#ifdef USE_EAGER
    mem_map *map = mm_create( mem_types, mem_sizes, mem_capacities );
#else
    mem_map *map = mm_create( mem_types, mem_sizes );
#endif

    uint64_t op_remaining, op_chunk;
    int status;
    struct timeval t0, t1;
    uint32_t iterations = 0;
    uint32_t total_time = 0;
    key_type k;
    //pq_node_type *min;

#ifndef CACHEGRIND
    while( iterations < 5 || total_time < PQ_MIN_USEC )
    {
        mm_clear( map );
        iterations++;
#endif

        trace_file = open( argv[1], O_RDONLY );
        if( trace_file < 0 )
        {
            fprintf( stderr, "Could not open file.\n" );
            return -1;
        }
        pq_trace_read_header( trace_file, &header );
        op_remaining = header.op_count;

        while( op_remaining > 0 )
        {
            op_chunk = MIN( CHUNK_SIZE, op_remaining );
            op_remaining -= op_chunk;

            for( i = 0; i < op_chunk; i++ )
            {
                status = pq_trace_read_op( trace_file, ops + i );
                if( status == -1 )
                {
                    fprintf( stderr, "Invalid operation!" );
                    return -1;
                }
            }

#ifndef CACHEGRIND
            gettimeofday(&t0, NULL);
#endif

            for( i = 0; i < op_chunk; i++ )
            {
                switch( ops[i].code )
                {
                    case PQ_OP_CREATE:
                        op_create = (pq_op_create*) ( ops + i );
                        //printf("pq_create(%d)\n", op_create->pq_id);
                        pq_index[op_create->pq_id] = pq_create( map );
                        break;
                    case PQ_OP_DESTROY:
                        op_destroy = (pq_op_destroy*) ( ops + i );
                        //printf("pq_destroy(%d)\n", op_destroy->pq_id);
                        q = pq_index[op_destroy->pq_id];
                        pq_destroy( q );
                        pq_index[op_destroy->pq_id] = NULL;
                        break;
                    case PQ_OP_CLEAR:
                        op_clear = (pq_op_clear*) ( ops + i );
                        //printf("pq_clear(%d)\n", op_clear->pq_id );
                        q = pq_index[op_clear->pq_id];
                        pq_clear( q );
                        break;
                    case PQ_OP_GET_KEY:
                        op_get_key = (pq_op_get_key*) ( ops + i );
                        //printf("pq_get_key(%d,%d)\n", op_get_key->pq_id,
                        //    op_get_key->node_id );
                        q = pq_index[op_get_key->pq_id];
                        n = node_index[op_get_key->node_id];
                        pq_get_key( q, n );
                        break;
                    case PQ_OP_GET_ITEM:
                        op_get_item = (pq_op_get_item*) ( ops + i );
                        //printf("pq_get_item(%d,%d)\n", op_get_item->pq_id,
                        //    op_get_item->node_id);
                        q = pq_index[op_get_item->pq_id];
                        n = node_index[op_get_item->node_id];
                        pq_get_item( q, n );
                        break;
                    case PQ_OP_GET_SIZE:
                        op_get_size = (pq_op_get_size*) ( ops + i );
                        //printf("pq_get_size(%d)\n", op_get_size->pq_id);
                        q = pq_index[op_get_size->pq_id];
                        pq_get_size( q );
                        break;
                    case PQ_OP_INSERT:
                        op_insert = (pq_op_insert*) ( ops + i );
                        //printf("pq_insert(%d,%d,%llu,%d)\n", op_insert->pq_id,
                        //    op_insert->node_id, op_insert->key, op_insert->item );
                        q = pq_index[op_insert->pq_id];
                        node_index[op_insert->node_id] = pq_insert( q,
                            op_insert->item, op_insert->key );
                        break;
                    case PQ_OP_FIND_MIN:
                        op_find_min = (pq_op_find_min*) ( ops + i );
                        //printf("pq_find_min(%d)\n", op_find_min->pq_id );
                        q = pq_index[op_find_min->pq_id];
                        pq_find_min( q );
                        break;
                    case PQ_OP_DELETE:
                        op_delete = (pq_op_delete*) ( ops + i );
                        //printf("pq_delete(%d,%d)\n", op_delete->pq_id,
                        //    op_delete->node_id );
                        q = pq_index[op_delete->pq_id];
                        n = node_index[op_delete->node_id];
                        pq_delete( q, n );
                        break;
                    case PQ_OP_DELETE_MIN:
                        op_delete_min = (pq_op_delete_min*) ( ops + i );
                        //printf("pq_delete_min(%d)\n", op_delete_min->pq_id);
                        q = pq_index[op_delete_min->pq_id];
                        //min = pq_find_min( q );
                        k = pq_delete_min( q );
#ifdef CACHEGRIND
                        if( argc > 2 )
                            printf("%llu\n",k);
#endif
                        break;
                    case PQ_OP_DECREASE_KEY:
                        op_decrease_key = (pq_op_decrease_key*) ( ops + i );
                        //printf("pq_decrease_key(%d,%d,%llu)\n", op_decrease_key->pq_id,
                        //    op_decrease_key->node_id, op_decrease_key->key);
                        q = pq_index[op_decrease_key->pq_id];
                        n = node_index[op_decrease_key->node_id];
                        pq_decrease_key( q, n, op_decrease_key->key );
                        break;
                    /*case PQ_OP_MELD:
                        printf("Meld.\n");
                        op_meld = (pq_op_meld*) ( ops + i );
                        q = pq_index[op_meld->pq_src1_id];
                        r = pq_index[op_meld->pq_src2_id];
                        pq_index[op_meld->pq_dst_id] = pq_meld( q, r );
                        break;*/
                    case PQ_OP_EMPTY:
                        op_empty = (pq_op_empty*) ( ops + i );
                        //printf("pq_empty(%d)\n", op_empty->pq_id);
                        q = pq_index[op_empty->pq_id];
                        pq_empty( q );
                        break;
                    default:
                        break;
                }
                //verify_queue( pq_index[0], header.node_ids );
            }

#ifndef CACHEGRIND
            gettimeofday(&t1, NULL);
            total_time += (t1.tv_sec - t0.tv_sec) * 1000000 +
                (t1.tv_usec - t0.tv_usec);
#endif
        }

        close( trace_file );
#ifndef CACHEGRIND
    }
#endif

    for( i = 0; i < header.pq_ids; i++ )
    {
        if( pq_index[i] != NULL )
            pq_destroy( pq_index[i] );
    }

    mm_destroy( map );
    free( pq_index );
    free( node_index );
    free( ops );

#ifndef CACHEGRIND
    printf( "%d\n", total_time / iterations );
#endif

    return 0;
}
Beispiel #23
0
static void
check_mm_swap(void) {
    size_t nr_free_pages_store = nr_free_pages();
    size_t slab_allocated_store = slab_allocated();

    int ret, i, j;
    for (i = 0; i < max_swap_offset; i ++) {
        assert(mem_map[i] == SWAP_UNUSED);
    }

    extern struct mm_struct *check_mm_struct;
    assert(check_mm_struct == NULL);

    // step1: check mm_map

    struct mm_struct *mm0 = mm_create(), *mm1;
    assert(mm0 != NULL && list_empty(&(mm0->mmap_list)));

    uintptr_t addr0, addr1;

    addr0 = 0;
    do {
        ret = mm_map(mm0, addr0, PTSIZE, 0, NULL);
        assert(ret == (USER_ACCESS(addr0, addr0 + PTSIZE)) ? 0 : -E_INVAL);
        addr0 += PTSIZE;
    } while (addr0 != 0);

    addr0 = 0;
    for (i = 0; i < 1024; i ++, addr0 += PTSIZE) {
        ret = mm_map(mm0, addr0, PGSIZE, 0, NULL);
        assert(ret == -E_INVAL);
    }

    mm_destroy(mm0);


    mm0 = mm_create();
    assert(mm0 != NULL && list_empty(&(mm0->mmap_list)));

    addr0 = 0, i = 0;
    do {
        ret = mm_map(mm0, addr0, PTSIZE - PGSIZE, 0, NULL);
        assert(ret == (USER_ACCESS(addr0, addr0 + PTSIZE)) ? 0 : -E_INVAL);
        if (ret == 0) {
            i ++;
        }
        addr0 += PTSIZE;
    } while (addr0 != 0);

    addr0 = 0, j = 0;
    do {
        addr0 += PTSIZE - PGSIZE;
        ret = mm_map(mm0, addr0, PGSIZE, 0, NULL);
        assert(ret == (USER_ACCESS(addr0, addr0 + PGSIZE)) ? 0 : -E_INVAL);
        if (ret == 0) {
            j ++;
        }
        addr0 += PGSIZE;
    } while (addr0 != 0);

    assert(j + 1 >= i);

    mm_destroy(mm0);

    assert(nr_free_pages_store == nr_free_pages());
    assert(slab_allocated_store == slab_allocated());

    cprintf("check_mm_swap: step1, mm_map ok.\n");

    // step2: check page fault

    mm0 = mm_create();
    assert(mm0 != NULL && list_empty(&(mm0->mmap_list)));

    // setup page table

    struct Page *page = alloc_page();
    assert(page != NULL);
    pde_t *pgdir = page2kva(page);
    memcpy(pgdir, boot_pgdir, PGSIZE);
    pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_P | PTE_W;

    // prepare for page fault

    mm0->pgdir = pgdir;
    check_mm_struct = mm0;
    lcr3(PADDR(mm0->pgdir));

    uint32_t vm_flags = VM_WRITE | VM_READ;
    struct vma_struct *vma;

    addr0 = 0;
    do {
        if ((ret = mm_map(mm0, addr0, PTSIZE, vm_flags, &vma)) == 0) {
            break;
        }
        addr0 += PTSIZE;
    } while (addr0 != 0);

    assert(ret == 0 && addr0 != 0 && mm0->map_count == 1);
    assert(vma->vm_start == addr0 && vma->vm_end == addr0 + PTSIZE);

    // check pte entry

    pte_t *ptep;
    for (addr1 = addr0; addr1 < addr0 + PTSIZE; addr1 += PGSIZE) {
        ptep = get_pte(pgdir, addr1, 0);
        assert(ptep == NULL);
    }

    memset((void *)addr0, 0xEF, PGSIZE * 2);
    ptep = get_pte(pgdir, addr0, 0);
    assert(ptep != NULL && (*ptep & PTE_P));
    ptep = get_pte(pgdir, addr0 + PGSIZE, 0);
    assert(ptep != NULL && (*ptep & PTE_P));

    ret = mm_unmap(mm0, - PTSIZE, PTSIZE);
    assert(ret == -E_INVAL);
    ret = mm_unmap(mm0, addr0 + PTSIZE, PGSIZE);
    assert(ret == 0);

    addr1 = addr0 + PTSIZE / 2;
    ret = mm_unmap(mm0, addr1, PGSIZE);
    assert(ret == 0 && mm0->map_count == 2);

    ret = mm_unmap(mm0, addr1 + 2 * PGSIZE, PGSIZE * 4);
    assert(ret == 0 && mm0->map_count == 3);

    ret = mm_map(mm0, addr1, PGSIZE * 6, 0, NULL);
    assert(ret == -E_INVAL);
    ret = mm_map(mm0, addr1, PGSIZE, 0, NULL);
    assert(ret == 0 && mm0->map_count == 4);
    ret = mm_map(mm0, addr1 + 2 * PGSIZE, PGSIZE * 4, 0, NULL);
    assert(ret == 0 && mm0->map_count == 5);

    ret = mm_unmap(mm0, addr1 + PGSIZE / 2, PTSIZE / 2 - PGSIZE);
    assert(ret == 0 && mm0->map_count == 1);

    addr1 = addr0 + PGSIZE;
    for (i = 0; i < PGSIZE; i ++) {
        assert(*(char *)(addr1 + i) == (char)0xEF);
    }

    ret = mm_unmap(mm0, addr1 + PGSIZE / 2, PGSIZE / 4);
    assert(ret == 0 && mm0->map_count == 2);
    ptep = get_pte(pgdir, addr0, 0);
    assert(ptep != NULL && (*ptep & PTE_P));
    ptep = get_pte(pgdir, addr0 + PGSIZE, 0);
    assert(ptep != NULL && *ptep == 0);

    ret = mm_map(mm0, addr1, PGSIZE, vm_flags, NULL);
    memset((void *)addr1, 0x88, PGSIZE);
    assert(*(char *)addr1 == (char)0x88 && mm0->map_count == 3);

    for (i = 1; i < 16; i += 2) {
        ret = mm_unmap(mm0, addr0 + PGSIZE * i, PGSIZE);
        assert(ret == 0);
        if (i < 8) {
            ret = mm_map(mm0, addr0 + PGSIZE * i, PGSIZE, 0, NULL);
            assert(ret == 0);
        }
    }
    assert(mm0->map_count == 13);

    ret = mm_unmap(mm0, addr0 + PGSIZE * 2, PTSIZE - PGSIZE * 2);
    assert(ret == 0 && mm0->map_count == 2);

    ret = mm_unmap(mm0, addr0, PGSIZE * 2);
    assert(ret == 0 && mm0->map_count == 0);

    cprintf("check_mm_swap: step2, mm_unmap ok.\n");

    // step3: check exit_mmap

    ret = mm_map(mm0, addr0, PTSIZE, vm_flags, NULL);
    assert(ret == 0);

    for (i = 0, addr1 = addr0; i < 4; i ++, addr1 += PGSIZE) {
        *(char *)addr1 = (char)0xFF;
    }

    exit_mmap(mm0);
    for (i = 0; i < PDX(KERNBASE); i ++) {
        assert(pgdir[i] == 0);
    }

    cprintf("check_mm_swap: step3, exit_mmap ok.\n");

    // step4: check dup_mmap

    for (i = 0; i < max_swap_offset; i ++) {
        assert(mem_map[i] == SWAP_UNUSED);
    }

    ret = mm_map(mm0, addr0, PTSIZE, vm_flags, NULL);
    assert(ret != 0);

    addr1 = addr0;
    for (i = 0; i < 4; i ++, addr1 += PGSIZE) {
        *(char *)addr1 = (char)(i * i);
    }

    ret = 0;
    ret += swap_out_mm(mm0, 10);
    ret += swap_out_mm(mm0, 10);
    assert(ret == 4);

    for (; i < 8; i ++, addr1 += PGSIZE) {
        *(char *)addr1 = (char)(i * i);
    }

    // setup mm1

    mm1 = mm_create();
    assert(mm1 != NULL);

    page = alloc_page();
    assert(page != NULL);
    pgdir = page2kva(page);
    memcpy(pgdir, boot_pgdir, PGSIZE);
    pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_P | PTE_W;
    mm1->pgdir = pgdir;

    ret = dup_mmap(mm1, mm0);
    assert(ret == 0);

    // switch to mm1

    check_mm_struct = mm1;
    lcr3(PADDR(mm1->pgdir));

    addr1 = addr0;
    for (i = 0; i < 8; i ++, addr1 += PGSIZE) {
        assert(*(char *)addr1 == (char)(i * i));
        *(char *)addr1 = (char)0x88;
    }

    // switch to mm0

    check_mm_struct = mm0;
    lcr3(PADDR(mm0->pgdir));

    addr1 = addr0;
    for (i = 0; i < 8; i ++, addr1 += PGSIZE) {
        assert(*(char *)addr1 == (char)(i * i));
    }

    // switch to boot_cr3

    check_mm_struct = NULL;
    lcr3(boot_cr3);

    // free memory

    exit_mmap(mm0);
    exit_mmap(mm1);

    free_page(kva2page(mm0->pgdir));
    mm_destroy(mm0);
    free_page(kva2page(mm1->pgdir));
    mm_destroy(mm1);

    cprintf("check_mm_swap: step4, dup_mmap ok.\n");

    refill_inactive_scan();
    page_launder();
    for (i = 0; i < max_swap_offset; i ++) {
        assert(mem_map[i] == SWAP_UNUSED);
    }

    assert(nr_free_pages_store == nr_free_pages());
    assert(slab_allocated_store == slab_allocated());

    cprintf("check_mm_swap() succeeded.\n");
}
Beispiel #24
0
static void check_swap(void)
{
	//backup mem env
	int ret, count = 0, total = 0, i;
	list_entry_t *le = &free_list;
	while ((le = list_next(le)) != &free_list)
	{
		struct Page *p = le2page(le, page_link);
		assert(PageProperty(p));
		count++, total += p->property;
	}
	assert(total == nr_free_pages());
	cprintf("BEGIN check_swap: count %d, total %d\n", count, total);

	//now we set the phy pages env
	struct mm_struct *mm = mm_create();
	assert(mm != NULL);

	extern struct mm_struct *check_mm_struct;
	assert(check_mm_struct == NULL);

	check_mm_struct = mm;

	pde_t *pgdir = mm->pgdir = boot_pgdir;
	assert(pgdir[0] == 0);

	struct vma_struct *vma = vma_create(BEING_CHECK_VALID_VADDR,
			CHECK_VALID_VADDR, VM_WRITE | VM_READ);
	assert(vma != NULL);

	insert_vma_struct(mm, vma);

	//setup the temp Page Table vaddr 0~4MB
	cprintf("setup Page Table for vaddr 0X1000, so alloc a page\n");
	pte_t *temp_ptep = NULL;
	temp_ptep = get_pte(mm->pgdir, BEING_CHECK_VALID_VADDR, 1);
	assert(temp_ptep!= NULL);
	cprintf("setup Page Table vaddr 0~4MB OVER!\n");

	for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++)
	{
		check_rp[i] = alloc_page();
		assert(check_rp[i] != NULL);
		assert(!PageProperty(check_rp[i]));
	}
	list_entry_t free_list_store = free_list;
	list_init(&free_list);
	assert(list_empty(&free_list));

	//assert(alloc_page() == NULL);

	unsigned int nr_free_store = nr_free;
	nr_free = 0;
	for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++)
	{
		free_pages(check_rp[i], 1);
	}
	assert(nr_free==CHECK_VALID_PHY_PAGE_NUM);

	cprintf("set up init env for check_swap begin!\n");
	//setup initial vir_page<->phy_page environment for page relpacement algorithm

	pgfault_num = 0;

	check_content_set();
	assert(nr_free == 0);
	for (i = 0; i < MAX_SEQ_NO; i++)
		swap_out_seq_no[i] = swap_in_seq_no[i] = -1;

	for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++)
	{
		check_ptep[i] = 0;
		check_ptep[i] = get_pte(pgdir, (i + 1) * 0x1000, 0);
		//cprintf("i %d, check_ptep addr %x, value %x\n", i, check_ptep[i], *check_ptep[i]);
		assert(check_ptep[i] != NULL);
		assert(pte2page(*check_ptep[i]) == check_rp[i]);
		assert((*check_ptep[i] & PTE_P));
	}
	cprintf("set up init env for check_swap over!\n");
	// now access the virt pages to test  page relpacement algorithm
	ret = check_content_access();
	assert(ret == 0);

	//restore kernel mem env
	for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++)
	{
		free_pages(check_rp[i], 1);
	}

	//free_page(pte2page(*temp_ptep));
	free_page(pde2page(pgdir[0]));
	pgdir[0] = 0;
	mm->pgdir = NULL;
	mm_destroy(mm);
	check_mm_struct = NULL;

	nr_free = nr_free_store;
	free_list = free_list_store;

	le = &free_list;
	while ((le = list_next(le)) != &free_list)
	{
		struct Page *p = le2page(le, page_link);
		count--, total -= p->property;
	}
	cprintf("count is %d, total is %d\n", count, total);
	//assert(count == 0);

	cprintf("check_swap() succeeded!\n");
}
Beispiel #25
0
static void
check_mm_shm_swap(void) {
    size_t nr_free_pages_store = nr_free_pages();
    size_t slab_allocated_store = slab_allocated();

    int ret, i;
    for (i = 0; i < max_swap_offset; i ++) {
        assert(mem_map[i] == SWAP_UNUSED);
    }

    extern struct mm_struct *check_mm_struct;
    assert(check_mm_struct == NULL);

    struct mm_struct *mm0 = mm_create(), *mm1;
    assert(mm0 != NULL && list_empty(&(mm0->mmap_list)));

    struct Page *page = alloc_page();
    assert(page != NULL);
    pde_t *pgdir = page2kva(page);
    memcpy(pgdir, boot_pgdir, PGSIZE);
    pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_P | PTE_W;

    mm0->pgdir = pgdir;
    check_mm_struct = mm0;
    lcr3(PADDR(mm0->pgdir));

    uint32_t vm_flags = VM_WRITE | VM_READ;

    uintptr_t addr0, addr1;

    addr0 = 0;
    do {
        if ((ret = mm_map(mm0, addr0, PTSIZE * 4, vm_flags, NULL)) == 0) {
            break;
        }
        addr0 += PTSIZE;
    } while (addr0 != 0);

    assert(ret == 0 && addr0 != 0 && mm0->map_count == 1);

    ret = mm_unmap(mm0, addr0, PTSIZE * 4);
    assert(ret == 0 && mm0->map_count == 0);

    struct shmem_struct *shmem = shmem_create(PTSIZE * 2);
    assert(shmem != NULL && shmem_ref(shmem) == 0);

    // step1: check share memory

    struct vma_struct *vma;

    addr1 = addr0 + PTSIZE * 2;
    ret = mm_map_shmem(mm0, addr0, vm_flags, shmem, &vma);
    assert(ret == 0);
    assert((vma->vm_flags & VM_SHARE) && vma->shmem == shmem && shmem_ref(shmem) == 1);
    ret = mm_map_shmem(mm0, addr1, vm_flags, shmem, &vma);
    assert(ret == 0);
    assert((vma->vm_flags & VM_SHARE) && vma->shmem == shmem && shmem_ref(shmem) == 2);

    // page fault

    for (i = 0; i < 4; i ++) {
        *(char *)(addr0 + i * PGSIZE) = (char)(i * i);
    }
    for (i = 0; i < 4; i ++) {
        assert(*(char *)(addr1 + i * PGSIZE) == (char)(i * i));
    }

    for (i = 0; i < 4; i ++) {
        *(char *)(addr1 + i * PGSIZE) = (char)(- i * i);
    }
    for (i = 0; i < 4; i ++) {
        assert(*(char *)(addr1 + i * PGSIZE) == (char)(- i * i));
    }

    // check swap

    ret = swap_out_mm(mm0, 8) + swap_out_mm(mm0, 8);
    assert(ret == 8 && nr_active_pages == 4 && nr_inactive_pages == 0);

    refill_inactive_scan();
    assert(nr_active_pages == 0 && nr_inactive_pages == 4);

    // write & read again

    memset((void *)addr0, 0x77, PGSIZE);
    for (i = 0; i < PGSIZE; i ++) {
        assert(*(char *)(addr1 + i) == (char)0x77);
    }

    // check unmap

    ret = mm_unmap(mm0, addr1, PGSIZE * 4);
    assert(ret == 0);

    addr0 += 4 * PGSIZE, addr1 += 4 * PGSIZE;
    *(char *)(addr0) = (char)(0xDC);
    assert(*(char *)(addr1) == (char)(0xDC));
    *(char *)(addr1 + PTSIZE) = (char)(0xDC);
    assert(*(char *)(addr0 + PTSIZE) == (char)(0xDC));

    cprintf("check_mm_shm_swap: step1, share memory ok.\n");

    // setup mm1

    mm1 = mm_create();
    assert(mm1 != NULL);


    page = alloc_page();
    assert(page != NULL);
    pgdir = page2kva(page);
    memcpy(pgdir, boot_pgdir, PGSIZE);
    pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_P | PTE_W;
    mm1->pgdir = pgdir;


    ret = dup_mmap(mm1, mm0);
    assert(ret == 0 && shmem_ref(shmem) == 4);

    // switch to mm1

    check_mm_struct = mm1;
    lcr3(PADDR(mm1->pgdir));

    for (i = 0; i < 4; i ++) {
        *(char *)(addr0 + i * PGSIZE) = (char)(0x57 + i);
    }
    for (i = 0; i < 4; i ++) {
        assert(*(char *)(addr1 + i * PGSIZE) == (char)(0x57 + i));
    }

    check_mm_struct = mm0;
    lcr3(PADDR(mm0->pgdir));

    for (i = 0; i < 4; i ++) {
        assert(*(char *)(addr0 + i * PGSIZE) == (char)(0x57 + i));
        assert(*(char *)(addr1 + i * PGSIZE) == (char)(0x57 + i));
    }

    swap_out_mm(mm1, 4);
    exit_mmap(mm1);

    free_page(kva2page(mm1->pgdir));
    mm_destroy(mm1);

    assert(shmem_ref(shmem) == 2);

    cprintf("check_mm_shm_swap: step2, dup_mmap ok.\n");

    // free memory

    check_mm_struct = NULL;
    lcr3(boot_cr3);

    exit_mmap(mm0);
    free_page(kva2page(mm0->pgdir));
    mm_destroy(mm0);

    refill_inactive_scan();
    page_launder();
    for (i = 0; i < max_swap_offset; i ++) {
        assert(mem_map[i] == SWAP_UNUSED);
    }

    assert(nr_free_pages_store == nr_free_pages());
    assert(slab_allocated_store == slab_allocated());

    cprintf("check_mm_shm_swap() succeeded.\n");
}
Beispiel #26
0
// check_swap - check the correctness of swap & page replacement algorithm
static void
check_swap(void) {
    size_t nr_free_pages_store = nr_free_pages();
    size_t slab_allocated_store = slab_allocated();

    size_t offset;
    for (offset = 2; offset < max_swap_offset; offset ++) {
        mem_map[offset] = 1;
    }

    struct mm_struct *mm = mm_create();
    assert(mm != NULL);

    extern struct mm_struct *check_mm_struct;
    assert(check_mm_struct == NULL);

    check_mm_struct = mm;

    pde_t *pgdir = mm->pgdir = boot_pgdir;
    assert(pgdir[0] == 0);

    struct vma_struct *vma = vma_create(0, PTSIZE, VM_WRITE | VM_READ);
    assert(vma != NULL);

    insert_vma_struct(mm, vma);

    struct Page *rp0 = alloc_page(), *rp1 = alloc_page();
    assert(rp0 != NULL && rp1 != NULL);

    uint32_t perm = PTE_U | PTE_W;
    int ret = page_insert(pgdir, rp1, 0, perm);
    assert(ret == 0 && page_ref(rp1) == 1);

    page_ref_inc(rp1);
    ret = page_insert(pgdir, rp0, 0, perm);
    assert(ret == 0 && page_ref(rp1) == 1 && page_ref(rp0) == 1);

    // check try_alloc_swap_entry

    swap_entry_t entry = try_alloc_swap_entry();
    assert(swap_offset(entry) == 1);
    mem_map[1] = 1;
    assert(try_alloc_swap_entry() == 0);

    // set rp1, Swap, Active, add to hash_list, active_list

    swap_page_add(rp1, entry);
    swap_active_list_add(rp1);
    assert(PageSwap(rp1));

    mem_map[1] = 0;
    entry = try_alloc_swap_entry();
    assert(swap_offset(entry) == 1);
    assert(!PageSwap(rp1));

    // check swap_remove_entry

    assert(swap_hash_find(entry) == NULL);
    mem_map[1] = 2;
    swap_remove_entry(entry);
    assert(mem_map[1] == 1);

    swap_page_add(rp1, entry);
    swap_inactive_list_add(rp1);
    swap_remove_entry(entry);
    assert(PageSwap(rp1));
    assert(rp1->index == entry && mem_map[1] == 0);

    // check page_launder, move page from inactive_list to active_list

    assert(page_ref(rp1) == 1);
    assert(nr_active_pages == 0 && nr_inactive_pages == 1);
    assert(list_next(&(inactive_list.swap_list)) == &(rp1->swap_link));

    page_launder();
    assert(nr_active_pages == 1 && nr_inactive_pages == 0);
    assert(PageSwap(rp1) && PageActive(rp1));

    entry = try_alloc_swap_entry();
    assert(swap_offset(entry) == 1);
    assert(!PageSwap(rp1) && nr_active_pages == 0);
    assert(list_empty(&(active_list.swap_list)));

    // set rp1 inactive again

    assert(page_ref(rp1) == 1);
    swap_page_add(rp1, 0);
    assert(PageSwap(rp1) && swap_offset(rp1->index) == 1);
    swap_inactive_list_add(rp1);
    mem_map[1] = 1;
    assert(nr_inactive_pages == 1);
    page_ref_dec(rp1);

    size_t count = nr_free_pages();
    swap_remove_entry(entry);
    assert(nr_inactive_pages == 0 && nr_free_pages() == count + 1);

    // check swap_out_mm

    pte_t *ptep0 = get_pte(pgdir, 0, 0), *ptep1;
    assert(ptep0 != NULL && pte2page(*ptep0) == rp0);

    ret = swap_out_mm(mm, 0);
    assert(ret == 0);

    ret = swap_out_mm(mm, 10);
    assert(ret == 1 && mm->swap_address == PGSIZE);

    ret = swap_out_mm(mm, 10);
    assert(ret == 0 && *ptep0 == entry && mem_map[1] == 1);
    assert(PageDirty(rp0) && PageActive(rp0) && page_ref(rp0) == 0);
    assert(nr_active_pages == 1 && list_next(&(active_list.swap_list)) == &(rp0->swap_link));

    // check refill_inactive_scan()

    refill_inactive_scan();
    assert(!PageActive(rp0) && page_ref(rp0) == 0);
    assert(nr_inactive_pages == 1 && list_next(&(inactive_list.swap_list)) == &(rp0->swap_link));

    page_ref_inc(rp0);
    page_launder();
    assert(PageActive(rp0) && page_ref(rp0) == 1);
    assert(nr_active_pages == 1 && list_next(&(active_list.swap_list)) == &(rp0->swap_link));

    page_ref_dec(rp0);
    refill_inactive_scan();
    assert(!PageActive(rp0));

    // save data in rp0

    int i;
    for (i = 0; i < PGSIZE; i ++) {
        ((char *)page2kva(rp0))[i] = (char)i;
    }

    page_launder();
    assert(nr_inactive_pages == 0 && list_empty(&(inactive_list.swap_list)));
    assert(mem_map[1] == 1);

    rp1 = alloc_page();
    assert(rp1 != NULL);
    ret = swapfs_read(entry, rp1);
    assert(ret == 0);

    for (i = 0; i < PGSIZE; i ++) {
        assert(((char *)page2kva(rp1))[i] == (char)i);
    }

    // page fault now

    *(char *)0 = 0xEF;

    rp0 = pte2page(*ptep0);
    assert(page_ref(rp0) == 1);
    assert(PageSwap(rp0) && PageActive(rp0));

    entry = try_alloc_swap_entry();
    assert(swap_offset(entry) == 1 && mem_map[1] == SWAP_UNUSED);
    assert(!PageSwap(rp0) && nr_active_pages == 0 && nr_inactive_pages == 0);

    // clear accessed flag

    assert(rp0 == pte2page(*ptep0));
    assert(!PageSwap(rp0));

    ret = swap_out_mm(mm, 10);
    assert(ret == 0);
    assert(!PageSwap(rp0) && (*ptep0 & PTE_P));

    // change page table

    ret = swap_out_mm(mm, 10);
    assert(ret == 1);
    assert(*ptep0 == entry && page_ref(rp0) == 0 && mem_map[1] == 1);

    count = nr_free_pages();
    refill_inactive_scan();
    page_launder();
    assert(count + 1 == nr_free_pages());

    ret = swapfs_read(entry, rp1);
    assert(ret == 0 && *(char *)(page2kva(rp1)) == (char)0xEF);
    free_page(rp1);

    // duplictate *ptep0

    ptep1 = get_pte(pgdir, PGSIZE, 0);
    assert(ptep1 != NULL && *ptep1 == 0);
    swap_duplicate(*ptep0);
    *ptep1 = *ptep0;

    // page fault again

    *(char *)0 = 0xFF;
    *(char *)(PGSIZE + 1) = 0x88;
    assert(pte2page(*ptep0) == pte2page(*ptep1));
    rp0 = pte2page(*ptep0);
    assert(*(char *)1 == (char)0x88 && *(char *)PGSIZE == (char)0xFF);

    assert(page_ref(rp0) == 2 && rp0->index == entry && mem_map[1] == 0);

    assert(PageSwap(rp0) && PageActive(rp0));
    entry = try_alloc_swap_entry();
    assert(swap_offset(entry) == 1 && mem_map[1] == SWAP_UNUSED);
    assert(!PageSwap(rp0));
    assert(list_empty(&(active_list.swap_list)));
    assert(list_empty(&(inactive_list.swap_list)));

    // check swap_out_mm

    *(char *)0 = *(char *)PGSIZE = 0xEE;
    mm->swap_address = PGSIZE * 2;
    ret = swap_out_mm(mm, 2);
    assert(ret == 0);
    assert((*ptep0 & PTE_P) && !(*ptep0 & PTE_A));
    assert((*ptep1 & PTE_P) && !(*ptep1 & PTE_A));

    ret = swap_out_mm(mm, 2);
    assert(ret == 2);
    assert(mem_map[1] == 2 && page_ref(rp0) == 0);

    refill_inactive_scan();
    page_launder();
    assert(mem_map[1] == 2 && swap_hash_find(entry) == NULL);

    // check copy entry

    swap_remove_entry(entry);
    *ptep1 = 0;
    assert(mem_map[1] == 1);

    swap_entry_t store;
    ret = swap_copy_entry(entry, &store);
    assert(ret == -E_NO_MEM);
    mem_map[2] = SWAP_UNUSED;

    ret = swap_copy_entry(entry, &store);
    assert(ret == 0 && swap_offset(store) == 2 && mem_map[2] == 0);
    mem_map[2] = 1;
    *ptep1 = store;

    assert(*(char *)PGSIZE == (char)0xEE && *(char *)(PGSIZE + 1)== (char)0x88);

    *(char *)PGSIZE = 1, *(char *)(PGSIZE + 1) = 2;
    assert(*(char *)0 == (char)0xEE && *(char *)1 == (char)0x88);

    ret = swap_in_page(entry, &rp0);
    assert(ret == 0);
    ret = swap_in_page(store, &rp1);
    assert(ret == 0);
    assert(rp1 != rp0);

    // free memory

    swap_list_del(rp0), swap_list_del(rp1);
    swap_page_del(rp0), swap_page_del(rp1);

    assert(page_ref(rp0) == 1 && page_ref(rp1) == 1);
    assert(nr_active_pages == 0 && list_empty(&(active_list.swap_list)));
    assert(nr_inactive_pages == 0 && list_empty(&(inactive_list.swap_list)));

    for (i = 0; i < HASH_LIST_SIZE; i ++) {
        assert(list_empty(hash_list + i));
    }

    page_remove(pgdir, 0);
    page_remove(pgdir, PGSIZE);

    free_page(pa2page(pgdir[0]));
    pgdir[0] = 0;

    mm->pgdir = NULL;
    mm_destroy(mm);
    check_mm_struct = NULL;

    assert(nr_active_pages == 0 && nr_inactive_pages == 0);
    for (offset = 0; offset < max_swap_offset; offset ++) {
        mem_map[offset] = SWAP_UNUSED;
    }

    assert(nr_free_pages_store == nr_free_pages());
    assert(slab_allocated_store == slab_allocated());

    cprintf("check_swap() succeeded.\n");
}
Beispiel #27
0
int main(int argc, char *argv[])
{
    unsigned char *core;
    int i;
    size_t s, s2;
    pid_t pid;
    int size;
    MM *mm;
    int n;
    char *cp[1025];
    int version;
    struct count_test { int count; int prev; } *ct;

    setbuf(stderr, NULL);

    /*
    **
    **  Test Global Library API
    **
    */

    fprintf(stderr, "\n*** TESTING GLOBAL LIBRARY API ***\n\n");

    fprintf(stderr, "Fetching library version\n");
    version = mm_lib_version();
    FAILED_IF(version == 0x0);
    fprintf(stderr, "version = 0x%X\n", version);

    /*
    **
    **  Test Low-Level Shared Memory API
    **
    */

    fprintf(stderr, "\n*** TESTING LOW-LEVEL SHARED MEMORY API ***\n");

    fprintf(stderr, "\n=== Testing Memory Segment Access ===\n");

    fprintf(stderr, "Creating 16KB shared memory core area\n");
    core = mm_core_create(1024*16, NULL);
    FAILED_IF(core == NULL);
    s = mm_core_size(core);
    FAILED_IF(s == 0);
    fprintf(stderr, "actually allocated core size = %d\n", s);

    fprintf(stderr, "Writing 0xF5 bytes to shared memory core area\n");
    for (i = 0; i < s; i++) {
        fprintf(stderr, "write to core[%06d]\r", i);
        core[i] = 0xF5;
    }
    fprintf(stderr, "\n");

    fprintf(stderr, "Reading back 0xF5 bytes from shared memory core area\n");
    for (i = 0; i < s; i++) {
        fprintf(stderr, "read from core[%06d]\r", i);
        if (core[i] != 0xF5) {
            fprintf(stderr, "Offset %d: 0xF5 not found (found 0x%X\n", i, core[i]);
            exit(0);
        }
    }
    fprintf(stderr, "\n");

    fprintf(stderr, "Destroying shared memory core area\n");
    mm_core_delete(core);

    fprintf(stderr, "\n=== Testing Memory Locking ===\n");

    fprintf(stderr, "Creating small shared memory core area\n");
    ct = mm_core_create(sizeof(struct count_test), NULL);
    FAILED_IF(ct == NULL);
    s = mm_core_size(ct);
    FAILED_IF(s == 0);
    fprintf(stderr, "actually allocated core size = %d\n", s);

    ct->prev  = 0;
    ct->count = 1;
    if ((pid = fork()) == 0) {
        /* child */
        while (ct->count < 32768) {
            if (!mm_core_lock(ct, MM_LOCK_RW)) {
                fprintf(stderr, "locking failed (child)\n");
                FAILED_IF(1);
            }
            if (ct->prev != (ct->count-1)) {
                fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count);
                exit(1);
            }
            ct->count += 1;
            fprintf(stderr, "count=%06d (child )\r", ct->count);
            ct->prev  += 1;
            if (!mm_core_unlock(ct)) {
                fprintf(stderr, "locking failed (child)\n");
                FAILED_IF(1);
            }
        }
        exit(0);
    }
    /* parent ... */
    while (ct->count < 32768) {
        if (!mm_core_lock(ct, MM_LOCK_RW)) {
            fprintf(stderr, "locking failed (parent)\n");
            FAILED_IF(1);
        }
        if (ct->prev != (ct->count-1)) {
            fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count);
            exit(1);
        }
        ct->count += 1;
        fprintf(stderr, "count=%06d (parent)\r", ct->count);
        ct->prev  += 1;
        if (!mm_core_unlock(ct)) {
            fprintf(stderr, "locking failed (parent)\n");
            kill(pid, SIGTERM);
            FAILED_IF(1);
        }
    }
    waitpid(pid, NULL, 0);
    fprintf(stderr, "\n");

    fprintf(stderr, "Destroying shared memory core area\n");
    mm_core_delete(ct);

    /*
    **
    **  Test Standard Malloc-style API
    **
    */

    fprintf(stderr, "\n*** TESTING STANDARD MALLOC-STYLE API ***\n");

    fprintf(stderr, "\n=== Testing Allocation ===\n");

    fprintf(stderr, "Creating MM object\n");
    size = mm_maxsize();
    if (size > 1024*1024*1)
        size = 1024*1024*1;
    mm = mm_create(size, NULL);
    FAILED_IF(mm == NULL)
    mm_display_info(mm);
    s = mm_available(mm);
    FAILED_IF(s == 0);
    fprintf(stderr, "actually available bytes = %d\n", s);

    fprintf(stderr, "Allocating areas inside MM\n");
    n = 0;
    for (i = 0; i < 1024; i++)
        cp[i] = NULL;
    for (i = 0; i < 1024; i++) {
        fprintf(stderr, "total=%09d allocated=%09d add=%06d\r", s, n, (i+1)*(i+1));
        s2 = mm_available(mm);
        if ((i+1)*(i+1) > s2) {
            cp[i] = mm_malloc(mm, (i+1)*(i+1));
            if (cp[i] != NULL) {
                fprintf(stderr, "\nExpected an out of memory situation. Hmmmmm\n");
                FAILED_IF(1);
            }
            break;
        }
        cp[i] = mm_malloc(mm, (i+1)*(i+1));
        n += (i+1)*(i+1);
        FAILED_IF(cp[i] == NULL)
        memset(cp[i], 0xF5, (i+1)*(i+1));
    }
    mm_display_info(mm);

    fprintf(stderr, "\n=== Testing Defragmentation ===\n");

    fprintf(stderr, "Fragmenting memory area by freeing some selected areas\n");
    for (i = 0; i < 1024; i++) {
        if (i % 2 == 0)
            continue;
        if (cp[i] != NULL)
            mm_free(mm, cp[i]);
        cp[i] = NULL;
    }
    mm_display_info(mm);

    fprintf(stderr, "Freeing all areas\n");
    for (i = 0; i < 1024; i++) {
        mm_free(mm, cp[i]);
    }
    mm_display_info(mm);

    fprintf(stderr, "Checking for memory leaks\n");
    s2 = mm_available(mm);
    if (s != s2) {
        fprintf(stderr, "Something is leaking, we've lost %d bytes\n", s - s2);
        FAILED_IF(1);
    }
    else {
        fprintf(stderr, "Fine, we have again %d bytes available\n", s2);
    }

    fprintf(stderr, "Destroying MM object\n");
    mm_destroy(mm);

    /******/

    fprintf(stderr, "\nOK - ALL TESTS SUCCESSFULLY PASSED.\n\n");
    exit(0);
}