summaryrefslogtreecommitdiff
path: root/test/time-sem.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/time-sem.c')
-rw-r--r--test/time-sem.c572
1 files changed, 0 insertions, 572 deletions
diff --git a/test/time-sem.c b/test/time-sem.c
deleted file mode 100644
index 7800844ed2..0000000000
--- a/test/time-sem.c
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
-time-sem.c has the basics of the semaphores we use in http_main.c. It's
-intended for timing differences between various methods on an
-architecture. In practice we've found many things affect which semaphore
-to be used:
-
- - NFS filesystems absolutely suck for fcntl() and flock()
-
- - uslock absolutely sucks on single-processor IRIX boxes, but
- absolutely rocks on multi-processor boxes. The converse
- is true for fcntl. sysvsem seems a moderate balance.
-
- - Under Solaris you can't have too many processes use SEM_UNDO, there
- might be a tuneable somewhere that increases the limit from 29.
- We're not sure what the tunable is, so there's a define
- NO_SEM_UNDO which can be used to simulate us trapping/blocking
- signals to be able to properly release the semaphore on a clean
- child death. You'll also need to define NEED_UNION_SEMUN
- under solaris.
-
-You'll need to define USE_SHMGET_SCOREBOARD if anonymous shared mmap()
-doesn't work on your system (i.e. linux).
-
-argv[1] is the #children, argv[2] is the #iterations per child
-
-You should run each over many different #children inputs, and choose
-#iter such that the program runs for at least a second or so... or even
-longer depending on your patience.
-
-compile with:
-
-gcc -o time-FCNTL -Wall -O time-sem.c -DUSE_FCNTL_SERIALIZED_ACCEPT
-gcc -o time-FLOCK -Wall -O time-sem.c -DUSE_FLOCK_SERIALIZED_ACCEPT
-gcc -o time-SYSVSEM -Wall -O time-sem.c -DUSE_SYSVSEM_SERIALIZED_ACCEPT
-gcc -o time-SYSVSEM2 -Wall -O time-sem.c -DUSE_SYSVSEM_SERIALIZED_ACCEPT -DNO_SEM_UNDO
-gcc -o time-PTHREAD -Wall -O time-sem.c -DUSE_PTHREAD_SERIALIZED_ACCEPT -lpthread
-gcc -o time-USLOCK -Wall -O time-sem.c -DUSE_USLOCK_SERIALIZED_ACCEPT
-
-not all versions work on all systems.
-*/
-
-#include <errno.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <sys/mman.h>
-#include <signal.h>
-
-#if defined(USE_FCNTL_SERIALIZED_ACCEPT)
-
-static struct flock lock_it;
-static struct flock unlock_it;
-
-static int fcntl_fd=-1;
-
-#define accept_mutex_child_init()
-#define accept_mutex_cleanup()
-
-/*
- * Initialize mutex lock.
- * Must be safe to call this on a restart.
- */
-void
-accept_mutex_init(void)
-{
-
- lock_it.l_whence = SEEK_SET; /* from current point */
- lock_it.l_start = 0; /* -"- */
- lock_it.l_len = 0; /* until end of file */
- lock_it.l_type = F_WRLCK; /* set exclusive/write lock */
- lock_it.l_pid = 0; /* pid not actually interesting */
- unlock_it.l_whence = SEEK_SET; /* from current point */
- unlock_it.l_start = 0; /* -"- */
- unlock_it.l_len = 0; /* until end of file */
- unlock_it.l_type = F_UNLCK; /* set exclusive/write lock */
- unlock_it.l_pid = 0; /* pid not actually interesting */
-
- printf("opening test-lock-thing in current directory\n");
- fcntl_fd = open("test-lock-thing", O_CREAT | O_WRONLY | O_EXCL, 0644);
- if (fcntl_fd == -1)
- {
- perror ("open");
- fprintf (stderr, "Cannot open lock file: %s\n", "test-lock-thing");
- exit (1);
- }
- unlink("test-lock-thing");
-}
-
-void accept_mutex_on(void)
-{
- int ret;
-
- while ((ret = fcntl(fcntl_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR)
- continue;
-
- if (ret < 0) {
- perror ("fcntl lock_it");
- exit(1);
- }
-}
-
-void accept_mutex_off(void)
-{
- if (fcntl (fcntl_fd, F_SETLKW, &unlock_it) < 0)
- {
- perror ("fcntl unlock_it");
- exit(1);
- }
-}
-
-#elif defined(USE_FLOCK_SERIALIZED_ACCEPT)
-
-#include <sys/file.h>
-
-static int flock_fd=-1;
-
-#define FNAME "test-lock-thing"
-
-/*
- * Initialize mutex lock.
- * Must be safe to call this on a restart.
- */
-void accept_mutex_init(void)
-{
-
- printf("opening " FNAME " in current directory\n");
- flock_fd = open(FNAME, O_CREAT | O_WRONLY | O_EXCL, 0644);
- if (flock_fd == -1)
- {
- perror ("open");
- fprintf (stderr, "Cannot open lock file: %s\n", "test-lock-thing");
- exit (1);
- }
-}
-
-void accept_mutex_child_init(void)
-{
- flock_fd = open(FNAME, O_WRONLY, 0600);
- if (flock_fd == -1) {
- perror("open");
- exit(1);
- }
-}
-
-void accept_mutex_cleanup(void)
-{
- unlink(FNAME);
-}
-
-void accept_mutex_on(void)
-{
- int ret;
-
- while ((ret = flock(flock_fd, LOCK_EX)) < 0 && errno == EINTR)
- continue;
-
- if (ret < 0) {
- perror ("flock(LOCK_EX)");
- exit(1);
- }
-}
-
-void accept_mutex_off(void)
-{
- if (flock (flock_fd, LOCK_UN) < 0)
- {
- perror ("flock(LOCK_UN)");
- exit(1);
- }
-}
-
-#elif defined (USE_SYSVSEM_SERIALIZED_ACCEPT)
-
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>
-
-static int sem_id = -1;
-#ifdef NO_SEM_UNDO
-static sigset_t accept_block_mask;
-static sigset_t accept_previous_mask;
-#endif
-
-#define accept_mutex_child_init()
-#define accept_mutex_cleanup()
-
-void accept_mutex_init(void)
-{
-#ifdef NEED_UNION_SEMUN
- /* believe it or not, you need to define this under solaris */
- union semun {
- int val;
- struct semid_ds *buf;
- ushort *array;
- };
-#endif
-
- union semun ick;
-
- sem_id = semget(999, 1, IPC_CREAT | 0666);
- if (sem_id < 0) {
- perror ("semget");
- exit (1);
- }
- ick.val = 1;
- if (semctl(sem_id, 0, SETVAL, ick) < 0) {
- perror ("semctl");
- exit(1);
- }
-#ifdef NO_SEM_UNDO
- sigfillset(&accept_block_mask);
- sigdelset(&accept_block_mask, SIGHUP);
- sigdelset(&accept_block_mask, SIGTERM);
- sigdelset(&accept_block_mask, SIGUSR1);
-#endif
-}
-
-void accept_mutex_on()
-{
- struct sembuf op;
-
-#ifdef NO_SEM_UNDO
- if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
- perror("sigprocmask(SIG_BLOCK)");
- exit (1);
- }
- op.sem_flg = 0;
-#else
- op.sem_flg = SEM_UNDO;
-#endif
- op.sem_num = 0;
- op.sem_op = -1;
- if (semop(sem_id, &op, 1) < 0) {
- perror ("accept_mutex_on");
- exit (1);
- }
-}
-
-void accept_mutex_off()
-{
- struct sembuf op;
-
- op.sem_num = 0;
- op.sem_op = 1;
-#ifdef NO_SEM_UNDO
- op.sem_flg = 0;
-#else
- op.sem_flg = SEM_UNDO;
-#endif
- if (semop(sem_id, &op, 1) < 0) {
- perror ("accept_mutex_off");
- exit (1);
- }
-#ifdef NO_SEM_UNDO
- if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
- perror("sigprocmask(SIG_SETMASK)");
- exit (1);
- }
-#endif
-}
-
-#elif defined (USE_PTHREAD_SERIALIZED_ACCEPT)
-
-/* note: pthread mutexes aren't released on child death, hence the
- * signal goop ... in a real implementation we'd do special things
- * during hup, term, usr1.
- */
-
-#include <pthread.h>
-
-static pthread_mutex_t *mutex;
-static sigset_t accept_block_mask;
-static sigset_t accept_previous_mask;
-
-#define accept_mutex_child_init()
-#define accept_mutex_cleanup()
-
-void accept_mutex_init(void)
-{
- pthread_mutexattr_t mattr;
- int fd;
-
- fd = open ("/dev/zero", O_RDWR);
- if (fd == -1) {
- perror ("open(/dev/zero)");
- exit (1);
- }
- mutex = (pthread_mutex_t *)mmap ((caddr_t)0, sizeof (*mutex),
- PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (mutex == (void *)(caddr_t)-1) {
- perror ("mmap");
- exit (1);
- }
- close (fd);
- if (pthread_mutexattr_init(&mattr)) {
- perror ("pthread_mutexattr_init");
- exit (1);
- }
- if (pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED)) {
- perror ("pthread_mutexattr_setpshared");
- exit (1);
- }
- if (pthread_mutex_init(mutex, &mattr)) {
- perror ("pthread_mutex_init");
- exit (1);
- }
- sigfillset(&accept_block_mask);
- sigdelset(&accept_block_mask, SIGHUP);
- sigdelset(&accept_block_mask, SIGTERM);
- sigdelset(&accept_block_mask, SIGUSR1);
-}
-
-void accept_mutex_on()
-{
- if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
- perror("sigprocmask(SIG_BLOCK)");
- exit (1);
- }
- if (pthread_mutex_lock (mutex)) {
- perror ("pthread_mutex_lock");
- exit (1);
- }
-}
-
-void accept_mutex_off()
-{
- if (pthread_mutex_unlock (mutex)) {
- perror ("pthread_mutex_unlock");
- exit (1);
- }
- if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
- perror("sigprocmask(SIG_SETMASK)");
- exit (1);
- }
-}
-
-#elif defined (USE_USLOCK_SERIALIZED_ACCEPT)
-
-#include <ulocks.h>
-
-static usptr_t *us = NULL;
-static ulock_t uslock = NULL;
-
-#define accept_mutex_child_init()
-#define accept_mutex_cleanup()
-
-void accept_mutex_init(void)
-{
- ptrdiff_t old;
- /* default is 8 */
-#define CONF_INITUSERS_MAX 15
- if ((old = usconfig(CONF_INITUSERS, CONF_INITUSERS_MAX)) == -1) {
- perror("usconfig");
- exit(-1);
- }
- if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) {
- perror("usconfig");
- exit(-1);
- }
- if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) {
- perror("usconfig");
- exit(-1);
- }
- if ((us = usinit("/dev/zero")) == NULL) {
- perror("usinit");
- exit(-1);
- }
- if ((uslock = usnewlock(us)) == NULL) {
- perror("usnewlock");
- exit(-1);
- }
-}
-void accept_mutex_on()
-{
- switch(ussetlock(uslock)) {
- case 1:
- /* got lock */
- break;
- case 0:
- fprintf(stderr, "didn't get lock\n");
- exit(-1);
- case -1:
- perror("ussetlock");
- exit(-1);
- }
-}
-void accept_mutex_off()
-{
- if (usunsetlock(uslock) == -1) {
- perror("usunsetlock");
- exit(-1);
- }
-}
-#endif
-
-
-#ifndef USE_SHMGET_SCOREBOARD
-static void *get_shared_mem(size_t size)
-{
- void *result;
-
- /* allocate shared memory for the shared_counter */
- result = (unsigned long *)mmap ((caddr_t)0, size,
- PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
- if (result == (void *)(caddr_t)-1) {
- perror ("mmap");
- exit (1);
- }
- return result;
-}
-#else
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-
-static void *get_shared_mem(size_t size)
-{
- key_t shmkey = IPC_PRIVATE;
- int shmid = -1;
- void *result;
-#ifdef MOVEBREAK
- char *obrk;
-#endif
-
- if ((shmid = shmget(shmkey, size, IPC_CREAT | SHM_R | SHM_W)) == -1) {
- perror("shmget");
- exit(1);
- }
-
-#ifdef MOVEBREAK
- /*
- * Some SysV systems place the shared segment WAY too close
- * to the dynamic memory break point (sbrk(0)). This severely
- * limits the use of malloc/sbrk in the program since sbrk will
- * refuse to move past that point.
- *
- * To get around this, we move the break point "way up there",
- * attach the segment and then move break back down. Ugly
- */
- if ((obrk = sbrk(MOVEBREAK)) == (char *) -1) {
- perror("sbrk");
- }
-#endif
-
-#define BADSHMAT ((void *)(-1))
- if ((result = shmat(shmid, 0, 0)) == BADSHMAT) {
- perror("shmat");
- }
- /*
- * We must avoid leaving segments in the kernel's
- * (small) tables.
- */
- if (shmctl(shmid, IPC_RMID, NULL) != 0) {
- perror("shmctl(IPC_RMID)");
- }
- if (result == BADSHMAT) /* now bailout */
- exit(1);
-
-#ifdef MOVEBREAK
- if (obrk == (char *) -1)
- return; /* nothing else to do */
- if (sbrk(-(MOVEBREAK)) == (char *) -1) {
- perror("sbrk 2");
- }
-#endif
- return result;
-}
-#endif
-
-#ifdef _POSIX_PRIORITY_SCHEDULING
-/* don't ask */
-#define _P __P
-#include <sched.h>
-#define YIELD sched_yield()
-#else
-#define YIELD do { struct timeval zero; zero.tv_sec = zero.tv_usec = 0; select(0,0,0,0,&zero); } while(0)
-#endif
-
-void main (int argc, char **argv)
-{
- int num_iter;
- int num_child;
- int i;
- struct timeval first;
- struct timeval last;
- long ms;
- int pid;
- unsigned long *shared_counter;
-
- if (argc != 3) {
- fprintf (stderr, "Usage: time-sem num-child num iter\n");
- exit (1);
- }
-
- num_child = atoi (argv[1]);
- num_iter = atoi (argv[2]);
-
- /* allocate shared memory for the shared_counter */
- shared_counter = get_shared_mem(sizeof(*shared_counter));
-
- /* initialize counter to 0 */
- *shared_counter = 0;
-
- accept_mutex_init ();
-
- /* parent grabs mutex until done spawning children */
- accept_mutex_on ();
-
- for (i = 0; i < num_child; ++i) {
- pid = fork();
- if (pid == 0) {
- /* child, do our thing */
- accept_mutex_child_init();
- for (i = 0; i < num_iter; ++i) {
- unsigned long tmp;
-
- accept_mutex_on ();
- tmp = *shared_counter;
- YIELD;
- *shared_counter = tmp + 1;
- accept_mutex_off ();
- }
- exit (0);
- } else if (pid == -1) {
- perror ("fork");
- exit (1);
- }
- }
-
- /* a quick test to see that nothing is screwed up */
- if (*shared_counter != 0) {
- puts ("WTF! shared_counter != 0 before the children have been started!");
- exit (1);
- }
-
- gettimeofday (&first, NULL);
- /* launch children into action */
- accept_mutex_off ();
- for (i = 0; i < num_child; ++i) {
- if (wait(NULL) == -1) {
- perror ("wait");
- }
- }
- gettimeofday (&last, NULL);
-
- if (*shared_counter != num_child * num_iter) {
- printf ("WTF! shared_counter != num_child * num_iter!\n"
- "shared_counter = %lu\nnum_child = %d\nnum_iter=%d\n",
- *shared_counter,
- num_child, num_iter);
- }
-
- last.tv_sec -= first.tv_sec;
- ms = last.tv_usec - first.tv_usec;
- if (ms < 0) {
- --last.tv_sec;
- ms += 1000000;
- }
- last.tv_usec = ms;
- printf ("%8lu.%06lu\n", last.tv_sec, last.tv_usec);
-
- accept_mutex_cleanup();
-
- exit(0);
-}
-