Created
February 8, 2013 01:34
-
-
Save drsnyder/4735889 to your computer and use it in GitHub Desktop.
Exercise the poll() on a shared pipe() context switching issue on Linux.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Exercise the poll() on a shared pipe() context switching issue on Linux using threads. Original code taken from | |
* http://lkml.indiana.edu/hypermail/linux/kernel/1012.1/03515.html and modified to use threads. | |
* | |
* On older 2.6 Linux kernels running this program will drive context switches per second up near 1M/s. | |
* On 3.x kernels you will see the csw/s pushed up to ~12k depending on the current process load. | |
* | |
* gcc -o t-poller t-poller.c -lpthread | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <poll.h> | |
#include <pthread.h> | |
#include <signal.h> | |
#include <sys/time.h> | |
#include <sys/resource.h> | |
#define THREADS 400 | |
#define ITERATIONS 5000 | |
void ignore_sigpipe(void) | |
{ | |
struct sigaction act; | |
int r; | |
memset(&act, 0, sizeof(act)); | |
act.sa_handler = SIG_IGN; | |
act.sa_flags = SA_RESTART; | |
r = sigaction(SIGPIPE, &act, NULL); | |
} | |
void * child(void * ptr) | |
{ | |
struct pollfd pfd; | |
struct rusage ru1, ru2; | |
int diff, msglen; | |
int fd = *(int*)ptr; | |
char * msg = "ping\n"; | |
int * total; | |
total = malloc(sizeof(int)); | |
*total = 0; | |
memset(&pfd, 0, sizeof(pfd)); | |
msglen = strlen(msg); | |
pfd.fd = fd; | |
pfd.events = 0; | |
while (write(fd, msg, msglen) == msglen) { | |
getrusage(RUSAGE_SELF, &ru1); | |
if (poll(&pfd, 1, 100) != 0) | |
break; | |
getrusage(RUSAGE_SELF, &ru2); | |
diff = ru2.ru_nvcsw - ru1.ru_nvcsw; | |
if (diff > 2) { | |
*total = *total + diff; | |
} | |
} | |
pthread_exit((void*)total); | |
return (void *)NULL; | |
} | |
int main(int argc, char ** argv) | |
{ | |
struct pollfd pfds[2]; | |
int ret, i, iterations, fd[2]; | |
char buf[1024]; | |
void * thread_data; | |
pthread_t threads[THREADS]; | |
memset(pfds, 0, sizeof(pfds)); | |
ignore_sigpipe(); | |
iterations = 0; | |
pipe(fd); | |
for (i = 0; i < THREADS; i++) { | |
pthread_create( &threads[i], NULL, child, (void *)&fd[1]); | |
} | |
pfds[0].fd = 0; | |
pfds[0].events = POLLIN; | |
pfds[1].fd = fd[0]; | |
pfds[1].events = POLLIN; | |
while (poll(pfds, 2, -1) > 0) { | |
if (pfds[0].revents != 0) | |
break; | |
if (iterations >= ITERATIONS) | |
break; | |
if (pfds[1].revents != 0) | |
read(fd[0], buf, sizeof(buf)); | |
iterations++; | |
} | |
close(fd[0]); | |
close(fd[1]); | |
for (i = 0; i < THREADS; i++) { | |
ret = pthread_join( threads[i], &thread_data); | |
if (ret == 0) { | |
ret = *(int*)thread_data; | |
fprintf(stderr, "%d\n", ret); | |
} else { | |
fprintf(stderr, "pthread_join: error %d\n", ret); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment