/*************************************************************************/
/* Copyright (c) 2004 */
/* Daniel Sleator, David Temperley, and John Lafferty */
/* All rights reserved */
/* */
/* Use of the link grammar parsing system is subject to the terms of the */
/* license set forth in the LICENSE file included with this software. */
/* This license allows free redistribution and use in source and binary */
/* forms, with or without modification, subject to certain conditions. */
/* */
/*************************************************************************/
#include <time.h>
#include <stdarg.h>
#include "externs.h"
#if !defined(_WIN32)
#include <sys/time.h>
#include <sys/resource.h>
#endif
#if defined(__linux__)
/* based on reading the man page for getrusage on linux, I inferred that
I needed to include this. However it doesn't seem to be necessary */
#include <unistd.h>
#endif
#if defined(__hpux__)
#include <sys/syscall.h>
int syscall(int, int, struct rusage *rusage); /* can't find
the prototype for this */
#define getrusage(a, b) syscall(SYS_GETRUSAGE, (a), (b))
#endif /* __hpux__ */
#if defined(__sun__)
int getrusage(int who, struct rusage *rusage);
/* Declaration missing from sys/resource.h in sun operating systems (?) */
#endif /* __sun__ */
#include "api-structures.h"
#include "resources.h"
#include "utilities.h"
#define MAX_PARSE_TIME_UNLIMITED -1
#define MAX_MEMORY_UNLIMITED ((size_t) -1)
/** Returns the CPU usage time, for this thread only, in seconds. */
static double current_usage_time(void)
{
#if defined RUSAGE_THREAD
struct rusage u;
getrusage (RUSAGE_THREAD, &u);
return (u.ru_utime.tv_sec + ((double) u.ru_utime.tv_usec) / 1000000.0);
#else
return ((double) clock())/CLOCKS_PER_SEC;
#endif
}
Resources resources_create(void)
{
Resources r;
double now;
r = (Resources) xalloc(sizeof(struct Resources_s));
r->max_parse_time = MAX_PARSE_TIME_UNLIMITED;
now = current_usage_time();
r->when_created = now;
r->when_last_called = now;
r->time_when_parse_started = now;
r->space_when_parse_started = get_space_in_use();
r->max_memory = MAX_MEMORY_UNLIMITED;
r->cumulative_time = 0;
r->memory_exhausted = false;
r->timer_expired = false;
return r;
}
void resources_delete(Resources r)
{
xfree(r, sizeof(struct Resources_s));
}
void resources_reset(Resources r)
{
r->when_last_called = r->time_when_parse_started = current_usage_time();
r->space_when_parse_started = get_space_in_use();
r->timer_expired = false;
r->memory_exhausted = false;
}
#if 0
static void resources_reset_time(Resources r)
{
r->when_last_called = r->time_when_parse_started = current_usage_time();
}
#endif
void resources_reset_space(Resources r)
{
r->space_when_parse_started = get_space_in_use();
}
bool resources_exhausted(Resources r)
{
if (!r->timer_expired && !resources_timer_expired(r)) return false;
if (!r->timer_expired && (verbosity_level(D_USER_TIMES)))
{
prt_error("#### Timeout (%.2f seconds)\n",
current_usage_time() - r->time_when_parse_started);
}
r->timer_expired = true;
return true;
}
#if 0 /* max_memory is not being set any more. */
bool resources_exhausted(Resources r)
{
if (r->timer_expired || r->memory_exhausted)
return true;
if (resources_timer_expired(r))
r->timer_expired = true;
if (resources_memory_exhausted(r))
r->memory_exhausted = true;
return (r->timer_expired || r->memory_exhausted);
}
#endif
bool resources_timer_expired(Resources r)
{
if (r->max_parse_time == MAX_PARSE_TIME_UNLIMITED) return false;
else return (r->timer_expired ||
(current_usage_time() - r->time_when_parse_started > r->max_parse_time));
}
bool resources_memory_exhausted(Resources r)
{
if (r->max_memory == MAX_MEMORY_UNLIMITED) return false;
else return (r->memory_exhausted || (get_space_in_use() > r->max_memory));
}
#define RES_COL_WIDTH 52
/** print out the cpu ticks since this was last called */
GNUC_PRINTF(2,0)
static void resources_print_time(Resources r, const char *fmt, va_list args)
{
double now;
now = current_usage_time();
char s[128] = "";
vsnprintf(s, sizeof(s), fmt, args);
prt_error("++++ %-*s %7.2f seconds\n",
RES_COL_WIDTH, s, now - r->when_last_called);
r->when_last_called = now;
}
/** print out the cpu ticks since this was last called */
static void resources_print_total_time(int verbosity_opt, Resources r)
{
double now;
now = current_usage_time();
r->cumulative_time += (now - r->time_when_parse_started);
if (verbosity_opt >= D_USER_BASIC)
{
prt_error("++++ %-*s %7.2f seconds (%.2f total)\n", RES_COL_WIDTH, "Time",
now - r->time_when_parse_started, r->cumulative_time);
}
r->time_when_parse_started = now;
}
static void resources_print_total_space(int verbosity_opt, Resources r)
{
if (verbosity_opt >= D_USER_TIMES)
{
prt_error("++++ %-*s %zu bytes (%zu max)\n", RES_COL_WIDTH, "Total space",
get_space_in_use(), get_max_space_used());
}
}
void print_time(Parse_Options opts, const char *fmt, ...)
{
if (verbosity < D_USER_TIMES) return;
va_list args;
va_start(args, fmt);
resources_print_time(opts->resources, fmt, args);
va_end(args);
}
void parse_options_print_total_time(Parse_Options opts)
{
resources_print_total_time(opts->verbosity, opts->resources);
}
void print_total_space(Parse_Options opts)
{
resources_print_total_space(opts->verbosity, opts->resources);
}