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 + -
显示快捷键?