Example #1
0
void q3(void)
{
    ptr_proc1_stack=proc1_stack;
    ptr_proc2_stack=proc2_stack;    
    vector[0]=print; 
    vector[1]=readline;
    vector[2]=getarg;
    vector[3]=yield12;
    vector[4]=yield21;
    vector[5]=uexit;
    FILE* fp=NULL;
    fp=fopen("q3prog1","r");
    if(fp==NULL){
	perror("fopen q3prog1:");
        exit(-1);
	};
    fread(proc1,4091,1,fp);
    fclose(fp);
    fp=fopen("q3prog2","r");
    if(fp==NULL){
	perror("fopen q3prog2:");
	exit(-1);
	};
    fread(proc2,4096,1,fp);
    fclose(fp);
   ptr_proc1_stack=setup_stack(ptr_proc1_stack,proc1); 
   ptr_proc2_stack=setup_stack(ptr_proc2_stack,proc2);
   do_switch(&main_stack,ptr_proc1_stack);
    
    /* load q3prog1 into process 1 and q3prog2 into process 2 */
    /* then switch to process 1 */
}
Example #2
0
static int init_stack(port_tls_data_t* tlsdata, size_t stack_size, Boolean temp)
{
    int err;
    size_t stack_begin;

    if (!port_shared_data)
        return -1;

    err = find_stack_addr_size(&tlsdata->stack_addr, &tlsdata->stack_size);
    if (err != 0) {fprintf(stderr, "init_stack:CP#1\n"); return err;}

    // Workaround for incorrect stack_size returned by pthread_attr_getstack
    // for main thread, while stack_addr + stack_size gives correct stack top
    if (tlsdata->foreign)
        tlsdata->stack_size = PSD->foreign_stack_size;

    if (stack_size != 0 && !tlsdata->foreign)
        tlsdata->stack_size = stack_size;

    tlsdata->guard_page_size = PSD->guard_page_size;
    tlsdata->guard_stack_size = PSD->guard_stack_size;
    tlsdata->mem_protect_size = PSD->mem_protect_size;

    if (temp)
        return 0;

    stack_begin = (size_t)tlsdata->stack_addr - tlsdata->stack_size;
    tlsdata->guard_stack_addr = (void*)(stack_begin + tlsdata->guard_page_size);
    tlsdata->guard_page_addr =
        (void*)((size_t)tlsdata->guard_stack_addr + tlsdata->guard_stack_size);

    return setup_stack(tlsdata);
}
Example #3
0
static void
global_setup (void)
{
    setup_stack (&parse_stack, parse_stack_buffer,
                 sizeof (parse_stack_buffer));
    setup_display ();
    setup_sgf ();

    set_defaults();
    if (configfile_load(SETTINGS_FILENAME, config,
                        sizeof(config)/sizeof(*config),
                        SETTINGS_MIN_VERSION ) < 0)
    {
        /* If the loading failed, save a new config file (as the disk is
           already spinning) */

        /* set defaults again just in case (don't know if they can ever
         * be messed up by configfile_load, and it's basically free anyway)
         */
        set_defaults();

        configfile_save(SETTINGS_FILENAME, config,
                        sizeof(config)/sizeof(*config),
                        SETTINGS_VERSION);
    }
}
Example #4
0
int main()
{
	int nrow_map = 0, ncol_map = 0;
	const char *filename = "D:\\data\\map.txt";
	int **maze;
	int **mark;
	TCellPtr pstack;

	if(!verify_mat(filename, &nrow_map, &ncol_map)){
		printf("请检查迷宫地图文件:文件读取失败,或地图每行的元素数目不相容\n");
		exit(0);
	}

	// 读入地图文件
	maze = read_map(filename, nrow_map, ncol_map);
	// 生成迷宫访问标记矩阵
	mark = setup_mat(nrow_map, ncol_map);
	// 初始化路径探测堆栈
	pstack = setup_stack(nrow_map, ncol_map);

	search_maze( maze, mark, pstack, nrow_map, ncol_map );


	// 销毁为存储迷宫地图而动态分配的内存
	destroy_map(maze, nrow_map);
	// 销毁为存储迷宫访问标记而动态分配的内存
	destroy_map(mark, nrow_map);
	// 销毁路径探测堆栈
	free(pstack);

	system("pause");
	return 0;
}
Example #5
0
void q3(void)
{
  vector[0] = &print;
  vector[1] = &readline;
  vector[2] = &getarg;
  vector[3] = &yield12;
  vector[4] = &yield21;
  vector[5] = &uexit;
  /* load q3prog1 into process 1 and q3prog2 into process 2 */

  if (!readfile("q3prog1", proc1)) {
    return;
  }

  if (!readfile("q3prog2", proc2)) {
    return;
  }

  process1 = setup_stack(proc1_stack, proc1);
  process2 = setup_stack(proc2_stack, proc2);

  do_switch(&homework_stack, process1);
}
Example #6
0
int main(int argc, char **argv)
{
	char *binary = "binary";
	char binary_buf[64];

	Obj_Entry *objp;
	func_ptr_type exit_proc;

	int fd = open(binary, O_RDONLY);

	/* find file name of file descriptor */
	if (!find_binary_name(fd, binary_buf, sizeof(binary_buf)))
		binary = binary_buf;

	/* build dummy stack */
	void *sp =  setup_stack(binary, (long)fd);
	func_ptr_type const program_main = _rtld(sp, &exit_proc, &objp);

	/* call main function of dynamic program */
	return call_program_main(program_main);
}
Example #7
0
int main(int argc, char **argv)
{
	char *binary = "binary";
	char binary_buf[64];

	Obj_Entry *objp;
	func_ptr_type exit_proc;

	int fd = open(binary, O_RDONLY);

	/* find file name of file descriptor */
	if (!find_binary_name(fd, binary_buf, sizeof(binary_buf)))
		binary = binary_buf;

	/* build dummy stack */
	void *sp =  setup_stack(binary, (long)fd);

	/* DEBUGGING
	printf("Starting ldso ...\n");
	*/

	/* this is usually '_start' */
	func_ptr_type main_func = _rtld(sp, &exit_proc, &objp);

	/* DEBUGGING
	char **p;
	for(p = environ; *p; p++)
		printf("env: %s\n", *p);
	
	printf("Starting application ... environ: %p\n", lx_environ);
	*/

	/* start loaded application */
	call_main(main_func);

	exit_proc();

	printf("Exiting ldso\n");
	return 0;
}
Example #8
0
main(int argc, char *argv[])
{
   int n;
   int rows, cols;
   int drawButtons;
   char *btn_font, *disp_font;
   /* GtkWidget *main_w; */
   GtkWidget *vbox;
   GtkWidget *menu;
   GtkWidget *mdisp;
   GtkWidget *lcd;
   GtkWidget *btns;
   GdkFont *new_font;
   GtkStyle *default_style, *new_style;
   GdkBitmap *icon_bitmap;
#ifdef USE_GNOME
   GnomeAppBar *appbar;
#endif

   setlocale(LC_ALL, "C");
#ifdef USE_GNOME
   gnome_init("grpn", "1.0", argc, argv);
   gnome_app_new("grpn", "grpn");
#else
   /* initialize gtk */
   gtk_init(&argc, &argv);
#endif

   /* initial values */
   drawButtons = 1;
   rows = 8;
   cols = 30;
   btn_font = disp_font = NULL;

   /* process command line args */
   n = 1;
   while(n < argc){
      if(0 == strcmp("-fn", argv[n])){
         n++;
         if(n >= argc){
            usage("Missing required argument for -fn.");
            exit(0);
         }
         btn_font = disp_font = argv[n];
      } else if(0 == strcmp("-btn-fn", argv[n])){
         n++;
         if(n >= argc){
            usage("Missing required argument for -btn-fn.");
            exit(0);
         }
         btn_font = argv[n];
      } else if(0 == strcmp("-disp-fn", argv[n])){
         n++;
         if(n >= argc){
            usage("Missing required argument for -disp-fn.");
            exit(0);
         }
         disp_font = argv[n];
      } else if(0 == strcmp("-rows", argv[n])){
         n++;
         if(n >= argc){
            usage("Missing required argument for -rows.");
            exit(0);
         }
         if(1 != sscanf(argv[n], "%d", &rows)){
            usage("Unable to read number or rows.");
            exit(0);
         }
      } else if(0 == strcmp("-cols", argv[n])){
         n++;
         if(n >= argc){
            usage("Missing required argument for -cols.");
            exit(0);
         }
         if(1 != sscanf(argv[n], "%d", &cols)){
            usage("Unable to read number or cols.");
            exit(0);
         }
      } else if(0 == strcmp("-b", argv[n])){
         drawButtons = 0;
      } else if(0 == strcmp("-bm", argv[n])){
         n++;
         if(n >= argc){
            usage("Missing required argument for -m.");
            exit(0);
         }
         if (0 == strcmp("dec", argv[n])){
             setBaseMode(DECIMAL);
	 } else if (0 == strcmp("eng", argv[n])){
             setBaseMode(DECIMAL_ENG);
	 } else if (0 == strcmp("bin", argv[n])){
             setBaseMode(BINARY);
	 } else if (0 == strcmp("oct", argv[n])){
             setBaseMode(OCTAL);
	 } else if (0 == strcmp("hex", argv[n])){
             setBaseMode(HEXADECIMAL);
	 } else {
             usage("Specify dec, eng, bin, oct or hex for -m.");
             exit(0);
         }
      } else {
         usage("Unknown Argument.");
         exit(0);
      }
      n++;
   }

   /* set up any constants we may use */
   setup_constant();

   /* initialize the undo system */
   initUndoSystem();

   /* setup the stack */
   if(0 == setup_stack()){
      fprintf(stderr, "Error: Could not initalize data structures.\n");
      exit(0);
   }

   /* set the font if told */
   if(btn_font != NULL){
      default_style = gtk_widget_get_default_style();
      if(NULL == (new_font = gdk_font_load(btn_font))){
         fprintf(stderr, "Unable to load font %s.\n", btn_font);
         exit(0);
      }
      new_style = gtk_style_copy(default_style);
      new_style->font_desc = new_font;
/* BDD - No longer in Gtk2.x */
/*      gtk_widget_set_default_style(new_style); */
   }
   

#ifdef USE_GNOME
   main_w = gnome_app_new("grpn", "grpn");
   setup_menu(main_w);

   appbar = GNOME_APPBAR(gnome_appbar_new(FALSE, FALSE, FALSE));
   gnome_app_set_statusbar(GNOME_APP(main_w), GTK_WIDGET(appbar));

   /*create the box that everyone goes in */
   vbox = gtk_vbox_new(FALSE, 0);
   gnome_app_set_contents(GNOME_APP(main_w), vbox);
   gtk_widget_show(vbox);

#else
   /* the main window contains the work area and the menubar */
   main_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_widget_set_name(main_w, "grpn");

   /*create the box that everyone goes in */
   vbox = gtk_vbox_new(FALSE, 0);
   gtk_container_add(GTK_CONTAINER(main_w), vbox);
   gtk_widget_show(vbox);

   /* set up the menu bar */
   menu = setup_menu(vbox);
#endif

   /* handle window manager close */
   gtk_signal_connect(GTK_OBJECT(main_w), "delete_event",
      GTK_SIGNAL_FUNC(delete_event), NULL);
   gtk_signal_connect(GTK_OBJECT(main_w), "destroy",
      GTK_SIGNAL_FUNC(destroy), NULL);

   /* create the varrious subsystems */
   mdisp = setupModeDisplay(vbox);
   if(drawButtons) btns = setupButtons(vbox);
   lcd = setupLCD(vbox, rows, cols, disp_font);

   /* Create pixmap of depth 1 (bitmap) for icon */
   gtk_widget_realize(main_w);
   icon_bitmap = gdk_bitmap_create_from_data(main_w->window,
      icon_bitmap_bits, icon_bitmap_width, icon_bitmap_height);
   gdk_window_set_icon(main_w->window, NULL, icon_bitmap, NULL);

   gtk_widget_show(main_w);

   gtk_main();

}
Example #9
0
//Initializes a process with its binary its argument
process_t* create_process_new(void* binary, pid_t ppid, int new_pid, 
                              const char *proc_name,
                              char * const argv[],
                              size_t argv_count,
                              char * const envp[],
                              size_t envp_count)
{
    uint64_t old_cr3 = 0;
    int32_t    rc   = 0;

    process_t *proc = allocate_process(new_pid);
    if (!proc)
    {
        #ifdef LOG
            printf("Failed to allocate memory for process\n");
        #endif
        return NULL;
    }
    
    // First process will be foreground... Need to change this logic
    // May be this will work fine when we will be running just shell
    if (foreground_proc == NULL)
    {
        proc->flags |= FOREGROUND_PROCESS;
        foreground_proc = proc;
    }

    strncpy(proc->name, proc_name, sizeof(proc->name));

    proc->kernel_stack = kmalloc(USER_KERNEL_STACK_SIZE);
    if(proc->kernel_stack == NULL)
    {
        reclaim_process_resources(proc);
        kfree(proc);
        #if LOG
            printf("failed to allocate memory for user-kern stack\n");
        #endif
        
        return NULL;
    }

    rc = setup_pagetable_proc(proc);
    if (rc)
    {
        reclaim_process_resources(proc);
        kfree(proc);
        #ifdef LOG
            printf("setup_pagetable_proc failed\n");
        #endif
        return NULL;
    }
    
    if (binary != NULL)
    {
        //If the process is child of some parent
        //So we don't need any binary
        rc = init_vmas_proc(proc, binary, argv_count, envp_count);
    }

    if (rc)
    {
        reclaim_process_resources(proc);
        kfree(proc);
        #ifdef LOG
            printf("init_vmas_proc failed\n");
        #endif
        return NULL;
    }

    //Setup registers for the process
    setup_registers_proc(proc);

    // Allocate a page for stack
    // Why we are not going for demand paging?
    //  We need to push env variables' addresses on stack while we are in kernel 
    //  and it's not a good idea to have a page fault in kernel
    if (binary != NULL)
    {   //Don't allocate page for stack because it's a child.
        allocate_memory((uint64_t)proc->page_table_base,
                    USER_STACK_TOP - PGSIZE,
                    PGSIZE,
                    PTE_P | PTE_U | PTE_W);
    }
    // This function should be last in this sequence since it uses rsp 
    // which we set in setup_registers_proc
    if (binary != NULL)
    {

        if (argv_count > 0)
        {
            allocate_memory((uint64_t)proc->page_table_base,
                            USER_ARGV_START,
                            argv_count * sizeof(execve_argv[0]),
                            PTE_P | PTE_U | PTE_W);
            old_cr3 = getcr3();
            setcr3((uint64_t)proc->page_table_base);
            memcpy((void *)USER_ARGV_START,
                    argv,
                    argv_count * sizeof(execve_argv[0]));
            setcr3(old_cr3);
        }

        if (envp_count > 0)
        {
            allocate_memory((uint64_t)proc->page_table_base,
                            USER_ENV_VARIABLE_START,
                            envp_count * sizeof(execve_envp[0]),
                            PTE_P | PTE_U | PTE_W);
            old_cr3 = getcr3();
            setcr3((uint64_t)proc->page_table_base);
            memcpy((void *)USER_ENV_VARIABLE_START,
                    envp,
                    envp_count * sizeof(execve_envp[0]));
            setcr3(old_cr3);
        }

        setup_stack(proc, argv_count, envp_count);
    }

    add_process_to_queue(proc, PROCESS_RUNNABLE_QUEUE);
    proc->ppid = ppid;
    //printf("New process PID = %d\n", proc->pid);

    return proc;
}
Example #10
0
bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
	bNodeTreeExec *exec;
	bNode *node;
	bNodeExec *nodeexec;
	bNodeInstanceKey nodekey;
	bNodeSocket *sock;
	bNodeStack *ns;
	int index;
	bNode **nodelist;
	int totnodes, n;
	
	/* ensure all sock->link pointers and node levels are correct */
	ntreeUpdateTree(G.main, ntree);
	
	/* get a dependency-sorted list of nodes */
	ntreeGetDependencyList(ntree, &nodelist, &totnodes);
	
	/* XXX could let callbacks do this for specialized data */
	exec = MEM_callocN(sizeof(bNodeTreeExec), "node tree execution data");
	/* backpointer to node tree */
	exec->nodetree = ntree;
	
	/* set stack indices */
	index = 0;
	for (n=0; n < totnodes; ++n) {
		node = nodelist[n];
		
		node->stack_index = index;
		
		/* init node socket stack indexes */
		for (sock = node->inputs.first; sock; sock = sock->next)
			node_init_input_index(sock, &index);
		
		if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
			for (sock = node->outputs.first; sock; sock = sock->next)
				node_init_output_index(sock, &index, &node->internal_links);
		}
		else {
			for (sock = node->outputs.first; sock; sock = sock->next)
				node_init_output_index(sock, &index, NULL);
		}
	}
	
	/* allocated exec data pointers for nodes */
	exec->totnodes = totnodes;
	exec->nodeexec = MEM_callocN(exec->totnodes * sizeof(bNodeExec), "node execution data");
	/* allocate data pointer for node stack */
	exec->stacksize = index;
	exec->stack = MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
	
	/* all non-const results are considered inputs */
	for (n=0; n < exec->stacksize; ++n)
		exec->stack[n].hasinput = 1;
	
	/* prepare all nodes for execution */
	for (n=0, nodeexec= exec->nodeexec; n < totnodes; ++n, ++nodeexec) {
		node = nodeexec->node = nodelist[n];
		
		/* tag inputs */
		for (sock = node->inputs.first; sock; sock = sock->next) {
			/* disable the node if an input link is invalid */
			if (sock->link && !(sock->link->flag & NODE_LINK_VALID))
				node->need_exec= 0;
			
			ns = setup_stack(exec->stack, ntree, node, sock);
			if (ns)
				ns->hasoutput = 1;
		}
		
		/* tag all outputs */
		for (sock = node->outputs.first; sock; sock = sock->next) {
			/* ns = */ setup_stack(exec->stack, ntree, node, sock);
		}
		
		nodekey = BKE_node_instance_key(parent_key, ntree, node);
		nodeexec->data.preview = context->previews ? BKE_node_instance_hash_lookup(context->previews, nodekey) : NULL;
		if (node->typeinfo->initexecfunc)
			nodeexec->data.data = node->typeinfo->initexecfunc(context, node, nodekey);
	}
	
	if (nodelist)
		MEM_freeN(nodelist);
	
	return exec;
}
Example #11
0
asmlinkage int pthread_create_sys (pthread_t *thread, 
				   const pthread_attr_t *attr,
                                   void *(*startup)(void *),
				   void *(*start_routine)(void *), 
				   void *args) {
  int flags;

  hw_save_flags_and_cli (flags);


  // Check policy & prio
  if (attr) {
    if (attr->policy != SCHED_FIFO) {
      SET_ERRNO(EINVAL);
      return -1;
    } else {

      if (attr -> sched_param.sched_priority > MIN_SCHED_PRIORITY ||
	  attr -> sched_param.sched_priority < MAX_SCHED_PRIORITY) {
	SET_ERRNO(EINVAL);
	return -1;
      }
    }
  }

  // Creating the pthread structure
  if (!(*thread = create_pthread_struct ())) {
    SET_ERRNO (EAGAIN);
    hw_restore_flags (flags);
    return -1;
  }
  
  /* 
   * Configuring the new thread either with attr (if not NULL)
   * or with the default values
   */
  if (attr) {
    (*thread) -> sched_param = attr -> sched_param;    
    (*thread) -> stack_info.stack_size = attr -> stack_size;
    (*thread) -> stack_info.stack_bottom = attr -> stack_addr;
    SET_THREAD_DETACH_STATE((*thread), attr -> detachstate);
    SET_THREAD_POLICY ((*thread), attr -> policy);
  } else {
    (*thread) -> sched_param.sched_priority = MIN_SCHED_PRIORITY;
    (*thread) -> stack_info.stack_size = STACK_SIZE;
    (*thread) -> stack_info.stack_bottom = 0;
    SET_THREAD_DETACH_STATE((*thread), 0);
    SET_THREAD_POLICY ((*thread), SCHED_FIFO);
  }

  if (!((*thread) -> stack_info.stack_bottom)) {
    // Creating the thread stack
    if (alloc_stack (&(*thread) -> stack_info) < 0) {
      SET_ERRNO (EAGAIN);
      hw_restore_flags (flags);
      return -1;
    }
  }

  // This is arhictecture dependent
  (*thread) -> stack = setup_stack ((*thread)->stack_info.stack_bottom +
				    (*thread)->stack_info.stack_size 
				    / sizeof (int),
                                    startup,
                                    start_routine, args);

  activate_thread (*thread);
  pthread_t tmp = *thread;
  printf("pthred_create_sys thread 0x%x state:%d\n", (unsigned long)tmp, GET_THREAD_STATE(tmp));

  // no error at all
  hw_restore_flags (flags);

  // Calling the scheduler
  scheduling ();
  return 0;
}
Example #12
0
bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
{
	bNodeTreeExec *exec;
	bNode *node;
	bNodeExec *nodeexec;
	bNodeSocket *sock, *gsock;
	bNodeStack *ns;
	int index= 0;
	bNode **nodelist;
	int totnodes, n;
	
	if((ntree->init & NTREE_TYPE_INIT)==0)
		ntreeInitTypes(ntree);
	
	/* get a dependency-sorted list of nodes */
	ntreeGetDependencyList(ntree, &nodelist, &totnodes);
	
	/* XXX could let callbacks do this for specialized data */
	exec = MEM_callocN(sizeof(bNodeTreeExec), "node tree execution data");
	/* backpointer to node tree */
	exec->nodetree = ntree;
	
	/* group inputs essentially work as outputs */
	for(gsock=ntree->inputs.first; gsock; gsock = gsock->next)
		node_init_output_index(gsock, &index);
	/* set stack indexes */
	for(n=0; n < totnodes; ++n) {
		node = nodelist[n];
		
		node->stack_index = index;
		
		/* init node socket stack indexes */
		for (sock=node->inputs.first; sock; sock=sock->next)
			node_init_input_index(sock, &index);
		for (sock=node->outputs.first; sock; sock=sock->next)
			node_init_output_index(sock, &index);
	}
	/* group outputs essentially work as inputs */
	for(gsock=ntree->outputs.first; gsock; gsock = gsock->next)
		node_init_input_index(gsock, &index);
	
	/* allocated exec data pointers for nodes */
	exec->totnodes = totnodes;
	exec->nodeexec = MEM_callocN(exec->totnodes * sizeof(bNodeExec), "node execution data");
	/* allocate data pointer for node stack */
	exec->stacksize = index;
	exec->stack = MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
	
	/* all non-const results are considered inputs */
	for (n=0; n < exec->stacksize; ++n)
		exec->stack[n].hasinput = 1;
	
	/* prepare group tree inputs */
	for (sock=ntree->inputs.first; sock; sock=sock->next) {
		/* ns = */ setup_stack(exec->stack, sock);
	}
	/* prepare all internal nodes for execution */
	for(n=0, nodeexec= exec->nodeexec; n < totnodes; ++n, ++nodeexec) {
		node = nodeexec->node = nodelist[n];
		
		/* tag inputs */
		for (sock=node->inputs.first; sock; sock=sock->next) {
			/* disable the node if an input link is invalid */
			if(sock->link && !(sock->link->flag & NODE_LINK_VALID))
				node->need_exec= 0;
			
			ns = setup_stack(exec->stack, sock);
			ns->hasoutput = 1;
		}
		
		/* tag all outputs */
		for (sock=node->outputs.first; sock; sock=sock->next) {
			/* ns = */ setup_stack(exec->stack, sock);
		}
		
		if(node->typeinfo->initexecfunc)
			nodeexec->data = node->typeinfo->initexecfunc(node);
	}
	/* prepare group tree outputs */
	for (sock=ntree->outputs.first; sock; sock=sock->next) {
		ns = setup_stack(exec->stack, sock);
		ns->hasoutput = 1;
	}
	
	if (nodelist)
		MEM_freeN(nodelist);
	
	return exec;
}
Example #13
0
/* Loads an ELF executable from FILE_NAME into the current thread.
   Stores the executable's entry point into *EIP
   and its initial stack pointer into *ESP.
   Returns true if successful, false otherwise. */
bool
load (const char *file_name, void (**eip) (void), void **esp) 
{
  struct thread *t = thread_current ();
  struct Elf32_Ehdr ehdr;
  struct file *file = NULL;
  off_t file_ofs;
  bool success = false;
  int i;

  /* Allocate and activate page directory. */
  t->pagedir = pagedir_create ();
  if (t->pagedir == NULL) 
    goto done;
  process_activate ();

  /* Set up stack. */
  if (!setup_stack (esp)){
    goto done;
  }

  /* Open executable file. */
  file = filesys_open (file_name);
  if (file == NULL) 
    {
      printf ("load: %s: open failed\n", file_name);
      goto done; 
    }

  /* Read and verify executable header. */
  if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
      || memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7)
      || ehdr.e_type != 2
      || ehdr.e_machine != 3
      || ehdr.e_version != 1
      || ehdr.e_phentsize != sizeof (struct Elf32_Phdr)
      || ehdr.e_phnum > 1024) 
    {
      printf ("load: %s: error loading executable\n", file_name);
      goto done; 
    }

  /* Read program headers. */
  file_ofs = ehdr.e_phoff;
  for (i = 0; i < ehdr.e_phnum; i++) 
    {
      struct Elf32_Phdr phdr;

      if (file_ofs < 0 || file_ofs > file_length (file))
        goto done;
      file_seek (file, file_ofs);

      if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
        goto done;
      file_ofs += sizeof phdr;
      switch (phdr.p_type) 
        {
        case PT_NULL:
        case PT_NOTE:
        case PT_PHDR:
        case PT_STACK:
        default:
          /* Ignore this segment. */
          break;
        case PT_DYNAMIC:
        case PT_INTERP:
        case PT_SHLIB:
          goto done;
        case PT_LOAD:
          if (validate_segment (&phdr, file)) 
            {
              bool writable = (phdr.p_flags & PF_W) != 0;
              uint32_t file_page = phdr.p_offset & ~PGMASK;
              uint32_t mem_page = phdr.p_vaddr & ~PGMASK;
              uint32_t page_offset = phdr.p_vaddr & PGMASK;
              uint32_t read_bytes, zero_bytes;
              if (phdr.p_filesz > 0)
                {
                  /* Normal segment.
                     Read initial part from disk and zero the rest. */
                  read_bytes = page_offset + phdr.p_filesz;
                  zero_bytes = (ROUND_UP (page_offset + phdr.p_memsz, PGSIZE)
                                - read_bytes);
                }
              else 
                {
                  /* Entirely zero.
                     Don't read anything from disk. */
                  read_bytes = 0;
                  zero_bytes = ROUND_UP (page_offset + phdr.p_memsz, PGSIZE);
                }
              if (!load_segment (file, file_page, (void *) mem_page,
                                 read_bytes, zero_bytes, writable))
                goto done;
            }
          else
            goto done;
          break;
        }
    }

  /* Start address. */
  *eip = (void (*) (void)) ehdr.e_entry;

  success = true;

 done:
  /* We arrive here whether the load is successful or not. */
  file_close (file);
  return success;
}