void start(void) { sys_priority(PRIORITY); sys_share(SHARE); sys_yield(); int i; for (i = 0; i < RUNCOUNT; i++) { // Write characters to the console, yielding after each one. //*cursorpos++ = PRINTCHAR; //call system call instead #ifndef __EXERCISE_8__ sys_print(PRINTCHAR); #endif #ifdef __EXERCISE_8__ while(atomic_swap(&spin_lock, 1) != 0){ //run 4ever until locked continue; } *cursorpos++ = PRINTCHAR; atomic_swap(&spin_lock, 0); //free #endif sys_yield(); } // Yield forever. while (1) //sys_yield(); sys_exit(0); }
void input(envid_t ns_envid) { binaryname = "ns_input"; // LAB 6: Your code here: // - read a packet from the device driver // - send it to the network server // Hint: When you IPC a page to the network server, it will be // reading from it for a while, so don't immediately receive // another packet in to the same physical page. uint8_t data[2048]; int length, r; for (;;) { while ((length = sys_pkt_receive(data)) < 0) sys_yield(); while (sys_page_alloc(0, &nsipcbuf, PTE_P | PTE_W | PTE_U) < 0) sys_yield(); nsipcbuf.pkt.jp_len = length; memmove(nsipcbuf.pkt.jp_data, data, length); while (sys_ipc_try_send(ns_envid, NSREQ_INPUT, &nsipcbuf, PTE_P | PTE_W | PTE_U) < 0) sys_yield(); } }
void start(void) { int i; proc_priority(PRIORITYCHECK); proc_share(PRIORITYCHECK); sys_yield(); for (i = 0; i < RUNCOUNT; i++) { #ifdef USE_SYSTEM_SYNC // use a safe system call to print character to avoid a race condition proc_print(PRINTCHAR); #else // use atomic_swap to get a lock while (atomic_swap(&lock, 1) !=0 ) { continue; } // Write characters to the console, yielding after each one. *cursorpos++ = PRINTCHAR; // use atomic_swap to release lock atomic_swap(&lock, 0); #endif sys_yield(); } // Yield forever. // while (1) // sys_yield(); sys_exit(0); }
void input(envid_t ns_envid) { binaryname = "ns_input"; // LAB 6: Your code here: // - read a packet from the device driver // - send it to the network server // Hint: When you IPC a page to the network server, it will be // reading from it for a while, so don't immediately receive // another packet in to the same physical page. int i, r; int32_t length; struct jif_pkt *cpkt = pkt; for(i = 0; i < 10; i++) if ((r = sys_page_alloc(0, (void*)((uintptr_t)pkt + i * PGSIZE), PTE_P | PTE_U | PTE_W)) < 0) panic("sys_page_alloc: %e", r); i = 0; while(1) { while((length = sys_netpacket_recv((void*)((uintptr_t)cpkt + sizeof(cpkt->jp_len)), PGSIZE - sizeof(cpkt->jp_len))) < 0) { // cprintf("len: %d\n", length); sys_yield(); } cpkt->jp_len = length; ipc_send(ns_envid, NSREQ_INPUT, cpkt, PTE_P | PTE_U); i = (i + 1) % 10; cpkt = (struct jif_pkt*)((uintptr_t)pkt + i * PGSIZE); sys_yield(); } }
u32_t sys_arch_mbox_fetch(struct sys_mbox** mbox, void** msg, u32_t timeout) { if(timeout) { timeout += timer_getms(); while(((*mbox)->count == 0) && (timeout > timer_getms())) sys_yield(); } else while(((*mbox)->count == 0)) sys_yield(); if((*mbox)->count == 0) return SYS_ARCH_TIMEOUT; void* mx = (*mbox)->msg[0]; memcpy(&(*mbox)->msg[0], &(*mbox)->msg[1], sizeof(void*) * (--(*mbox)->count)); if(msg) *msg = mx; if(timeout == 0) return SYS_ARCH_TIMEOUT; int s = timeout - (timeout - timer_getms()); if(s < timeout) return s; return SYS_ARCH_TIMEOUT; }
// Send 'val' (and 'pg' with 'perm', assuming 'pg' is nonnull) to 'toenv'. // This function keeps trying until it succeeds. // It should panic() on any error other than -E_IPC_NOT_RECV. // // Hint: // Use sys_yield() to be CPU-friendly. // If 'pg' is null, pass sys_ipc_recv a value that it will understand // as meaning "no page". (Zero is not the right value.) void ipc_send(envid_t to_env, uint32_t val, void *pg, int perm) { // LAB 4: Your code here. int ret; void * srcva; if(pg == 0) srcva = (void*)UTOP; else srcva = pg; while(1) { ret = sys_ipc_try_send(to_env,val,srcva,perm); if(ret == 0 || ret == 1) { //cprintf("return 0\n"); sys_yield(); break; } else if(ret == -E_IPC_NOT_RECV) { //cprintf("ipc not recv\n"); sys_yield(); continue; } else panic("error occur in ipc send:%e",ret); } //cprintf("return from ipc send\n"); //panic("ipc_send not implemented"); }
static void global_tests(uint32_t vcoreid) { switch (test) { case TEST_YIELD_ALL: printf("Core %d yielding\n", vcoreid); sys_yield(0); // should be RUNNABLE_M now, amt_wanted == 1 while(1); case TEST_SWITCH_TO_RUNNABLE_S: if (vcoreid == 2) { printf("Core %d trying to request 0/ switch to _S\n", vcoreid); udelay(3000000); vcore_request_more(0); // will only see this if we are scheduled() printf("Core %d back up!\n"); printf("And exiting\n"); exit(0); } while(1); case TEST_CRAZY_YIELDS: udelay(300000*vcoreid); vcore_request_more(5); sys_yield(0); printf("should never see me, unless you slip into *_S\n"); break; case TEST_CONCURRENT_SYSCALLS: for (int i = 0; i < 10; i++) { for (int j = 0; j < 100; j++) sys_null(); printf("Hello from vcore %d, iteration %d\n", vcoreid, i); } break; } }
void start(void) { int i; sys_share(SHARE); sys_priority(PRIORITY); #ifdef __EXERCISE_4A__ sys_yield();//for 4a #endif for (i = 0; i < RUNCOUNT; i++) { // Write characters to the console, yielding after each one. //cursorpos++ = PRINTCHAR; //atomic_swap(uint32_t *addr, uint32_t val); #ifdef __EXERCISE_8__ // exercise 8 sync method sys_atomic_print(PRINTCHAR); #else // exercise 6 sync method while(atomic_swap(&lock,1)!= 0) { //return 0 means get the lock; continue; } *cursorpos++ = PRINTCHAR; atomic_swap(&lock,0); #endif sys_yield(); //release the lock } // Yield forever. sys_exit(0); }
void umain(int argc, char **argv) { int i, j; int seen; envid_t parent = sys_getenvid(); // Fork several environments for (i = 0; i < 20; i++) if (fork() == 0) break; if (i == 20) { sys_yield(); return; } // Wait for the parent to finish forking while (envs[ENVX(parent)].env_status != ENV_FREE) asm volatile("pause"); // Check that one environment doesn't run on two CPUs at once for (i = 0; i < 10; i++) { sys_yield(); for (j = 0; j < 10000; j++) counter++; } if (counter != 10*10000) panic("ran on two CPUs at once (counter is %d)", counter); // Check that we see environments running on different CPUs cprintf("[%08x] stresssched on CPU %d\n", thisenv->env_id, thisenv->env_cpunum); }
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(); } } }
void umain(int argc, char **argv) { envid_t env; cprintf("I am the parent. Forking the child...\n"); if ((env = fork()) == 0) { cprintf("I am the child. Spinning...\n"); while (1) /* do nothing */; } cprintf("I am the parent. Running the child...\n"); sys_yield(); sys_yield(); sys_yield(); sys_yield(); sys_yield(); sys_yield(); sys_yield(); sys_yield(); cprintf("I am the parent. Killing the child...\n"); sys_env_destroy(env); }
void start(void) { int i; for (i = 0; i < RUNCOUNT; i++) { // Write characters to the console, yielding after each one. *cursorpos++ = PRINTCHAR; sys_yield(); } // Yield forever. while (1) sys_yield(); }
void start(void) { int i; for (i = 0; i < RUNCOUNT; i++) { // Write characters to the console, yielding after each one. #ifndef __EXERCISE_8__ // (exercise 6 code) sys_print(PRINTCHAR); #else // (exercise 8 code) // Implemented spinlock to remove race condition of printing for each process. while (atomic_swap(&spin_lock, 1) != 0) continue; *cursorpos++ = PRINTCHAR; atomic_swap(&spin_lock, 0); #endif sys_yield(); } sys_exit(0); // // Yield forever. // while (1) // sys_yield(); }
static ssize_t devpipe_write(struct Fd *fd, const void *vbuf, size_t n) { const uint8_t *buf; size_t i; struct Pipe *p; p = (struct Pipe*) fd2data(fd); if (debug) cprintf("[%08x] devpipe_write %08x %d rpos %d wpos %d\n", thisenv->env_id, uvpt[PGNUM(p)], n, p->p_rpos, p->p_wpos); buf = vbuf; for (i = 0; i < n; i++) { while (p->p_wpos >= p->p_rpos + sizeof(p->p_buf)) { // pipe is full // if all the readers are gone // (it's only writers like us now), // note eof if (_pipeisclosed(fd, p)) return 0; // yield and see what happens if (debug) cprintf("devpipe_write yield\n"); sys_yield(); } // there's room for a byte. store it. // wait to increment wpos until the byte is stored! p->p_buf[p->p_wpos % PIPEBUFSIZ] = buf[i]; p->p_wpos++; } return i; }
static ssize_t devpipe_read(struct Fd *fd, void *vbuf, size_t n) { uint8_t *buf; size_t i; struct Pipe *p; p = (struct Pipe*)fd2data(fd); if (debug) cprintf("[%08x] devpipe_read %08x %d rpos %d wpos %d\n", thisenv->env_id, uvpt[PGNUM(p)], n, p->p_rpos, p->p_wpos); buf = vbuf; for (i = 0; i < n; i++) { while (p->p_rpos == p->p_wpos) { // pipe is empty // if we got any data, return it if (i > 0) return i; // if all the writers are gone, note eof if (_pipeisclosed(fd, p)) return 0; // yield and see what happens if (debug) cprintf("devpipe_read yield\n"); sys_yield(); } // there's a byte. take it. // wait to increment rpos until the byte is taken! buf[i] = p->p_buf[p->p_rpos % PIPEBUFSIZ]; p->p_rpos++; } return i; }
void umain(int argc, char **argv) { envid_t ns_envid = sys_getenvid(); int i, r; binaryname = "testoutput"; output_envid = fork(); if (output_envid < 0) panic("error forking"); else if (output_envid == 0) { output(ns_envid); return; } for (i = 0; i < TESTOUTPUT_COUNT; i++) { if ((r = sys_page_alloc(0, pkt, PTE_P|PTE_U|PTE_W)) < 0) panic("sys_page_alloc: %e", r); pkt->jp_len = snprintf(pkt->jp_data, PGSIZE - sizeof(pkt->jp_len), "Packet %02d", i); cprintf("Transmitting packet %d\n", i); ipc_send(output_envid, NSREQ_OUTPUT, pkt, PTE_P|PTE_W|PTE_U); sys_page_unmap(0, pkt); } // Spin for a while, just in case IPC's or packets need to be flushed for (i = 0; i < TESTOUTPUT_COUNT*2; i++) sys_yield(); }
static ssize_t pipewrite(struct Fd *fd, const void *vbuf, size_t n, off_t offset) { // Your code here. See the lab text for a description of what // pipewrite needs to do. Write a loop that transfers one byte // at a time. Unlike in read, it is not okay to write only some // of the data. If the pipe fills and you've only copied some of // the data, wait for the pipe to empty and then keep copying. // If the pipe is full and closed, return 0. // Use _pipeisclosed to check whether the pipe is closed. struct Pipe *p; const uint8_t *buf; int i; USED(offset); p = (struct Pipe *)fd2data(fd); buf = vbuf; for (i = 0; i < n; i++) { while (p->p_wpos - p->p_rpos >= PIPEBUFSIZ) { if (_pipeisclosed(fd, p)) return 0; sys_yield(); } p->p_buf[p->p_wpos % PIPEBUFSIZ] = buf[i]; p->p_wpos++; } return n; }
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 start(void) { int i; for (i = 0; i < RUNCOUNT; i++) { // Write characters to the console, yielding after each one. //*cursorpos++ = PRINTCHAR; // Atomic syscall version #ifdef __EXERCISE_6__ sys_print(PRINTCHAR); #endif // Atomic lock version #ifdef __EXERCISE_8__ while (atomic_swap(&lock, 1) != 0) continue; *cursorpos++ = PRINTCHAR; atomic_swap(&lock, 0); #endif sys_yield(); } /*// Yield forever. while (1) sys_yield();*/ sys_exit(0); }
void start(void) { int i; sys_set_priority(__PRIORITY__); sys_set_share(__SHARE__); sys_set_lottery_tickets(__LOTTERY_TICKETS__); for (i = 0; i < RUNCOUNT; i++) { // Write characters to the console, yielding after each one. #ifdef __PRINT_METHOD_LOCK__ while(atomic_swap(&lock, 1) != 0) continue; *cursorpos++ = PRINTCHAR; atomic_swap(&lock, 0); #else sys_atomic_print(PRINTCHAR); #endif sys_yield(); } // Yield forever. //while (1) // sys_yield(); sys_exit(0); }
void umain(int argc, char **argv) { int i, r; // Spin for a bit to let the console quiet for (i = 0; i < 10; ++i) sys_yield(); close(0); if ((r = opencons()) < 0) panic("opencons: %e", r); if (r != 0) panic("first opencons used fd %d", r); if ((r = dup(0, 1)) < 0) panic("dup: %e", r); for(;;){ char *buf; buf = readline("Type a line: "); if (buf != NULL) fprintf(1, "%s\n", buf); else fprintf(1, "(end of file received)\n"); cprintf("read a line finish\n"); } }
void sleep(int sec) { unsigned end = sys_time_msec() + sec * 1000; while (sys_time_msec() < end) sys_yield(); }
static ssize_t devpipe_read(struct Fd *fd, void *vbuf, size_t n) { struct Pipe *p = (struct Pipe *) fd2data(fd); uint8_t *buf = (uint8_t *) vbuf; size_t i; for (i = 0; i < n; i++) { while (p->p_rpos == p->p_wpos) { // The pipe is currently empty. // If any data has been read, return it. // Otherwise, check for EOF; if not EOF, yield // and try again. if (i > 0) return i; else if (_pipeisclosed(fd, p)) return 0; else sys_yield(); } buf[i] = p->p_buf[p->p_rpos % PIPEBUFSIZ]; // The increment must come AFTER we write to the buffer, // or the C compiler might update the pointer before writing // to the buffer! In fact, we need a memory barrier here--- // on some machines a memory barrier instruction. asm volatile("" : : : "memory"); p->p_rpos++; } return i; }
// Send 'val' (and 'pg' with 'perm', if 'pg' is nonnull) to 'toenv'. // This function keeps trying until it succeeds. // It should panic() on any error other than -E_IPC_NOT_RECV. // // Hint: // Use sys_yield() to be CPU-friendly. // If 'pg' is null, pass sys_ipc_recv a value that it will understand // as meaning "no page". (Zero is not the right value.) void ipc_send(envid_t to_env, uint32_t val, void *pg, int perm) { // LAB 4: Your code here. //panic("ipc_send not implemented"); /* lj */ int ret = 0; void *addr = NULL; addr = pg ? pg : (void *)-1; //cprintf("%x->%x [%d]\n", thisenv->env_id, to_env, val); while (1) { if(-E_IPC_NOT_RECV == ret) { sys_yield(); } ret = sys_ipc_try_send(to_env, val, addr, perm); if(0 == ret) { break; } else if(-E_IPC_NOT_RECV == ret) { //cprintf("%x continue\n", thisenv->env_id); continue; } else if(ret < 0) { panic("ipc_send error:%e", ret); } } }
// Send 'val' (and 'pg' with 'perm', if 'pg' is nonnull) to 'toenv'. // This function keeps trying until it succeeds. // It should panic() on any error other than -E_IPC_NOT_RECV. // // Hint: // Use sys_yield() to be CPU-friendly. // If 'pg' is null, pass sys_ipc_recv a value that it will understand // as meaning "no page". (Zero is not the right value.) void ipc_send(envid_t to_env, uint32_t val, void *pg, int perm) { int r; if (pg == NULL) pg = (void *)UTOP; do { int r = sys_ipc_try_send(to_env, val, pg, perm); switch (r) { case 0: case 1: return; case -E_IPC_NOT_RECV: sys_yield(); continue; default: panic("sys_ipc_try_send(%08x, %u, %08x, %d) failed: %e\n", to_env, val, pg, perm, r); } } while (1); }
u32_t sys_arch_sem_wait(struct sys_sem** sem, u32_t __timeout) { register u32_t timeout = __timeout; if(timeout) timeout += timer_getms(); #if CONFIG_SMP __sync_synchronize(); #endif (*sem)->lock--; while( ((*sem)->lock < 0) && (__timeout ? timeout > timer_getms() : 1) ) sys_yield(); if(__timeout == 0) return SYS_ARCH_TIMEOUT; int s = timeout - (timeout - timer_getms()); if(s < timeout) return s; return SYS_ARCH_TIMEOUT; }
void start(void) { int i; for (i = 0; i < RUNCOUNT; i++) { #ifndef __EXERCISE_8__ /* EXERCISE 6: use a system call to print characters *****************/ sys_print(PRINTCHAR); #endif #ifdef __EXERCISE_8__ /* EXERCISE 8: use a lock to prevent race conditions *****************/ // spinlock until we obtain write lock while (atomic_swap(&spinlock, 1) != 0) continue; // write *cursorpos++ = PRINTCHAR; // release write lock atomic_swap(&spinlock, 0); #endif sys_yield(); } // Yield forever. while (1) sys_exit(0); }
void vcore_entry(void) { uint32_t vcoreid = vcore_id(); if (vcoreid) { mcs_barrier_wait(&b, vcoreid); udelay(5000000); if (vcoreid == 1) printf("Proc %d's vcores are yielding\n", getpid()); sys_yield(0); } else { /* trip the barrier here, all future times are in the loop */ mcs_barrier_wait(&b, vcoreid); while (1) { udelay(15000000); printf("Proc %d requesting its cores again\n", getpid()); begin = read_tsc(); sys_resource_req(RES_CORES, max_vcores(), 1, REQ_SOFT); mcs_barrier_wait(&b, vcoreid); end = read_tsc(); printf("Took %llu usec (%llu nsec) to get my yielded cores back.\n", udiff(begin, end), ndiff(begin, end)); printf("[T]:010:%llu:%llu\n", udiff(begin, end), ndiff(begin, end)); } } printf("We're screwed!\n"); exit(-1); }
void vcore_entry(void) { uint32_t vcoreid = vcore_id(); /* begin: stuff userspace needs to do to handle notifications */ struct vcore *vc = &__procinfo.vcoremap[vcoreid]; struct preempt_data *vcpd; vcpd = &__procdata.vcore_preempt_data[vcoreid]; /* Lets try to restart vcore0's context. Note this doesn't do anything to * set the appropriate TLS. On x86, this will involve changing the LDT * entry for this vcore to point to the TCB of the new user-thread. */ if (vcoreid == 0) { handle_events(vcoreid); set_tls_desc(core0_tls, 0); assert(__vcoreid == 0); /* in case anyone uses this */ /* Load silly state (Floating point) too */ pop_user_ctx(&vcpd->uthread_ctx, vcoreid); panic("should never see me!"); } /* end: stuff userspace needs to do to handle notifications */ /* all other vcores are down here */ core1_up = TRUE; while (core1_up) cpu_relax(); printf("Proc %d's vcore %d is yielding\n", getpid(), vcoreid); sys_yield(0); while(1); }
// Send 'val' (and 'pg' with 'perm', if 'pg' is nonnull) to 'toenv'. // This function keeps trying until it succeeds. // It should panic() on any error other than -E_IPC_NOT_RECV. // // Hint: // Use sys_yield() to be CPU-friendly. // If 'pg' is null, pass sys_ipc_recv a value that it will understand // as meaning "no page". (Zero is not the right value.) void ipc_send(envid_t to_env, uint32_t val, void *pg, int perm) { // LAB 4: Your code here. //panic("ipc_send not implemented"); int result; if(pg == NULL) { result=sys_ipc_try_send(to_env, val, (void *)UTOP, perm); } else { result=sys_ipc_try_send(to_env, val, pg, perm); } while(result < 0) { if(result != -E_IPC_NOT_RECV) { panic ("ipc send error!"); } sys_yield (); if(pg == NULL) { result=sys_ipc_try_send(to_env, val, (void *)UTOP, perm); } else { result=sys_ipc_try_send(to_env, val, pg, perm); } } }