sys.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,232 行 · 第 1/2 页
C
1,232 行
int i; for (i=0; i<dir->nbentries; i++) free(dir->entries[i]); free(dir->entries); free(dir->name); free(dir); return 0;}/* We assume that only the main thread calls select(). */static const char file_types[] = { [FTYPE_NONE] = 'N', [FTYPE_CONSOLE] = 'C', [FTYPE_FILE] = 'F', [FTYPE_XENBUS] = 'S', [FTYPE_XC] = 'X', [FTYPE_EVTCHN] = 'E', [FTYPE_SOCKET] = 's', [FTYPE_TAP] = 'T', [FTYPE_BLK] = 'B', [FTYPE_KBD] = 'K', [FTYPE_FB] = 'G',};#ifdef LIBC_DEBUGstatic void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout){ int i, comma;#define printfds(set) do {\ comma = 0; \ for (i = 0; i < nfds; i++) { \ if (FD_ISSET(i, set)) { \ if (comma) \ printk(", "); \ printk("%d(%c)", i, file_types[files[i].type]); \ comma = 1; \ } \ } \} while (0) printk("["); if (readfds) printfds(readfds); printk("], ["); if (writefds) printfds(writefds); printk("], ["); if (exceptfds) printfds(exceptfds); printk("], "); if (timeout) printk("{ %ld, %ld }", timeout->tv_sec, timeout->tv_usec);}#else#define dump_set(nfds, readfds, writefds, exceptfds, timeout)#endif/* Just poll without blocking */static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds){ int i, n = 0;#ifdef HAVE_LWIP int sock_n, sock_nfds = 0; fd_set sock_readfds, sock_writefds, sock_exceptfds; struct timeval timeout = { .tv_sec = 0, .tv_usec = 0};#endif#ifdef LIBC_VERBOSE static int nb; static int nbread[NOFILE], nbwrite[NOFILE], nbexcept[NOFILE]; static s_time_t lastshown; nb++;#endif#ifdef HAVE_LWIP /* first poll network */ FD_ZERO(&sock_readfds); FD_ZERO(&sock_writefds); FD_ZERO(&sock_exceptfds); for (i = 0; i < nfds; i++) { if (files[i].type == FTYPE_SOCKET) { if (FD_ISSET(i, readfds)) { FD_SET(files[i].socket.fd, &sock_readfds); sock_nfds = i+1; } if (FD_ISSET(i, writefds)) { FD_SET(files[i].socket.fd, &sock_writefds); sock_nfds = i+1; } if (FD_ISSET(i, exceptfds)) { FD_SET(files[i].socket.fd, &sock_exceptfds); sock_nfds = i+1; } } } DEBUG("lwip_select("); dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout); DEBUG("); -> "); sock_n = lwip_select(sock_nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout); dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout); DEBUG("\n");#endif /* Then see others as well. */ for (i = 0; i < nfds; i++) { switch(files[i].type) { default: if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds)) printk("bogus fd %d in select\n", i); /* Fallthrough. */ case FTYPE_FILE: FD_CLR(i, readfds); FD_CLR(i, writefds); FD_CLR(i, exceptfds); break; case FTYPE_CONSOLE: if (FD_ISSET(i, readfds)) { if (xencons_ring_avail()) n++; else FD_CLR(i, readfds); } if (FD_ISSET(i, writefds)) n++; FD_CLR(i, exceptfds); break; case FTYPE_XENBUS: if (FD_ISSET(i, readfds)) { if (files[i].xenbus.events) n++; else FD_CLR(i, readfds); } FD_CLR(i, writefds); FD_CLR(i, exceptfds); break; case FTYPE_EVTCHN: case FTYPE_TAP: case FTYPE_BLK: case FTYPE_KBD: case FTYPE_FB: if (FD_ISSET(i, readfds)) { if (files[i].read) n++; else FD_CLR(i, readfds); } FD_CLR(i, writefds); FD_CLR(i, exceptfds); break;#ifdef HAVE_LWIP case FTYPE_SOCKET: if (FD_ISSET(i, readfds)) { /* Optimize no-network-packet case. */ if (sock_n && FD_ISSET(files[i].socket.fd, &sock_readfds)) n++; else FD_CLR(i, readfds); } if (FD_ISSET(i, writefds)) { if (sock_n && FD_ISSET(files[i].socket.fd, &sock_writefds)) n++; else FD_CLR(i, writefds); } if (FD_ISSET(i, exceptfds)) { if (sock_n && FD_ISSET(files[i].socket.fd, &sock_exceptfds)) n++; else FD_CLR(i, exceptfds); } break;#endif }#ifdef LIBC_VERBOSE if (FD_ISSET(i, readfds)) nbread[i]++; if (FD_ISSET(i, writefds)) nbwrite[i]++; if (FD_ISSET(i, exceptfds)) nbexcept[i]++;#endif }#ifdef LIBC_VERBOSE if (NOW() > lastshown + 1000000000ull) { lastshown = NOW(); printk("%lu MB free, ", num_free_pages() / ((1 << 20) / PAGE_SIZE)); printk("%d(%d): ", nb, sock_n); for (i = 0; i < nfds; i++) { if (nbread[i] || nbwrite[i] || nbexcept[i]) printk(" %d(%c):", i, file_types[files[i].type]); if (nbread[i]) printk(" %dR", nbread[i]); if (nbwrite[i]) printk(" %dW", nbwrite[i]); if (nbexcept[i]) printk(" %dE", nbexcept[i]); } printk("\n"); memset(nbread, 0, sizeof(nbread)); memset(nbwrite, 0, sizeof(nbwrite)); memset(nbexcept, 0, sizeof(nbexcept)); nb = 0; }#endif return n;}/* The strategy is to * - announce that we will maybe sleep * - poll a bit ; if successful, return * - if timeout, return * - really sleep (except if somebody woke us in the meanwhile) */int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout){ int n, ret; fd_set myread, mywrite, myexcept; struct thread *thread = get_current(); s_time_t start = NOW(), stop; DEFINE_WAIT(w1); DEFINE_WAIT(w2); DEFINE_WAIT(w3); DEFINE_WAIT(w4); DEFINE_WAIT(w5); DEFINE_WAIT(w6); assert(thread == main_thread); DEBUG("select(%d, ", nfds); dump_set(nfds, readfds, writefds, exceptfds, timeout); DEBUG(");\n"); if (timeout) stop = start + SECONDS(timeout->tv_sec) + timeout->tv_usec * 1000; else /* just make gcc happy */ stop = start; /* Tell people we're going to sleep before looking at what they are * saying, hence letting them wake us if events happen between here and * schedule() */ add_waiter(w1, netfront_queue); add_waiter(w2, event_queue); add_waiter(w3, blkfront_queue); add_waiter(w4, xenbus_watch_queue); add_waiter(w5, kbdfront_queue); add_waiter(w6, console_queue); if (readfds) myread = *readfds; else FD_ZERO(&myread); if (writefds) mywrite = *writefds; else FD_ZERO(&mywrite); if (exceptfds) myexcept = *exceptfds; else FD_ZERO(&myexcept); DEBUG("polling "); dump_set(nfds, &myread, &mywrite, &myexcept, timeout); DEBUG("\n"); n = select_poll(nfds, &myread, &mywrite, &myexcept); if (n) { dump_set(nfds, readfds, writefds, exceptfds, timeout); if (readfds) *readfds = myread; if (writefds) *writefds = mywrite; if (exceptfds) *exceptfds = myexcept; DEBUG(" -> "); dump_set(nfds, readfds, writefds, exceptfds, timeout); DEBUG("\n"); wake(thread); ret = n; goto out; } if (timeout && NOW() >= stop) { if (readfds) FD_ZERO(readfds); if (writefds) FD_ZERO(writefds); if (exceptfds) FD_ZERO(exceptfds); timeout->tv_sec = 0; timeout->tv_usec = 0; wake(thread); ret = 0; goto out; } if (timeout) thread->wakeup_time = stop; schedule(); if (readfds) myread = *readfds; else FD_ZERO(&myread); if (writefds) mywrite = *writefds; else FD_ZERO(&mywrite); if (exceptfds) myexcept = *exceptfds; else FD_ZERO(&myexcept); n = select_poll(nfds, &myread, &mywrite, &myexcept); if (n) { if (readfds) *readfds = myread; if (writefds) *writefds = mywrite; if (exceptfds) *exceptfds = myexcept; ret = n; goto out; } errno = EINTR; ret = -1;out: remove_waiter(w1); remove_waiter(w2); remove_waiter(w3); remove_waiter(w4); remove_waiter(w5); remove_waiter(w6); return ret;}#ifdef HAVE_LWIPint socket(int domain, int type, int protocol){ int fd, res; fd = lwip_socket(domain, type, protocol); if (fd < 0) return -1; res = alloc_fd(FTYPE_SOCKET); printk("socket -> %d\n", res); files[res].socket.fd = fd; return res;}int accept(int s, struct sockaddr *addr, socklen_t *addrlen){ int fd, res; if (files[s].type != FTYPE_SOCKET) { printk("accept(%d): Bad descriptor\n", s); errno = EBADF; return -1; } fd = lwip_accept(files[s].socket.fd, addr, addrlen); if (fd < 0) return -1; res = alloc_fd(FTYPE_SOCKET); files[res].socket.fd = fd; printk("accepted on %d -> %d\n", s, res); return res;}#define LWIP_STUB(ret, name, proto, args) \ret name proto \{ \ if (files[s].type != FTYPE_SOCKET) { \ printk(#name "(%d): Bad descriptor\n", s); \ errno = EBADF; \ return -1; \ } \ s = files[s].socket.fd; \ return lwip_##name args; \}LWIP_STUB(int, bind, (int s, struct sockaddr *my_addr, socklen_t addrlen), (s, my_addr, addrlen))LWIP_STUB(int, getsockopt, (int s, int level, int optname, void *optval, socklen_t *optlen), (s, level, optname, optval, optlen))LWIP_STUB(int, setsockopt, (int s, int level, int optname, void *optval, socklen_t optlen), (s, level, optname, optval, optlen))LWIP_STUB(int, connect, (int s, struct sockaddr *serv_addr, socklen_t addrlen), (s, serv_addr, addrlen))LWIP_STUB(int, listen, (int s, int backlog), (s, backlog));LWIP_STUB(ssize_t, recv, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))LWIP_STUB(ssize_t, recvfrom, (int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen), (s, buf, len, flags, from, fromlen))LWIP_STUB(ssize_t, send, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))LWIP_STUB(ssize_t, sendto, (int s, void *buf, size_t len, int flags, struct sockaddr *to, socklen_t tolen), (s, buf, len, flags, to, tolen))LWIP_STUB(int, getsockname, (int s, struct sockaddr *name, socklen_t *namelen), (s, name, namelen))#endifint nanosleep(const struct timespec *req, struct timespec *rem){ s_time_t start = NOW(); s_time_t stop = start + SECONDS(req->tv_sec) + req->tv_nsec; s_time_t stopped; struct thread *thread = get_current(); thread->wakeup_time = stop; clear_runnable(thread); schedule(); stopped = NOW(); if (rem) { s_time_t remaining = stop - stopped; if (remaining > 0) { rem->tv_nsec = remaining % 1000000000ULL; rem->tv_sec = remaining / 1000000000ULL; } else memset(rem, 0, sizeof(*rem)); } return 0;}int usleep(useconds_t usec){ /* "usec shall be less than one million." */ struct timespec req; req.tv_nsec = usec * 1000; req.tv_sec = 0; if (nanosleep(&req, NULL)) return -1; return 0;}unsigned int sleep(unsigned int seconds){ struct timespec req, rem; req.tv_sec = seconds; req.tv_nsec = 0; if (nanosleep(&req, &rem)) return -1; if (rem.tv_nsec > 0) rem.tv_sec++; return rem.tv_sec;}int clock_gettime(clockid_t clk_id, struct timespec *tp){ switch (clk_id) { case CLOCK_MONOTONIC: { struct timeval tv; gettimeofday(&tv, NULL); tp->tv_sec = tv.tv_sec; tp->tv_nsec = tv.tv_usec * 1000; break; } case CLOCK_REALTIME: { u64 nsec = monotonic_clock(); tp->tv_sec = nsec / 1000000000ULL; tp->tv_nsec = nsec % 1000000000ULL; break; } default: print_unsupported("clock_gettime(%d)", clk_id); errno = EINVAL; return -1; } return 0;}size_t getpagesize(void){ return PAGE_SIZE;}void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset){ unsigned long n = (length + PAGE_SIZE - 1) / PAGE_SIZE; ASSERT(!start); ASSERT(prot == (PROT_READ|PROT_WRITE)); ASSERT((fd == -1 && (flags == (MAP_SHARED|MAP_ANON) || flags == (MAP_PRIVATE|MAP_ANON))) || (fd != -1 && flags == MAP_SHARED)); ASSERT(offset == 0); if (fd == -1) return map_zero(n, 1); else if (files[fd].type == FTYPE_XC) { unsigned long zero = 0; return map_frames_ex(&zero, n, 0, 0, 1, DOMID_SELF, 0, 0); } else ASSERT(0);}int munmap(void *start, size_t length){ int i, n = length / PAGE_SIZE; multicall_entry_t call[n]; unsigned char (*data)[PAGE_SIZE] = start; int ret; ASSERT(!((unsigned long)start & ~PAGE_MASK)); ASSERT(!(length & ~PAGE_MASK)); for (i = 0; i < n; i++) { call[i].op = __HYPERVISOR_update_va_mapping; call[i].args[0] = (unsigned long) &data[i]; call[i].args[1] = 0; call[i].args[2] = 0; call[i].args[3] = UVMF_INVLPG; } ret = HYPERVISOR_multicall(call, n); if (ret) { errno = -ret; return -1; } for (i = 0; i < n; i++) { if (call[i].result) { errno = call[i].result; return -1; } } return 0;}void sparse(unsigned long data, size_t size){ unsigned long newdata; xen_pfn_t *mfns; int i, n; newdata = (data + PAGE_SIZE - 1) & PAGE_MASK; if (newdata - data > size) return; size -= newdata - data; data = newdata; n = size / PAGE_SIZE; size = n * PAGE_SIZE; mfns = malloc(n * sizeof(*mfns)); for (i = 0; i < n; i++) {#ifdef LIBC_DEBUG int j; for (j=0; j<PAGE_SIZE; j++) if (((char*)data + i * PAGE_SIZE)[j]) { printk("%lx is not zero!\n", data + i * PAGE_SIZE + j); exit(1); }#endif mfns[i] = virtual_to_mfn(data + i * PAGE_SIZE); } printk("sparsing %ldMB at %lx\n", size >> 20, data); munmap((void *) data, size); free_physical_pages(mfns, n); do_map_zero(data, n);}/* Not supported by FS yet. */unsupported_function_crash(link);unsupported_function(int, readlink, -1);unsupported_function_crash(umask);/* We could support that. */unsupported_function_log(int, chdir, -1);/* No dynamic library support. */ unsupported_function_log(void *, dlopen, NULL);unsupported_function_log(void *, dlsym, NULL);unsupported_function_log(char *, dlerror, NULL);unsupported_function_log(int, dlclose, -1);/* We don't raise signals anyway. */unsupported_function(int, sigemptyset, -1);unsupported_function(int, sigfillset, -1);unsupported_function(int, sigaddset, -1);unsupported_function(int, sigdelset, -1);unsupported_function(int, sigismember, -1);unsupported_function(int, sigprocmask, -1);unsupported_function(int, sigaction, -1);unsupported_function(int, __sigsetjmp, 0);unsupported_function(int, sigaltstack, -1);unsupported_function_crash(kill);/* Unsupported */unsupported_function_crash(pipe);unsupported_function_crash(fork);unsupported_function_crash(execv);unsupported_function_crash(execve);unsupported_function_crash(waitpid);unsupported_function_crash(wait);unsupported_function_crash(lockf);unsupported_function_crash(sysconf);unsupported_function(int, tcsetattr, -1);unsupported_function(int, tcgetattr, 0);/* Linuxish abi for the Caml runtime, don't support */unsupported_function_log(struct dirent *, readdir64, NULL);unsupported_function_log(int, getrusage, -1);unsupported_function_log(int, getrlimit, -1);unsupported_function_log(int, getrlimit64, -1);unsupported_function_log(int, __xstat64, -1);unsupported_function_log(long, __strtol_internal, LONG_MIN);unsupported_function_log(double, __strtod_internal, HUGE_VAL);#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?