Replace timeout/scaling macros with functions.
diff --git a/tools/run_tests/generated/configs.json b/tools/run_tests/generated/configs.json
index f2c1107..091f5d9 100644
--- a/tools/run_tests/generated/configs.json
+++ b/tools/run_tests/generated/configs.json
@@ -7,7 +7,6 @@
   }, 
   {
     "config": "helgrind", 
-    "timeout_multiplier": 20, 
     "tool_prefix": [
       "valgrind", 
       "--tool=helgrind"
@@ -17,16 +16,14 @@
     "config": "asan-noleaks", 
     "environ": {
       "ASAN_OPTIONS": "detect_leaks=0:color=always"
-    }, 
-    "timeout_multiplier": 3
+    }
   }, 
   {
     "config": "asan-trace-cmp", 
     "environ": {
       "ASAN_OPTIONS": "detect_leaks=1:color=always", 
       "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
-    }, 
-    "timeout_multiplier": 3
+    }
   }, 
   {
     "config": "dbg"
@@ -39,7 +36,6 @@
   }, 
   {
     "config": "memcheck", 
-    "timeout_multiplier": 10, 
     "tool_prefix": [
       "valgrind", 
       "--tool=memcheck", 
@@ -51,26 +47,22 @@
     "environ": {
       "ASAN_OPTIONS": "detect_leaks=1:color=always", 
       "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
-    }, 
-    "timeout_multiplier": 3
+    }
   }, 
   {
     "config": "tsan", 
     "environ": {
       "TSAN_OPTIONS": "suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1"
-    }, 
-    "timeout_multiplier": 5
+    }
   }, 
   {
     "config": "ubsan", 
     "environ": {
       "UBSAN_OPTIONS": "halt_on_error=1:print_stacktrace=1"
-    }, 
-    "timeout_multiplier": 1.5
+    }
   }, 
   {
-    "config": "msan", 
-    "timeout_multiplier": 4
+    "config": "msan"
   }, 
   {
     "config": "mutrace"
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 5aae343..c182288 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -234,6 +234,17 @@
         timeout_scaling = 1
         if polling_strategy == 'poll-cv':
           timeout_scaling *= 5
+
+        # Scale overall test timeout if running under various sanitizers.
+        config = self.args.config
+        if ('asan' in config
+            or config == 'msan'
+            or config == 'tsan'
+            or config == 'ubsan'
+            or config == 'helgrind'
+            or config == 'memcheck'):
+          timeout_scaling *= 20
+
         if self.config.build_config in target['exclude_configs']:
           continue
         if self.args.iomgr_platform in target.get('exclude_iomgrs', []):