Home | History | Annotate | Download | only in liblog
      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