The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / platform-openbsd.cc @ f230a1cf

History | View | Annotate | Download (11 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
// Platform specific code for OpenBSD and NetBSD goes here. For the POSIX
29
// comaptible parts the implementation is in platform-posix.cc.
30

    
31
#include <pthread.h>
32
#include <semaphore.h>
33
#include <signal.h>
34
#include <sys/time.h>
35
#include <sys/resource.h>
36
#include <sys/syscall.h>
37
#include <sys/types.h>
38
#include <stdlib.h>
39

    
40
#include <sys/types.h>  // mmap & munmap
41
#include <sys/mman.h>   // mmap & munmap
42
#include <sys/stat.h>   // open
43
#include <fcntl.h>      // open
44
#include <unistd.h>     // sysconf
45
#include <strings.h>    // index
46
#include <errno.h>
47
#include <stdarg.h>
48

    
49
#undef MAP_TYPE
50

    
51
#include "v8.h"
52

    
53
#include "platform.h"
54
#include "v8threads.h"
55
#include "vm-state-inl.h"
56

    
57

    
58
namespace v8 {
59
namespace internal {
60

    
61

    
62
const char* OS::LocalTimezone(double time) {
63
  if (std::isnan(time)) return "";
64
  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
65
  struct tm* t = localtime(&tv);
66
  if (NULL == t) return "";
67
  return t->tm_zone;
68
}
69

    
70

    
71
double OS::LocalTimeOffset() {
72
  time_t tv = time(NULL);
73
  struct tm* t = localtime(&tv);
74
  // tm_gmtoff includes any daylight savings offset, so subtract it.
75
  return static_cast<double>(t->tm_gmtoff * msPerSecond -
76
                             (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
77
}
78

    
79

    
80
void* OS::Allocate(const size_t requested,
81
                   size_t* allocated,
82
                   bool is_executable) {
83
  const size_t msize = RoundUp(requested, AllocateAlignment());
84
  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
85
  void* addr = OS::GetRandomMmapAddr();
86
  void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
87
  if (mbase == MAP_FAILED) {
88
    LOG(i::Isolate::Current(),
89
        StringEvent("OS::Allocate", "mmap failed"));
90
    return NULL;
91
  }
92
  *allocated = msize;
93
  return mbase;
94
}
95

    
96

    
97
class PosixMemoryMappedFile : public OS::MemoryMappedFile {
98
 public:
99
  PosixMemoryMappedFile(FILE* file, void* memory, int size)
100
    : file_(file), memory_(memory), size_(size) { }
101
  virtual ~PosixMemoryMappedFile();
102
  virtual void* memory() { return memory_; }
103
  virtual int size() { return size_; }
104
 private:
105
  FILE* file_;
106
  void* memory_;
107
  int size_;
108
};
109

    
110

    
111
OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
112
  FILE* file = fopen(name, "r+");
113
  if (file == NULL) return NULL;
114

    
115
  fseek(file, 0, SEEK_END);
116
  int size = ftell(file);
117

    
118
  void* memory =
119
      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
120
  return new PosixMemoryMappedFile(file, memory, size);
121
}
122

    
123

    
124
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
125
    void* initial) {
126
  FILE* file = fopen(name, "w+");
127
  if (file == NULL) return NULL;
128
  int result = fwrite(initial, size, 1, file);
129
  if (result < 1) {
130
    fclose(file);
131
    return NULL;
132
  }
133
  void* memory =
134
      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
135
  return new PosixMemoryMappedFile(file, memory, size);
136
}
137

    
138

    
139
PosixMemoryMappedFile::~PosixMemoryMappedFile() {
140
  if (memory_) OS::Free(memory_, size_);
141
  fclose(file_);
142
}
143

    
144

    
145
void OS::LogSharedLibraryAddresses(Isolate* isolate) {
146
  // This function assumes that the layout of the file is as follows:
147
  // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
148
  // If we encounter an unexpected situation we abort scanning further entries.
149
  FILE* fp = fopen("/proc/self/maps", "r");
150
  if (fp == NULL) return;
151

    
152
  // Allocate enough room to be able to store a full file name.
153
  const int kLibNameLen = FILENAME_MAX + 1;
154
  char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
155

    
156
  // This loop will terminate once the scanning hits an EOF.
157
  while (true) {
158
    uintptr_t start, end;
159
    char attr_r, attr_w, attr_x, attr_p;
160
    // Parse the addresses and permission bits at the beginning of the line.
161
    if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
162
    if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
163

    
164
    int c;
165
    if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
166
      // Found a read-only executable entry. Skip characters until we reach
167
      // the beginning of the filename or the end of the line.
168
      do {
169
        c = getc(fp);
170
      } while ((c != EOF) && (c != '\n') && (c != '/'));
171
      if (c == EOF) break;  // EOF: Was unexpected, just exit.
172

    
173
      // Process the filename if found.
174
      if (c == '/') {
175
        ungetc(c, fp);  // Push the '/' back into the stream to be read below.
176

    
177
        // Read to the end of the line. Exit if the read fails.
178
        if (fgets(lib_name, kLibNameLen, fp) == NULL) break;
179

    
180
        // Drop the newline character read by fgets. We do not need to check
181
        // for a zero-length string because we know that we at least read the
182
        // '/' character.
183
        lib_name[strlen(lib_name) - 1] = '\0';
184
      } else {
185
        // No library name found, just record the raw address range.
186
        snprintf(lib_name, kLibNameLen,
187
                 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
188
      }
189
      LOG(isolate, SharedLibraryEvent(lib_name, start, end));
190
    } else {
191
      // Entry not describing executable data. Skip to end of line to set up
192
      // reading the next entry.
193
      do {
194
        c = getc(fp);
195
      } while ((c != EOF) && (c != '\n'));
196
      if (c == EOF) break;
197
    }
198
  }
199
  free(lib_name);
200
  fclose(fp);
201
}
202

    
203

    
204
void OS::SignalCodeMovingGC() {
205
  // Support for ll_prof.py.
206
  //
207
  // The Linux profiler built into the kernel logs all mmap's with
208
  // PROT_EXEC so that analysis tools can properly attribute ticks. We
209
  // do a mmap with a name known by ll_prof.py and immediately munmap
210
  // it. This injects a GC marker into the stream of events generated
211
  // by the kernel and allows us to synchronize V8 code log and the
212
  // kernel log.
213
  int size = sysconf(_SC_PAGESIZE);
214
  FILE* f = fopen(FLAG_gc_fake_mmap, "w+");
215
  if (f == NULL) {
216
    OS::PrintError("Failed to open %s\n", FLAG_gc_fake_mmap);
217
    OS::Abort();
218
  }
219
  void* addr = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_PRIVATE,
220
                    fileno(f), 0);
221
  ASSERT(addr != MAP_FAILED);
222
  OS::Free(addr, size);
223
  fclose(f);
224
}
225

    
226

    
227

    
228
// Constants used for mmap.
229
static const int kMmapFd = -1;
230
static const int kMmapFdOffset = 0;
231

    
232

    
233
VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
234

    
235

    
236
VirtualMemory::VirtualMemory(size_t size)
237
    : address_(ReserveRegion(size)), size_(size) { }
238

    
239

    
240
VirtualMemory::VirtualMemory(size_t size, size_t alignment)
241
    : address_(NULL), size_(0) {
242
  ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
243
  size_t request_size = RoundUp(size + alignment,
244
                                static_cast<intptr_t>(OS::AllocateAlignment()));
245
  void* reservation = mmap(OS::GetRandomMmapAddr(),
246
                           request_size,
247
                           PROT_NONE,
248
                           MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
249
                           kMmapFd,
250
                           kMmapFdOffset);
251
  if (reservation == MAP_FAILED) return;
252

    
253
  Address base = static_cast<Address>(reservation);
254
  Address aligned_base = RoundUp(base, alignment);
255
  ASSERT_LE(base, aligned_base);
256

    
257
  // Unmap extra memory reserved before and after the desired block.
258
  if (aligned_base != base) {
259
    size_t prefix_size = static_cast<size_t>(aligned_base - base);
260
    OS::Free(base, prefix_size);
261
    request_size -= prefix_size;
262
  }
263

    
264
  size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
265
  ASSERT_LE(aligned_size, request_size);
266

    
267
  if (aligned_size != request_size) {
268
    size_t suffix_size = request_size - aligned_size;
269
    OS::Free(aligned_base + aligned_size, suffix_size);
270
    request_size -= suffix_size;
271
  }
272

    
273
  ASSERT(aligned_size == request_size);
274

    
275
  address_ = static_cast<void*>(aligned_base);
276
  size_ = aligned_size;
277
}
278

    
279

    
280
VirtualMemory::~VirtualMemory() {
281
  if (IsReserved()) {
282
    bool result = ReleaseRegion(address(), size());
283
    ASSERT(result);
284
    USE(result);
285
  }
286
}
287

    
288

    
289
bool VirtualMemory::IsReserved() {
290
  return address_ != NULL;
291
}
292

    
293

    
294
void VirtualMemory::Reset() {
295
  address_ = NULL;
296
  size_ = 0;
297
}
298

    
299

    
300
bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
301
  return CommitRegion(address, size, is_executable);
302
}
303

    
304

    
305
bool VirtualMemory::Uncommit(void* address, size_t size) {
306
  return UncommitRegion(address, size);
307
}
308

    
309

    
310
bool VirtualMemory::Guard(void* address) {
311
  OS::Guard(address, OS::CommitPageSize());
312
  return true;
313
}
314

    
315

    
316
void* VirtualMemory::ReserveRegion(size_t size) {
317
  void* result = mmap(OS::GetRandomMmapAddr(),
318
                      size,
319
                      PROT_NONE,
320
                      MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
321
                      kMmapFd,
322
                      kMmapFdOffset);
323

    
324
  if (result == MAP_FAILED) return NULL;
325

    
326
  return result;
327
}
328

    
329

    
330
bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
331
  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
332
  if (MAP_FAILED == mmap(base,
333
                         size,
334
                         prot,
335
                         MAP_PRIVATE | MAP_ANON | MAP_FIXED,
336
                         kMmapFd,
337
                         kMmapFdOffset)) {
338
    return false;
339
  }
340
  return true;
341
}
342

    
343

    
344
bool VirtualMemory::UncommitRegion(void* base, size_t size) {
345
  return mmap(base,
346
              size,
347
              PROT_NONE,
348
              MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED,
349
              kMmapFd,
350
              kMmapFdOffset) != MAP_FAILED;
351
}
352

    
353

    
354
bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
355
  return munmap(base, size) == 0;
356
}
357

    
358

    
359
bool VirtualMemory::HasLazyCommits() {
360
  // TODO(alph): implement for the platform.
361
  return false;
362
}
363

    
364
} }  // namespace v8::internal