Update.
authorUlrich Drepper <drepper@redhat.com>
Sun, 3 Oct 2004 21:11:37 +0000 (21:11 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sun, 3 Oct 2004 21:11:37 +0000 (21:11 +0000)
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.

ChangeLog
nscd/connections.c
nscd/nscd.conf
nscd/nscd.h
nscd/nscd_conf.c
nscd/nscd_stat.c

index 6ecb996..b454dc3 100644 (file)
--- 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.
index ace69fb..45042be 100644 (file)
@@ -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
index 35f65a4..87e7a84 100644 (file)
@@ -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
index 56073eb..4e00f69 100644 (file)
@@ -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?  */
index 591dea8..d21f2fc 100644 (file)
@@ -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.  */
index a56a381..9231642 100644 (file)
@@ -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