aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--nscd/connections.c35
-rw-r--r--nscd/nscd.conf4
-rw-r--r--nscd/nscd.h4
-rw-r--r--nscd/nscd_conf.c8
-rw-r--r--nscd/nscd_stat.c22
6 files changed, 64 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 6ecb996c9d..b454dc31a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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