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