1 /* 2 ** Copyright 2016, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 #include <errno.h> 18 #include <pthread.h> 19 #include <time.h> 20 21 #include <log/log.h> 22 23 #include "log_portability.h" 24 25 // Global default if 'last' argument in __android_log_ratelimit is NULL 26 static time_t g_last_clock; 27 // Global above can not deal well with callers playing games with the 28 // seconds argument, so we will also hold on to the maximum value 29 // ever provided and use that to gain consistency. If the caller 30 // provides their own 'last' argument, then they can play such games 31 // of varying the 'seconds' argument to their pleasure. 32 static time_t g_last_seconds; 33 static const time_t last_seconds_default = 10; 34 static const time_t last_seconds_max = 24 * 60 * 60; // maximum of a day 35 static const time_t last_seconds_min = 2; // granularity 36 // Lock to protect last_clock and last_seconds, but also 'last' 37 // argument (not NULL) as supplied to __android_log_ratelimit. 38 static pthread_mutex_t lock_ratelimit = PTHREAD_MUTEX_INITIALIZER; 39 40 // if last is NULL, caller _must_ provide a consistent value for 41 // seconds, otherwise we will take the maximum ever issued and hold 42 // on to that. Preserves value of non-zero errno. Return -1 if we 43 // can not acquire a lock, 0 if we are not to log a message, and 1 44 // if we are ok to log a message. Caller should check > 0 for true. 45 LIBLOG_ABI_PUBLIC int __android_log_ratelimit(time_t seconds, time_t* last) { 46 int save_errno = errno; 47 48 // Two reasons for trylock failure: 49 // 1. In a signal handler. Must prevent deadlock 50 // 2. Too many threads calling __android_log_ratelimit. 51 // Bonus to not print if they race here because that 52 // dovetails the goal of ratelimiting. One may print 53 // and the others will wait their turn ... 54 if (pthread_mutex_trylock(&lock_ratelimit)) { 55 if (save_errno) errno = save_errno; 56 return -1; 57 } 58 59 if (seconds == 0) { 60 seconds = last_seconds_default; 61 } else if (seconds < last_seconds_min) { 62 seconds = last_seconds_min; 63 } else if (seconds > last_seconds_max) { 64 seconds = last_seconds_max; 65 } 66 67 if (!last) { 68 if (g_last_seconds > seconds) { 69 seconds = g_last_seconds; 70 } else if (g_last_seconds < seconds) { 71 g_last_seconds = seconds; 72 } 73 last = &g_last_clock; 74 } 75 76 time_t now = time(NULL); 77 if ((now == (time_t)-1) || ((*last + seconds) > now)) { 78 pthread_mutex_unlock(&lock_ratelimit); 79 if (save_errno) errno = save_errno; 80 return 0; 81 } 82 *last = now; 83 pthread_mutex_unlock(&lock_ratelimit); 84 if (save_errno) errno = save_errno; 85 return 1; 86 } 87