Revision 82f7a22c9167811d09df9481537806eba49eea20 authored by johannes hanika on 25 October 2016, 15:30:34 UTC, committed by johannes hanika on 25 October 2016, 15:31:35 UTC
getrusage.c
/*
Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
Portions Copyright (c) 1994, Regents of the University of California
This file is licensed under a BSD license.
*/
#ifdef __WIN32__
#include "win/win.h"
#endif
#include <errno.h>
#include "getrusage.h"
/*
* lengthof
* Number of elements in an array.
*/
#define lengthof(array) (sizeof(array) / sizeof((array)[0]))
static const struct
{
DWORD winerr;
int doserr;
} doserrors[] =
{ { ERROR_INVALID_FUNCTION, EINVAL },
{ ERROR_FILE_NOT_FOUND, ENOENT },
{ ERROR_PATH_NOT_FOUND, ENOENT },
{ ERROR_TOO_MANY_OPEN_FILES, EMFILE },
{ ERROR_ACCESS_DENIED, EACCES },
{ ERROR_INVALID_HANDLE, EBADF },
{ ERROR_ARENA_TRASHED, ENOMEM },
{ ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
{ ERROR_INVALID_BLOCK, ENOMEM },
{ ERROR_BAD_ENVIRONMENT, E2BIG },
{ ERROR_BAD_FORMAT, ENOEXEC },
{ ERROR_INVALID_ACCESS, EINVAL },
{ ERROR_INVALID_DATA, EINVAL },
{ ERROR_INVALID_DRIVE, ENOENT },
{ ERROR_CURRENT_DIRECTORY, EACCES },
{ ERROR_NOT_SAME_DEVICE, EXDEV },
{ ERROR_NO_MORE_FILES, ENOENT },
{ ERROR_LOCK_VIOLATION, EACCES },
{ ERROR_SHARING_VIOLATION, EACCES },
{ ERROR_BAD_NETPATH, ENOENT },
{ ERROR_NETWORK_ACCESS_DENIED, EACCES },
{ ERROR_BAD_NET_NAME, ENOENT },
{ ERROR_FILE_EXISTS, EEXIST },
{ ERROR_CANNOT_MAKE, EACCES },
{ ERROR_FAIL_I24, EACCES },
{ ERROR_INVALID_PARAMETER, EINVAL },
{ ERROR_NO_PROC_SLOTS, EAGAIN },
{ ERROR_DRIVE_LOCKED, EACCES },
{ ERROR_BROKEN_PIPE, EPIPE },
{ ERROR_DISK_FULL, ENOSPC },
{ ERROR_INVALID_TARGET_HANDLE, EBADF },
{ ERROR_INVALID_HANDLE, EINVAL },
{ ERROR_WAIT_NO_CHILDREN, ECHILD },
{ ERROR_CHILD_NOT_COMPLETE, ECHILD },
{ ERROR_DIRECT_ACCESS_HANDLE, EBADF },
{ ERROR_NEGATIVE_SEEK, EINVAL },
{ ERROR_SEEK_ON_DEVICE, EACCES },
{ ERROR_DIR_NOT_EMPTY, ENOTEMPTY },
{ ERROR_NOT_LOCKED, EACCES },
{ ERROR_BAD_PATHNAME, ENOENT },
{ ERROR_MAX_THRDS_REACHED, EAGAIN },
{ ERROR_LOCK_FAILED, EACCES },
{ ERROR_ALREADY_EXISTS, EEXIST },
{ ERROR_FILENAME_EXCED_RANGE, ENOENT },
{ ERROR_NESTING_NOT_ALLOWED, EAGAIN },
{ ERROR_NOT_ENOUGH_QUOTA, ENOMEM } };
static void _dosmaperr(unsigned long e)
{
int i;
if(e == 0)
{
errno = 0;
return;
}
for(i = 0; i < lengthof(doserrors); i++)
{
if(doserrors[i].winerr == e)
{
errno = doserrors[i].doserr;
// #ifndef FRONTEND
// ereport(DEBUG5,
// (errmsg_internal("mapped win32 error code %lu to %d",
// e, errno)));
// #elif FRONTEND_DEBUG
// fprintf(stderr, _("mapped win32 error code %lu to %d"), e, errno);
// #endif
return;
}
}
// #ifndef FRONTEND
// ereport(LOG,
// (errmsg_internal("unrecognized win32 error code: %lu",
// e)));
// #else
// fprintf(stderr, _("unrecognized win32 error code: %lu"), e);
// #endif
errno = EINVAL;
return;
}
/* This code works on:
* univel
* solaris_i386
* sco
* solaris_sparc
* svr4
* hpux 9.*
* win32
* which currently is all the supported platforms that don't have a
* native version of getrusage(). So, if configure decides to compile
* this file at all, we just use this version unconditionally.
*/
int getrusage(int who, struct rusage *rusage)
{
#ifdef __WIN32__
FILETIME starttime;
FILETIME exittime;
FILETIME kerneltime;
FILETIME usertime;
ULARGE_INTEGER li;
if(who != RUSAGE_SELF)
{
/* Only RUSAGE_SELF is supported in this implementation for now */
errno = EINVAL;
return -1;
}
if(rusage == (struct rusage *)NULL)
{
errno = EFAULT;
return -1;
}
memset(rusage, 0, sizeof(struct rusage));
if(GetProcessTimes(GetCurrentProcess(), &starttime, &exittime, &kerneltime, &usertime) == 0)
{
_dosmaperr(GetLastError());
return -1;
}
/* Convert FILETIMEs (0.1 us) to struct timeval */
memcpy(&li, &kerneltime, sizeof(FILETIME));
li.QuadPart /= 10L; /* Convert to microseconds */
rusage->ru_stime.tv_sec = li.QuadPart / 1000000L;
rusage->ru_stime.tv_usec = li.QuadPart % 1000000L;
memcpy(&li, &usertime, sizeof(FILETIME));
li.QuadPart /= 10L; /* Convert to microseconds */
rusage->ru_utime.tv_sec = li.QuadPart / 1000000L;
rusage->ru_utime.tv_usec = li.QuadPart % 1000000L;
#else /* all but __WIN32__ */
struct tms tms;
int tick_rate = CLK_TCK; /* ticks per second */
clock_t u, s;
if(rusage == (struct rusage *)NULL)
{
errno = EFAULT;
return -1;
}
if(times(&tms) < 0)
{
/* errno set by times */
return -1;
}
switch(who)
{
case RUSAGE_SELF:
u = tms.tms_utime;
s = tms.tms_stime;
break;
case RUSAGE_CHILDREN:
u = tms.tms_cutime;
s = tms.tms_cstime;
break;
default:
errno = EINVAL;
return -1;
}
#define TICK_TO_SEC(T, RATE) ((T) / (RATE))
#define TICK_TO_USEC(T, RATE) (((T) % (RATE)*1000000) / RATE)
rusage->ru_utime.tv_sec = TICK_TO_SEC(u, tick_rate);
rusage->ru_utime.tv_usec = TICK_TO_USEC(u, tick_rate);
rusage->ru_stime.tv_sec = TICK_TO_SEC(s, tick_rate);
rusage->ru_stime.tv_usec = TICK_TO_USEC(u, tick_rate);
#endif /* __WIN32__ */
return 0;
}
// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
// vim: shiftwidth=2 expandtab tabstop=2 cindent
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
Computing file changes ...