2000-08-02 23:54:04 +02:00
|
|
|
// posix.cc -- Helper functions for POSIX-flavored OSs.
|
|
|
|
|
2006-03-09 19:47:54 +01:00
|
|
|
/* Copyright (C) 2000, 2001, 2002, 2006 Free Software Foundation
|
2000-08-02 23:54:04 +02:00
|
|
|
|
|
|
|
This file is part of libgcj.
|
|
|
|
|
|
|
|
This software is copyrighted work licensed under the terms of the
|
|
|
|
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "posix.h"
|
|
|
|
|
2002-04-07 13:27:00 +02:00
|
|
|
#include <stdlib.h>
|
2000-08-02 23:54:04 +02:00
|
|
|
#include <errno.h>
|
2002-02-07 19:59:52 +01:00
|
|
|
#include <signal.h>
|
2003-07-08 06:49:16 +02:00
|
|
|
#include <stdio.h>
|
2000-08-02 23:54:04 +02:00
|
|
|
|
2006-06-29 16:57:39 +02:00
|
|
|
#ifdef HAVE_DLFCN_H
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#endif
|
|
|
|
|
2001-02-13 19:44:51 +01:00
|
|
|
#include <jvm.h>
|
2006-06-29 16:57:39 +02:00
|
|
|
#include <java-stack.h>
|
2001-02-13 19:44:51 +01:00
|
|
|
#include <java/lang/Thread.h>
|
|
|
|
#include <java/io/InterruptedIOException.h>
|
2002-04-07 13:27:00 +02:00
|
|
|
#include <java/util/Properties.h>
|
2001-02-13 19:44:51 +01:00
|
|
|
|
2000-08-02 23:54:04 +02:00
|
|
|
#if defined (ECOS)
|
|
|
|
extern "C" unsigned long long _clock (void);
|
|
|
|
#endif
|
|
|
|
|
2003-03-10 20:45:30 +01:00
|
|
|
#if defined(HAVE_PROC_SELF_EXE)
|
|
|
|
static char exec_name[20];
|
|
|
|
// initialized in _Jv_platform_initialize()
|
|
|
|
#endif
|
|
|
|
|
|
|
|
const char *_Jv_ThisExecutable (void)
|
|
|
|
{
|
|
|
|
#if defined(DISABLE_MAIN_ARGS)
|
|
|
|
return "[Embedded App]";
|
|
|
|
#elif defined(HAVE_PROC_SELF_EXE)
|
|
|
|
return exec_name;
|
|
|
|
// initialized in _Jv_platform_initialize()
|
|
|
|
#else
|
2003-04-25 18:48:13 +02:00
|
|
|
return _Jv_GetSafeArg (0);
|
2003-03-10 20:45:30 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2000-08-02 23:54:04 +02:00
|
|
|
// gettimeofday implementation.
|
2002-03-08 02:03:56 +01:00
|
|
|
jlong
|
|
|
|
_Jv_platform_gettimeofday ()
|
2000-08-02 23:54:04 +02:00
|
|
|
{
|
|
|
|
#if defined (HAVE_GETTIMEOFDAY)
|
2002-03-08 02:03:56 +01:00
|
|
|
timeval tv;
|
|
|
|
gettimeofday (&tv, NULL);
|
2002-03-09 06:48:38 +01:00
|
|
|
return (tv.tv_sec * 1000LL) + (tv.tv_usec / 1000LL);
|
2000-08-02 23:54:04 +02:00
|
|
|
#elif defined (HAVE_TIME)
|
2002-03-09 06:48:38 +01:00
|
|
|
return time (NULL) * 1000LL;
|
2000-08-02 23:54:04 +02:00
|
|
|
#elif defined (HAVE_FTIME)
|
|
|
|
struct timeb t;
|
|
|
|
ftime (&t);
|
2002-03-09 06:48:38 +01:00
|
|
|
return (t.time * 1000LL) + t.millitm;
|
2000-08-02 23:54:04 +02:00
|
|
|
#elif defined (ECOS)
|
|
|
|
// FIXME.
|
2002-03-08 02:03:56 +01:00
|
|
|
return _clock();
|
2000-08-02 23:54:04 +02:00
|
|
|
#else
|
|
|
|
// In the absence of any function, time remains forever fixed.
|
2002-03-08 02:03:56 +01:00
|
|
|
return 23000;
|
2000-08-02 23:54:04 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2006-03-09 19:47:54 +01:00
|
|
|
jlong
|
|
|
|
_Jv_platform_nanotime ()
|
|
|
|
{
|
|
|
|
#ifdef HAVE_CLOCK_GETTIME
|
|
|
|
struct timespec now;
|
2006-03-31 22:38:55 +02:00
|
|
|
clockid_t id;
|
2006-03-29 17:22:30 +02:00
|
|
|
#ifdef CLOCK_MONOTONIC
|
|
|
|
id = CLOCK_MONOTONIC;
|
|
|
|
#elif defined (CLOCK_HIGHRES)
|
|
|
|
id = CLOCK_HIGHRES;
|
|
|
|
#else
|
|
|
|
id = CLOCK_REALTIME;
|
|
|
|
#endif
|
|
|
|
if (clock_gettime (id, &now) == 0)
|
2006-03-09 19:47:54 +01:00
|
|
|
{
|
|
|
|
jlong result = (jlong) now.tv_sec;
|
2006-09-14 03:17:31 +02:00
|
|
|
result = result * 1000000000LL + now.tv_nsec;
|
2006-03-09 19:47:54 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
// clock_gettime failed, but we can fall through.
|
|
|
|
#endif // HAVE_CLOCK_GETTIME
|
2006-09-14 03:17:31 +02:00
|
|
|
#if defined (HAVE_GETTIMEOFDAY)
|
|
|
|
{
|
|
|
|
timeval tv;
|
|
|
|
gettimeofday (&tv, NULL);
|
|
|
|
return (tv.tv_sec * 1000000000LL) + tv.tv_usec * 1000LL;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
return _Jv_platform_gettimeofday () * 1000000LL;
|
|
|
|
#endif
|
2006-03-09 19:47:54 +01:00
|
|
|
}
|
|
|
|
|
2002-02-07 19:59:52 +01:00
|
|
|
// Platform-specific VM initialization.
|
|
|
|
void
|
|
|
|
_Jv_platform_initialize (void)
|
|
|
|
{
|
|
|
|
#if defined (HAVE_SIGACTION)
|
|
|
|
// We only want this on POSIX systems.
|
|
|
|
struct sigaction act;
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
|
|
sigemptyset (&act.sa_mask);
|
|
|
|
act.sa_flags = 0;
|
|
|
|
sigaction (SIGPIPE, &act, NULL);
|
|
|
|
#else
|
|
|
|
signal (SIGPIPE, SIG_IGN);
|
|
|
|
#endif
|
2003-03-10 20:45:30 +01:00
|
|
|
|
|
|
|
#if defined (HAVE_PROC_SELF_EXE)
|
|
|
|
// Compute our executable name
|
|
|
|
sprintf (exec_name, "/proc/%d/exe", getpid ());
|
|
|
|
#endif
|
2002-02-07 19:59:52 +01:00
|
|
|
}
|
|
|
|
|
2002-04-07 13:27:00 +02:00
|
|
|
// Set platform-specific System properties.
|
|
|
|
void
|
|
|
|
_Jv_platform_initProperties (java::util::Properties* newprops)
|
|
|
|
{
|
|
|
|
// A convenience define.
|
|
|
|
#define SET(Prop,Val) \
|
|
|
|
newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
|
|
|
|
|
|
|
|
SET ("file.separator", "/");
|
|
|
|
SET ("path.separator", ":");
|
|
|
|
SET ("line.separator", "\n");
|
2006-02-09 02:35:33 +01:00
|
|
|
const char *tmpdir = ::getenv("TMPDIR");
|
2002-04-07 13:27:00 +02:00
|
|
|
if (! tmpdir)
|
|
|
|
tmpdir = "/tmp";
|
|
|
|
SET ("java.io.tmpdir", tmpdir);
|
re PR libgcj/17002 (java.util.TimeZone.getDefault() is broken)
libjava/
PR libgcj/17002
PR classpath/28550
* java/util/VMTimeZone.java (getDefaultTimeZoneId): To read
/etc/localtime, use ZoneInfo.readTZFile instead of
VMTimeZone.readtzFile. Get better timezone name for /etc/localtime,
either if it is a symlink or through /etc/sysconfig/clock.
(readSysconfigClockFile): New static method.
(readtzFile): Removed.
* java/lang/System.java: Add gnu.java.util.zoneinfo.dir to comments.
* posix.cc (_Jv_platform_initProperties): Set
gnu.java.util.zoneinfo.dir.
* sources.am (gnu_java_util_source_files): Add
classpath/gnu/java/util/ZoneInfo.java.
* Makefile.in: Regenerated.
* java/util/VMTimeZone.h: Regenerated.
* java/util/TimeZone.h: Regenerated.
* gnu/java/util/ZoneInfo.h: Generated.
libjava/classpath/
* java/util/Date.java (parse): Properly parse 09:01:02 as
hours/minutes/seconds, not as hours/minutes/year.
* java/util/SimpleTimeZone.java (SimpleTimeZone): Simplify
{start,end}TimeMode constructor by calling shorter constructor,
set {start,end}TimeMode fields after it returns.
(setStartRule): Don't adjust startTime into WALL_TIME. Set
startTimeMode to WALL_TIME.
(endStartRule): Similarly.
(getOffset): Handle properly millis + dstOffset overflowing into the
next day. Adjust startTime resp. endTime based on startTimeMode
resp. endTimeMode.
* java/util/TimeZone.java (zoneinfo_dir, availableIDs, aliases0): New
static fields.
(timezones): Remove synchronized keyword. Set zoneinfo_dir.
If non-null, set up aliases0 and don't put anything into
timezones0.
(defaultZone): Call getTimeZone instead of timezones().get.
(getDefaultTimeZone): Fix parsing of EST5 or EST5EDT6. Use
getTimeZoneInternal instead of timezones().get.
(parseTime): Parse correctly hour:minute.
(getTimeZoneInternal): New private method.
(getTimeZone): Do the custom ID checking first, canonicalize
ID for custom IDs as required by documentation. Call
getTimeZoneInternal to handle the rest.
(getAvailableIDs(int)): Add locking. Handle zoneinfo_dir != null.
(getAvailableIDs(File,String,ArrayList)): New private method.
(getAvailableIDs()): Add locking. Handle zoneinfo_dir != null.
* gnu/java/util/ZoneInfo.java: New file.
From-SVN: r122229
2007-02-22 17:04:55 +01:00
|
|
|
const char *zoneinfodir = ::getenv("TZDATA");
|
|
|
|
if (! zoneinfodir)
|
|
|
|
zoneinfodir = "/usr/share/zoneinfo";
|
|
|
|
SET ("gnu.java.util.zoneinfo.dir", zoneinfodir);
|
2002-04-07 13:27:00 +02:00
|
|
|
}
|
|
|
|
|
2002-03-08 17:31:28 +01:00
|
|
|
static inline void
|
|
|
|
internal_gettimeofday (struct timeval *result)
|
|
|
|
{
|
|
|
|
#if defined (HAVE_GETTIMEOFDAY)
|
|
|
|
gettimeofday (result, NULL);
|
|
|
|
#else
|
|
|
|
jlong val = _Jv_platform_gettimeofday ();
|
|
|
|
result->tv_sec = val / 1000;
|
|
|
|
result->tv_usec = (val % 1000) * 1000;
|
|
|
|
#endif /* HAVE_GETTIMEOFDAY */
|
|
|
|
}
|
|
|
|
|
2000-08-02 23:54:04 +02:00
|
|
|
// A wrapper for select() which ignores EINTR.
|
|
|
|
int
|
|
|
|
_Jv_select (int n, fd_set *readfds, fd_set *writefds,
|
|
|
|
fd_set *exceptfds, struct timeval *timeout)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_SELECT
|
|
|
|
// If we have a timeout, compute the absolute ending time.
|
|
|
|
struct timeval end, delay;
|
|
|
|
if (timeout)
|
|
|
|
{
|
2002-03-08 17:31:28 +01:00
|
|
|
internal_gettimeofday (&end);
|
2000-08-02 23:54:04 +02:00
|
|
|
end.tv_usec += timeout->tv_usec;
|
|
|
|
if (end.tv_usec >= 1000000)
|
|
|
|
{
|
|
|
|
++end.tv_sec;
|
|
|
|
end.tv_usec -= 1000000;
|
|
|
|
}
|
|
|
|
end.tv_sec += timeout->tv_sec;
|
|
|
|
delay = *timeout;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Placate compiler.
|
|
|
|
delay.tv_sec = delay.tv_usec = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
int r = select (n, readfds, writefds, exceptfds,
|
|
|
|
timeout ? &delay : NULL);
|
|
|
|
if (r != -1 || errno != EINTR)
|
|
|
|
return r;
|
|
|
|
|
2001-02-13 19:44:51 +01:00
|
|
|
// Here we know we got EINTR.
|
|
|
|
if (java::lang::Thread::interrupted ())
|
|
|
|
throw new java::io::InterruptedIOException (JvNewStringLatin1 ("select interrupted"));
|
|
|
|
|
2000-08-02 23:54:04 +02:00
|
|
|
struct timeval after;
|
|
|
|
if (timeout)
|
|
|
|
{
|
2002-03-08 17:31:28 +01:00
|
|
|
internal_gettimeofday (&after);
|
2000-08-02 23:54:04 +02:00
|
|
|
// Now compute new timeout argument.
|
|
|
|
delay.tv_usec = end.tv_usec - after.tv_usec;
|
|
|
|
delay.tv_sec = end.tv_sec - after.tv_sec;
|
|
|
|
if (delay.tv_usec < 0)
|
|
|
|
{
|
|
|
|
--delay.tv_sec;
|
|
|
|
delay.tv_usec += 1000000;
|
|
|
|
}
|
|
|
|
if (delay.tv_sec < 0)
|
|
|
|
{
|
|
|
|
// We assume that the user wants a valid select() call
|
|
|
|
// more than precise timing. So if we get a series of
|
|
|
|
// EINTR we just keep trying with delay 0 until we get a
|
|
|
|
// valid result.
|
|
|
|
delay.tv_sec = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else /* HAVE_SELECT */
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
2006-06-29 16:57:39 +02:00
|
|
|
|
|
|
|
// Given an address, find the object that defines it and the nearest
|
|
|
|
// defined symbol to that address. Returns 0 if no object defines this
|
|
|
|
// address.
|
|
|
|
int
|
2006-07-04 22:21:40 +02:00
|
|
|
_Jv_platform_dladdr (void *addr, _Jv_AddrInfo *info)
|
2006-06-29 16:57:39 +02:00
|
|
|
{
|
|
|
|
int ret_val = 0;
|
|
|
|
|
|
|
|
#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
|
|
|
|
Dl_info addr_info;
|
|
|
|
ret_val = dladdr (addr, &addr_info);
|
|
|
|
if (ret_val != 0)
|
|
|
|
{
|
|
|
|
info->file_name = addr_info.dli_fname;
|
|
|
|
info->base = addr_info.dli_fbase;
|
|
|
|
info->sym_name = addr_info.dli_sname;
|
|
|
|
info->sym_addr = addr_info.dli_saddr;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
info->file_name = NULL;
|
|
|
|
info->base = NULL;
|
|
|
|
info->sym_name = NULL;
|
|
|
|
info->sym_addr = NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|