Beispiel #1
0
void process_main(void) {
    // Fork a total of three new copies.
    pid_t p = sys_fork();
    assert(p >= 0);
    p = sys_fork();
    assert(p >= 0);

    // The rest of this code is like p-allocator.c.

    p = sys_getpid();
    srand(p);

    heap_top = ROUNDUP((uint8_t *) end, PAGESIZE);
    stack_bottom = ROUNDDOWN((uint8_t *) read_esp() - 1, PAGESIZE);

    while (1) {
	if ((rand() % ALLOC_SLOWDOWN) < p) {
	    if (heap_top == stack_bottom || sys_page_alloc(heap_top) < 0)
		break;
	    *heap_top = p;	/* check we have write access to new page */
	    heap_top += PAGESIZE;
	}
	sys_yield();
    }

    // After running out of memory, do nothing forever
    while (1)
	sys_yield();
}
Beispiel #2
0
void process_main(void) {
    while (1) {
        if (rand() % ALLOC_SLOWDOWN == 0) {
            if (sys_fork() == 0) {
                break;
            }
        } else {
            sys_yield();
        }
    }

    pid_t p = sys_getpid();
    srand(p);

    // The heap starts on the page right after the 'end' symbol,
    // whose address is the first address not allocated to process code
    // or data.
    heap_top = ROUNDUP((uint8_t*) end, PAGESIZE);

    // The bottom of the stack is the first address on the current
    // stack page (this process never needs more than one stack page).
    stack_bottom = ROUNDDOWN((uint8_t*) read_rsp() - 1, PAGESIZE);

    // Allocate heap pages until (1) hit the stack (out of address space)
    // or (2) allocation fails (out of physical memory).
    while (1) {
        int x = rand() % (8 * ALLOC_SLOWDOWN);
        if (x < 8 * p) {
            if (heap_top == stack_bottom || sys_page_alloc(heap_top) < 0) {
                break;
            }
            *heap_top = p;      /* check we have write access to new page */
            heap_top += PAGESIZE;
            if (console[CPOS(24, 0)]) {
                /* clear "Out of physical memory" msg */
                console_printf(CPOS(24, 0), 0, "\n");
            }
        } else if (x == 8 * p) {
            if (sys_fork() == 0) {
                p = sys_getpid();
            }
        } else if (x == 8 * p + 1) {
            sys_exit();
        } else {
            sys_yield();
        }
    }

    // After running out of memory
    while (1) {
        if (rand() % (2 * ALLOC_SLOWDOWN) == 0) {
            sys_exit();
        } else {
            sys_yield();
        }
    }
}
Beispiel #3
0
Datei: main.c Projekt: glguida/mh
int main()
{
	pid_t pid;
	struct sys_hwcreat_cfg cfg;

	printf("Hello!\n");

	cfg.nameid = squoze("platform");
	cfg.nirqsegs = 1;
	cfg.npiosegs = 0;
	cfg.nmemsegs = 0;
	cfg.segs[0].base = 1; /* IRQ 1 */
	cfg.segs[0].len = 1;
	printf("creat[%llx]: %d\n", cfg.nameid, sys_hwcreat(&cfg, 0111));

	if (sys_fork() == 0)
		goto child;
	inthandler(INTR_CHILD, do_child, NULL);
	lwt_sleep();

 child:
	if (sys_fork())
		sys_die(-3);
	/* Child of Child */
	printf("Opening platform [%llx]\n", squoze("platform"));
	printf("open[%llx]: %d\n", squoze("platform"), sys_open(squoze("platform")));
	printf("irqmap[%llx]: %d\n", squoze("platform"), sys_mapirq(0, 1, 5));
	lwt_sleep();
	printf("Goodbye!");
	sys_die(5);
#if 0
	int j;
	size_t len;
	struct diodevice *dc;
	struct iovec iov[11];
	uint64_t val;
	

		do {
			dc = dirtio_pipe_open(500);
		} while(dc == NULL);

		dirtio_mmio_inw(&dc->desc, PORT_DIRTIO_MAGIC, 0, &val);
		printf("PORT_DIRTIO_MAGIC is %"PRIx64"\n", val);
		dirtio_mmio_inw(&dc->desc, PORT_DIRTIO_MAGIC, 0, &val);
		printf("PORT_DIRTIO_MAGIC is %"PRIx64"\n", val);

		len = dirtio_allocv(dc, iov, 11, 11 * 128 * 1024 - 1);

		for (j = 0; j < 11; j++)
			printf("\t%p -> %d\n",
			       iov[j].iov_base, iov[j].iov_len);
		dioqueue_addv(&dc->dqueues[0], 1, 10, iov);
#endif

}
Beispiel #4
0
void
start(void)
{
	volatile int checker = 0; /* This variable checks that you correctly
								gave the child process a new stack. */
	pid_t p;
	int status;

	app_printf("About to start a new process...\n");

	p = sys_fork();
	if (p == 0)
		run_child();
	else if (p > 0) {
		app_printf("Main process %d!\n", sys_getpid());
		do {
			status = sys_wait(p);
			app_printf("W");
		} while (status == WAIT_TRYAGAIN);
		app_printf("Child %d exited with status %d!\n", p, status);

		// Check whether the child process corrupted our stack.
		// (This check doesn't find all errors, but it helps.)
		if (checker != 0) {
			app_printf("Error: stack collision!\n");
			sys_exit(1);
		} else
			sys_exit(0);

	} else {
		app_printf("Error!\n");
		sys_exit(1);
	}
}
Beispiel #5
0
_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout)
{
	if (do_fork) {
		if (sys_fork()) {
			_exit(0);
		}
	}

	/* detach from the terminal */
#ifdef HAVE_SETSID
	if (!no_process_group) setsid();
#elif defined(TIOCNOTTY)
	if (!no_process_group) {
		int i = sys_open("/dev/tty", O_RDWR, 0);
		if (i != -1) {
			ioctl(i, (int) TIOCNOTTY, (char *)0);
			close(i);
		}
	}
#endif /* HAVE_SETSID */

	if (!log_stdout) {
		/* Close fd's 0,1,2. Needed if started by rsh */
		close_low_fds(false);  /* Don't close stderr, let the debug system
					  attach it to the logfile */
	}
}
Beispiel #6
0
int base_schedule_snapshot(struct base *base)
{
	if (base->snapshot_child_pid == -1) {
		return _base_save_state(base);
	}
	if (base->snapshot_child_pid == 0) {
		base->snapshot_child_pid = sys_fork(_do_snapshot, base);
		return base->snapshot_child_pid == -1 ? -1 : 0;
	}

	if (sys_pid_exist(base->snapshot_child_pid) == 0) {
		base->snapshot_child_pid = sys_fork(_do_snapshot, base);
		return base->snapshot_child_pid == -1 ? -1 : 0;
	}
	return -2;
}
Beispiel #7
0
int process_screen_top_left()
{
    int status;
    uint32_t width = getWidthFB() / 4;
    uint32_t height = getHeightFB() / 2;
    struct pcb_s* child_process;

    child_process = sys_fork();

    if (child_process == 0)
    {
        //On est dans le processus fils.
        game_of_life(0, 0, width - 5, height - 5, 8);

        return EXIT_SUCCESS;
    }
    else
    {
        //On est dans le processus pere.
        game_of_life(width + 5, 0, width - 5, height - 5, 8);

        status = sys_wait(child_process);
    }

    return status;
}
Beispiel #8
0
/***************************************************************************
  create a child process to handle DNS lookups
  ****************************************************************************/
void start_async_dns(void)
{
	int fd1[2], fd2[2];

	CatchChild();

	if (pipe(fd1) || pipe(fd2)) {
		DEBUG(0,("can't create asyncdns pipes\n"));
		return;
	}

	child_pid = sys_fork();

	if (child_pid) {
		fd_in = fd1[0];
		fd_out = fd2[1];
		close(fd1[1]);
		close(fd2[0]);
		DEBUG(0,("started asyncdns process %d\n", (int)child_pid));
		return;
	}

	fd_in = fd2[0];
	fd_out = fd1[1];

	CatchSignal(SIGUSR2, SIG_IGN);
	CatchSignal(SIGUSR1, SIG_IGN);
	CatchSignal(SIGHUP, SIG_IGN);
        CatchSignal(SIGTERM, SIGNAL_CAST sig_term );

	asyncdns_process();
}
Beispiel #9
0
int fork(void)
{
	int ret;
	lock_fork();
	ret = sys_fork();
	unlock_fork();
	return ret;
}
Beispiel #10
0
void sync_browse_lists(struct work_record *work,
		       char *name, int nm_type, 
		       struct in_addr ip, bool local, bool servers)
{
	struct sync_record *s;
	static int counter;

	START_PROFILE(sync_browse_lists);
	/* Check we're not trying to sync with ourselves. This can
	   happen if we are a domain *and* a local master browser. */
	if (ismyip_v4(ip)) {
done:
		END_PROFILE(sync_browse_lists);
		return;
	}

	s = SMB_MALLOC_P(struct sync_record);
	if (!s) goto done;

	ZERO_STRUCTP(s);

	unstrcpy(s->workgroup, work->work_group);
	unstrcpy(s->server, name);
	s->ip = ip;

	if (asprintf(&s->fname, "%s/sync.%d", lp_lockdir(), counter++) < 0) {
		SAFE_FREE(s);
		goto done;
	}
	/* Safe to use as 0 means no size change. */
	all_string_sub(s->fname,"//", "/", 0);

	DLIST_ADD(syncs, s);

	/* the parent forks and returns, leaving the child to do the
	   actual sync and call END_PROFILE*/
	CatchChild();
	if ((s->pid = sys_fork())) return;

	BlockSignals( False, SIGTERM );

	DEBUG(2,("Initiating browse sync for %s to %s(%s)\n",
		 work->work_group, name, inet_ntoa(ip)));

	fp = x_fopen(s->fname,O_WRONLY|O_CREAT|O_TRUNC, 0644);
	if (!fp) {
		END_PROFILE(sync_browse_lists);
		_exit(1);
	}

	sync_child(name, nm_type, work->work_group, ip, local, servers,
		   s->fname);

	x_fclose(fp);
	END_PROFILE(sync_browse_lists);
	_exit(0);
}
Beispiel #11
0
int init(void)
{
	int ret = 0;
	pid_t pid;
	if (!(pid = sys_fork())) {
		set_kernel_stack(current_task->kernel_stack + KERNEL_STACK_SIZE);
		asm volatile ("int $0x80":"=a"(ret):"a"(__NR_execve), "b"("/bin/init"), "c"(0), "d"(0));
		asm volatile ("int $0x80"::"a"(__NR_exit), "b"(ret));
		for (;;);
	}
Beispiel #12
0
static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
				       void *private_data,
				       uint32_t msg_type,
				       struct server_id server_id,
				       DATA_BLOB *data)
{
	uint8 ret;
	pid_t child_pid;
	struct sigaction act;
	struct sigaction oldact;

	DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
		   "message.\n"));

	/*
	 * call the validation code from a child:
	 * so we don't block the main winbindd and the validation
	 * code can safely use fork/waitpid...
	 */
	CatchChild();
	child_pid = sys_fork();

	if (child_pid == -1) {
		DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
			  strerror(errno)));
		return;
	}

	if (child_pid != 0) {
		/* parent */
		DEBUG(5, ("winbind_msg_validate_cache: child created with "
			  "pid %d.\n", (int)child_pid));
		return;
	}

	/* child */

	/* install default SIGCHLD handler: validation code uses fork/waitpid */
	ZERO_STRUCT(act);
	act.sa_handler = SIG_DFL;
#ifdef SA_RESTART
	/* We *want* SIGALRM to interrupt a system call. */
	act.sa_flags = SA_RESTART;
#endif
	sigemptyset(&act.sa_mask);
	sigaddset(&act.sa_mask,SIGCHLD);
	sigaction(SIGCHLD,&act,&oldact);

	ret = (uint8)winbindd_validate_cache_nobackup();
	DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
	messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
			   (size_t)1);
	_exit(0);
}
Beispiel #13
0
static bool cups_pcap_load_async(int *pfd)
{
	int fds[2];
	pid_t pid;

	*pfd = -1;

	if (cache_fd_event) {
		DEBUG(3,("cups_pcap_load_async: already waiting for "
			"a refresh event\n" ));
		return false;
	}

	DEBUG(5,("cups_pcap_load_async: asynchronously loading cups printers\n"));

	if (pipe(fds) == -1) {
		return false;
	}

	pid = sys_fork();
	if (pid == (pid_t)-1) {
		DEBUG(10,("cups_pcap_load_async: fork failed %s\n",
			strerror(errno) ));
		close(fds[0]);
		close(fds[1]);
		return false;
	}

	if (pid) {
		DEBUG(10,("cups_pcap_load_async: child pid = %u\n",
			(unsigned int)pid ));
		/* Parent. */
		close(fds[1]);
		*pfd = fds[0];
		return true;
	}

	/* Child. */

	close_all_print_db();

	if (!reinit_after_fork(smbd_messaging_context(),
			       smbd_event_context(), true)) {
		DEBUG(0,("cups_pcap_load_async: reinit_after_fork() failed\n"));
		smb_panic("cups_pcap_load_async: reinit_after_fork() failed");
	}

	close(fds[0]);
	cups_cache_reload_async(fds[1]);
	close(fds[1]);
	_exit(0);
}
Beispiel #14
0
void
start(void)
{
	int x = 0;
	
	pid_t p = sys_fork();
	if (p == 0)
		x++;	
	else if (p > 0)
		sys_wait(p);
	app_printf("%d",x);
	sys_exit(0);	
}
Beispiel #15
0
static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
				       void *private_data,
				       uint32_t msg_type,
				       struct server_id server_id,
				       DATA_BLOB *data)
{
	uint8 ret;
	pid_t child_pid;
	NTSTATUS status;

	DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
		   "message.\n"));

	/*
	 * call the validation code from a child:
	 * so we don't block the main winbindd and the validation
	 * code can safely use fork/waitpid...
	 */
	child_pid = sys_fork();

	if (child_pid == -1) {
		DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
			  strerror(errno)));
		return;
	}

	if (child_pid != 0) {
		/* parent */
		DEBUG(5, ("winbind_msg_validate_cache: child created with "
			  "pid %d.\n", (int)child_pid));
		return;
	}

	/* child */

	status = winbindd_reinit_after_fork(NULL, NULL);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
			  nt_errstr(status)));
		_exit(0);
	}

	/* install default SIGCHLD handler: validation code uses fork/waitpid */
	CatchSignal(SIGCHLD, SIG_DFL);

	ret = (uint8)winbindd_validate_cache_nobackup();
	DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
	messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
			   (size_t)1);
	_exit(0);
}
Beispiel #16
0
int
pltconsole_process(void)
{
	int ret, pid;

	/* Search for console devices */
	pid = sys_fork();
	if (pid < 0)
		return pid;

	if (pid == 0)
		pltconsole();

	return pid;
}
Beispiel #17
0
void
start(void)
{
	pid_t p;
	int status;

	counter = 0;

	while (counter < 1025) {
		int n_started = 0;

		// Start as many processes as possible, until we fail to start
		// a process or we have started 1025 processes total.
		while (counter + n_started < 1025) {
			p = sys_fork();
			if (p == 0)
				run_child();
			else if (p > 0)
				n_started++;
			else
				break;
		}
                //app_printf("Process %d lives, Status_FORK: %d, Start: %d!",
		//sys_getpid(), p, n_started);
		// If we could not start any new processes, give up!
		if (n_started == 0)
			break;

		// We started at least one process, but then could not start
		// any more.
		// That means we ran out of room to start processes.
		// Retrieve old processes' exit status with sys_wait(),
		// to make room for new processes.

		for (p = 2; p < NPROCS; p++)
                {
                        //app_printf("Process %d lives, Wait: %d!", sys_getpid(), p);
 			(void)sys_wait(p);
                        status = sys_wait(p);
                        //app_printf("Process %d lives, Status: %d!",
		       // sys_getpid(), status);
                }
	}

	sys_exit(0);
}
static int
filemon_wrapper_fork(struct lwp * l, const void *v, register_t * retval)
{
	int ret;
	struct filemon *filemon;

	if ((ret = sys_fork(l, v, retval)) == 0) {
		filemon = filemon_lookup(curproc);

		if (filemon) {
			filemon_printf(filemon, "F %d %ld\n",
			    curproc->p_pid, (long) retval[0]);
			rw_exit(&filemon->fm_mtx);
		}
	}
	return (ret);
}
Beispiel #19
0
void
pmain(void)
{
	volatile int checker = 30; /* This variable checks for some common
				      stack errors. */
	pid_t p;
	int i, status;

	app_printf("About to start a new process...\n");

	p = sys_fork();
	if (p == 0) {
		// Check that the kernel correctly copied the parent's stack.
		check(checker, 30, "new child");
		checker = 30 + sys_getpid();

		// Yield several times to help test Exercise 3
		app_printf("Child process %d!\n", sys_getpid());
		for (i = 0; i < 20; i++)
			sys_yield();

		// Check that no one else corrupted our stack.
		check(checker, 30 + sys_getpid(), "end child");
		sys_exit(1000);

	} else if (p > 0) {
		// Check that the child didn't corrupt our stack.
		check(checker, 30, "main parent");

		app_printf("Main process %d!\n", sys_getpid());
		do {
			status = sys_wait(p);
		} while (status == WAIT_TRYAGAIN);
		app_printf("Child %d exited with status %d!\n", p, status);
		check(status, 1000, "sys_wait for child");

		// Check again that the child didn't corrupt our stack.
		check(checker, 30, "end parent");
		sys_exit(0);

	} else {
		app_printf("Error!\n");
		sys_exit(1);
	}
}
Beispiel #20
0
int process_fork()
{
    int status;
    struct pcb_s* child_process = sys_fork();

    if (child_process == 0)
    {
        //On est dans le processus fils.
        return EXIT_SUCCESS;
    }
    else
    {
        //On est dans le processus pere.
        status = sys_wait(child_process);
    }

    return status;
}
Beispiel #21
0
void process_command(char* string) {
	prepare_shell();

	if (((string != NULL) && (string[0] == '\0')) || !strlen(string))
		return;

	int argc;
	char *sdup = strdup(string);
	char **argv = buildargv(sdup, &argc);
	kfree(sdup);

	if (argc == 0) {
		freeargv(argv);
		return;
	}

	char* command = argv[0];

	int i = findCommand(command);
	if (i >= 0) {
		void (*command_function)(int, char **) = (void(*)(int, char**))CommandTable[i].function;
		command_function(argc, argv);
	}
	else {
		//not a valid command
		//are we trying to execute a binary?
		FILE* stream = fopen(command, "r");
		if (stream) {
			int pid = sys_fork();
			if (!pid) {
				execve(command, 0, 0);
				sys__exit(1);
			}
			else {
				int status;
				waitpid(pid, &status, 0);
			}
		}
		else {
			//invalid input
			printf("Command '\e[9;%s\e[15;' not found.", command);
		}
		fclose(stream);
	}
Beispiel #22
0
/***
 *
 * @TODO Could be handled by a lowlevel lookup-table, but this is probably a bit more readable
 *
 * Calling paramters:
 *   param 1 : EBX
 *   param 2 : ECX
 *   param 3 : EDX
 *   param 4 : ESI
 *   param 5 : EDI
 *   param 6 : time for using a structure instead of so many parameters...
 *
 *  This parameter list is defined in the create_syscall_entryX macro's (service.h)
 *
 */
int service_interrupt (regs_t *r) {
    int retval = 0;
    int service = (r->eax & 0x0000FFFF);

    switch (service) {
    default        :
    case  SYS_NULL :
        retval = sys_null ();
        break;
    case  SYS_CONSOLE :
        retval = sys_console (r->ebx, (console_t *)r->ecx, (char *)r->edx);
        break;
    case  SYS_CONWRITE :
        retval = sys_conwrite ((char)r->ebx, r->ecx);
        break;
    case  SYS_CONFLUSH :
        retval = sys_conflush ();
        break;
    case  SYS_FORK :
        retval = sys_fork (r);
        break;
    case  SYS_GETPID :
        retval = sys_getpid ();
        break;
    case  SYS_GETPPID :
        retval = sys_getppid ();
        break;
    case  SYS_SLEEP :
        retval = sys_sleep (r->ebx);
        break;
    case  SYS_IDLE :
        retval = sys_idle ();
        break;
    case  SYS_EXIT :
        retval = sys_exit (r->ebx);
        break;
    case  SYS_EXECVE :
        retval = sys_execve (r, (char *)r->ebx, (char **)r->ecx, (char **)r->edx);
        break;
    }
    return retval;
}
Beispiel #23
0
int process()
{
	int32_t cpt = 10;
	
	int pid = sys_fork();
	if (pid == -1)
	{
		// failed, should not happen
	}
	else if (pid == 0)
	{
		// Child
		cpt--;
		sys_nop();
	}
	else
	{
		// Parent
		cpt++;
		sys_nop();
	}
	
	return 0;
}
Beispiel #24
0
/*===========================================================================*
 *				do_fork					     *
 *===========================================================================*/
int do_fork(message *msg)
{
  int r, proc, childproc;
  struct vmproc *vmp, *vmc;
  pt_t origpt;
  vir_bytes msgaddr;

  SANITYCHECK(SCL_FUNCTIONS);

  if(vm_isokendpt(msg->VMF_ENDPOINT, &proc) != OK) {
	printf("VM: bogus endpoint VM_FORK %d\n", msg->VMF_ENDPOINT);
  SANITYCHECK(SCL_FUNCTIONS);
	return EINVAL;
  }

  childproc = msg->VMF_SLOTNO;
  if(childproc < 0 || childproc >= NR_PROCS) {
	printf("VM: bogus slotno VM_FORK %d\n", msg->VMF_SLOTNO);
  SANITYCHECK(SCL_FUNCTIONS);
	return EINVAL;
  }

  vmp = &vmproc[proc];		/* parent */
  vmc = &vmproc[childproc];	/* child */
  assert(vmc->vm_slot == childproc);

  /* The child is basically a copy of the parent. */
  origpt = vmc->vm_pt;
  *vmc = *vmp;
  vmc->vm_slot = childproc;
  region_init(&vmc->vm_regions_avl);
  vmc->vm_endpoint = NONE;	/* In case someone tries to use it. */
  vmc->vm_pt = origpt;

#if VMSTATS
  vmc->vm_bytecopies = 0;
#endif

  if(pt_new(&vmc->vm_pt) != OK) {
	printf("VM: fork: pt_new failed\n");
	return ENOMEM;
  }

  SANITYCHECK(SCL_DETAIL);

  if(map_proc_copy(vmc, vmp) != OK) {
	printf("VM: fork: map_proc_copy failed\n");
	pt_free(&vmc->vm_pt);
	return(ENOMEM);
  }

  /* Only inherit these flags. */
  vmc->vm_flags &= VMF_INUSE;

  /* inherit the priv call bitmaps */
  memcpy(&vmc->vm_call_mask, &vmp->vm_call_mask, sizeof(vmc->vm_call_mask));

  /* Tell kernel about the (now successful) FORK. */
  if((r=sys_fork(vmp->vm_endpoint, childproc,
	&vmc->vm_endpoint, PFF_VMINHIBIT, &msgaddr)) != OK) {
        panic("do_fork can't sys_fork: %d", r);
  }

  if((r=pt_bind(&vmc->vm_pt, vmc)) != OK)
	panic("fork can't pt_bind: %d", r);

  {
	vir_bytes vir;
	/* making these messages writable is an optimisation
	 * and its return value needn't be checked.
	 */
	vir = msgaddr;
	if (handle_memory(vmc, vir, sizeof(message), 1) != OK)
	    panic("do_fork: handle_memory for child failed\n");
	vir = msgaddr;
	if (handle_memory(vmp, vir, sizeof(message), 1) != OK)
	    panic("do_fork: handle_memory for parent failed\n");
  }

  /* Inform caller of new child endpoint. */
  msg->VMF_CHILD_ENDPOINT = vmc->vm_endpoint;

  SANITYCHECK(SCL_FUNCTIONS);
  return OK;
}
/*
 * System call dispatcher.
 *
 * A pointer to the trapframe created during exception entry (in
 * exception-*.S) is passed in.
 *
 * The calling conventions for syscalls are as follows: Like ordinary
 * function calls, the first 4 32-bit arguments are passed in the 4
 * argument registers a0-a3. 64-bit arguments are passed in *aligned*
 * pairs of registers, that is, either a0/a1 or a2/a3. This means that
 * if the first argument is 32-bit and the second is 64-bit, a1 is
 * unused.
 *
 * This much is the same as the calling conventions for ordinary
 * function calls. In addition, the system call number is passed in
 * the v0 register.
 *
 * On successful return, the return value is passed back in the v0
 * register, or v0 and v1 if 64-bit. This is also like an ordinary
 * function call, and additionally the a3 register is also set to 0 to
 * indicate success.
 *
 * On an error return, the error code is passed back in the v0
 * register, and the a3 register is set to 1 to indicate failure.
 * (Userlevel code takes care of storing the error code in errno and
 * returning the value -1 from the actual userlevel syscall function.
 * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.)
 *
 * Upon syscall return the program counter stored in the trapframe
 * must be incremented by one instruction; otherwise the exception
 * return code will restart the "syscall" instruction and the system
 * call will repeat forever.
 *
 * If you run out of registers (which happens quickly with 64-bit
 * values) further arguments must be fetched from the user-level
 * stack, starting at sp+16 to skip over the slots for the
 * registerized values, with copyin().
 */
void syscall(struct trapframe *tf) {
	int callno;
	int32_t retval;
	int err;

	KASSERT(curthread != NULL);
	KASSERT(curthread->t_curspl == 0);
	KASSERT(curthread->t_iplhigh_count == 0);

	callno = tf->tf_v0;

	/*
	 * Initialize retval to 0. Many of the system calls don't
	 * really return a value, just 0 for success and -1 on
	 * error. Since retval is the value returned on success,
	 * initialize it to 0 by default; thus it's not necessary to
	 * deal with it except for calls that return other values,
	 * like write.
	 */

	retval = 0;


	off_t pos, new_pos;
	switch (callno) {
	case SYS_reboot:
		err = sys_reboot(tf->tf_a0);
		break;

	case SYS___time:
		err = sys___time((userptr_t) tf->tf_a0, (userptr_t) tf->tf_a1);
		break;

	case SYS_open:
		err = sys_open((userptr_t) tf->tf_a0, (int) tf->tf_a1,
				(int) tf->tf_a2, &retval);
		break;

	case SYS_read:
		err = sys_read((int) tf->tf_a0, (userptr_t) tf->tf_a1,
				(int) tf->tf_a2, &retval);
		break;

	case SYS_write:
		err = sys_write((int) tf->tf_a0, (userptr_t) tf->tf_a1,
				(int) tf->tf_a2, &retval);
		break;
	case SYS_lseek:

		pos = (((off_t)tf->tf_a2 << 32) | tf->tf_a3);
		err = sys_lseek((userptr_t) tf->tf_a0, pos,
				(userptr_t)(tf->tf_sp+16), &new_pos);

		if (err == 0)
		{
			retval = (int32_t)(new_pos >> 32);
			tf->tf_v1 = (int32_t)(new_pos & 0xFFFFFFFF);
		}


		break;

	case SYS_close:
		err = sys_close((userptr_t) tf->tf_a0, &retval);
		break;

	case SYS_dup2:
		err = sys_dup2((userptr_t) tf->tf_a0, (userptr_t) tf->tf_a1, &retval);
		break;

	case SYS_getpid:
		err = sys_getpid(&retval);
		break;
	case SYS_sbrk:
		err = sys_sbrk((userptr_t)tf->tf_a0, &retval);
		break;
	case SYS_fork:
		err = sys_fork(tf, &retval);
		break;
	case SYS_execv:
		err = sys_execv((userptr_t) tf->tf_a0, (userptr_t) tf->tf_a1, &retval);
		retval = 0;
		break;
	case SYS_waitpid:
		err = sys_waitpid((userptr_t) tf->tf_a0, (userptr_t) tf->tf_a1,
				(userptr_t) tf->tf_a2, &retval);
		break;
	case SYS__exit:
		//kprintf("TEMPPPP:Exit has been called!	\n");
		err = sys__exit((int) tf->tf_a0);
		break;
		/* Add stuff here */

	default:
		kprintf("Unknown syscall %d\n", callno);
		err = ENOSYS;
		break;
	}
Beispiel #26
0
/*
 * System call dispatcher.
 *
 * A pointer to the trapframe created during exception entry (in
 * exception.S) is passed in.
 *
 * The calling conventions for syscalls are as follows: Like ordinary
 * function calls, the first 4 32-bit arguments are passed in the 4
 * argument registers a0-a3. 64-bit arguments are passed in *aligned*
 * pairs of registers, that is, either a0/a1 or a2/a3. This means that
 * if the first argument is 32-bit and the second is 64-bit, a1 is
 * unused.
 *
 * This much is the same as the calling conventions for ordinary
 * function calls. In addition, the system call number is passed in
 * the v0 register.
 *
 * On successful return, the return value is passed back in the v0
 * register, or v0 and v1 if 64-bit. This is also like an ordinary
 * function call, and additionally the a3 register is also set to 0 to
 * indicate success.
 *
 * On an error return, the error code is passed back in the v0
 * register, and the a3 register is set to 1 to indicate failure.
 * (Userlevel code takes care of storing the error code in errno and
 * returning the value -1 from the actual userlevel syscall function.
 * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.)
 *
 * Upon syscall return the program counter stored in the trapframe
 * must be incremented by one instruction; otherwise the exception
 * return code will restart the "syscall" instruction and the system
 * call will repeat forever.
 *
 * If you run out of registers (which happens quickly with 64-bit
 * values) further arguments must be fetched from the user-level
 * stack, starting at sp+16 to skip over the slots for the
 * registerized values, with copyin().
 */
void
syscall(struct trapframe *tf)
{
    //kprintf("Starting syscall\n");
	int callno;
	int32_t retval;
	int err;

	KASSERT(curthread != NULL);
	KASSERT(curthread->t_curspl == 0);
	KASSERT(curthread->t_iplhigh_count == 0);

	callno = tf->tf_v0;

	/*
	 * Initialize retval to 0. Many of the system calls don't
	 * really return a value, just 0 for success and -1 on
	 * error. Since retval is the value returned on success,
	 * initialize it to 0 by default; thus it's not necessary to
	 * deal with it except for calls that return other values, 
	 * like write.
	 */

	retval = 0;

	switch (callno) {
	    case SYS_reboot:
		err = sys_reboot(tf->tf_a0);
		break;

	    case SYS___time:
		err = sys___time((userptr_t)tf->tf_a0,
				 (userptr_t)tf->tf_a1);
		break;
#ifdef UW
	case SYS_write:
	  err = sys_write((int)tf->tf_a0,
			  (userptr_t)tf->tf_a1,
			  (int)tf->tf_a2,
			  (int *)(&retval));
	  break;
	case SYS__exit:
	  sys__exit((int)tf->tf_a0);
	  /* sys__exit does not return, execution should not get here */
	  panic("unexpected return from sys__exit");
	  break;
	case SYS_getpid:
	  err = sys_getpid((pid_t *)&retval);
	  break;
	case SYS_waitpid:
	  err = sys_waitpid((pid_t)tf->tf_a0,
			    (userptr_t)tf->tf_a1,
			    (int)tf->tf_a2,
			    (pid_t *)&retval);
	  break;
	case SYS_fork:
	    err = sys_fork(tf, (pid_t *)&retval);
	    break;
	case SYS_execv:
	    err=sys_execv((char *)tf->tf_a0, (char **) tf->tf_a1);
	    break;
#endif // UW

	    /* Add stuff here */
 
	default:
	  kprintf("Unknown syscall %d\n", callno);
	  err = ENOSYS;
	  break;
	}


	if (err) {
		/*
		 * Return the error code. This gets converted at
		 * userlevel to a return value of -1 and the error
		 * code in errno.
		 */
		tf->tf_v0 = err;
		tf->tf_a3 = 1;      /* signal an error */
	}
	else {
		/* Success. */
		tf->tf_v0 = retval;
		tf->tf_a3 = 0;      /* signal no error */
	}
	
	/*
	 * Now, advance the program counter, to avoid restarting
	 * the syscall over and over again.
	 */
	
	tf->tf_epc += 4;

	/* Make sure the syscall code didn't forget to lower spl */
	KASSERT(curthread->t_curspl == 0);
	/* ...or leak any spinlocks */
	KASSERT(curthread->t_iplhigh_count == 0);
}
Beispiel #27
0
static int syscall_dispatch(uint32_t sysnum, uint32_t args, regs_t *regs)
{
    switch (sysnum) {
        case SYS_waitpid:
            return sys_waitpid((waitpid_args_t *)args);
            
        case SYS_exit:
            do_exit((int)args);
            panic("exit failed!\n");
            return 0;
            
        case SYS_thr_exit:
            kthread_exit((void *)args);
            panic("thr_exit failed!\n");
            return 0;
            
        case SYS_thr_yield:
            sched_make_runnable(curthr);
            sched_switch();
            return 0;
            
        case SYS_fork:
            return sys_fork(regs);
            
        case SYS_getpid:
            return curproc->p_pid;
            
        case SYS_sync:
            sys_sync();
            return 0;
            
#ifdef __MOUNTING__
        case SYS_mount:
            return sys_mount((mount_args_t *) args);
            
        case SYS_umount:
            return sys_umount((argstr_t *) args);
#endif
            
        case SYS_mmap:
            return (int) sys_mmap((mmap_args_t *) args);
            
        case SYS_munmap:
            return sys_munmap((munmap_args_t *) args);
            
        case SYS_open:
            return sys_open((open_args_t *) args);
            
        case SYS_close:
            return sys_close((int)args);
            
        case SYS_read:
            return sys_read((read_args_t *)args);
            
        case SYS_write:
            return sys_write((write_args_t *)args);
            
        case SYS_dup:
            return sys_dup((int)args);
            
        case SYS_dup2:
            return sys_dup2((dup2_args_t *)args);
            
        case SYS_mkdir:
            return sys_mkdir((mkdir_args_t *)args);
            
        case SYS_rmdir:
            return sys_rmdir((argstr_t *)args);
            
        case SYS_unlink:
            return sys_unlink((argstr_t *)args);
            
        case SYS_link:
            return sys_link((link_args_t *)args);
            
        case SYS_rename:
            return sys_rename((rename_args_t *)args);
            
        case SYS_chdir:
            return sys_chdir((argstr_t *)args);
            
        case SYS_getdents:
            return sys_getdents((getdents_args_t *)args);
            
        case SYS_brk:
            return (int) sys_brk((void *)args);
            
        case SYS_lseek:
            return sys_lseek((lseek_args_t *)args);
            
        case SYS_halt:
            sys_halt();
            return -1;
            
        case SYS_set_errno:
            curthr->kt_errno = (int)args;
            return 0;
            
        case SYS_errno:
            return curthr->kt_errno;
            
        case SYS_execve:
            return sys_execve((execve_args_t *)args, regs);
            
        case SYS_stat:
            return sys_stat((stat_args_t *)args);
            
        case SYS_uname:
            return sys_uname((struct utsname *)args);
            
        case SYS_debug:
            return sys_debug((argstr_t *)args);
        case SYS_kshell:
            return sys_kshell((int)args);
        default:
            dbg(DBG_ERROR, "ERROR: unknown system call: %d (args: %#08x)\n", sysnum, args);
            curthr->kt_errno = ENOSYS;
            return -1;
    }
}
Beispiel #28
0
/**
 * main replayer method
 */
static void start(int option, int argc, char* argv[], char** envp)
{
	pid_t pid;
	int status, fake_argc;

	if (option == RECORD) {
		copy_executable(argv[2]);
		if (access(__executable, X_OK)) {
			printf("The specified file '%s' does not exist or is not executable\n", __executable);
			return;
		}

		/* create directory for trace files */
		setup_trace_dir(0);

		/* initialize trace files */
		open_trace_files();
		init_trace_files();
		copy_argv(argc, argv);
		copy_envp(envp);
		record_argv_envp(argc, __argv, __envp);
		close_trace_files();

		pid = sys_fork();
		/* child process */
		if (pid == 0) {
			sys_start_trace(__executable, __argv, __envp);
			/* parent process */
		} else {
			child = pid;

			/* make sure that the child process dies when the master process gets interrupted */
			install_signal_handler();

			/* sync with the child process */
			sys_waitpid(pid, &status);

			/* configure the child process to get a message upon a thread start, fork(), etc. */
			sys_ptrace_setup(pid);

			/* initialize stuff */
			init_libpfm();
			/* initialize the trace file here -- we need to record argc and envp */
			open_trace_files();

			/* register thread at the scheduler and start the HPC */
			rec_sched_register_thread(0, pid);

			/* perform the action recording */
			fprintf(stderr, "start recording...\n");
			start_recording();
			fprintf(stderr, "done recording -- cleaning up\n");
			/* cleanup all initialized data-structures */
			close_trace_files();
			close_libpfm();
		}

		/* replayer code comes here */
	} else if (option == REPLAY) {
		init_environment(argv[2], &fake_argc, __argv, __envp);

		copy_executable(__argv[0]);
		if (access(__executable, X_OK)) {
			printf("The specified file '%s' does not exist or is not executable\n", __executable);
			return;
		}

		pid = sys_fork();
		//child process
		if (pid == 0) {
			sys_start_trace(__executable, __argv, __envp);
			/* parent process */
		} else {
			child = pid;
			/* make sure that the child process dies when the master process gets interrupted */
			install_signal_handler();

			sys_waitpid(pid, &status);
			sys_ptrace_setup(pid);


			/* initialize stuff */
			init_libpfm();
			rep_sched_init();
			/* sets the file pointer to the first trace entry */

			read_trace_init(argv[2]);

			pid_t rec_main_thread = get_recorded_main_thread();
			rep_sched_register_thread(pid, rec_main_thread);

			/* main loop */
			replay();
			/* thread wants to exit*/
			close_libpfm();
			read_trace_close();
			rep_sched_close();
		}
	}
}
Beispiel #29
0
void
mips_syscall(struct trapframe *tf)
{
	int callno;
	int32_t retval;
	int err;

	assert(curspl==0);

	callno = tf->tf_v0;

	/*
	 * Initialize retval to 0. Many of the system calls don't
	 * really return a value, just 0 for success and -1 on
	 * error. Since retval is the value returned on success,
	 * initialize it to 0 by default; thus it's not necessary to
	 * deal with it except for calls that return other values, 
	 * like write.
	 */

	retval = 0;

	switch (callno) {
	    case SYS_reboot:
			err = sys_reboot(tf->tf_a0);
			break;
		
	    case SYS_getpid:
			retval = ((int32_t)sys_getpid());
			err=retval;
			break;
			
		case SYS_waitpid:
			//just passing the the first arg from users waitpid
			err = (sys_waitpid(tf->tf_a0,&retval,0));
			break;
		
		case SYS__exit:
		
			retval = ((int32_t)sys__exit());
			err=retval;
			break;
			
		case SYS_fork:
			//http://jhshi.me/2012/03/21/os161-how-to-add-a-system-call/
			err = ((int32_t)sys_fork(tf));
			break;
		case SYS_execv:
			break;

		case SYS_read:
			//err = ((int32_t)sys_read(tf->tf_a0,(userptr_t)tf->tf_a1,tf->tf_a2)); //original
			err = ((int32_t)sys_read(tf->tf_a0,(char*)tf->tf_a1,tf->tf_a2));
			break;
		case SYS_write:
			err = ((int32_t)sys_write(tf->tf_a0,(char*)tf->tf_a1,tf->tf_a2));
			break;
	    default:
		kprintf("Unknown syscall %d\n", callno);
		err = ENOSYS;
		break;
	}


	if (err) {
		/*
		 * Return the error code. This gets converted at
		 * userlevel to a return value of -1 and the error
		 * code in errno.
		 */
		tf->tf_v0 = err;
		tf->tf_a3 = 1;      /* signal an error */
	}
	else {
		/* Success. */
		tf->tf_v0 = retval;
		tf->tf_a3 = 0;      /* signal no error */
	}
	
	/*
	 * Now, advance the program counter, to avoid restarting
	 * the syscall over and over again.
	 */
	
	tf->tf_epc += 4;

	/* Make sure the syscall code didn't forget to lower spl */
	assert(curspl==0);
}
Beispiel #30
0
/*===========================================================================*
 *				do_fork					     *
 *===========================================================================*/
PUBLIC int do_fork(message *msg)
{
  int r, proc, s, childproc, fullvm;
  struct vmproc *vmp, *vmc;
  pt_t origpt;
  vir_bytes msgaddr;

  SANITYCHECK(SCL_FUNCTIONS);

  if(vm_isokendpt(msg->VMF_ENDPOINT, &proc) != OK) {
	printf("VM: bogus endpoint VM_FORK %d\n", msg->VMF_ENDPOINT);
  SANITYCHECK(SCL_FUNCTIONS);
	return EINVAL;
  }

  childproc = msg->VMF_SLOTNO;
  if(childproc < 0 || childproc >= NR_PROCS) {
	printf("VM: bogus slotno VM_FORK %d\n", msg->VMF_SLOTNO);
  SANITYCHECK(SCL_FUNCTIONS);
	return EINVAL;
  }

  vmp = &vmproc[proc];		/* parent */
  vmc = &vmproc[childproc];	/* child */
  assert(vmc->vm_slot == childproc);

  if(vmp->vm_flags & VMF_HAS_DMA) {
	printf("VM: %d has DMA memory and may not fork\n", msg->VMF_ENDPOINT);
	return EINVAL;
  }

  fullvm = vmp->vm_flags & VMF_HASPT;

  /* The child is basically a copy of the parent. */
  origpt = vmc->vm_pt;
  *vmc = *vmp;
  vmc->vm_slot = childproc;
  vmc->vm_regions = NULL;
  yielded_init(&vmc->vm_yielded_blocks);
  vmc->vm_endpoint = NONE;	/* In case someone tries to use it. */
  vmc->vm_pt = origpt;
  vmc->vm_flags &= ~VMF_HASPT;

#if VMSTATS
  vmc->vm_bytecopies = 0;
#endif

  if(pt_new(&vmc->vm_pt) != OK) {
	printf("VM: fork: pt_new failed\n");
	return ENOMEM;
  }

  vmc->vm_flags |= VMF_HASPT;

  if(fullvm) {
	SANITYCHECK(SCL_DETAIL);

	if(map_proc_copy(vmc, vmp) != OK) {
		printf("VM: fork: map_proc_copy failed\n");
		pt_free(&vmc->vm_pt);
		return(ENOMEM);
	}

	if(vmp->vm_heap) {
		vmc->vm_heap = map_region_lookup_tag(vmc, VRT_HEAP);
		assert(vmc->vm_heap);
	}

	SANITYCHECK(SCL_DETAIL);
  } else {
	vir_bytes sp;
	struct vir_region *heap, *stack;
	vir_bytes text_bytes, data_bytes, stack_bytes, parent_gap_bytes,
		child_gap_bytes;

	/* Get SP of new process (using parent). */
	if(get_stack_ptr(vmp->vm_endpoint, &sp) != OK) {
		printf("VM: fork: get_stack_ptr failed for %d\n",
			vmp->vm_endpoint);
		return ENOMEM;
	}

	/* Update size of stack segment using current SP. */
	if(adjust(vmp, vmp->vm_arch.vm_seg[D].mem_len, sp) != OK) {
		printf("VM: fork: adjust failed for %d\n",
			vmp->vm_endpoint);
		return ENOMEM;
	}

	/* Copy newly adjust()ed stack segment size to child. */
	vmc->vm_arch.vm_seg[S] = vmp->vm_arch.vm_seg[S];

        text_bytes = CLICK2ABS(vmc->vm_arch.vm_seg[T].mem_len);
        data_bytes = CLICK2ABS(vmc->vm_arch.vm_seg[D].mem_len);
	stack_bytes = CLICK2ABS(vmc->vm_arch.vm_seg[S].mem_len);

	/* how much space after break and before lower end (which is the
	 * logical top) of stack for the parent
	 */
	parent_gap_bytes = CLICK2ABS(vmc->vm_arch.vm_seg[S].mem_vir -
		vmc->vm_arch.vm_seg[D].mem_len);

	/* how much space can the child stack grow downwards, below
	 * the current SP? The rest of the gap is available for the
	 * heap to grow upwards.
	 */
	child_gap_bytes = VM_PAGE_SIZE;

        if((r=proc_new(vmc, VM_PROCSTART,
		text_bytes, data_bytes, stack_bytes, child_gap_bytes, 0, 0,
		CLICK2ABS(vmc->vm_arch.vm_seg[S].mem_vir +
                        vmc->vm_arch.vm_seg[S].mem_len), 1)) != OK) {
			printf("VM: fork: proc_new failed\n");
			return r;
	}

	if(!(heap = map_region_lookup_tag(vmc, VRT_HEAP)))
		panic("couldn't lookup heap");
	assert(heap->phys);
	if(!(stack = map_region_lookup_tag(vmc, VRT_STACK)))
		panic("couldn't lookup stack");
	assert(stack->phys);

	/* Now copy the memory regions. */

	if(vmc->vm_arch.vm_seg[T].mem_len > 0) {
		struct vir_region *text;
		if(!(text = map_region_lookup_tag(vmc, VRT_TEXT)))
			panic("couldn't lookup text");
		assert(text->phys);
		if(copy_abs2region(CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys),
			text, 0, text_bytes) != OK)
				panic("couldn't copy text");
	}

	if(copy_abs2region(CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys),
		heap, 0, data_bytes) != OK)
			panic("couldn't copy heap");

	if(copy_abs2region(CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys +
			vmc->vm_arch.vm_seg[D].mem_len) + parent_gap_bytes,
			stack, child_gap_bytes, stack_bytes) != OK)
			panic("couldn't copy stack");
  }

  /* Only inherit these flags. */
  vmc->vm_flags &= (VMF_INUSE|VMF_SEPARATE|VMF_HASPT);

  /* inherit the priv call bitmaps */
  memcpy(&vmc->vm_call_mask, &vmp->vm_call_mask, sizeof(vmc->vm_call_mask));

  /* Tell kernel about the (now successful) FORK. */
  if((r=sys_fork(vmp->vm_endpoint, childproc,
	&vmc->vm_endpoint, vmc->vm_arch.vm_seg,
	PFF_VMINHIBIT, &msgaddr)) != OK) {
        panic("do_fork can't sys_fork: %d", r);
  }

  if(fullvm) {
	vir_bytes vir;
	/* making these messages writable is an optimisation
	 * and its return value needn't be checked.
	 */
	vir = arch_vir2map(vmc, msgaddr);
	handle_memory(vmc, vir, sizeof(message), 1);
	vir = arch_vir2map(vmp, msgaddr);
	handle_memory(vmp, vir, sizeof(message), 1);
  }

  if((r=pt_bind(&vmc->vm_pt, vmc)) != OK)
	panic("fork can't pt_bind: %d", r);

  /* Inform caller of new child endpoint. */
  msg->VMF_CHILD_ENDPOINT = vmc->vm_endpoint;

  SANITYCHECK(SCL_FUNCTIONS);
  return OK;
}