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.
This commit is contained in:
Ulrich Drepper 2004-10-03 21:11:37 +00:00
parent 4401d75905
commit 27e8285643
6 changed files with 64 additions and 18 deletions

View File

@ -1,5 +1,14 @@
2004-10-03 Ulrich Drepper <drepper@redhat.com> 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. Implement paranoia mode.
* nscd/connections.c (nscd_init): Mark database and socket descriptors * nscd/connections.c (nscd_init): Mark database and socket descriptors
as close on exec. as close on exec.

View File

@ -69,6 +69,8 @@ static gid_t *server_groups;
#endif #endif
static int server_ngroups; static int server_ngroups;
static pthread_attr_t attr;
static void begin_drop_privileges (void); static void begin_drop_privileges (void);
static void finish_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 #define CACHE_PRUNE_INTERVAL 15
/* Number of threads to use. */ /* Initial number of threads to use. */
int nthreads = -1; int nthreads = -1;
/* Maximum number of threads to use. */
int max_nthreads = 32;
/* Socket for incoming connections. */ /* Socket for incoming connections. */
static int sock; static int sock;
@ -1206,6 +1210,19 @@ fd_ready (int fd)
{ {
++client_queued; ++client_queued;
do_signal = false; 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); pthread_mutex_unlock (&readylist_lock);
@ -1452,21 +1469,29 @@ start_threads (void)
/* Create the attribute for the threads. They are all created /* Create the attribute for the threads. They are all created
detached. */ detached. */
pthread_attr_t attr;
pthread_attr_init (&attr); pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); 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. */ /* We allow less than LASTDB threads only for debugging. */
if (debug_level == 0) if (debug_level == 0)
nthreads = MAX (nthreads, lastdb); nthreads = MAX (nthreads, lastdb);
int nfailed = 0;
for (long int i = 0; i < nthreads; ++i) for (long int i = 0; i < nthreads; ++i)
{ {
pthread_t th; 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 /* Determine how much room for descriptors we should initially
allocate. This might need to change later if we cap the number allocate. This might need to change later if we cap the number

View File

@ -7,7 +7,8 @@
# #
# logfile <file> # logfile <file>
# debug-level <level> # 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 <user to run server as instead of root>
# server-user is ignored if nscd is started with -S parameters # server-user is ignored if nscd is started with -S parameters
# stat-user <user who is allowed to request statistics> # stat-user <user who is allowed to request statistics>
@ -29,6 +30,7 @@
# logfile /var/log/nscd.log # logfile /var/log/nscd.log
# threads 6 # threads 6
# max-threads 128
# server-user nobody # server-user nobody
# stat-user somebody # stat-user somebody
debug-level 0 debug-level 0

View File

@ -102,8 +102,10 @@ extern const struct iovec grp_iov_disabled;
extern const struct iovec hst_iov_disabled; extern const struct iovec hst_iov_disabled;
/* Number of threads to run. */ /* Initial number of threads to run. */
extern int nthreads; extern int nthreads;
/* Maximum number of threads to use. */
extern int max_nthreads;
/* Tables for which we cache data with uid. */ /* Tables for which we cache data with uid. */
extern int secure_in_use; /* Is one of the above 1? */ extern int secure_in_use; /* Is one of the above 1? */

View File

@ -184,6 +184,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
if (nthreads == -1) if (nthreads == -1)
nthreads = MAX (atol (arg1), lastdb); 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) else if (strcmp (entry, "server-user") == 0)
{ {
if (!arg1) 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 the buffer. */
free (line); free (line);
/* Close configuration file. */ /* Close configuration file. */

View File

@ -143,8 +143,8 @@ receive_print_stats (void)
int fd; int fd;
int i; int i;
uid_t uid = getuid (); uid_t uid = getuid ();
const char *yesstr = _(" yes"); const char *yesstr = nl_langinfo (YESSTR);
const char *nostr = _(" no"); const char *nostr = nl_langinfo (NOSTR);
/* Find out whether there is another user but root allowed to /* Find out whether there is another user but root allowed to
request statistics. */ request statistics. */
@ -225,22 +225,22 @@ receive_print_stats (void)
else else
printf (_(" %2lus server runtime\n"), diff); 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" "%15s paranoia mode enabled\n"
"%15lu restart internal\n"), "%15lu restart internal\n"),
data.client_queued, paranoia ? yesstr : nostr, nthreads, max_nthreads, data.client_queued,
(unsigned long int) restart_interval); paranoia ? yesstr : nostr, (unsigned long int) restart_interval);
for (i = 0; i < lastdb; ++i) for (i = 0; i < lastdb; ++i)
{ {
unsigned long int hit = data.dbs[i].poshit + data.dbs[i].neghit; 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; 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 *enabled = data.dbs[i].enabled ? yesstr : nostr;
const char *check_file = nl_langinfo (data.dbs[i].check_file const char *check_file = data.dbs[i].check_file ? yesstr : nostr;
? YESSTR : NOSTR); const char *shared = data.dbs[i].shared ? yesstr : nostr;
const char *shared = nl_langinfo (data.dbs[i].shared ? YESSTR : NOSTR); const char *persistent = data.dbs[i].persistent ? yesstr : nostr;
const char *persistent = nl_langinfo (data.dbs[i].persistent
? YESSTR : NOSTR);
if (enabled[0] == '\0') if (enabled[0] == '\0')
/* The locale does not provide this information so we have to /* The locale does not provide this information so we have to