diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | nscd/connections.c | 35 | ||||
-rw-r--r-- | nscd/nscd.conf | 4 | ||||
-rw-r--r-- | nscd/nscd.h | 4 | ||||
-rw-r--r-- | nscd/nscd_conf.c | 8 | ||||
-rw-r--r-- | nscd/nscd_stat.c | 22 |
6 files changed, 64 insertions, 18 deletions
@@ -1,5 +1,14 @@ 2004-10-03 Ulrich Drepper <drepper@redhat.com> + Dynamically create new threads if necessary. + * nscd/connections.c (fd_ready): If no thread available for processing + the request, create a new one unless the limit is reached. + (start_threads): Check errors from pthread_create. + * nscd/nscd.h: Declare max_nthreads. + * nscd/nscd_conf.c: Parse max-nthreads entry. + * nscd/nscd.conf: Add max-threads entry. + * nscd/nscd_stat.c: Print current and maximum number of threads. + Implement paranoia mode. * nscd/connections.c (nscd_init): Mark database and socket descriptors as close on exec. diff --git a/nscd/connections.c b/nscd/connections.c index ace69fb455..45042beaab 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -69,6 +69,8 @@ static gid_t *server_groups; #endif static int server_ngroups; +static pthread_attr_t attr; + static void begin_drop_privileges (void); static void finish_drop_privileges (void); @@ -167,8 +169,10 @@ static struct database_dyn *const serv2db[LASTREQ] = #define CACHE_PRUNE_INTERVAL 15 -/* Number of threads to use. */ +/* Initial number of threads to use. */ int nthreads = -1; +/* Maximum number of threads to use. */ +int max_nthreads = 32; /* Socket for incoming connections. */ static int sock; @@ -1206,6 +1210,19 @@ fd_ready (int fd) { ++client_queued; do_signal = false; + + /* Try to start another thread to help out. */ + pthread_t th; + if (nthreads < max_nthreads + && pthread_create (&th, &attr, nscd_run, + (void *) (long int) nthreads) == 0) + { + /* We got another thread. */ + ++nthreads; + /* The new thread might new a kick. */ + do_signal = true; + } + } pthread_mutex_unlock (&readylist_lock); @@ -1452,21 +1469,29 @@ start_threads (void) /* Create the attribute for the threads. They are all created detached. */ - pthread_attr_t attr; pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + /* Use 1MB stacks, twice as much for 64-bit architectures. */ + pthread_attr_setstacksize (&attr, 1024 * 1024 * (sizeof (void *) / 4)); /* We allow less than LASTDB threads only for debugging. */ if (debug_level == 0) nthreads = MAX (nthreads, lastdb); + int nfailed = 0; for (long int i = 0; i < nthreads; ++i) { pthread_t th; - pthread_create (&th, &attr, nscd_run, (void *) i); + if (pthread_create (&th, &attr, nscd_run, (void *) (i - nfailed)) != 0) + ++nfailed; + } + if (nthreads - nfailed < lastdb) + { + /* We could not start enough threads. */ + dbg_log (_("could only start %d threads; terminating"), + nthreads - nfailed); + exit (1); } - - pthread_attr_destroy (&attr); /* Determine how much room for descriptors we should initially allocate. This might need to change later if we cap the number diff --git a/nscd/nscd.conf b/nscd/nscd.conf index 35f65a4a36..87e7a84487 100644 --- a/nscd/nscd.conf +++ b/nscd/nscd.conf @@ -7,7 +7,8 @@ # # logfile <file> # debug-level <level> -# threads <#threads to use> +# threads <initial #threads to use> +# max-threads <maximum #threads to use> # server-user <user to run server as instead of root> # server-user is ignored if nscd is started with -S parameters # stat-user <user who is allowed to request statistics> @@ -29,6 +30,7 @@ # logfile /var/log/nscd.log # threads 6 +# max-threads 128 # server-user nobody # stat-user somebody debug-level 0 diff --git a/nscd/nscd.h b/nscd/nscd.h index 56073ebd0c..4e00f69fb9 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -102,8 +102,10 @@ extern const struct iovec grp_iov_disabled; extern const struct iovec hst_iov_disabled; -/* Number of threads to run. */ +/* Initial number of threads to run. */ extern int nthreads; +/* Maximum number of threads to use. */ +extern int max_nthreads; /* Tables for which we cache data with uid. */ extern int secure_in_use; /* Is one of the above 1? */ diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c index 591dea8d64..d21f2fc501 100644 --- a/nscd/nscd_conf.c +++ b/nscd/nscd_conf.c @@ -184,6 +184,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) if (nthreads == -1) nthreads = MAX (atol (arg1), lastdb); } + else if (strcmp (entry, "max-threads") == 0) + { + max_nthreads = MAX (atol (arg1), lastdb); + } else if (strcmp (entry, "server-user") == 0) { if (!arg1) @@ -282,6 +286,10 @@ cannot get current working directory: %s; disabling paranoia mode"), } } + /* Enforce sanity. */ + if (max_nthreads < nthreads) + max_nthreads = nthreads; + /* Free the buffer. */ free (line); /* Close configuration file. */ diff --git a/nscd/nscd_stat.c b/nscd/nscd_stat.c index a56a381b25..9231642278 100644 --- a/nscd/nscd_stat.c +++ b/nscd/nscd_stat.c @@ -143,8 +143,8 @@ receive_print_stats (void) int fd; int i; uid_t uid = getuid (); - const char *yesstr = _(" yes"); - const char *nostr = _(" no"); + const char *yesstr = nl_langinfo (YESSTR); + const char *nostr = nl_langinfo (NOSTR); /* Find out whether there is another user but root allowed to request statistics. */ @@ -225,22 +225,22 @@ receive_print_stats (void) else printf (_(" %2lus server runtime\n"), diff); - printf (_("%15lu number of times clients had to wait\n" + printf (_("%15d current number of threads\n" + "%15d maximum number of threads\n" + "%15lu number of times clients had to wait\n" "%15s paranoia mode enabled\n" "%15lu restart internal\n"), - data.client_queued, paranoia ? yesstr : nostr, - (unsigned long int) restart_interval); + nthreads, max_nthreads, data.client_queued, + paranoia ? yesstr : nostr, (unsigned long int) restart_interval); for (i = 0; i < lastdb; ++i) { unsigned long int hit = data.dbs[i].poshit + data.dbs[i].neghit; unsigned long int all = hit + data.dbs[i].posmiss + data.dbs[i].negmiss; - const char *enabled = nl_langinfo (data.dbs[i].enabled ? YESSTR : NOSTR); - const char *check_file = nl_langinfo (data.dbs[i].check_file - ? YESSTR : NOSTR); - const char *shared = nl_langinfo (data.dbs[i].shared ? YESSTR : NOSTR); - const char *persistent = nl_langinfo (data.dbs[i].persistent - ? YESSTR : NOSTR); + const char *enabled = data.dbs[i].enabled ? yesstr : nostr; + const char *check_file = data.dbs[i].check_file ? yesstr : nostr; + const char *shared = data.dbs[i].shared ? yesstr : nostr; + const char *persistent = data.dbs[i].persistent ? yesstr : nostr; if (enabled[0] == '\0') /* The locale does not provide this information so we have to |