blob: 33770dda49468586fce205c0bf761fe9b7b2e071 [file] [log] [blame]
Mark Salyzynfc148f72016-12-14 12:52:50 -08001/*
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
26static 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.
32static time_t g_last_seconds;
33static const time_t last_seconds_default = 10;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080034static const time_t last_seconds_max = 24 * 60 * 60; // maximum of a day
35static const time_t last_seconds_min = 2; // granularity
Mark Salyzynfc148f72016-12-14 12:52:50 -080036// Lock to protect last_clock and last_seconds, but also 'last'
37// argument (not NULL) as supplied to __android_log_ratelimit.
38static 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.
45LIBLOG_ABI_PUBLIC int __android_log_ratelimit(time_t seconds, time_t* last) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080046 int save_errno = errno;
Mark Salyzynfc148f72016-12-14 12:52:50 -080047
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080048 // 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 }
Mark Salyzynfc148f72016-12-14 12:52:50 -080058
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080059 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 }
Mark Salyzynfc148f72016-12-14 12:52:50 -080066
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080067 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;
Mark Salyzynfc148f72016-12-14 12:52:50 -080072 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080073 last = &g_last_clock;
74 }
Mark Salyzynfc148f72016-12-14 12:52:50 -080075
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080076 time_t now = time(NULL);
77 if ((now == (time_t)-1) || ((*last + seconds) > now)) {
Mark Salyzynfc148f72016-12-14 12:52:50 -080078 pthread_mutex_unlock(&lock_ratelimit);
79 if (save_errno) errno = save_errno;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080080 return 0;
81 }
82 *last = now;
83 pthread_mutex_unlock(&lock_ratelimit);
84 if (save_errno) errno = save_errno;
85 return 1;
Mark Salyzynfc148f72016-12-14 12:52:50 -080086}