void umain(int argc, char **argv) { envid_t who; if ((who = fork()) == 0) { // Child ipc_recv(&who, TEMP_ADDR_CHILD, 0); cprintf("%x got message: %s\n", who, TEMP_ADDR_CHILD); if (strncmp(TEMP_ADDR_CHILD, str1, strlen(str1)) == 0) cprintf("child received correct message\n"); memcpy(TEMP_ADDR_CHILD, str2, strlen(str2) + 1); ipc_send(who, 0, TEMP_ADDR_CHILD, PTE_P | PTE_W | PTE_U); return; } // Parent sys_page_alloc(thisenv->env_id, TEMP_ADDR, PTE_P | PTE_W | PTE_U); memcpy(TEMP_ADDR, str1, strlen(str1) + 1); ipc_send(who, 0, TEMP_ADDR, PTE_P | PTE_W | PTE_U); ipc_recv(&who, TEMP_ADDR, 0); cprintf("%x got message: %s\n", who, TEMP_ADDR); if (strncmp(TEMP_ADDR, str2, strlen(str2)) == 0) cprintf("parent received correct message\n"); return; }
void umain(int argc, char **argv) { envid_t who; uint32_t i; i = 0; if ((who = sfork()) != 0) { cprintf("i am %08x; thisenv is %p\n", sys_getenvid(), thisenv); // get the ball rolling cprintf("send 0 from %x to %x\n", sys_getenvid(), who); ipc_send(who, 0, 0, 0); } while (1) { cprintf("%x prepare to recv from %x (thisenv is %p %x)\n", sys_getenvid(), who, thisenv, thisenv->env_id); ipc_recv(&who, 0, 0); cprintf("%x got %d from %x (thisenv is %p %x)\n", sys_getenvid(), val, who, thisenv, thisenv->env_id); if (val == 10) return; ++val; ipc_send(who, 0, 0, 0); if (val == 10) return; } }
void timer(envid_t ns_envid, uint32_t initial_to) { int r; uint32_t stop = sys_time_msec() + initial_to; binaryname = "ns_timer"; while (1) { while((r = sys_time_msec()) < stop && r >= 0) { sys_yield(); } if (r < 0) panic("sys_time_msec: %e", r); ipc_send(ns_envid, NSREQ_TIMER, 0, 0); while (1) { uint32_t to, whom; to = ipc_recv((int32_t *) &whom, 0, 0); if (whom != ns_envid) { cprintf("NS TIMER: timer thread got IPC message from env %x not NS\n", whom); continue; } stop = sys_time_msec() + to; break; } } }
void output(envid_t ns_envid) { binaryname = "ns_output"; // LAB 6: Your code here: // - read a packet from the network server // - send the packet to the device driver envid_t sender_envid; uint32_t req; int perm; while(1) { perm = 0; req = ipc_recv(&sender_envid, &nsipcbuf, &perm); if (((uint32_t *) sender_envid == 0) || (perm == 0)) { cprintf("Invalid request; ipc_recv encountered an error %e\n", req); continue; } if (sender_envid != ns_envid) { cprintf("Received IPC from envid %08x, expected to receive from %08x\n", sender_envid, ns_envid); continue; } // Note that we are passing in the envid of the output environment and not // the network server envid. That is because the IPC page is being mapped to // an address within output's address space (nsipcbuf). if (sys_e1000_transmit(sys_getenvid(), nsipcbuf.pkt.jp_data, nsipcbuf.pkt.jp_len) == -E_E1000_TXBUF_FULL) cprintf("Dropping packet, after 20 tries cannot transmit"); } }
void umain(int argc, char **argv) { envid_t who; if ((who = fork()) != 0) { // get the ball rolling cprintf("send 0 from %x to %x\n", sys_getenvid(), who); ipc_send(who, 0, 0, 0); //cprintf("send finish\n"); } while (1) { uint32_t i = ipc_recv(&who, 0, 0); // cprintf("%x ipc_recv finish\n",sys_getenvid()); cprintf("%x got %d from %x\n", sys_getenvid(), i, who); if (i == 10) return; i++; ipc_send(who, i, 0, 0); if (i == 10) return; } }
void output(envid_t ns_envid) { binaryname = "ns_output"; int32_t reqType; int perm; envid_t envid_sender; // LAB 6: Your code here: // - read a packet from the network server // - send the packet to the device driver while(1) { perm = 0; //Read a packet from ns reqType = ipc_recv(&envid_sender, &nsipcbuf, &perm); //Check if ipc_recv has received correctly if(!(perm & PTE_P)) { cprintf("Invalid request from network server[%08x]:no page",envid_sender); continue; } if(reqType != NSREQ_OUTPUT) { cprintf("Invalid request from network server[%08x]:not a NSREQ_OUTPUT message",envid_sender); continue; } //Send packet to device driver.If packet send fails, give up CPU while(sys_send_packet(nsipcbuf.pkt.jp_data, nsipcbuf.pkt.jp_len) < 0) sys_yield(); } }
void serve(void) { uint32_t req, whom; int perm, r; void *pg; while (1) { perm = 0; req = ipc_recv((int32_t *) &whom, fsreq, &perm); if (debug) cprintf("fs req %d from %08x [page %08x: %s]\n", req, whom, vpt[PGNUM(fsreq)], fsreq); // All requests must contain an argument page if (!(perm & PTE_P)) { cprintf("Invalid request from %08x: no argument page\n", whom); continue; // just leave it hanging... } pg = NULL; if (req == FSREQ_OPEN) { r = serve_open(whom, (struct Fsreq_open*)fsreq, &pg, &perm); } else if (req < NHANDLERS && handlers[req]) { r = handlers[req](whom, fsreq); } else { cprintf("Invalid request code %d from %08x\n", whom, req); r = -E_INVAL; } ipc_send(whom, r, pg, perm); sys_page_unmap(0, fsreq); } }
// Open a file (or directory). // // Returns: // The file descriptor index on success // -E_BAD_PATH if the path is too long (>= MAXPATHLEN) // < 0 for other errors. int open(const char *path, int mode) { // Find an unused file descriptor page using fd_alloc. // Then send a file-open request to the file server. // Include 'path' and 'omode' in request, // and map the returned file descriptor page // at the appropriate fd address. // FSREQ_OPEN returns 0 on success, < 0 on failure. // // (fd_alloc does not allocate a page, it just returns an // unused fd address. Do you need to allocate a page?) // // Return the file descriptor index. // If any step after fd_alloc fails, use fd_close to free the // file descriptor. // LAB 5: Your code here. struct Fd *fd; int r; if((r = fd_alloc(&fd)) < 0) return r; strcpy(fsipcbuf.open.req_path, path); fsipcbuf.open.req_omode = mode; ipc_send(envs[1].env_id, FSREQ_OPEN, &fsipcbuf, PTE_P | PTE_W | PTE_U); if((r = ipc_recv(NULL, fd, NULL))<0) return r; return fd2num(fd); panic("open not implemented"); }
void umain(void) { u_int who, i; i = 0; if ((who = sfork()) != 0) { printf("i am %08x; env is %p\n", sys_getenvid(), env); // get the ball rolling printf("send 0 from %x to %x\n", sys_getenvid(), who); ipc_send(who, 0, 0, 0); } for (;;) { ipc_recv(&who, 0, 0); printf("%x got %d from %x (env is %p %x)\n", sys_getenvid(), val, who, env, env->env_id); if (val == 10) return; ++val; ipc_send(who, 0, 0, 0); if (val == 10) return; } }
void output(envid_t ns_envid) { binaryname = "ns_output"; // code for lab 6 -M.G // - read a packet from the network server // - send the packet to the device driver envid_t from_env_store; int perm_store; int return_value; while(1) { return_value = ipc_recv(&from_env_store, &nsipcbuf, &perm_store); if (!(from_env_store == ns_envid && return_value == NSREQ_OUTPUT)) { continue; } // Send while (sys_E1000_tx_packet(nsipcbuf.pkt.jp_data, nsipcbuf.pkt.jp_len)); } }
// Send an inter-environment request to the file server, and wait for // a reply. The request body should be in fsipcbuf, and parts of the // response may be written back to fsipcbuf. // type: request code, passed as the simple integer IPC value. // dstva: virtual address at which to receive reply page, 0 if none. // Returns result from the file server. static int fsipc(unsigned type, void *dstva) { if (debug) cprintf("[%08x] fsipc %d %08x\n", env->env_id, type, *(uint32_t *)&fsipcbuf); ipc_send(envs[1].env_id, type, &fsipcbuf, PTE_P | PTE_W | PTE_U); return ipc_recv(NULL, dstva, NULL); }
void swap_in_page() { uint32_t faultva, whom; int perm, isMapped, msgFromFS; uint32_t blockva; while(1) { // receive the faulting address from the user defined pgfault handler. perm = 0; isMapped = -1; msgFromFS = -1; faultva = 0; whom = 0; blockva = 0; //receive faultva from the user environment. if((faultva = ipc_recv((int32_t *) &whom , NULL , &perm)) < 0) panic("Fault Address given to swapin env"); // get the corresponding block no from the kernel swap_store. if((blockva = sys_get_swapped_block(faultva,whom)) < 0) panic("swap_store does not have entry for this va %e",faultva); memset((void *)fs_req,0,PGSIZE); fs_req->swap.blockva = blockva; // send msg to file system to map the page at the corresponding blockva ipc_send(envs[1].env_id, SWAP_IN_PAGE , fs_req , PTE_P | PTE_U | PTE_W); // Return status from the file system whether it was able to map the block at its blockva. if((isMapped = ipc_recv(NULL,NULL,NULL)<0) sys_yield(); // or continue; // Make request to kernel to swap in page in all the env corresponding to this blockva. if(sys_page_swap_in(blockva) < 0) { ipc_send(envs[1].env_id, SWAP_IN_ERROR , fs_req , PTE_P | PTE_U | PTE_W); } else { ipc_send(envs[1].env_id, SWAP_IN_SUCCESS , fs_req , PTE_P | PTE_U | PTE_W); } if( msgFromFS = ipc_recv(NULL,NULL,NULL)) < 0) panic("FS Failed while handling Swap in"); } }
int ipc_recv_argv(int sock, char ***argv, int *argc) { char *buf; size_t buf_len, size; int i, err; err = ipc_recv(sock, argc, sizeof(*argc)); if (err < 0) return err; err = ipc_recv(sock, &buf_len, sizeof(buf_len)); if (err < 0) return err; if (*argc > (int) sysconf(_SC_ARG_MAX)) return -EINVAL; /* allocate space for 'argv' array plus all transmitted strings */ size = *argc * sizeof(*argv) + buf_len - sizeof(*argc) - sizeof(buf_len); buf = malloc(size); if (!buf) return -errno; *argv = (char **) buf; /* * leave space for the 'argv' array * and jump to the beginning of the string buffer */ buf += *argc * sizeof(*argv); /* read in all strings at once */ err = ipc_recv(sock, buf, buf_len - sizeof(*argc) - sizeof(buf_len)); if (err < 0) { free(*argv); return err; } for (i = 0; i < *argc; ++i, buf = strchr(buf, '\0') + 1) (*argv)[i] = buf; return 0; }
void serve(void) { u_int req, whom, perm; for (;;) { perm = 0; req = ipc_recv(&whom, REQVA, &perm); // All requests must contain an argument page if (!(perm & PTE_V)) { writef("Invalid request from %08x: no argument page\n", whom); continue; // just leave it hanging... } switch (req) { case FSREQ_OPEN: serve_open(whom, (struct Fsreq_open *)REQVA); break; case FSREQ_MAP: serve_map(whom, (struct Fsreq_map *)REQVA); break; case FSREQ_SET_SIZE: serve_set_size(whom, (struct Fsreq_set_size *)REQVA); break; case FSREQ_CLOSE: serve_close(whom, (struct Fsreq_close *)REQVA); break; case FSREQ_DIRTY: serve_dirty(whom, (struct Fsreq_dirty *)REQVA); break; case FSREQ_REMOVE: serve_remove(whom, (struct Fsreq_remove *)REQVA); break; case FSREQ_SYNC: serve_sync(whom); break; default: writef("Invalid request code %d from %08x\n", whom, req); break; } syscall_mem_unmap(0, REQVA); } }
// Send an IP request to the file server, and wait for a reply. // type: request code, passed as the simple integer IPC value. // fsreq: page to send containing additional request data, usually fsipcbuf. // Can be modified by server to return additional response info. // dstva: virtual address at which to receive reply page, 0 if none. // *perm: permissions of received page. // Returns 0 if successful, < 0 on failure. static int fsipc(unsigned type, void *fsreq, void *dstva, int *perm) { envid_t whom; if (debug) cprintf("[%08x] fsipc %d %08x\n", env->env_id, type, fsipcbuf); ipc_send(envs[1].env_id, type, fsreq, PTE_P | PTE_W | PTE_U); return ipc_recv(&whom, dstva, perm); }
static int xopen(const char *path, int mode) { extern union Fsipc fsipcbuf; envid_t fsenv; strcpy(fsipcbuf.open.req_path, path); fsipcbuf.open.req_omode = mode; fsenv = ipc_find_env(ENV_TYPE_FS); ipc_send(fsenv, FSREQ_OPEN, &fsipcbuf, PTE_P | PTE_W | PTE_U); return ipc_recv(NULL, FVA, NULL); }
void umain(int argc, char **argv) { envid_t ns_envid = sys_getenvid(); int i, r, first = 1; binaryname = "testinput"; output_envid = fork(); if (output_envid < 0) panic("error forking"); else if (output_envid == 0) { output(ns_envid); return; } input_envid = fork(); if (input_envid < 0) panic("error forking"); else if (input_envid == 0) { input(ns_envid); return; } cprintf("Sending ARP announcement...\n"); announce(); while (1) { envid_t whom; int perm; int32_t req = ipc_recv((int32_t *)&whom, pkt, &perm); if (req < 0) panic("ipc_recv: %e", req); if (whom != input_envid) panic("IPC from unexpected environment %08x", whom); if (req != NSREQ_INPUT) panic("Unexpected IPC %d", req); hexdump("input: ", pkt->jp_data, pkt->jp_len); cprintf("\n"); // Only indicate that we're waiting for packets once // we've received the ARP reply if (first) cprintf("Waiting for packets...\n"); first = 0; } }
void serve(void) { uint32_t req, whom; int perm; while (1) { perm = 0; req = ipc_recv((int32_t *) &whom, (void *) REQVA, &perm); if (debug) cprintf("fs req %d from %08x [page %08x: %s]\n", req, whom, vpt[VPN(REQVA)], REQVA); // All requests must contain an argument page if (!(perm & PTE_P)) { cprintf("Invalid request from %08x: no argument page\n", whom); continue; // just leave it hanging... } switch (req) { case FSREQ_OPEN: serve_open(whom, (struct Fsreq_open*)REQVA); break; case FSREQ_MAP: serve_map(whom, (struct Fsreq_map*)REQVA); break; case FSREQ_SET_SIZE: serve_set_size(whom, (struct Fsreq_set_size*)REQVA); break; case FSREQ_CLOSE: serve_close(whom, (struct Fsreq_close*)REQVA); break; case FSREQ_DIRTY: serve_dirty(whom, (struct Fsreq_dirty*)REQVA); break; case FSREQ_REMOVE: serve_remove(whom, (struct Fsreq_remove*)REQVA); break; case FSREQ_SYNC: serve_sync(whom); break; default: cprintf("Invalid request code %d from %08x\n", whom, req); break; } sys_page_unmap(0, (void*) REQVA); } }
// Send an inter-environment request to the file server, and wait for // a reply. The request body should be in fsipcbuf, and parts of the // response may be written back to fsipcbuf. // type: request code, passed as the simple integer IPC value. // dstva: virtual address at which to receive reply page, 0 if none. // Returns result from the file server. static int fsipc(unsigned type, void *dstva) { static envid_t fsenv; if (fsenv == 0) fsenv = ipc_find_env(ENV_TYPE_FS); static_assert(sizeof(fsipcbuf) == PGSIZE); if (debug) cprintf("[%08x] fsipc %d %08x\n", thisenv->env_id, type, *(uint32_t *)&fsipcbuf); ipc_send(fsenv, type, &fsipcbuf, PTE_P | PTE_W | PTE_U); return ipc_recv(NULL, dstva, NULL); }
u_int primeproc(void) { int i, id, p; u_int envid; // fetch a prime from our left neighbor top: p = ipc_recv(&envid, 0, 0); printf("%d ", p); // fork a right neighbor to continue the chain if ((id = fork()) < 0) panic("fork: %e", id); if (id == 0) goto top; // filter out multiples of our prime for (;;) { i = ipc_recv(&envid, 0, 0); if (i%p) ipc_send(id, i, 0, 0); } }
void serve(void) { int32_t reqno; uint32_t whom; int i, perm; void *va; while (1) { // ipc_recv will block the entire process, so we flush // all pending work from other threads. We limit the // number of yields in case there's a rogue thread. for (i = 0; thread_wakeups_pending() && i < 32; ++i) thread_yield(); perm = 0; va = get_buffer(); reqno = ipc_recv((int32_t *) &whom, (void *) va, &perm); if (debug) { cprintf("ns req %d from %08x\n", reqno, whom); } // first take care of requests that do not contain an argument page if (reqno == NSREQ_TIMER) { process_timer(whom); put_buffer(va); continue; } // All remaining requests must contain an argument page if (!(perm & PTE_P)) { cprintf("Invalid request from %08x: no argument page\n", whom); continue; // just leave it hanging... } // Since some lwIP socket calls will block, create a thread and // process the rest of the request in the thread. struct st_args *args = malloc(sizeof(struct st_args)); if (!args) panic("could not allocate thread args structure"); args->reqno = reqno; args->whom = whom; args->req = va; thread_create(0, "serve_thread", serve_thread, (uint32_t)args); thread_yield(); // let the thread created run } }
// // Accept NSREQ_OUTPUT IPC messages from the core network server and send the // packets accompanying these IPC message to the network device driver // void output(envid_t ns_envid) { binaryname = "ns_output"; while (1) { // When servicing user environment socket calls, lwIP will generate packets // for the network card to transmit. LwIP will send each packet to be // transmitted to this output helper environment using the NSREQ_OUTPUT IPC // message with the packet attached in the page argument of the IPC message. if (ipc_recv(NULL, &nsipcbuf, NULL) != NSREQ_OUTPUT) continue; // Forward the packet to the E100 device driver to transmit. sys_xmit_frame(nsipcbuf.pkt.jp_data, nsipcbuf.pkt.jp_len); } }
void umain(int argc, char **argv) { int r; static_assert(sizeof(struct BlockInfo) == 64); static_assert(BLOCKINFOMAP + (DISKSIZE / BLKSIZE) * sizeof(struct BlockInfo) <= DISKMAP); assert(thisenv->env_id == ENVID_BUFCACHE); binaryname = "bufcache"; cprintf("bufcache is running\n"); // Check that we are able to do I/O // If it looks like I/O will definitely fail, then yield first to // other runnable, non-idle environments. // (This helps previous grading scripts: environment IDs are as // expected, but tests still complete quickly.) while (!(thisenv->env_tf.tf_eflags & FL_IOPL_MASK) && another_runnable_environment_exists()) sys_yield(); outw(0x8A00, 0x8A00); cprintf("bufcache can do I/O\n"); // Find a JOS disk. Use the second IDE disk (number 1) if available. if (ide_probe_disk1()) ide_set_disk(1); else ide_set_disk(0); // Set up the flush pipe if ((r = pipe(p)) < 0) panic("Error setting up pipe: %e\n", r); // Process incoming requests while (1) { int32_t breq; envid_t envid; breq = ipc_recv(&envid, 0, 0); handle_flush_queue(); handle_breq(envid, breq); } }
// Buffer cache IPC helper function. // Send a buffer cache 'reqtype' IPC (one of the BCREQ_ constants) // for the file system block containing 'addr'. // Returns 0 on success, < 0 on error. // static int bcache_ipc(void *addr, int reqtype) { int r; blocknum_t b = ((uintptr_t) addr - FSMAP) / BLKSIZE; if (b < 0 || b > (blocknum_t) (DISKSIZE / BLKSIZE)) panic("bcache_ipc: va %08x out of disk address range", addr); // Be careful: check 'super' might not be loaded! if (b >= 2 && b >= super->s_nblocks) panic("bcache_ipc: block %d out of file system bounds", b); do { ipc_send(ENVID_BUFCACHE, MAKE_BCREQ(b, reqtype), 0, 0); r = ipc_recv(0, (void *) (FSMAP + b * PGSIZE), 0); } while (r == -E_AGAIN); return r; }
void high_prio_rx(unsigned long data) { struct net_device *dev = (struct net_device *)data; const unsigned base_addr = ipc_regs[LOCAL_IPC_ID]; /* Clear interrupt source. */ __raw_writel_no_log(IPC_INTR(IPC_INTR_FIFO_AF), (void *)(base_addr + CDU_INT0_CLEAR_F0)); /* Process all messages. */ ipc_recv(IPC_FIFO_BUF_NUM_HIGH, ipc_trns_prio_1); /* Unmask IPC AF interrupt again. */ __raw_writel_no_log(~IPC_INTR(IPC_INTR_FIFO_AF), (void *)(base_addr + CDU_INT0_MASK_F0)); enable_irq(dev->irq); }
void umain(void) { envid_t who, id; id = sys_getenvid(); if (env == &envs[1]) { while (1) { ipc_recv(&who, 0, 0); cprintf("%x recv from %x\n", id, who); } } else { cprintf("%x loop sending to %x\n", id, envs[1].env_id); while (1) ipc_send(envs[1].env_id, 0, 0, 0); } }
void output(envid_t ns_envid) { binaryname = "ns_output"; int val; envid_t from; // LAB 6: Your code here: // - read a packet from the network server // - send the packet to the device driver while (1) { val = ipc_recv(&from, &nsipcbuf, 0); if (val != NSREQ_OUTPUT) continue; if (from != ns_envid) panic("from != ns"); sys_tx_data(nsipcbuf.pkt.jp_data, nsipcbuf.pkt.jp_len); } }
void output(envid_t ns_envid) { binaryname = "ns_output"; // LAB 6: Your code here: // - read a packet from the network server // - send the packet to the device driver int retval; envid_t envid; int perms = 0; while(1){ retval = ipc_recv(&envid, &nsipcbuf, &perms); if (retval != NSREQ_OUTPUT) continue; sys_transmit_packet(nsipcbuf.pkt.jp_data, nsipcbuf.pkt.jp_len); } }
static void job_proc(void) { struct ProcChild *sender; char *t, *s; int cmd; size_t size; while (1) { if (1 == proc_listen(&sender, &cmd, &size, 1)) break; } ipc_recv(sender, size); chan = ipc_get_data(); chan_id = ipc_get_id(); switch (cmd) { case CMD_REGISTER: ipc_get_arg(&t, NULL); ipc_get_arg(&s, NULL); do_register(ipc_get_node(), t, s); break; case CMD_REMOVE: ipc_get_arg(&t, NULL); do_remove(t); break; case CMD_CALL: do_call(ipc_get_node()); break; case CMD_CALL_PACKAGE: ipc_get_arg(&t, NULL); do_call_package(ipc_get_node(), t); break; case CMD_GETLIST: do_getlist(ipc_get_node()); break; case CMD_DUMP_PROFILE: do_dump_profile(); break; } }
void output(envid_t ns_envid) { binaryname = "ns_output"; // LAB 6: Your code here: // - read a packet from the network server // - send the packet to the device driver int perm; envid_t eid; while(1) { if(ipc_recv(&eid, &nsipcbuf, &perm) != NSREQ_OUTPUT) continue; while(sys_transmit(nsipcbuf.pkt.jp_data, nsipcbuf.pkt.jp_len) < 0) sys_yield(); } }