#include #include #include #include #include #include #include #include #include /* * Initialize a timeval to be used to time something. */ static int time_begin(struct timeval *tv) { return (gettimeofday(tv, NULL)); } /* * End the timing of something which started with time_begin(). The * elapsed time is returned in the second timeval passed, which can * be the same as the first. */ static int time_end(const struct timeval *otv, struct timeval *tv) { struct timeval endtv; int error; error = gettimeofday(&endtv, NULL); if (error != 0) return (error); tv->tv_sec = endtv.tv_sec - otv->tv_sec; tv->tv_usec = endtv.tv_usec - otv->tv_usec; if (tv->tv_usec < 0) { tv->tv_sec--; tv->tv_usec += 1000000; } return (0); } /* * Convert a timeval to... well... a double. */ static inline double tvtod(const struct timeval *tv) { return ((double)tv->tv_sec + (double)tv->tv_usec / 1000000); } pthread_mutex_t netdb_mutex; void * lookup(void *arg) { const char *host = arg; struct hostent *h; char addr[64]; struct timeval tv; if (pthread_mutex_lock(&netdb_mutex) != 0) { warn("mutex_lock"); pthread_exit(NULL); } (void)time_begin(&tv); h = gethostbyname(host); (void)time_end(&tv, &tv); if (h == NULL || inet_ntop(h->h_addrtype, h->h_addr, addr, sizeof(addr)) == NULL) strncpy(addr, "failure", sizeof(addr)); (void)pthread_mutex_unlock(&netdb_mutex); printf("lookup %s: %s\t\t%.3f seconds\n", host, addr, tvtod(&tv)); pthread_exit(NULL); } int main() { const char *const hosts[] = { "freefall.freebsd.org", "localhost", "www.mozilla.org", "www.ruby-lang.org" }; const size_t nlookups = sizeof(hosts) / sizeof(hosts[0]); pthread_t lookups[nlookups]; int i; if (pthread_mutex_init(&netdb_mutex, NULL) != 0) err(1, "mutex_init"); for (i = 0; i < nlookups; i++) if (pthread_create(&lookups[i], NULL, lookup, (void *)hosts[i]) != 0) err(1, "create"); for (i = 0; i < nlookups; i++) (void)pthread_join(lookups[i], NULL); exit(0); }