| // Copyright 2012 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Platform-specific code for FreeBSD goes here. For the POSIX-compatible |
| // parts, the implementation is in platform-posix.cc. |
| |
| #include <pthread.h> |
| #include <pthread_np.h> |
| #include <semaphore.h> |
| #include <signal.h> |
| #include <stdlib.h> |
| #include <sys/resource.h> |
| #include <sys/time.h> |
| #include <sys/types.h> |
| #include <sys/ucontext.h> |
| #include <sys/user.h> |
| |
| #include <sys/fcntl.h> // open |
| #include <sys/mman.h> // mmap & munmap |
| #include <sys/stat.h> // open |
| #include <sys/sysctl.h> |
| #include <unistd.h> // getpagesize |
| // If you don't have execinfo.h then you need devel/libexecinfo from ports. |
| #include <errno.h> |
| #include <limits.h> |
| #include <stdarg.h> |
| #include <strings.h> // index |
| |
| #include <cmath> |
| |
| #undef MAP_TYPE |
| |
| #include "src/base/macros.h" |
| #include "src/base/platform/platform-posix-time.h" |
| #include "src/base/platform/platform-posix.h" |
| #include "src/base/platform/platform.h" |
| |
| namespace v8 { |
| namespace base { |
| |
| TimezoneCache* OS::CreateTimezoneCache() { |
| return new PosixDefaultTimezoneCache(); |
| } |
| |
| static unsigned StringToLong(char* buffer) { |
| return static_cast<unsigned>(strtol(buffer, nullptr, 16)); // NOLINT |
| } |
| |
| std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { |
| std::vector<SharedLibraryAddress> result; |
| int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; |
| size_t miblen = sizeof(mib) / sizeof(mib[0]); |
| size_t buffer_size; |
| if (sysctl(mib, miblen, nullptr, &buffer_size, nullptr, 0) == 0) { |
| // Overallocate the buffer by 1/3 to account for concurrent |
| // kinfo_vmentry change. 1/3 is an arbitrary constant that |
| // works in practice. |
| buffer_size = buffer_size * 4 / 3; |
| std::vector<char> buffer(buffer_size); |
| int ret = sysctl(mib, miblen, buffer.data(), &buffer_size, nullptr, 0); |
| |
| if (ret == 0 || (ret == -1 && errno == ENOMEM)) { |
| char* start = buffer.data(); |
| char* end = start + buffer_size; |
| |
| while (start < end) { |
| struct kinfo_vmentry* map = |
| reinterpret_cast<struct kinfo_vmentry*>(start); |
| const size_t ssize = map->kve_structsize; |
| char* path = map->kve_path; |
| |
| CHECK_NE(0, ssize); |
| |
| if ((map->kve_protection & KVME_PROT_READ) != 0 && |
| (map->kve_protection & KVME_PROT_EXEC) != 0 && path[0] != '\0') { |
| char* sep = strrchr(path, '/'); |
| std::string lib_name; |
| if (sep != nullptr) { |
| lib_name = std::string(++sep); |
| } else { |
| lib_name = std::string(path); |
| } |
| result.push_back(SharedLibraryAddress( |
| lib_name, reinterpret_cast<uintptr_t>(map->kve_start), |
| reinterpret_cast<uintptr_t>(map->kve_end))); |
| } |
| |
| start += ssize; |
| } |
| } |
| } |
| return result; |
| } |
| |
| void OS::SignalCodeMovingGC() {} |
| |
| void OS::AdjustSchedulingParams() {} |
| |
| // static |
| Stack::StackSlot Stack::GetStackStart() { |
| pthread_attr_t attr; |
| int error; |
| pthread_attr_init(&attr); |
| error = pthread_attr_get_np(pthread_self(), &attr); |
| if (!error) { |
| void* base; |
| size_t size; |
| error = pthread_attr_getstack(&attr, &base, &size); |
| CHECK(!error); |
| pthread_attr_destroy(&attr); |
| return reinterpret_cast<uint8_t*>(base) + size; |
| } |
| pthread_attr_destroy(&attr); |
| return nullptr; |
| } |
| |
| } // namespace base |
| } // namespace v8 |