v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
platform-aix.cc
Go to the documentation of this file.
1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Platform specific code for AIX goes here. For the POSIX comaptible parts
6// the implementation is in platform-posix.cc.
7
8#include <pthread.h>
9#include <semaphore.h>
10#include <signal.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <sys/resource.h>
14#include <sys/time.h>
15#include <sys/ucontext.h>
16
17#include <errno.h>
18#include <fcntl.h> // open
19#include <limits.h>
20#include <stdarg.h>
21#include <strings.h> // index
22#include <sys/mman.h> // mmap & munmap
23#include <sys/stat.h> // open
24#include <sys/types.h> // mmap & munmap
25#include <unistd.h> // getpagesize
26
27#include <cmath>
28
29#undef MAP_TYPE
30
31#include "src/base/macros.h"
34
35namespace v8 {
36namespace base {
37
38
39int64_t get_gmt_offset(const tm& localtm) {
40 // replacement for tm->tm_gmtoff field in glibc
41 // returns seconds east of UTC, taking DST into account
42 struct timeval tv;
43 struct timezone tz;
44 int ret_code = gettimeofday(&tv, &tz);
45 // 0 = success, -1 = failure
46 DCHECK_NE(ret_code, -1);
47 if (ret_code == -1) {
48 return 0;
49 }
50 return (-tz.tz_minuteswest * 60) + (localtm.tm_isdst > 0 ? 3600 : 0);
51}
52
54 const char* LocalTimezone(double time) override;
55
56 double LocalTimeOffset(double time_ms, bool is_utc) override;
57
58 ~AIXTimezoneCache() override {}
59};
60
61const char* AIXTimezoneCache::LocalTimezone(double time_ms) {
62 if (std::isnan(time_ms)) return "";
63 time_t tv = static_cast<time_t>(floor(time_ms / msPerSecond));
64 struct tm tm;
65 struct tm* t = localtime_r(&tv, &tm);
66 if (nullptr == t) return "";
67 return tzname[0]; // The location of the timezone string on AIX.
68}
69
70double AIXTimezoneCache::LocalTimeOffset(double time_ms, bool is_utc) {
71 // On AIX, struct tm does not contain a tm_gmtoff field, use get_gmt_offset
72 // helper function
73 time_t utc = time(nullptr);
74 DCHECK_NE(utc, -1);
75 struct tm tm;
76 struct tm* loc = localtime_r(&utc, &tm);
77 DCHECK_NOT_NULL(loc);
78 return static_cast<double>(get_gmt_offset(*loc) * msPerSecond -
79 (loc->tm_isdst > 0 ? 3600 * msPerSecond : 0));
80}
81
83
84static unsigned StringToLong(char* buffer) {
85 return static_cast<unsigned>(strtol(buffer, nullptr, 16));
86}
87
88std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
89 std::vector<SharedLibraryAddress> result;
90 static const int MAP_LENGTH = 1024;
91 int fd = open("/proc/self/maps", O_RDONLY);
92 if (fd < 0) return result;
93 while (true) {
94 char addr_buffer[11];
95 addr_buffer[0] = '0';
96 addr_buffer[1] = 'x';
97 addr_buffer[10] = 0;
98 ssize_t rc = read(fd, addr_buffer + 2, 8);
99 if (rc < 8) break;
100 unsigned start = StringToLong(addr_buffer);
101 rc = read(fd, addr_buffer + 2, 1);
102 if (rc < 1) break;
103 if (addr_buffer[2] != '-') break;
104 rc = read(fd, addr_buffer + 2, 8);
105 if (rc < 8) break;
106 unsigned end = StringToLong(addr_buffer);
107 char buffer[MAP_LENGTH];
108 int bytes_read = -1;
109 do {
110 bytes_read++;
111 if (bytes_read >= MAP_LENGTH - 1) break;
112 rc = read(fd, buffer + bytes_read, 1);
113 if (rc < 1) break;
114 } while (buffer[bytes_read] != '\n');
115 buffer[bytes_read] = 0;
116 // Ignore mappings that are not executable.
117 if (buffer[3] != 'x') continue;
118 char* start_of_path = index(buffer, '/');
119 // There may be no filename in this line. Skip to next.
120 if (start_of_path == nullptr) continue;
121 buffer[bytes_read] = 0;
122 result.push_back(SharedLibraryAddress(start_of_path, start, end));
123 }
124 close(fd);
125 return result;
126}
127
129
131
132std::optional<OS::MemoryRange> OS::GetFirstFreeMemoryRangeWithin(
133 OS::Address boundary_start, OS::Address boundary_end, size_t minimum_size,
134 size_t alignment) {
135 return std::nullopt;
136}
137
138// static
140 // pthread_getthrds_np creates 3 values:
141 // __pi_stackaddr, __pi_stacksize, __pi_stackend
142
143 // higher address ----- __pi_stackend, stack base
144 //
145 // |
146 // | __pi_stacksize, stack grows downwards
147 // |
148 // V
149 //
150 // lower address ----- __pi_stackaddr, current sp
151
152 pthread_t tid = pthread_self();
153 struct __pthrdsinfo buf;
154 // clear buf
155 memset(&buf, 0, sizeof(buf));
156 char regbuf[1];
157 int regbufsize = sizeof(regbuf);
158 const int rc = pthread_getthrds_np(&tid, PTHRDSINFO_QUERY_ALL, &buf,
159 sizeof(buf), regbuf, &regbufsize);
160 CHECK(!rc);
161 if (buf.__pi_stackend == NULL || buf.__pi_stackaddr == NULL) {
162 return nullptr;
163 }
164 return reinterpret_cast<void*>(buf.__pi_stackend);
165}
166
167// static
168bool OS::DecommitPages(void* address, size_t size) {
169 // The difference between this implementation and the alternative under
170 // platform-posix.cc is that on AIX, calling mmap on a pre-designated address
171 // with MAP_FIXED will fail and return -1 unless the application has requested
172 // SPEC1170 compliant behaviour:
173 // https://www.ibm.com/docs/en/aix/7.3?topic=m-mmap-mmap64-subroutine
174 // Therefore in case if failure we need to unmap the address before trying to
175 // map it again. The downside is another thread could place another mapping at
176 // the same address after the munmap but before the mmap, therefore a CHECK is
177 // also added to assure the address is mapped successfully. Refer to the
178 // comments under https://crrev.com/c/3010195 for more details.
179#define MMAP() \
180 mmap(address, size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)
181 DCHECK_EQ(0, reinterpret_cast<uintptr_t>(address) % CommitPageSize());
182 DCHECK_EQ(0, size % CommitPageSize());
183 void* ptr;
184 // Try without mapping first.
185 ptr = MMAP();
186 if (ptr != address) {
187 DCHECK_EQ(ptr, MAP_FAILED);
188 // Returns 0 when successful.
189 if (munmap(address, size)) {
190 return false;
191 }
192 // Try again after unmap.
193 ptr = MMAP();
194 // If this check fails it's most likely due to a racing condition where
195 // another thread has mapped the same address right before we do.
196 // Since this could cause hard-to-debug issues, potentially with security
197 // impact, and we can't recover from this, the best we can do is abort the
198 // process.
199 CHECK_EQ(ptr, address);
200 }
201#undef MMAP
202 return true;
203}
204
205} // namespace base
206} // namespace v8
const char * LocalTimezone(double time) override
double LocalTimeOffset(double time_ms, bool is_utc) override
static void SignalCodeMovingGC()
static V8_WARN_UNUSED_RESULT bool DecommitPages(void *address, size_t size)
static size_t CommitPageSize()
static std::vector< SharedLibraryAddress > GetSharedLibraryAddresses()
uintptr_t Address
Definition platform.h:315
static TimezoneCache * CreateTimezoneCache()
static std::optional< MemoryRange > GetFirstFreeMemoryRangeWithin(Address boundary_start, Address boundary_end, size_t minimum_size, size_t alignment)
static void AdjustSchedulingParams()
static Stack::StackSlot ObtainCurrentThreadStackStart()
int start
int end
OptionalOpIndex index
TimeRecord time
ZoneVector< RpoNumber > & result
int64_t get_gmt_offset(const tm &localtm)
static unsigned StringToLong(char *buffer)
#define MMAP()
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define CHECK_EQ(lhs, rhs)
#define DCHECK_EQ(v1, v2)
Definition logging.h:485