OSDN Git Service

PR target/49461
[pf3gnuchains/gcc-fork.git] / libjava / posix.cc
1 // posix.cc -- Helper functions for POSIX-flavored OSs.
2
3 /* Copyright (C) 2000, 2001, 2002, 2006  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12
13 #include "posix.h"
14
15 #include <stdlib.h>
16 #include <errno.h>
17 #include <signal.h>
18 #include <stdio.h>
19
20 #ifdef HAVE_DLFCN_H
21 #include <dlfcn.h>
22 #endif
23
24 #include <jvm.h>
25 #include <java-stack.h>
26 #include <java/lang/Thread.h>
27 #include <java/io/InterruptedIOException.h>
28 #include <java/util/Properties.h>
29
30 #if defined (ECOS)
31 extern "C" unsigned long long _clock (void);
32 #endif
33
34 #if defined(HAVE_PROC_SELF_EXE)
35 static char exec_name[20];
36   // initialized in _Jv_platform_initialize()
37 #endif
38
39 const char *_Jv_ThisExecutable (void)
40 {
41 #if defined(DISABLE_MAIN_ARGS)
42   return "[Embedded App]";
43 #elif defined(HAVE_PROC_SELF_EXE)
44   return exec_name;
45     // initialized in _Jv_platform_initialize()
46 #else
47   return _Jv_GetSafeArg (0);
48 #endif
49 }
50
51 // gettimeofday implementation.
52 jlong
53 _Jv_platform_gettimeofday ()
54 {
55 #if defined (HAVE_GETTIMEOFDAY)
56   timeval tv;
57   gettimeofday (&tv, NULL);
58   return (tv.tv_sec * 1000LL) + (tv.tv_usec / 1000LL);
59 #elif defined (HAVE_TIME)
60   return time (NULL) * 1000LL;
61 #elif defined (HAVE_FTIME)
62   struct timeb t;
63   ftime (&t);
64   return (t.time * 1000LL) + t.millitm;
65 #elif defined (ECOS)
66   // FIXME.
67   return _clock();
68 #else
69   // In the absence of any function, time remains forever fixed.
70   return 23000;
71 #endif
72 }
73
74 jlong
75 _Jv_platform_nanotime ()
76 {
77 #ifdef HAVE_CLOCK_GETTIME
78   struct timespec now;
79   clockid_t id;
80 #ifdef CLOCK_MONOTONIC
81   id = CLOCK_MONOTONIC;
82 #elif defined (CLOCK_HIGHRES)
83   id = CLOCK_HIGHRES;
84 #else
85   id = CLOCK_REALTIME;
86 #endif
87   if (clock_gettime (id, &now) == 0)
88     {
89       jlong result = (jlong) now.tv_sec;
90       result = result * 1000000000LL + now.tv_nsec;
91       return result;
92     }
93   // clock_gettime failed, but we can fall through.
94 #endif // HAVE_CLOCK_GETTIME
95 #if defined (HAVE_GETTIMEOFDAY)
96  {
97    timeval tv;
98    gettimeofday (&tv, NULL);
99    return (tv.tv_sec * 1000000000LL) + tv.tv_usec * 1000LL;
100  }
101 #else
102   return _Jv_platform_gettimeofday () * 1000000LL;
103 #endif
104 }
105
106 // Platform-specific VM initialization.
107 void
108 _Jv_platform_initialize (void)
109 {
110 #if defined (HAVE_SIGACTION)
111   // We only want this on POSIX systems.
112   struct sigaction act;
113   act.sa_handler = SIG_IGN;
114   sigemptyset (&act.sa_mask);
115   act.sa_flags = 0;
116   sigaction (SIGPIPE, &act, NULL);
117 #else
118   signal (SIGPIPE, SIG_IGN);
119 #endif
120
121 #if defined (HAVE_PROC_SELF_EXE)
122   // Compute our executable name
123   sprintf (exec_name, "/proc/%d/exe", getpid ());
124 #endif
125 }
126
127 // Set platform-specific System properties.
128 void
129 _Jv_platform_initProperties (java::util::Properties* newprops)
130 {
131   // A convenience define.
132 #define SET(Prop,Val) \
133   newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
134
135   SET ("file.separator", "/");
136   SET ("path.separator", ":");
137   SET ("line.separator", "\n");
138   const char *tmpdir = ::getenv("TMPDIR");
139   if (! tmpdir)
140     tmpdir = "/tmp";
141   SET ("java.io.tmpdir", tmpdir);
142   const char *zoneinfodir = ::getenv("TZDATA");
143   if (! zoneinfodir)
144     zoneinfodir = "/usr/share/zoneinfo";
145   SET ("gnu.java.util.zoneinfo.dir", zoneinfodir);
146 }
147
148 static inline void
149 internal_gettimeofday (struct timeval *result)
150 {
151 #if defined (HAVE_GETTIMEOFDAY)
152   gettimeofday (result, NULL);
153 #else
154   jlong val = _Jv_platform_gettimeofday ();
155   result->tv_sec = val / 1000;
156   result->tv_usec = (val % 1000) * 1000;
157 #endif /* HAVE_GETTIMEOFDAY */
158 }
159
160 // A wrapper for select() which ignores EINTR.
161 int
162 _Jv_select (int n, fd_set *readfds, fd_set  *writefds,
163             fd_set *exceptfds, struct timeval *timeout)
164 {
165 #ifdef HAVE_SELECT
166   // If we have a timeout, compute the absolute ending time.
167   struct timeval end, delay;
168   if (timeout)
169     {
170       internal_gettimeofday (&end);
171       end.tv_usec += timeout->tv_usec;
172       if (end.tv_usec >= 1000000)
173         {
174           ++end.tv_sec;
175           end.tv_usec -= 1000000;
176         }
177       end.tv_sec += timeout->tv_sec;
178       delay = *timeout;
179     }
180   else
181     {
182       // Placate compiler.
183       delay.tv_sec = delay.tv_usec = 0;
184     }
185
186   while (1)
187     {
188       int r = select (n, readfds, writefds, exceptfds,
189                       timeout ? &delay : NULL);
190       if (r != -1 || errno != EINTR)
191         return r;
192
193       // Here we know we got EINTR.
194       if (java::lang::Thread::interrupted ())
195         throw new java::io::InterruptedIOException (JvNewStringLatin1 ("select interrupted"));
196
197       struct timeval after;
198       if (timeout)
199         {
200           internal_gettimeofday (&after);
201           // Now compute new timeout argument.
202           delay.tv_usec = end.tv_usec - after.tv_usec;
203           delay.tv_sec = end.tv_sec - after.tv_sec;
204           if (delay.tv_usec < 0)
205             {
206               --delay.tv_sec;
207               delay.tv_usec += 1000000;
208             }
209           if (delay.tv_sec < 0)
210             {
211               // We assume that the user wants a valid select() call
212               // more than precise timing.  So if we get a series of
213               // EINTR we just keep trying with delay 0 until we get a
214               // valid result.
215               delay.tv_sec = 0;
216             }
217         }
218     }
219 #else /* HAVE_SELECT */
220   return 0;
221 #endif
222 }
223
224 // Given an address, find the object that defines it and the nearest
225 // defined symbol to that address.  Returns 0 if no object defines this
226 // address.
227 int
228 _Jv_platform_dladdr (void *addr, _Jv_AddrInfo *info)
229 {
230   int ret_val = 0;
231
232 #if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
233   Dl_info addr_info;
234   ret_val = dladdr (addr, &addr_info);
235   if (ret_val != 0)
236     {
237       info->file_name = addr_info.dli_fname;
238       info->base = addr_info.dli_fbase;
239       info->sym_name = addr_info.dli_sname;
240       info->sym_addr = addr_info.dli_saddr;
241     }
242 #else
243   info->file_name = NULL;
244   info->base = NULL;
245   info->sym_name = NULL;
246   info->sym_addr = NULL;
247 #endif
248
249   return ret_val;
250 }