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 * 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.
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
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding - NFS filesystems absolutely suck for fcntl() and flock()
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 - 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.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingYou'll need to define USE_SHMGET_SCOREBOARD if anonymous shared mmap()
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingdoesn't work on your system (i.e. linux).
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingargv[1] is the #children, argv[2] is the #iterations per child
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.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingcompile with:
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
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingnot all versions work on all systems.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Initialize mutex lock.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Must be safe to call this on a restart.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding lock_it.l_whence = SEEK_SET; /* from current point */
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_type = F_UNLCK; /* set exclusive/write lock */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding unlock_it.l_pid = 0; /* pid not actually interesting */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding printf("opening test-lock-thing in current directory\n");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding fcntl_fd = open("test-lock-thing", O_CREAT | O_WRONLY | O_EXCL, 0644);
43c3e6a4b559b76b750c245ee95e2782c15b4296jim fprintf (stderr, "Cannot open lock file: %s\n", "test-lock-thing");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while ((ret = fcntl(fcntl_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Initialize mutex lock.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Must be safe to call this on a restart.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding printf("opening " FNAME " in current directory\n");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding flock_fd = open(FNAME, O_CREAT | O_WRONLY | O_EXCL, 0644);
43c3e6a4b559b76b750c245ee95e2782c15b4296jim fprintf (stderr, "Cannot open lock file: %s\n", "test-lock-thing");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while ((ret = flock(flock_fd, LOCK_EX)) < 0 && errno == EINTR)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* believe it or not, you need to define this under solaris */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
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 mutex = (pthread_mutex_t *)mmap ((caddr_t)0, sizeof (*mutex),
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* default is 8 */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((old = usconfig(CONF_INITUSERS, CONF_INITUSERS_MAX)) == -1) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* got lock */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* allocate shared memory for the shared_counter */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((shmid = shmget(shmkey, size, IPC_CREAT | SHM_R | SHM_W)) == -1) {
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 * To get around this, we move the break point "way up there",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * attach the segment and then move break back down. Ugly
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * We must avoid leaving segments in the kernel's
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * (small) tables.
f05787953018140838ad51456c86c965d6a86267jim return; /* nothing else to do */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* don't ask */
f05787953018140838ad51456c86c965d6a86267jim#define YIELD do { struct timeval zero; zero.tv_sec = zero.tv_usec = 0; select(0,0,0,0,&zero); } while(0)
43c3e6a4b559b76b750c245ee95e2782c15b4296jim fprintf (stderr, "Usage: time-sem num-child num iter\n");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* allocate shared memory for the shared_counter */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding shared_counter = get_shared_mem(sizeof(*shared_counter));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* initialize counter to 0 */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* parent grabs mutex until done spawning children */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; i < num_child; ++i) {
43c3e6a4b559b76b750c245ee95e2782c15b4296jim if (pid == 0) {
43c3e6a4b559b76b750c245ee95e2782c15b4296jim /* child, do our thing */
43c3e6a4b559b76b750c245ee95e2782c15b4296jim for (i = 0; i < num_iter; ++i) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* a quick test to see that nothing is screwed up */
43c3e6a4b559b76b750c245ee95e2782c15b4296jim puts ("WTF! shared_counter != 0 before the children have been started!");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* launch children into action */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; i < num_child; ++i) {
43c3e6a4b559b76b750c245ee95e2782c15b4296jim printf ("WTF! shared_counter != num_child * num_iter!\n"
43c3e6a4b559b76b750c245ee95e2782c15b4296jim "shared_counter = %lu\nnum_child = %d\nnum_iter=%d\n",