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