posix.cc 5.7 KB
Newer Older
Tom Tromey committed
1 2
// posix.cc -- Helper functions for POSIX-flavored OSs.

3
/* Copyright (C) 2000, 2001, 2002, 2006  Free Software Foundation
Tom Tromey committed
4 5 6 7 8 9 10 11 12 13 14

   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"

15
#include <stdlib.h>
Tom Tromey committed
16
#include <errno.h>
17
#include <signal.h>
18
#include <stdio.h>
Tom Tromey committed
19

20 21 22 23
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif

24
#include <jvm.h>
25
#include <java-stack.h>
26 27
#include <java/lang/Thread.h>
#include <java/io/InterruptedIOException.h>
28
#include <java/util/Properties.h>
29

Tom Tromey committed
30 31 32 33
#if defined (ECOS)
extern "C" unsigned long long _clock (void);
#endif

Andrew Haley committed
34 35 36 37 38 39 40 41 42 43 44 45 46
#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
47
  return _Jv_GetSafeArg (0);
Andrew Haley committed
48 49 50
#endif
}

Tom Tromey committed
51
// gettimeofday implementation.
52 53
jlong
_Jv_platform_gettimeofday ()
Tom Tromey committed
54 55
{
#if defined (HAVE_GETTIMEOFDAY)
56 57
  timeval tv;
  gettimeofday (&tv, NULL);
58
  return (tv.tv_sec * 1000LL) + (tv.tv_usec / 1000LL);
Tom Tromey committed
59
#elif defined (HAVE_TIME)
60
  return time (NULL) * 1000LL;
Tom Tromey committed
61 62 63
#elif defined (HAVE_FTIME)
  struct timeb t;
  ftime (&t);
64
  return (t.time * 1000LL) + t.millitm;
Tom Tromey committed
65 66
#elif defined (ECOS)
  // FIXME.
67
  return _clock();
Tom Tromey committed
68 69
#else
  // In the absence of any function, time remains forever fixed.
70
  return 23000;
Tom Tromey committed
71 72 73
#endif
}

74 75 76 77 78
jlong
_Jv_platform_nanotime ()
{
#ifdef HAVE_CLOCK_GETTIME
  struct timespec now;
79
  clockid_t id;
80 81 82 83 84 85 86 87
#ifdef CLOCK_MONOTONIC
  id = CLOCK_MONOTONIC;
#elif defined (CLOCK_HIGHRES)
  id = CLOCK_HIGHRES;
#else
  id = CLOCK_REALTIME;
#endif
  if (clock_gettime (id, &now) == 0)
88 89
    {
      jlong result = (jlong) now.tv_sec;
90
      result = result * 1000000000LL + now.tv_nsec;
91 92 93 94
      return result;
    }
  // clock_gettime failed, but we can fall through.
#endif // HAVE_CLOCK_GETTIME
95 96 97 98 99 100 101 102 103
#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
104 105
}

106 107 108 109 110 111 112 113 114 115 116 117 118 119
// 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
Andrew Haley committed
120 121 122 123 124

#if defined (HAVE_PROC_SELF_EXE)
  // Compute our executable name
  sprintf (exec_name, "/proc/%d/exe", getpid ());
#endif
125 126
}

127 128 129 130 131 132 133 134 135 136 137
// 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");
138
  const char *tmpdir = ::getenv("TMPDIR");
139 140 141
  if (! tmpdir)
    tmpdir = "/tmp";
  SET ("java.io.tmpdir", tmpdir);
142 143 144 145
  const char *zoneinfodir = ::getenv("TZDATA");
  if (! zoneinfodir)
    zoneinfodir = "/usr/share/zoneinfo";
  SET ("gnu.java.util.zoneinfo.dir", zoneinfodir);
146 147
}

148 149 150 151 152 153 154 155 156 157 158 159
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 */
}

Tom Tromey committed
160 161 162 163 164 165 166 167 168 169
// 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)
    {
170
      internal_gettimeofday (&end);
Tom Tromey committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
      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;

193 194 195 196
      // Here we know we got EINTR.
      if (java::lang::Thread::interrupted ())
	throw new java::io::InterruptedIOException (JvNewStringLatin1 ("select interrupted"));

Tom Tromey committed
197 198 199
      struct timeval after;
      if (timeout)
	{
200
	  internal_gettimeofday (&after);
Tom Tromey committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
	  // 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
}
223 224 225 226 227

// 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
228
_Jv_platform_dladdr (void *addr, _Jv_AddrInfo *info)
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
{
  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;
}