diff -Naur apache_2.0a6/10xpatchlevel-0 apache_2.0a6/10xpatchlevel --- apache_2.0a6/10xpatchlevel-0 Wed Aug 23 14:14:54 2000 +++ apache_2.0a6/10xpatchlevel Thu Sep 7 21:06:35 2000 @@ -2,4 +2,4 @@ available from http://oss.sgi.com/projects/apache/ -10xpatchlevel=2.0a6-0 +10xpatchlevel=2.0a6-1 diff -Naur apache_2.0a6/htdocs/manual/stm.html-0 apache_2.0a6/htdocs/manual/stm.html --- apache_2.0a6/htdocs/manual/stm.html-0 Wed Aug 23 14:14:59 2000 +++ apache_2.0a6/htdocs/manual/stm.html Thu Sep 7 21:26:55 2000 @@ -144,7 +144,10 @@ routines, a crucial and required part of using state threads.

Informal performance measurements reveal that the STM is faster than -any other standard MPM on all the systems it currently supports. +any other standard MPM on all the systems it currently supports. In +particular on a dual Pentium III Linux 2.4 system the STM is 25% faster +than the dexter MPM, which uses a similar MPMT architecture with +pthreads.

It is a credit to the Apache developers that integrating state threads into Apache/2.0 was easy and (mostly) clean. @@ -188,7 +191,9 @@ library), apply the patches, and build and install the state threads library. -

It's a good idea to try out the STM with To use the STM you must only specify --with-mpm=stm to +configure. All of what follows is optional, although it's +a good idea to try out the STM with STM_DEBUG defined at first, to catch internal inconsistencies, especially on new platforms. Please report errors @@ -207,6 +212,11 @@ configure --with-mpm=stm ... +

To view the options used to compile Apache, run: +

+  % httpd -V
+
+
@@ -755,7 +765,7 @@

Apache Server Status for myserver

- Server Version: Apache/2.0a6 (Unix) STM/1.0
+ Server Version: Apache/2.0a6 (Unix) 10xpatchlevel/2.0a6-1 STM/1.0
Server Built: Aug 22 2000 17:15:14

Current Time: Wednesday, 23-Aug-2000 13:29:39 PDT
@@ -764,7 +774,7 @@

Connection -1

Total connections served
130573 -
Most threads used +
Most threads used at once
39
Total connections served for 100.100.100.1:80
31798 @@ -789,6 +799,8 @@
Wed Aug 23 13:12:15 2000
Incarnations
1 +
Bound to CPU +
0
Thread starts
39
Thread exits @@ -820,11 +832,13 @@ inhabiting this slot, that is, the number of times a VP has been started to replace a dead one, including the initial VP. (The STM restarts VPs when the die, which can be voluntarily by exceeding its -VPConnections limit or unexpectedly by crashing.) Next -comes thread activity and connection activity. Connections served is -split by incarnations so you can see how many connections remain before -the VP reaches its VPConnections limit. Connections served -also is broken down by listener (this VP happens to listen to only one +VPConnections limit or unexpectedly by crashing.) The next +item reports the CPU to which the VP is actually bound, or -1 if no +binding was requested or successfully performed. Next comes thread +activity and connection activity. Connections served is split by +incarnations so you can see how many connections remain before the VP +reaches its VPConnections limit. Connections served also +is broken down by listener (this VP happens to listen to only one socket) and by thread, to give a really detailed understanding of server activity.

@@ -872,6 +886,8 @@
Wed Aug 23 13:12:15 2000
Incarnations
1 +
Bound to CPU +
0
Thread starts
39
Thread exits @@ -935,6 +951,8 @@
Wed Aug 23 13:12:15 2000
Incarnations
1 +
Bound to CPU +
1
Thread starts
39
Thread exits @@ -992,6 +1010,8 @@
Start time
Wed Aug 23 13:12:15 2000
Incarnations +
1 +
Bound to CPU
1
Thread starts
41 diff -Naur apache_2.0a6/src/main/Makefile.in-0 apache_2.0a6/src/main/Makefile.in --- apache_2.0a6/src/main/Makefile.in-0 Fri Jul 28 13:31:00 2000 +++ apache_2.0a6/src/main/Makefile.in Thu Sep 7 21:08:16 2000 @@ -1,9 +1,10 @@ -CLEANFILES = gen_test_char gen_uri_delims test_char.h uri_delims.h +CLEANFILES = gen_test_char gen_uri_delims test_char.h uri_delims.h \ + aap_version.h LTLIBRARY_NAME = libmain.la LTLIBRARY_SOURCES = \ - uri_delims.h test_char.h \ + uri_delims.h test_char.h aap_version.h \ buff.c http_config.c http_core.c http_log.c http_main.c \ http_protocol.c http_request.c http_vhost.c util.c util_date.c \ util_script.c util_uri.c util_md5.c util_cfgtree.c util_ebcdic.c \ @@ -27,5 +28,9 @@ test_char.h: gen_test_char ./gen_test_char > test_char.h +aap_version.h: + ./gen_aap_version > aap_version.h + util_uri.lo: uri_delims.h util.lo: test_char.h +http_core.lo: aap_version.h diff -Naur apache_2.0a6/src/main/gen_aap_version-0 apache_2.0a6/src/main/gen_aap_version --- apache_2.0a6/src/main/gen_aap_version-0 +++ apache_2.0a6/src/main/gen_aap_version Thu Sep 7 21:05:00 2000 @@ -0,0 +1,16 @@ +pl=`grep 10xpatchlevel= ../../10xpatchlevel 2>/dev/null | sed 's,=,/,'` +case "$pl" in +"") # missing or broken 10xpatchlevel file, do nothing + ;; +*) cat << EOF +/* + * Accelerating Apache Project patch level. + * http://oss.sgi.com/projects/apache/ + * + * Automatically generated by gen_aap_version. + * Do not edit. + */ +#define AAP_VERSION "$pl" +EOF + ;; +esac diff -Naur apache_2.0a6/src/main/http_core.c-0 apache_2.0a6/src/main/http_core.c --- apache_2.0a6/src/main/http_core.c-0 Thu Aug 17 21:46:07 2000 +++ apache_2.0a6/src/main/http_core.c Thu Sep 7 21:08:30 2000 @@ -3031,9 +3031,14 @@ { NULL, NULL } }; +#include "aap_version.h" static void core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { ap_set_version(pconf); + +#if defined(AAP_VERSION) && !defined(NO_AAP_VERSION) + ap_add_version_component(pconf, AAP_VERSION); +#endif } static void core_open_logs(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) diff -Naur apache_2.0a6/src/main/http_main.c-0 apache_2.0a6/src/main/http_main.c --- apache_2.0a6/src/main/http_main.c-0 Wed Aug 9 07:56:55 2000 +++ apache_2.0a6/src/main/http_main.c Thu Sep 7 21:30:53 2000 @@ -155,6 +155,33 @@ #ifdef SHARED_CORE printf(" -D SHARED_CORE\n"); #endif +#ifdef IRIX + printf(" -D IRIX=%ld\n", (long) IRIX); +#endif +#ifdef STIOL_DEBUG + printf(" -D STIOL_DEBUG\n"); +#endif +#ifdef STM_DEBUG + printf(" -D STM_DEBUG\n"); +#endif +#ifdef STM_LISTENER_LIMIT + printf(" -D STM_LISTENER_LIMIT=%ld\n", (long) STM_LISTENER_LIMIT); +#endif +#ifdef STM_SCORE_KEY_SIZE + printf(" -D STM_SCORE_KEY_SIZE=%ld\n", (long) STM_SCORE_KEY_SIZE); +#endif +#ifdef STM_SCORE_LIMIT + printf(" -D STM_SCORE_LIMIT=%ld\n", (long) STM_SCORE_LIMIT); +#endif +#ifdef STM_SCORE_VALUE_SIZE + printf(" -D STM_SCORE_VALUE_SIZE=%ld\n", (long) STM_SCORE_VALUE_SIZE); +#endif +#ifdef STM_ST_LIMIT + printf(" -D STM_ST_LIMIT=%ld\n", (long) STM_ST_LIMIT); +#endif +#ifdef STM_VP_LIMIT + printf(" -D STM_VP_LIMIT=%ld\n", (long) STM_VP_LIMIT); +#endif /* This list displays the compiled in default paths: */ #ifdef HTTPD_ROOT diff -Naur apache_2.0a6/src/modules/mpm/stm/stm.c-0 apache_2.0a6/src/modules/mpm/stm/stm.c --- apache_2.0a6/src/modules/mpm/stm/stm.c-0 Wed Aug 23 14:15:37 2000 +++ apache_2.0a6/src/modules/mpm/stm/stm.c Thu Sep 7 21:17:46 2000 @@ -582,7 +582,7 @@ * Do not change STM_SCOREBOARD_VERSION_LENGTH. */ #define STM_SCOREBOARD_VERSION_LENGTH 16 -#define STM_SCOREBOARD_VERSION "STM-MPM-sb-0001\n" +#define STM_SCOREBOARD_VERSION "STM-MPM-sb-0002\n" typedef struct stm_scoreboard { char version[STM_SCOREBOARD_VERSION_LENGTH]; /* see above */ apr_int32_t st_limit; /* size of arrays below */ @@ -594,6 +594,7 @@ apr_time_t start_time; /* server's start time */ apr_time_t vp_start_time; /* this VP's start time */ apr_int32_t incarnations; /* # of different VPs in this slot */ + apr_int32_t cpu; /* CPU to which this VP is bound */ apr_int32_t thread_starts; /* # of thread start events */ apr_int32_t thread_exits; /* # of thread exit events */ apr_int32_t most_threads; /* most threads ever used */ @@ -823,7 +824,9 @@ { STM_TRACE(("%d: stm_post_config()\n", getpid())); +#ifndef NO_STM_VERSION ap_add_version_component(conf_pool, stm_version); +#endif } /* @@ -1374,6 +1377,7 @@ sb->start_time = stm.start_time; sb->vp_start_time = 0; /* leave sb->incarnations alone */ + sb->cpu = -1; sb->thread_starts = 0; sb->thread_exits = 0; /* leave sb->most_threads alone */ @@ -1970,10 +1974,12 @@ int cpu; cpu = stm.config.vp_bind[vp->id]; - if (cpu >= 0) { + if (cpu >= 0 && vp->scoreboard->cpu != cpu) { #if defined(IRIX) && IRIX >= 50 /* only Irix 5.0 and beyond have sysmp(MP_MUSTRUN_PID) */ - if (sysmp(MP_MUSTRUN_PID, cpu, vp->pid) == -1) + if (sysmp(MP_MUSTRUN_PID, cpu, vp->pid) != -1) + vp->scoreboard->cpu = cpu; + else ap_log_error(APLOG_MARK, APLOG_WARNING, errno, stm.server, "cannot bind process %d to cpu %d: sysmp(MP_MUSTRUN_PID)", vp->pid, cpu); @@ -3050,11 +3056,11 @@ /* * Create tables large enough to hold: - * - eight data about VP-specific status + * - nine data about VP-specific status * - one datum per listener about listener-specific status * - one datum per thread about connection-specific status */ - tsize = 8 + vp->num_listeners + stm.config.max_threads; + tsize = 9 + vp->num_listeners + stm.config.max_threads; vrp = apr_push_array(ap); vrp->conn_id = -1000 - i; @@ -3066,6 +3072,8 @@ apr_pstrdup(pool, timebuf)); apr_table_addn(vrp->data, "Incarnations", apr_psprintf(pool, "%d", sbp->incarnations)); + apr_table_addn(vrp->data, "Bound to CPU", + apr_psprintf(pool, "%d", sbp->cpu)); apr_table_addn(vrp->data, "Thread starts", apr_psprintf(pool, "%d", sbp->thread_starts)); apr_table_addn(vrp->data, "Thread exits", @@ -3138,7 +3146,7 @@ srp->data = apr_make_table(pool, tsize); apr_table_addn(srp->data, "Total connections served", apr_psprintf(pool, "%d", total_connections)); - apr_table_addn(srp->data, "Most threads used", + apr_table_addn(srp->data, "Most threads used at once", apr_psprintf(pool, "%d", most_threads)); for (i = 0; i < stm.num_listeners; i++) apr_table_addn(srp->data, diff -Naur apache_2.0a6/src/support/stmstat.c-0 apache_2.0a6/src/support/stmstat.c --- apache_2.0a6/src/support/stmstat.c-0 Wed Aug 23 14:16:06 2000 +++ apache_2.0a6/src/support/stmstat.c Thu Sep 7 21:18:13 2000 @@ -169,8 +169,8 @@ /* The scoreboard version size must never change. */ #define STM_SCOREBOARD_VERSION_LENGTH 16 -typedef int ap_int32_t; -typedef long long ap_time_t; +typedef int apr_int32_t; +typedef long long apr_time_t; /* insert new scoreboard version data and procedures here */ @@ -177,24 +177,50 @@ /***************************************** - * Scoreboard version 0001 + * Scoreboard version 0002 data + * just adds cpu to version 0001 */ +#define STM_SCOREBOARD_VERSION_0002 "STM-MPM-sb-0002\n" +typedef struct { + apr_int32_t st_limit; /* size of arrays below */ + apr_int32_t listener_limit; /* size of arrays below */ + apr_int32_t score_limit; /* size of arrays below */ + apr_int32_t key_size; /* size of arrays below */ + apr_int32_t value_size; /* size of arrays below */ + apr_int32_t pid; /* this VP's PID */ + apr_time_t start_time; /* server's start time */ + apr_time_t vp_start_time; /* this VP's start time */ + apr_int32_t incarnations; /* # of different VPs in this slot */ + apr_int32_t cpu; /* CPU to which this VP is bound */ + apr_int32_t thread_starts; /* # of thread start events */ + apr_int32_t thread_exits; /* # of thread exit events */ + apr_int32_t most_threads; /* most threads ever used */ + apr_int32_t historic_vp_connections;/* # of conns, prior incarnations */ + apr_int32_t vp_connections; /* # of conns, this incarnation */ +} scoreboard_0002_fixed; /* fixed-size portion of the scoreboard */ +#define score_0002 score_0001 +#define scoreboard_0002_vary scoreboard_0001_vary +#define ttoa_0002 ttoa_0001 + +/***************************************** + * Scoreboard version 0001 data + */ #define STM_SCOREBOARD_VERSION_0001 "STM-MPM-sb-0001\n" typedef struct { - ap_int32_t st_limit; /* size of arrays below */ - ap_int32_t listener_limit; /* size of arrays below */ - ap_int32_t score_limit; /* size of arrays below */ - ap_int32_t key_size; /* size of arrays below */ - ap_int32_t value_size; /* size of arrays below */ - ap_int32_t pid; /* this VP's PID */ - ap_time_t start_time; /* server's start time */ - ap_time_t vp_start_time; /* this VP's start time */ - ap_int32_t incarnations; /* # of different VPs in this slot */ - ap_int32_t thread_starts; /* # of thread start events */ - ap_int32_t thread_exits; /* # of thread exit events */ - ap_int32_t most_threads; /* most threads ever used */ - ap_int32_t historic_vp_connections;/* # of conns, prior incarnations */ - ap_int32_t vp_connections; /* # of conns, this incarnation */ + apr_int32_t st_limit; /* size of arrays below */ + apr_int32_t listener_limit; /* size of arrays below */ + apr_int32_t score_limit; /* size of arrays below */ + apr_int32_t key_size; /* size of arrays below */ + apr_int32_t value_size; /* size of arrays below */ + apr_int32_t pid; /* this VP's PID */ + apr_time_t start_time; /* server's start time */ + apr_time_t vp_start_time; /* this VP's start time */ + apr_int32_t incarnations; /* # of different VPs in this slot */ + apr_int32_t thread_starts; /* # of thread start events */ + apr_int32_t thread_exits; /* # of thread exit events */ + apr_int32_t most_threads; /* most threads ever used */ + apr_int32_t historic_vp_connections;/* # of conns, prior incarnations */ + apr_int32_t vp_connections; /* # of conns, this incarnation */ } scoreboard_0001_fixed; /* fixed-size portion of the scoreboard */ typedef struct { char *key; @@ -201,22 +227,145 @@ char *value; } score_0001; /* scores are key-value pairs */ typedef struct { - ap_int32_t *thread_connections; /* per thread */ - ap_int32_t *listener_connections; /* per listener */ - char **listeners; /* IP address:port */ + apr_int32_t *thread_connections; /* per thread */ + apr_int32_t *listener_connections; /* per listener */ + char **listeners; /* IP address:port */ score_0001 **scores; /* per-conn data */ } scoreboard_0001_vary; /* varying-size portion of the scoreboard */ - /* for gcc in maintainer-mode */ -const char *ttoa_0001(ap_time_t); +const char *ttoa_0001(apr_time_t); void show_0001(int, const char *); + +/***************************************** + * Scoreboard version 0002 functions + */ + +/* + * Read the scoreboard data from the given file descriptor (which is from + * the given file name) and parse and print all the information. + */ +void +show_0002(int fd, const char *fn) +{ + scoreboard_0002_fixed fixed; + scoreboard_0002_vary vary; + size_t size; + int i, j; + + /* + * The output could be prettier. I mostly wanted to write this as a + * proof of concept. + */ + + printf("%s\n", fn); + printf("version " STM_SCOREBOARD_VERSION_0002); + + /* first read and sanity check the fixed-size portion */ + readn(fd, &fixed, sizeof fixed, "fixed-size portion", fn); + if (verbose) { + printf("st_limit %-5d\n", fixed.st_limit); + printf("listener_limit %-5d\n", fixed.listener_limit); + printf("score_limit %-5d\n", fixed.score_limit); + printf("key_size %-5d\n", fixed.key_size); + printf("value_size %-5d\n", fixed.value_size); + } + if (fixed.st_limit < 1 || fixed.st_limit > 1000000 || + fixed.listener_limit < 1 || fixed.listener_limit > 1000000 || + fixed.score_limit < 1 || fixed.score_limit > 1000000 || + fixed.key_size < 1 || fixed.key_size > 1000000 || + fixed.value_size < 1 || fixed.value_size > 1000000) { + fprintf(stderr, "invalid sizes in %s\n", fn); + exit(1); + } + + /* dead VP? */ + if (fixed.pid == -1) { + printf("blank\n"); + return; + } + + /* then read the varying-size portion in chunks */ + + size = fixed.st_limit * sizeof *vary.thread_connections; + vary.thread_connections = (apr_int32_t *) malloc(size); + readn(fd, vary.thread_connections, size, "thread_connections", fn); + + size = fixed.listener_limit * sizeof *vary.listener_connections; + vary.listener_connections = (apr_int32_t *) malloc(size); + readn(fd, vary.listener_connections, size, "listener_connections", fn); + + size = fixed.listener_limit * sizeof *vary.listeners; + vary.listeners = (char **) malloc(size); + for (i = 0; i < fixed.listener_limit; i++) { + size = 24; + vary.listeners[i] = (char *) malloc(size); + readn(fd, vary.listeners[i], size, "listeners", fn); + } + + size = fixed.st_limit * sizeof *vary.scores; + vary.scores = (score_0002 **) malloc(size); + for (i = 0; i < fixed.st_limit; i++) { + size = fixed.score_limit * sizeof *vary.scores[i]; + vary.scores[i] = (score_0002 *) malloc(size); + + for (j = 0; j < fixed.score_limit; j++) { + size = fixed.key_size * sizeof *vary.scores[i][j].key; + vary.scores[i][j].key = (char *) malloc(size); + readn(fd, vary.scores[i][j].key, size, "scores", fn); + + size = fixed.value_size * sizeof *vary.scores[i][j].value; + vary.scores[i][j].value = (char *) malloc(size); + readn(fd, vary.scores[i][j].value, size, "scores", fn); + } + } + +#if defined(_MIPS_SIM) && _MIPS_SIM != _ABIO32 + /* + * SGI's MIPSpro compilers pad the struct out to an 8-byte boundary + * in the N32 and 64-bit ABIs. + */ + padto(fd, 8, fn); +#endif + eof(fd, fn); + + /* now report */ + + printf("Server started at %s\n", ttoa_0002(fixed.start_time)); + printf("VP started at %s\n", ttoa_0002(fixed.vp_start_time)); + printf("VP pid %d\n", fixed.pid); + printf("incarnations %d\n", fixed.incarnations); + printf("bound to cpu %d\n", fixed.cpu); + printf("thread_starts %d\n", fixed.thread_starts); + printf("thread_exits %d\n", fixed.thread_exits); + printf("most_threads %d\n", fixed.most_threads); + printf("historic_vp_connections %d\n", fixed.historic_vp_connections); + printf("vp_connections %d\n", fixed.vp_connections); + for (i = 0; i < fixed.st_limit; i++) + printf("thread_connections[%d] %d\n", i, vary.thread_connections[i]); + for (i = 0; i < fixed.listener_limit; i++) { + printf("listeners[%d] = %.*s\n", i, 24, vary.listeners[i]); + printf("listener_connections[%d] %d\n", i, vary.listener_connections[i]); + } + for (i = 0; i < fixed.st_limit; i++) + for (j = 0; j < fixed.score_limit; j++) + if (vary.scores[i][j].key[0]) + printf("score[%d][%d] %.*s = %.*s\n", i, j, + fixed.key_size, vary.scores[i][j].key, + fixed.value_size, vary.scores[i][j].value); +} + + +/***************************************** + * Scoreboard version 0002 functions + */ + /* * Convert the given time (in microseconds since the epoch) to a string. * Returns a static buffer. */ const char * -ttoa_0001(ap_time_t t) +ttoa_0001(apr_time_t t) { static char buf[64]; time_t s; @@ -249,6 +398,7 @@ */ printf("%s\n", fn); + printf("version " STM_SCOREBOARD_VERSION_0001); /* first read and sanity check the fixed-size portion */ readn(fd, &fixed, sizeof fixed, "fixed-size portion", fn); @@ -277,11 +427,11 @@ /* then read the varying-size portion in chunks */ size = fixed.st_limit * sizeof *vary.thread_connections; - vary.thread_connections = (ap_int32_t *) malloc(size); + vary.thread_connections = (apr_int32_t *) malloc(size); readn(fd, vary.thread_connections, size, "thread_connections", fn); size = fixed.listener_limit * sizeof *vary.listener_connections; - vary.listener_connections = (ap_int32_t *) malloc(size); + vary.listener_connections = (apr_int32_t *) malloc(size); readn(fd, vary.listener_connections, size, "listener_connections", fn); size = fixed.listener_limit * sizeof *vary.listeners; @@ -363,7 +513,10 @@ /* insert new version checks here */ - if (!memcmp(version, STM_SCOREBOARD_VERSION_0001, sizeof version)) { + if (!memcmp(version, STM_SCOREBOARD_VERSION_0002, sizeof version)) { + show_0002(fd, fn); + return 1; + } else if (!memcmp(version, STM_SCOREBOARD_VERSION_0001, sizeof version)) { show_0001(fd, fn); return 1; } else