X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Futimecmp.c;h=49ea5f86bae6521d620aee7215fc5b22c5e41084;hb=cd56634a4a8179fd5a4419fbb3e27211b042ab1c;hp=63a0c9a822000e0b36e92c7ab9c270f94a760b79;hpb=692679fcbebba0095bae0f1f1a99bd1f0f5a0476;p=gnulib.git diff --git a/lib/utimecmp.c b/lib/utimecmp.c index 63a0c9a82..49ea5f86b 100644 --- a/lib/utimecmp.c +++ b/lib/utimecmp.c @@ -1,6 +1,6 @@ /* utimecmp.c -- compare file time stamps - Copyright (C) 2004-2007, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 2004-2007, 2009-2014 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,7 +33,6 @@ #include "stat-time.h" #include "utimens.h" #include "verify.h" -#include "xalloc.h" #ifndef MAX # define MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -122,7 +121,9 @@ utimecmp (char const *dst_name, /* Things to watch out for: The code uses a static hash table internally and is not safe in the - presence of signals, multiple threads, etc. + presence of signals, multiple threads, etc. However, memory pressure + that prevents use of the hash table is not fatal - we just fall back + to redoing the computations on every call in that case. int and long int might be 32 bits. Many of the calculations store numbers up to 2 billion, and multiply by 10; they have to avoid @@ -143,12 +144,13 @@ utimecmp (char const *dst_name, { /* Look up the time stamp resolution for the destination device. */ - /* Hash table for devices. */ + /* Hash table for caching information learned about devices. */ static Hash_table *ht; /* Information about the destination file system. */ static struct fs_res *new_dst_res; - struct fs_res *dst_res; + struct fs_res *dst_res = NULL; + struct fs_res tmp_dst_res; /* Time stamp resolution in nanoseconds. */ int res; @@ -163,24 +165,46 @@ utimecmp (char const *dst_name, if (src_s <= dst_s - 2) return 1; + /* Try to do a hash lookup, but fall back to stack variables and + recomputation on low memory situations. */ if (! ht) ht = hash_initialize (16, NULL, dev_info_hash, dev_info_compare, free); - if (! new_dst_res) + if (ht) { - new_dst_res = xmalloc (sizeof *new_dst_res); - new_dst_res->resolution = 2 * BILLION; - new_dst_res->exact = false; - } - new_dst_res->dev = dst_stat->st_dev; - dst_res = hash_insert (ht, new_dst_res); - if (! dst_res) - xalloc_die (); + if (! new_dst_res) + { + new_dst_res = malloc (sizeof *new_dst_res); + if (!new_dst_res) + goto low_memory; + new_dst_res->resolution = 2 * BILLION; + new_dst_res->exact = false; + } + new_dst_res->dev = dst_stat->st_dev; + dst_res = hash_insert (ht, new_dst_res); + if (! dst_res) + goto low_memory; - if (dst_res == new_dst_res) + if (dst_res == new_dst_res) + { + /* NEW_DST_RES is now in use in the hash table, so allocate a + new entry next time. */ + new_dst_res = NULL; + } + } + else { - /* NEW_DST_RES is now in use in the hash table, so allocate a - new entry next time. */ - new_dst_res = NULL; + low_memory: + if (ht) + { + tmp_dst_res.dev = dst_stat->st_dev; + dst_res = hash_lookup (ht, &tmp_dst_res); + } + if (!dst_res) + { + dst_res = &tmp_dst_res; + dst_res->resolution = 2 * BILLION; + dst_res->exact = false; + } } res = dst_res->resolution; @@ -325,7 +349,7 @@ utimecmp (char const *dst_name, res = SYSCALL_RESOLUTION; - for (a /= res; a % 10 != 0; a /= 10) + for (a /= res; a % 10 == 0; a /= 10) { if (res == BILLION) {