From: Ulrich Drepper Date: Sun, 18 May 2008 21:54:43 +0000 (+0000) Subject: * nscd/cache.c (cache_add): Take additional parameter specifying X-Git-Tag: cvs/fedora-glibc-20080520T1924~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=528741cb6c7218e7f2f764fa10aa7e67699eadaa;p=platform%2Fupstream%2Fglibc.git * nscd/cache.c (cache_add): Take additional parameter specifying whether this is in response of a cache refill. Check alignment of package data. Revamp waking of pruning thread. (prune_cache): Small optimization. * nscd/nscd.h: Adjust cache_add prototypes. * nscd/aicache.c: Adjust cache_add calls. * nscd/grpcache.c: Likewise. * nscd/hstcache.c: Likewise. * nscd/initgrcache.c: Likewise. * nscd/pwdcache.c: Likewise. * nscd/servicescache.c: Likewise. * nscd/connections.c (restart): Really disable cache use before exec attempt. If it fails, reenable cache. (nscd_run_prune): Initialize wakeup_time. After wakeup, set wakeup time to max to be able to notice concurrent cache additions. Unlock prune_lock while performing gc. Afterwards compute wakeup time with current wakeup_time value in mind. --- diff --git a/ChangeLog b/ChangeLog index d053ed0..da8b1b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2008-05-18 Ulrich Drepper + + * nscd/cache.c (cache_add): Take additional parameter specifying + whether this is in response of a cache refill. Check alignment + of package data. Revamp waking of pruning thread. + (prune_cache): Small optimization. + * nscd/nscd.h: Adjust cache_add prototypes. + * nscd/aicache.c: Adjust cache_add calls. + * nscd/grpcache.c: Likewise. + * nscd/hstcache.c: Likewise. + * nscd/initgrcache.c: Likewise. + * nscd/pwdcache.c: Likewise. + * nscd/servicescache.c: Likewise. + * nscd/connections.c (restart): Really disable cache use before + exec attempt. If it fails, reenable cache. + (nscd_run_prune): Initialize wakeup_time. After wakeup, set wakeup + time to max to be able to notice concurrent cache additions. Unlock + prune_lock while performing gc. Afterwards compute wakeup time with + current wakeup_time value in mind. + 2008-05-17 Ulrich Drepper * nscd/mem.c (gc): Avoid stack overflow when allocating move list. diff --git a/nscd/aicache.c b/nscd/aicache.c index 7ae5a16..5ffab76 100644 --- a/nscd/aicache.c +++ b/nscd/aicache.c @@ -558,7 +558,7 @@ next_nip: pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, &dataset->head, - true, db, uid); + true, db, uid, he == NULL); pthread_rwlock_unlock (&db->lock); diff --git a/nscd/cache.c b/nscd/cache.c index f4a9de5..2faaf34 100644 --- a/nscd/cache.c +++ b/nscd/cache.c @@ -135,7 +135,7 @@ cache_search (request_type type, void *key, size_t len, int cache_add (int type, const void *key, size_t len, struct datahead *packet, bool first, struct database_dyn *table, - uid_t owner) + uid_t owner, bool prune_wakeup) { if (__builtin_expect (debug_level >= 2, 0)) { @@ -180,6 +180,7 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet, assert (newp->key + newp->len <= table->head->first_free); newp->owner = owner; newp->packet = (char *) packet - table->data; + assert ((newp->packet & BLOCK_ALIGN_M1) == 0); /* Put the new entry in the first position. */ do @@ -211,19 +212,27 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet, (char *) &table->head->array[hash] - (char *) table->head + sizeof (ref_t), MS_ASYNC); - /* Perhaps the prune thread for the data is not running in a long - time. Wake it if necessary. */ - time_t next_wakeup = table->wakeup_time; - while (next_wakeup + CACHE_PRUNE_INTERVAL > packet->timeout) - if (atomic_compare_and_exchange_bool_acq (&table->wakeup_time, - packet->timeout, - next_wakeup) == 0) - { + /* We do not have to worry about the pruning thread if we are + re-adding the data since this is done by the pruning thread. We + also do not have to do anything in case this is not the first + time the data is entered since different data heads all have the + same timeout. */ + if (first && prune_wakeup) + { + /* Perhaps the prune thread for the table is not running in a long + time. Wake it if necessary. */ + pthread_mutex_lock (&table->prune_lock); + time_t next_wakeup = table->wakeup_time; + bool do_wakeup = false; + if (next_wakeup > packet->timeout + CACHE_PRUNE_INTERVAL) + { + table->wakeup_time = packet->timeout; + do_wakeup = true; + } + pthread_mutex_unlock (&table->prune_lock); + if (do_wakeup) pthread_cond_signal (&table->prune_cond); - break; - } - else - next_wakeup = table->wakeup_time; + } /* Mark the in-flight memory as unused. */ for (enum in_flight idx = 0; idx < IDX_last; ++idx) @@ -436,7 +445,8 @@ prune_cache (struct database_dyn *table, time_t now, int fd) ref_t *old = &table->head->array[first]; ref_t run = table->head->array[first]; - while (run != ENDREF) + assert (run != ENDREF); + do { struct hashentry *runp = (struct hashentry *) (data + run); struct datahead *dh @@ -462,6 +472,7 @@ prune_cache (struct database_dyn *table, time_t now, int fd) run = runp->next; } } + while (run != ENDREF); } ++first; diff --git a/nscd/connections.c b/nscd/connections.c index 15148bd..e6a2c94 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -1330,11 +1330,14 @@ cannot change to old working directory: %s; disabling paranoia mode"), } /* Synchronize memory. */ + int32_t certainly[lastdb]; for (int cnt = 0; cnt < lastdb; ++cnt) if (dbs[cnt].enabled) { /* Make sure nobody keeps using the database. */ dbs[cnt].head->timestamp = 0; + certainly[cnt] = dbs[cnt].head->nscd_certainly_running; + dbs[cnt].head->nscd_certainly_running = 0; if (dbs[cnt].persistent) // XXX async OK? @@ -1357,6 +1360,15 @@ cannot change to old working directory: %s; disabling paranoia mode"), dbg_log (_("cannot change current working directory to \"/\": %s"), strerror (errno)); paranoia = 0; + + /* Reenable the databases. */ + time_t now = time (NULL); + for (int cnt = 0; cnt < lastdb; ++cnt) + if (dbs[cnt].enabled) + { + dbs[cnt].head->timestamp = now; + dbs[cnt].head->nscd_certainly_running = certainly[cnt]; + } } @@ -1394,42 +1406,68 @@ nscd_run_prune (void *p) int dont_need_update = setup_thread (&dbs[my_number]); + time_t now = time (NULL); + /* We are running. */ - dbs[my_number].head->timestamp = time (NULL); + dbs[my_number].head->timestamp = now; struct timespec prune_ts; - if (clock_gettime (timeout_clock, &prune_ts) == -1) + if (__builtin_expect (clock_gettime (timeout_clock, &prune_ts) == -1, 0)) /* Should never happen. */ abort (); /* Compute the initial timeout time. Prevent all the timers to go off at the same time by adding a db-based value. */ prune_ts.tv_sec += CACHE_PRUNE_INTERVAL + my_number; + dbs[my_number].wakeup_time = now + CACHE_PRUNE_INTERVAL + my_number; + + pthread_mutex_t *prune_lock = &dbs[my_number].prune_lock; + pthread_cond_t *prune_cond = &dbs[my_number].prune_cond; - pthread_mutex_lock (&dbs[my_number].prune_lock); + pthread_mutex_lock (prune_lock); while (1) { /* Wait, but not forever. */ - int e = pthread_cond_timedwait (&dbs[my_number].prune_cond, - &dbs[my_number].prune_lock, - &prune_ts); - assert (e == 0 || e == ETIMEDOUT); + int e = pthread_cond_timedwait (prune_cond, prune_lock, &prune_ts); + assert (__builtin_expect (e == 0 || e == ETIMEDOUT, 1)); time_t next_wait; - time_t now = time (NULL); + now = time (NULL); if (e == ETIMEDOUT || now >= dbs[my_number].wakeup_time) { + /* We will determine the new timout values based on the + cache content. Should there be concurrent additions to + the cache which are not accounted for in the cache + pruning we want to know about it. Therefore set the + timeout to the maximum. It will be descreased when adding + new entries to the cache, if necessary. */ + if (sizeof (time_t) == sizeof (long int)) + dbs[my_number].wakeup_time = LONG_MAX; + else + dbs[my_number].wakeup_time = INT_MAX; + + pthread_mutex_unlock (prune_lock); + next_wait = prune_cache (&dbs[my_number], now, -1); + next_wait = MAX (next_wait, CACHE_PRUNE_INTERVAL); /* If clients cannot determine for sure whether nscd is running we need to wake up occasionally to update the timestamp. Wait 90% of the update period. */ #define UPDATE_MAPPING_TIMEOUT (MAPPING_TIMEOUT * 9 / 10) if (__builtin_expect (! dont_need_update, 0)) - next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait); + { + next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait); + dbs[my_number].head->timestamp = now; + } + + pthread_mutex_lock (prune_lock); /* Make it known when we will wake up again. */ - dbs[my_number].wakeup_time = now + next_wait; + if (now + next_wait < dbs[my_number].wakeup_time) + dbs[my_number].wakeup_time = now + next_wait; + else + next_wait = dbs[my_number].wakeup_time - now; } else /* The cache was just pruned. Do not do it again now. Just diff --git a/nscd/grpcache.c b/nscd/grpcache.c index 9921ae3..e391dc3 100644 --- a/nscd/grpcache.c +++ b/nscd/grpcache.c @@ -147,7 +147,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -353,7 +353,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, if (req->type == GETGRBYGID) { if (cache_add (GETGRBYGID, cp, key_offset, &dataset->head, true, - db, owner) < 0) + db, owner, he == NULL) < 0) goto out; first = false; @@ -362,7 +362,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, else if (strcmp (key_copy, gr_name) != 0) { if (cache_add (GETGRBYNAME, key_copy, key_len + 1, - &dataset->head, true, db, owner) < 0) + &dataset->head, true, db, owner, he == NULL) < 0) goto out; first = false; @@ -372,12 +372,13 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, if ((req->type == GETGRBYNAME || db->propagate) && __builtin_expect (cache_add (GETGRBYNAME, gr_name, gr_name_len, - &dataset->head, first, db, owner) + &dataset->head, first, db, owner, + he == NULL) == 0, 1)) { if (req->type == GETGRBYNAME && db->propagate) (void) cache_add (GETGRBYGID, cp, key_offset, &dataset->head, - false, db, owner); + false, db, owner, false); } out: diff --git a/nscd/hstcache.c b/nscd/hstcache.c index 3ceb671..d4dd51f 100644 --- a/nscd/hstcache.c +++ b/nscd/hstcache.c @@ -156,7 +156,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -408,7 +408,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, || req->type == GETHOSTBYADDRv6); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); } diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c index 94e909d..3355df5 100644 --- a/nscd/initgrcache.c +++ b/nscd/initgrcache.c @@ -231,7 +231,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, uid); + &dataset->head, true, db, uid, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -398,7 +398,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (INITGROUPS, cp, req->key_len, &dataset->head, true, - db, uid); + db, uid, he == NULL); pthread_rwlock_unlock (&db->lock); } diff --git a/nscd/nscd.h b/nscd/nscd.h index b024017..b07256d 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -231,7 +231,8 @@ extern struct datahead *cache_search (request_type, void *key, size_t len, uid_t owner); extern int cache_add (int type, const void *key, size_t len, struct datahead *packet, bool first, - struct database_dyn *table, uid_t owner); + struct database_dyn *table, uid_t owner, + bool prune_wakeup); extern time_t prune_cache (struct database_dyn *table, time_t now, int fd); /* pwdcache.c */ diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c index 2d0a265..4a0cabd 100644 --- a/nscd/pwdcache.c +++ b/nscd/pwdcache.c @@ -154,7 +154,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -348,7 +348,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, if (req->type == GETPWBYUID) { if (cache_add (GETPWBYUID, cp, key_offset, &dataset->head, true, - db, owner) < 0) + db, owner, he == NULL) < 0) goto out; first = false; @@ -357,7 +357,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, else if (strcmp (key_copy, dataset->strdata) != 0) { if (cache_add (GETPWBYNAME, key_copy, key_len + 1, - &dataset->head, true, db, owner) < 0) + &dataset->head, true, db, owner, he == NULL) < 0) goto out; first = false; @@ -367,11 +367,12 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, if ((req->type == GETPWBYNAME || db->propagate) && __builtin_expect (cache_add (GETPWBYNAME, dataset->strdata, pw_name_len, &dataset->head, - first, db, owner) == 0, 1)) + first, db, owner, he == NULL) + == 0, 1)) { if (req->type == GETPWBYNAME && db->propagate) (void) cache_add (GETPWBYUID, cp, key_offset, &dataset->head, - false, db, owner); + false, db, owner, false); } out: diff --git a/nscd/servicescache.c b/nscd/servicescache.c index c6f0b47..c952fa1 100644 --- a/nscd/servicescache.c +++ b/nscd/servicescache.c @@ -137,7 +137,7 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -331,7 +331,7 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); }