Add a thread-safe version of unix_time and friends.

These are not used in a thread-safe way, but it opens the path towards
per-tox-instance time keeping and removal of some unsafe global state.
This commit is contained in:
iphydf 2018-07-07 22:15:08 +00:00
parent c8697ccc20
commit 4e21c06551
No known key found for this signature in database
GPG Key ID: 3855DBA2D74403C9
2 changed files with 59 additions and 12 deletions

View File

@ -36,33 +36,70 @@
#include "crypto_core.h" /* for CRYPTO_PUBLIC_KEY_SIZE */
#include "network.h" /* for current_time_monotonic */
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* don't call into system billions of times for no reason */
static uint64_t unix_time_value;
static uint64_t unix_base_time_value;
struct Unix_Time {
uint64_t time;
uint64_t base_time;
};
Unix_Time *unix_time_new(void)
{
Unix_Time *unixtime = (Unix_Time *)malloc(sizeof(Unix_Time));
if (unixtime == nullptr) {
return nullptr;
}
unixtime->time = 0;
unixtime->base_time = 0;
return unixtime;
}
void unix_time_free(Unix_Time *unixtime)
{
free(unixtime);
}
void unix_time_update_r(Unix_Time *unixtime)
{
if (unixtime->base_time == 0) {
unixtime->base_time = ((uint64_t)time(nullptr) - (current_time_monotonic() / 1000ULL));
}
unixtime->time = (current_time_monotonic() / 1000ULL) + unixtime->base_time;
}
uint64_t unix_time_get(const Unix_Time *unixtime)
{
return unixtime->time;
}
int unix_time_is_timeout(const Unix_Time *unixtime, uint64_t timestamp, uint64_t timeout)
{
return timestamp + timeout <= unix_time_get(unixtime);
}
static Unix_Time global_time;
/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of
* unix_time() may fail to increase monotonically with increasing time */
void unix_time_update(void)
{
if (unix_base_time_value == 0) {
unix_base_time_value = ((uint64_t)time(nullptr) - (current_time_monotonic() / 1000ULL));
}
unix_time_value = (current_time_monotonic() / 1000ULL) + unix_base_time_value;
unix_time_update_r(&global_time);
}
uint64_t unix_time(void)
{
return unix_time_value;
return unix_time_get(&global_time);
}
int is_timeout(uint64_t timestamp, uint64_t timeout)
{
return timestamp + timeout <= unix_time();
return unix_time_is_timeout(&global_time, timestamp, timeout);
}

View File

@ -39,11 +39,21 @@ extern "C" {
#define MIN(a,b) (((a)<(b))?(a):(b))
#define PAIR(TYPE1__, TYPE2__) struct { TYPE1__ first; TYPE2__ second; }
typedef struct Unix_Time Unix_Time;
Unix_Time *unix_time_new(void);
void unix_time_free(Unix_Time *unixtime);
// TODO(#405): Use per-tox unixtime, remove unix_time_update, and rename
// unix_time_update_r to unix_time_update.
void unix_time_update_r(Unix_Time *unixtime);
uint64_t unix_time_get(const Unix_Time *unixtime);
int unix_time_is_timeout(const Unix_Time *unixtime, uint64_t timestamp, uint64_t timeout);
void unix_time_update(void);
uint64_t unix_time(void);
int is_timeout(uint64_t timestamp, uint64_t timeout);
/* id functions */
bool id_equal(const uint8_t *dest, const uint8_t *src);
uint32_t id_copy(uint8_t *dest, const uint8_t *src); /* return value is CLIENT_ID_SIZE */