uint64_t sec2tsc(uint64_t sec) { if (mult_will_overflow_u64(sec, get_tsc_freq())) return (uint64_t)(-1); else return sec * get_tsc_freq(); }
uint64_t nsec2tsc(uint64_t nsec) { if (mult_will_overflow_u64(nsec, get_tsc_freq())) return usec2tsc(nsec / 1000); else return (nsec * get_tsc_freq()) / 1000000000; }
uint64_t tsc2nsec(uint64_t tsc_time) { if (mult_will_overflow_u64(tsc_time, 1000000000)) return tsc2usec(tsc_time) * 1000; else return (tsc_time * 1000000000) / get_tsc_freq(); }
void set_tsc_freq(void) { uint64_t freq = get_tsc_freq(); if (!freq) freq = estimate_tsc_freq(); RTE_LOG(DEBUG, EAL, "TSC frequency is ~%" PRIu64 " KHz\n", freq / 1000); eal_tsc_resolution_hz = freq; }
/* Not super accurate, due to overheads of reading tsc and looping */ void ndelay(uint64_t nsec) { uint64_t start, end, now; start = read_tsc(); end = start + (get_tsc_freq() * nsec) / 1000000000; do { cpu_relax(); now = read_tsc(); } while (now < end || (now > start && end < start)); }
UINT64 silvermont_get_current_time_us() { static UINT64 tsc_freq, start; UINT64 cur = rdtsc(); if (tsc_freq == 0) tsc_freq = get_tsc_freq(); if (start == 0) start = cur; return (cur - start) / tsc_freq; }
/* We can overflow/wraparound when we multiply up, but we have to divide last, * or else we lose precision. If we're too big and will overflow, we'll * sacrifice precision for correctness, and degrade to the next lower level * (losing 3 digits worth). The recursive case shouldn't overflow, since it * called something that scaled down the tsc_time by more than 1000. */ uint64_t tsc2sec(uint64_t tsc_time) { return tsc_time / get_tsc_freq(); }
/* Difference between the ticks in nanoseconds */ uint64_t ndiff(uint64_t begin, uint64_t end) { return (end - begin) * 1000000000 / get_tsc_freq(); }
int main(int argc, char **argv) { int port, pid, socketfd; socklen_t length; static struct sockaddr_in cli_addr; /* static = initialised to zeros */ static struct sockaddr_in serv_addr; /* static = initialised to zeros */ InitializeMagick(*argv); /* Verify proper number of args and print usage if invalid */ if( argc < 3 || argc > 4 || !strcmp(argv[1], "-?") ) { printf("" "kweb - Version %s\n" "Usage: kweb <port_number> <top_directory> [<tpool_size=MAX_INT>]\n" "Example: kweb 8181 /home/kwebdir &\n\n" " kweb 8181 /home/kwebdir 50 &\n\n" "kweb is a small and safe multi-threaded static web server\n" "It only serves files with the extensions named below.\n" "It also only serves files from the named directory or its sub-directories.\n\n" "Supports:", VERSION); for(int i=0; extensions[i].ext != 0; i++) printf(" %s", extensions[i].ext); printf("" "\n" "Not Supported: URLs including \"..\", Java, Javascript, CGI\n" "Not Supported: directories / /etc /bin /lib /tmp /usr /dev /sbin\n\n" "No warranty given or implied\n" "Kevin Klues <*****@*****.**>\n" "(Adapted from nweb Version 23 by Nigel Griffiths <*****@*****.**>)\n"); exit(0); } /* Make sure the specified ROOT directory is a valid one */ if(!strncmp(argv[2], "/" , 2 ) || !strncmp(argv[2], "/etc", 5 ) || !strncmp(argv[2], "/bin", 5 ) || !strncmp(argv[2], "/lib", 5 ) || !strncmp(argv[2], "/tmp", 5 ) || !strncmp(argv[2], "/usr", 5 ) || !strncmp(argv[2], "/dev", 5 ) || !strncmp(argv[2], "/sbin", 6)) { printf("ERROR: Bad top directory %s, see kweb -?\n", argv[2]); exit(1); } /* Verify that the specified port number is a valid one */ port = atoi(argv[1]); if(port < 0 || port > 60000) { printf("ERROR: Invalid port number %d (try 1->60000)\n", port); exit(1); } /* Change to the specified ROOT directory to set it as the ROOT of the fs */ if(chdir(argv[2]) == -1) { printf("ERROR: Can't Change to directory %s\n", argv[2]); exit(1); } /* Change to the specified ROOT directory to set it as the ROOT of the fs */ if(argc == 4) { tpool_size = atoi(argv[3]); if(tpool_size < 1 || tpool_size > INT_MAX) { printf("ERROR: Invalid tpool size %d. Must be >= 1.\n", tpool_size); exit(1); } } /* Setup the network socket */ if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("ERROR: System call - socket\n"); exit(1); } /* Set the sockopts so that we can rebind in case of ungracefully shutting * down the server */ int yes = 1; if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) { printf("ERROR: System call - setsockopt\n"); exit(1); } /* Bind to the specified address and listen on the specified port */ serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(port); if(bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("ERROR: System call - bind\n"); exit(1); } if(listen(listenfd, 64) < 0) { printf("ERROR: System call - listen\n"); exit(1); } /* Register a signal handler so we can print out some statistics once we kill * the server */ if(signal(SIGINT, sig_int) == SIG_ERR) { printf("\nCan't catch SIGINT\n"); exit(1); } /* Register a signal handler for sigpipe in case someone closes a socket * while we are in the middle of writing it */ if(signal(SIGPIPE, sig_pipe) == SIG_ERR) { printf("\nCan't catch SIGPIPE\n"); exit(1); } /* Initialize necessary data structures */ os_init(); /* Get the TSC frequency for our timestamp measurements */ server_stats.tsc_freq = get_tsc_freq(); /* Start accepting requests and processing them */ fflush(stdout); logger(LOG, "Starting kweb", argv[1], getpid()); printf("Server Started\n"); printf("Thread Pool Size: %d\n", tpool.size); printf("TSC Frequency: %lu\n", server_stats.tsc_freq); length = sizeof(cli_addr); for(;;) { if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0) { logger(ERROR, "System call", "accept", 0); } else { dispatch_call(socketfd, (void*)&cli_addr); } } }