rbb 99/02/19 12:35:42
Modified: pthreads/src/main http_main.c Log: Logic to serialize per socket, instead of one mutex for the whole server. Probably not optimal yet, but this will still improve our performance. Revision Changes Path 1.50 +245 -178 apache-apr/pthreads/src/main/http_main.c Index: http_main.c =================================================================== RCS file: /home/cvs/apache-apr/pthreads/src/main/http_main.c,v retrieving revision 1.49 retrieving revision 1.50 diff -u -r1.49 -r1.50 --- http_main.c 1999/02/19 20:33:23 1.49 +++ http_main.c 1999/02/19 20:35:41 1.50 @@ -253,7 +253,6 @@ static server_rec *server_conf; static struct pollfd *listenfds; /* ZZZZZ abstract fd_set */ -static int num_listenfds; /* ZZZZZ abstract num_listenfds */ static pid_t pgrp; /* one_process --- debugging mode variable; can be set from the command line @@ -435,11 +434,13 @@ /****** ZZZ this should probably be abstracted to it's own file. ****/ #if defined(USE_FCNTL_SERIALIZED_ACCEPT) || defined(USE_FLOCK_SERIALIZED_ACCEPT) -static void expand_lock_fname(pool *p) +char * expand_lock_fname(pool *p, int i) { + char *fname; /* XXXX possibly bogus cast */ - ap_lock_fname = ap_psprintf(p, "%s.%lu", - ap_server_root_relative(p, ap_lock_fname), (unsigned long)getpid()); + fname = ap_psprintf(p, "%s.%d", + ap_server_root_relative(p, ap_lock_fname), i, (unsigned long)getpid()); + return fname; } #endif @@ -447,7 +448,7 @@ #include <ulocks.h> -static ulock_t uslock = NULL; +static ulock_t *uslock = NULL; #define accept_mutex_child_init(x) @@ -455,36 +456,40 @@ { ptrdiff_t old; usptr_t *us; + int i; + uslock = (ulock_t *)ap_palloc(p, ap_acceptors_per_child * sizeof(ulock_t)); + for (i = 0; i < ap_acceptors_per_child; i++) { /* default is 8, allocate enough for all the children plus the parent */ - if ((old = usconfig(CONF_INITUSERS, HARD_SERVER_LIMIT + 1)) == -1) { - perror("usconfig(CONF_INITUSERS)"); - exit(-1); - } - - if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) { - perror("usconfig(CONF_LOCKTYPE)"); - exit(-1); - } - if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) { - perror("usconfig(CONF_ARENATYPE)"); - exit(-1); - } - if ((us = usinit("/dev/zero")) == NULL) { - perror("usinit"); - exit(-1); - } - - if ((uslock = usnewlock(us)) == NULL) { - perror("usnewlock"); - exit(-1); + if ((old = usconfig(CONF_INITUSERS, HARD_SERVER_LIMIT + 1)) == -1) { + perror("usconfig(CONF_INITUSERS)"); + exit(-1); + } + + if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) { + perror("usconfig(CONF_LOCKTYPE)"); + exit(-1); + } + if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) { + perror("usconfig(CONF_ARENATYPE)"); + exit(-1); + } + if ((us = usinit("/dev/zero")) == NULL) { + perror("usinit"); + exit(-1); + } + + if ((uslock[i] = usnewlock(us)) == NULL) { + perror("usnewlock"); + exit(-1); + } } } -static void accept_mutex_on(void) +static void accept_mutex_on(int locknum) { - switch (ussetlock(uslock)) { + switch (ussetlock(uslock[locknum])) { case 1: /* got lock */ break; @@ -497,9 +502,9 @@ } } -static void accept_mutex_off(void) +static void accept_mutex_off(int locknum) { - if (usunsetlock(uslock) == -1) { + if (usunsetlock(uslock[locknum]) == -1) { perror("usunsetlock"); clean_child_exit(APEXIT_CHILDFATAL); } @@ -515,19 +520,22 @@ #include <pthread.h> -static pthread_mutex_t *accept_mutex = (void *)(caddr_t) -1; -static int have_accept_mutex; +static pthread_mutex_t **accept_mutex = (void *)(caddr_t) -1; +static int *have_accept_mutex; static sigset_t accept_block_mask; static sigset_t accept_previous_mask; static void accept_mutex_child_cleanup(void *foo) { - if (accept_mutex != (void *)(caddr_t)-1 - && have_accept_mutex) { - pthread_mutex_unlock(accept_mutex); + int i; + + for (i = 0; i < ap_acceptors_per_child; i++) { + if (accept_mutex[i] != (void *)(caddr_t)-1 + && have_accept_mutex[i]) { + pthread_mutex_unlock(accept_mutex[i]); + } } } - static void accept_mutex_child_init(pool *p) { ap_register_cleanup(p, NULL, accept_mutex_child_cleanup, ap_null_cleanup); @@ -535,51 +543,65 @@ static void accept_mutex_cleanup(void *foo) { - if (accept_mutex != (void *)(caddr_t)-1 - && munmap((caddr_t) accept_mutex, sizeof(*accept_mutex))) { - perror("munmap"); + int i; + + for (i = 0; i < ap_acceptors_per_child; i++) { + if (accept_mutex[i] != (void *)(caddr_t)-1 + && munmap((caddr_t) accept_mutex[i], sizeof(pthread_mutex_t))) { + perror("munmap"); + } + accept_mutex[i] = (void *)(caddr_t)-1; } - accept_mutex = (void *)(caddr_t)-1; } static void accept_mutex_init(pool *p) { pthread_mutexattr_t mattr; int fd; + int i; + + accept_mutex = (pthread_mutex_t *)ap_palloc(p, + ap_acceptors_per_child * sizeof(pthread_mutex_t *)); + have_accept_mutex = (int *)ap_palloc(p, + ap_acceptors_per_child * sizeof(int)); + - fd = open("/dev/zero", O_RDWR); - if (fd == -1) { - perror("open(/dev/zero)"); - exit(APEXIT_INIT); - } - accept_mutex = (pthread_mutex_t *) mmap((caddr_t) 0, sizeof(*accept_mutex), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (accept_mutex == (void *) (caddr_t) - 1) { - perror("mmap"); - exit(APEXIT_INIT); - } - close(fd); - if ((errno = pthread_mutexattr_init(&mattr))) { - perror("pthread_mutexattr_init"); - exit(APEXIT_INIT); - } - if ((errno = pthread_mutexattr_setpshared(&mattr, - PTHREAD_PROCESS_SHARED))) { - perror("pthread_mutexattr_setpshared"); - exit(APEXIT_INIT); - } - if ((errno = pthread_mutex_init(accept_mutex, &mattr))) { - perror("pthread_mutex_init"); - exit(APEXIT_INIT); - } - sigfillset(&accept_block_mask); - sigdelset(&accept_block_mask, SIGHUP); - sigdelset(&accept_block_mask, SIGTERM); - sigdelset(&accept_block_mask, SIGWINCH); - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + for (i = 0; i < ap_acceptors_per_child; i++) { + fd = open("/dev/zero", O_RDWR); + if (fd == -1) { + perror("open(/dev/zero)"); + exit(APEXIT_INIT); + } + accept_mutex[i] = (pthread_mutex_t *) mmap((caddr_t) 0, + sizeof(*accept_mutex), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (accept_mutex[i] == (void *) (caddr_t) - 1) { + perror("mmap"); + exit(APEXIT_INIT); + } + close(fd); + if ((errno = pthread_mutexattr_init(&mattr))) { + perror("pthread_mutexattr_init"); + exit(APEXIT_INIT); + } + if ((errno = pthread_mutexattr_setpshared(&mattr, + PTHREAD_PROCESS_SHARED))) { + perror("pthread_mutexattr_setpshared"); + exit(APEXIT_INIT); + } + if ((errno = pthread_mutex_init(accept_mutex, &mattr))) { + perror("pthread_mutex_init"); + exit(APEXIT_INIT); + } + sigfillset(&accept_block_mask); + sigdelset(&accept_block_mask, SIGHUP); + sigdelset(&accept_block_mask, SIGTERM); + sigdelset(&accept_block_mask, SIGWINCH); + ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + } } -static void accept_mutex_on(void) +static void accept_mutex_on(int locknum) { int err; @@ -587,19 +609,19 @@ perror("sigprocmask(SIG_BLOCK)"); clean_child_exit(APEXIT_CHILDFATAL); } - if ((err = pthread_mutex_lock(accept_mutex))) { + if ((err = pthread_mutex_lock(accept_mutex[locknum]))) { errno = err; perror("pthread_mutex_lock"); clean_child_exit(APEXIT_CHILDFATAL); } - have_accept_mutex = 1; + have_accept_mutex[locknum] = 1; } -static void accept_mutex_off(void) +static void accept_mutex_off(int locknum) { int err; - if ((err = pthread_mutex_unlock(accept_mutex))) { + if ((err = pthread_mutex_unlock(accept_mutex[locknum]))) { errno = err; perror("pthread_mutex_unlock"); clean_child_exit(APEXIT_CHILDFATAL); @@ -617,7 +639,7 @@ * child might be in the critical section ... at least it's still serving * hits. */ - have_accept_mutex = 0; + have_accept_mutex[locknum] = 0; if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) { perror("sigprocmask(SIG_SETMASK)"); clean_child_exit(1); @@ -640,7 +662,7 @@ #endif -static int sem_id = -1; +static int *sem_id = NULL; static struct sembuf op_on; static struct sembuf op_off; @@ -651,12 +673,15 @@ static void accept_mutex_cleanup(void *foo) { union semun ick; + int i; - if (sem_id < 0) - return; - /* this is ignored anyhow */ - ick.val = 0; - semctl(sem_id, 0, IPC_RMID, ick); + for (i = 0; i < ap_acceptors_per_child; i++) { + if (sem_id[i] < 0) + return; + /* this is ignored anyhow */ + ick.val = 0; + semctl(sem_id[i], 0, IPC_RMID, ick); + } } #define accept_mutex_child_init(x) @@ -665,53 +690,58 @@ { union semun ick; struct semid_ds buf; + int i; + + sem_id = (int *)ap_palloc(p, ap_acceptors_per_child * sizeof(int)); - /* acquire the semaphore */ - sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600); - if (sem_id < 0) { - perror("semget"); - exit(APEXIT_INIT); - } - ick.val = 1; - if (semctl(sem_id, 0, SETVAL, ick) < 0) { - perror("semctl(SETVAL)"); - exit(APEXIT_INIT); - } - if (!getuid()) { - /* restrict it to use only by the appropriate user_id ... not that this - * stops CGIs from acquiring it and dinking around with it. - */ - buf.sem_perm.uid = ap_user_id; - buf.sem_perm.gid = ap_group_id; - buf.sem_perm.mode = 0600; - ick.buf = &buf; - if (semctl(sem_id, 0, IPC_SET, ick) < 0) { - perror("semctl(IPC_SET)"); + for (i = 0; i < ap_acceptors_per_child; i++) { + /* acquire the semaphore */ + sem_id[i] = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600); + if (sem_id[i] < 0) { + perror("semget"); exit(APEXIT_INIT); } - } - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + ick.val = 1; + if (semctl(sem_id[i], 0, SETVAL, ick) < 0) { + perror("semctl(SETVAL)"); + exit(APEXIT_INIT); + } + if (!getuid()) { + /* restrict it to use only by the appropriate user_id ... not that this + * stops CGIs from acquiring it and dinking around with it. + */ + buf.sem_perm.uid = ap_user_id; + buf.sem_perm.gid = ap_group_id; + buf.sem_perm.mode = 0600; + ick.buf = &buf; + if (semctl(sem_id[i], 0, IPC_SET, ick) < 0) { + perror("semctl(IPC_SET)"); + exit(APEXIT_INIT); + } + } + ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); - /* pre-initialize these */ - op_on.sem_num = 0; - op_on.sem_op = -1; - op_on.sem_flg = SEM_UNDO; - op_off.sem_num = 0; - op_off.sem_op = 1; - op_off.sem_flg = SEM_UNDO; + /* pre-initialize these */ + op_on.sem_num = 0; + op_on.sem_op = -1; + op_on.sem_flg = SEM_UNDO; + op_off.sem_num = 0; + op_off.sem_op = 1; + op_off.sem_flg = SEM_UNDO; + } } -static void accept_mutex_on(void) +static void accept_mutex_on(int locknum) { - if (semop(sem_id, &op_on, 1) < 0) { + if (semop(sem_id[locknum], &op_on, 1) < 0) { perror("accept_mutex_on"); clean_child_exit(APEXIT_CHILDFATAL); } } -static void accept_mutex_off(void) +static void accept_mutex_off(int locknum) { - if (semop(sem_id, &op_off, 1) < 0) { + if (semop(sem_id[locknum], &op_off, 1) < 0) { perror("accept_mutex_off"); clean_child_exit(APEXIT_CHILDFATAL); } @@ -721,7 +751,7 @@ static struct flock lock_it; static struct flock unlock_it; -static int lock_fd = -1; +static int *lock_fd = NULL; #define accept_mutex_child_init(x) @@ -731,6 +761,9 @@ */ static void accept_mutex_init(pool *p) { + int i; + char * lock_fname; + lock_fd = (int *)ap_palloc(p, ap_acceptors_per_child * sizeof(int *)); lock_it.l_whence = SEEK_SET; /* from current point */ lock_it.l_start = 0; /* -"- */ @@ -743,21 +776,25 @@ unlock_it.l_type = F_UNLCK; /* set exclusive/write lock */ unlock_it.l_pid = 0; /* pid not actually interesting */ - expand_lock_fname(p); - lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644); - if (lock_fd == -1) { - perror("open"); - fprintf(stderr, "Cannot open lock file: %s\n", ap_lock_fname); - exit(APEXIT_INIT); + for (i = 0; i < ap_acceptors_per_child; i++) { + lock_fname = expand_lock_fname(p, i); + lock_fd[i] = ap_popenf(p, lock_fname, + O_CREAT | O_WRONLY | O_EXCL, 0644); + if (lock_fd[i] == -1) { + perror("open"); + fprintf(stderr, "Cannot open lock file: %s\n", lock_fname); + exit(APEXIT_INIT); + } + unlink(lock_fname); } - unlink(ap_lock_fname); } -static void accept_mutex_on(void) +static void accept_mutex_on(int locknum) { int ret; - while ((ret = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0 && errno != EINTR) { + while ((ret = fcntl(lock_fd[locknum], F_SETLKW, &lock_it)) < 0 && + errno != EINTR) { /* nop */ } @@ -770,11 +807,12 @@ } } -static void accept_mutex_off(void) +static void accept_mutex_off(int locknum) { int ret; - while ((ret = fcntl(lock_fd, F_SETLKW, &unlock_it)) < 0 && errno != EINTR) { + while ((ret = fcntl(lock_fd[locknum], F_SETLKW, &unlock_it)) < 0 + && errno != EINTR) { /* nop */ } if (ret < 0 && errno != EINTR) { @@ -788,11 +826,17 @@ #elif defined(USE_FLOCK_SERIALIZED_ACCEPT) -static int lock_fd = -1; +static int *lock_fd = NULL; static void accept_mutex_cleanup(void *foo) { - unlink(ap_lock_fname); + int i; + + char * lock_fname; + for (i = 0; i < ap_acceptors_per_child; i++) { + lock_fname = expand_lock_fname(foo, i); + unlink(lock_fname); + } } /* @@ -801,12 +845,17 @@ */ static void accept_mutex_child_init(pool *p) { - - lock_fd = ap_popenf(p, ap_lock_fname, O_WRONLY, 0600); - if (lock_fd == -1) { - ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, - "Child cannot open lock file: %s", ap_lock_fname); - clean_child_exit(APEXIT_CHILDINIT); + int i; + + for (i = 0; i < ap_acceptors_per_child; i++) { + char *lock_fname = expand_lock_fname(p, i); + + lock_fd[i] = ap_popenf(p, lock_fname, O_WRONLY, 0600); + if (lock_fd[i] == -1) { + ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, + "Child cannot open lock file: %s", lock_fname); + clean_child_exit(APEXIT_CHILDINIT); + } } } @@ -816,22 +865,29 @@ */ static void accept_mutex_init(pool *p) { - expand_lock_fname(p); - unlink(ap_lock_fname); - lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600); - if (lock_fd == -1) { - ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, - "Parent cannot open lock file: %s", ap_lock_fname); - exit(APEXIT_INIT); + int i; + char * lock_fname; + lock_fd = (int *)ap_palloc(p, ap_acceptors_per_child * sizeof(int *)); + + for (i = 0; i < ap_acceptors_per_child; i++) { + lock_fname = expand_lock_fname(p, i); + unlink(lock_fname); + lock_fd[i] = ap_popenf(p, lock_fname, + O_CREAT | O_WRONLY | O_EXCL, 0600); + if (lock_fd[i] == -1) { + ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, + "Parent cannot open lock file: %s", lock_fname); + exit(APEXIT_INIT); + } + ap_register_cleanup(p, p, accept_mutex_cleanup, ap_null_cleanup); } - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); } -static void accept_mutex_on(void) +static void accept_mutex_on(int locknum) { int ret; - while ((ret = flock(lock_fd, LOCK_EX)) < 0 && errno != EINTR) + while ((ret = flock(lock_fd[locknum], LOCK_EX)) < 0 && errno != EINTR) continue; if (ret < 0 && errno != EINTR) { @@ -841,9 +897,9 @@ } } -static void accept_mutex_off(void) +static void accept_mutex_off(int locknum) { - if (flock(lock_fd, LOCK_UN) < 0 && errno != EINTR) { + if (flock(lock_fd[locknum], LOCK_UN) < 0 && errno != EINTR) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "flock: LOCK_UN: Error freeing accept lock. Exiting!"); clean_child_exit(APEXIT_CHILDFATAL); @@ -852,12 +908,16 @@ #elif defined(USE_OS2SEM_SERIALIZED_ACCEPT) -static HMTX lock_sem = -1; +static HMTX *lock_sem = NULL; static void accept_mutex_cleanup(void *foo) -{ - DosReleaseMutexSem(lock_sem); - DosCloseMutexSem(lock_sem); +{ + int i; + + for (i = 0; i < ap_acceptors_per_child; i++) { + DosReleaseMutexSem(lock_sem[i]); + DosCloseMutexSem(lock_sem[i]); + } } /* @@ -866,35 +926,45 @@ */ static void accept_mutex_child_init(pool *p) { - int rc = DosOpenMutexSem(NULL, &lock_sem); + int i; + + for(i = 0; i < ap_acceptors_per_child; i++) { + int rc = DosOpenMutexSem(NULL, &lock_sem[locknum]); - if (rc != 0) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf, - "Child cannot open lock semaphore, rc=%d", rc); - clean_child_exit(APEXIT_CHILDINIT); + if (rc != 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf, + "Child cannot open lock semaphore, rc=%d", rc); + clean_child_exit(APEXIT_CHILDINIT); + } } } - /* * Initialize mutex lock. * Must be safe to call this on a restart. */ static void accept_mutex_init(pool *p) { - int rc = DosCreateMutexSem(NULL, &lock_sem, DC_SEM_SHARED, FALSE); + int rc; + int i; - if (rc != 0) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf, - "Parent cannot create lock semaphore, rc=%d", rc); - exit(APEXIT_INIT); - } + lock_fd = (int *)ap_palloc(p, ap_acceptors_per_child * sizeof(int *)); + + for (i = 0; i < ap_acceptors_per_child; i++) { + rc = DosCreateMutexSem(NULL, &lock_sem[i], DC_SEM_SHARED, FALSE); - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + if (rc != 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf, + "Parent cannot create lock semaphore, rc=%d", rc); + exit(APEXIT_INIT); + } + + ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + } } -static void accept_mutex_on(void) +static void accept_mutex_on(int locknum) { - int rc = DosRequestMutexSem(lock_sem, SEM_INDEFINITE_WAIT); + int rc = DosRequestMutexSem(lock_sem[locknum], SEM_INDEFINITE_WAIT); if (rc != 0) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf, @@ -903,9 +973,9 @@ } } -static void accept_mutex_off(void) +static void accept_mutex_off(int locknum) { - int rc = DosReleaseMutexSem(lock_sem); + int rc = DosReleaseMutexSem(lock_sem[locknum]); if (rc != 0) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf, @@ -924,8 +994,8 @@ #define NO_SERIALIZED_ACCEPT #define accept_mutex_child_init(x) #define accept_mutex_init(x) -#define accept_mutex_on() -#define accept_mutex_off() +#define accept_mutex_on(x) +#define accept_mutex_off(x) #endif #endif @@ -1985,7 +2055,7 @@ int i; lr = ap_listeners; - num_listenfds = 0; + ap_acceptors_per_child = 0; for (;;) { fd = find_listener(lr); if (fd < 0) { @@ -1995,7 +2065,7 @@ ap_note_cleanups_for_socket(p, fd); } if (fd >= 0) { - ++num_listenfds; + ++ap_acceptors_per_child; } lr->fd = fd; if (lr->next == NULL) @@ -2272,9 +2342,9 @@ (void) ap_update_child_status(my_pid, my_tid, SERVER_ACCEPTING, (request_rec *) NULL); /* lock around the accept if necessary */ - SAFE_ACCEPT(accept_mutex_on()); + SAFE_ACCEPT(accept_mutex_on(my_tid - ap_threads_per_child)); csd = accept(sd, &sa_client, &len); - SAFE_ACCEPT(accept_mutex_off()); + SAFE_ACCEPT(accept_mutex_off(my_tid - ap_threads_per_child)); (void) ap_update_child_status(my_pid, my_tid, SERVER_QUEUEING, (request_rec *) NULL); if (csd >= 0) { @@ -2602,9 +2672,6 @@ pthread_t tid; /* ZZZZ */ int pid; listen_rec *lr; - - for (lr = ap_listeners, ap_acceptors_per_child = 0; lr; - lr=lr->next, ap_acceptors_per_child++); if (ap_acceptors_per_child + ap_threads_per_child > HARD_THREAD_LIMIT) { ap_log_error(APLOG_MARK, APLOG_ERR, s,