Update from https://crrev.com/320931 - Add IsFlat() definition to ui/gfx/transform - Change sky's uses of skia's FilterLevel to FilterQuality - Update cc_strip_video.patch R=jamesr@chromium.org Review URL: https://codereview.chromium.org/1013463003
diff --git a/BUILD.gn b/BUILD.gn index 69f366e..f103446 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -9,6 +9,10 @@ import("//build/config/android/rules.gni") } +config("base_implementation") { + defines = [ "BASE_IMPLEMENTATION" ] +} + source_set("base_paths") { sources = [ "base_paths.cc", @@ -34,7 +38,7 @@ ] } - defines = [ "BASE_IMPLEMENTATION" ] + configs += [ ":base_implementation" ] deps = [ "//base/memory", @@ -607,7 +611,7 @@ "sys_info_openbsd.cc", ] - defines = [ "BASE_IMPLEMENTATION" ] + configs += [ ":base_implementation" ] deps = [ ":base_static", @@ -630,7 +634,7 @@ # Allow more direct string conversions on platforms with native utf8 # strings if (is_mac || is_ios || is_chromeos) { - defines += [ "SYSTEM_NATIVE_UTF8" ] + defines = [ "SYSTEM_NATIVE_UTF8" ] } if (is_android) { @@ -758,12 +762,9 @@ configs += linux_configs all_dependent_configs = linux_configs - defines += [ "USE_SYMBOLIZE" ] - # These dependencies are not required on Android, and in the case # of xdg_mime must be excluded due to licensing restrictions. deps += [ - "//base/third_party/symbolize", "//base/third_party/xdg_mime", "//base/third_party/xdg_user_dirs", ] @@ -1135,7 +1136,6 @@ "mac/scoped_sending_event_unittest.mm", "md5_unittest.cc", "memory/aligned_memory_unittest.cc", - "memory/discardable_memory_unittest.cc", "memory/discardable_shared_memory_unittest.cc", "memory/linked_ptr_unittest.cc", "memory/ref_counted_memory_unittest.cc", @@ -1283,8 +1283,6 @@ "win/wrapped_window_proc_unittest.cc", ] - defines = [] - deps = [ ":base", ":i18n", @@ -1304,7 +1302,7 @@ # Allow more direct string conversions on platforms with native utf8 # strings if (is_mac || is_ios || is_chromeos) { - defines += [ "SYSTEM_NATIVE_UTF8" ] + defines = [ "SYSTEM_NATIVE_UTF8" ] } if (is_android) { @@ -1341,7 +1339,6 @@ if (is_linux) { sources -= [ "file_version_info_unittest.cc" ] sources += [ "nix/xdg_util_unittest.cc" ] - defines += [ "USE_SYMBOLIZE" ] if (use_glib) { configs += [ "//build/config/linux:glib" ] }
diff --git a/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index c7d8527..484c6bc 100644 --- a/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -5,6 +5,8 @@ package org.chromium.base.library_loader; import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.os.AsyncTask; import android.os.SystemClock; import android.util.Log; @@ -13,6 +15,13 @@ import org.chromium.base.JNINamespace; import org.chromium.base.TraceEvent; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.util.HashMap; import java.util.Locale; import javax.annotation.Nullable; @@ -87,6 +96,9 @@ // final (like now) or be protected in some way (volatile of synchronized). private final int mLibraryProcessType; + // Library -> Path it has been loaded from. + private final HashMap<String, String> mLoadedFrom; + /** * @param libraryProcessType the process the shared library is loaded in. refer to * LibraryProcessType for possible values. @@ -106,6 +118,7 @@ private LibraryLoader(int libraryProcessType) { mLibraryProcessType = libraryProcessType; + mLoadedFrom = new HashMap<String, String>(); } /** @@ -189,6 +202,68 @@ } } + private void prefetchLibraryToMemory(Context context, String library) { + String libFilePath = mLoadedFrom.get(library); + if (libFilePath == null) { + Log.i(TAG, "File path not found for " + library); + return; + } + String apkFilePath = context.getApplicationInfo().sourceDir; + if (libFilePath.equals(apkFilePath)) { + // TODO(lizeb): Make pre-faulting work with libraries loaded from the APK. + return; + } + try { + TraceEvent.begin("LibraryLoader.prefetchLibraryToMemory"); + File file = new File(libFilePath); + int size = (int) file.length(); + FileChannel channel = new RandomAccessFile(file, "r").getChannel(); + MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, size); + // TODO(lizeb): Figure out whether walking the entire library is really necessary. + // Page size is 4096 for all current Android architectures. + for (int index = 0; index < size; index += 4096) { + // Note: Testing shows that neither the Java compiler nor + // Dalvik/ART eliminates this loop. + buffer.get(index); + } + } catch (FileNotFoundException e) { + Log.w(TAG, "Library file not found: " + e); + } catch (IOException e) { + Log.w(TAG, "Impossible to map the file: " + e); + } finally { + TraceEvent.end("LibraryLoader.prefetchLibraryToMemory"); + } + } + + /** Prefetches the native libraries in a background thread. + * + * Launches an AsyncTask that maps the native libraries into memory, reads a + * part of each page from it, than unmaps it. This is done to warm up the + * page cache, turning hard page faults into soft ones. + * + * This is done this way, as testing shows that fadvise(FADV_WILLNEED) is + * detrimental to the startup time. + * + * @param context the application context. + */ + public void asyncPrefetchLibrariesToMemory(final Context context) { + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + // Note: AsyncTasks are executed in a low priority background + // thread, which is the desired behavior here since we don't + // want to interfere with the rest of the initialization. + for (String library : NativeLibraries.LIBRARIES) { + if (Linker.isChromiumLinkerLibrary(library)) { + continue; + } + prefetchLibraryToMemory(context, library); + } + return null; + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + // Invoke System.loadLibrary(...), triggering JNI_OnLoad in native code private void loadAlreadyLocked( Context context, boolean shouldDeleteFallbackLibraries) @@ -263,6 +338,7 @@ ? "using no map executable support fallback" : "directly") + " from within " + apkFilePath); + mLoadedFrom.put(library, apkFilePath); } else { // Unpack library fallback. Log.i(TAG, "Loading " + library @@ -272,10 +348,14 @@ context, library); fallbackWasUsed = true; Log.i(TAG, "Built fallback library " + libFilePath); + mLoadedFrom.put(library, libFilePath); } } else { // The library is in its own file. Log.i(TAG, "Loading " + library); + ApplicationInfo applicationInfo = context.getApplicationInfo(); + mLoadedFrom.put(library, new File(applicationInfo.nativeLibraryDir, + libFilePath).getAbsolutePath()); } // Load the library.
diff --git a/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/android/java/src/org/chromium/base/metrics/RecordHistogram.java index 08c314f..c1f6d36 100644 --- a/android/java/src/org/chromium/base/metrics/RecordHistogram.java +++ b/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -43,6 +43,16 @@ } /** + * Records a sample in a count histogram of the given name. This is the Java equivalent of the + * UMA_HISTOGRAM_COUNTS C++ macro. + * @param name name of the histogram + * @param sample sample to be recorded, at least 1 and at most 999999 + */ + public static void recordCountHistogram(String name, int sample) { + nativeRecordCountHistogram(name, System.identityHashCode(name), sample); + } + + /** * Records a sample in a histogram of times. Useful for recording short durations. This is the * Java equivalent of the UMA_HISTOGRAM_TIMES C++ macro. * @param name name of the histogram @@ -123,6 +133,7 @@ private static native void nativeRecordBooleanHistogram(String name, int key, boolean sample); private static native void nativeRecordEnumeratedHistogram( String name, int key, int sample, int boundary); + private static native void nativeRecordCountHistogram(String name, int key, int sample); private static native int nativeGetHistogramValueCountForTesting(String name, int sample); private static native void nativeInitialize();
diff --git a/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java b/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java index f0489d3..24af056 100644 --- a/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java +++ b/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
@@ -80,6 +80,47 @@ } /** + * Tests recording of count histograms. + */ + @SmallTest + public void testRecordCountHistogram() { + String histogram = "HelloWorld.CountMetric"; + HistogramDelta zeroCount = new HistogramDelta(histogram, 0); + HistogramDelta oneCount = new HistogramDelta(histogram, 1); + HistogramDelta twoCount = new HistogramDelta(histogram, 2); + HistogramDelta eightThousandCount = new HistogramDelta(histogram, 8000); + + assertEquals(0, zeroCount.getDelta()); + assertEquals(0, oneCount.getDelta()); + assertEquals(0, twoCount.getDelta()); + assertEquals(0, eightThousandCount.getDelta()); + + RecordHistogram.recordCountHistogram(histogram, 0); + assertEquals(1, zeroCount.getDelta()); + assertEquals(0, oneCount.getDelta()); + assertEquals(0, twoCount.getDelta()); + assertEquals(0, eightThousandCount.getDelta()); + + RecordHistogram.recordCountHistogram(histogram, 0); + assertEquals(2, zeroCount.getDelta()); + assertEquals(0, oneCount.getDelta()); + assertEquals(0, twoCount.getDelta()); + assertEquals(0, eightThousandCount.getDelta()); + + RecordHistogram.recordCountHistogram(histogram, 2); + assertEquals(2, zeroCount.getDelta()); + assertEquals(0, oneCount.getDelta()); + assertEquals(1, twoCount.getDelta()); + assertEquals(0, eightThousandCount.getDelta()); + + RecordHistogram.recordCountHistogram(histogram, 8000); + assertEquals(2, zeroCount.getDelta()); + assertEquals(0, oneCount.getDelta()); + assertEquals(1, twoCount.getDelta()); + assertEquals(1, eightThousandCount.getDelta()); + } + + /** * Tests recording of custom times histograms. */ @SmallTest
diff --git a/android/jni_android.cc b/android/jni_android.cc index a2de00a..1b715dc 100644 --- a/android/jni_android.cc +++ b/android/jni_android.cc
@@ -159,10 +159,25 @@ ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) { jclass clazz; if (!g_class_loader.Get().is_null()) { + // ClassLoader.loadClass expects a classname with components separated by + // dots instead of the slashes that JNIEnv::FindClass expects. The JNI + // generator generates names with slashes, so we have to replace them here. + // TODO(torne): move to an approach where we always use ClassLoader except + // for the special case of base::android::GetClassLoader(), and change the + // JNI generator to generate dot-separated names. http://crbug.com/461773 + size_t bufsize = strlen(class_name) + 1; + char dotted_name[bufsize]; + memmove(dotted_name, class_name, bufsize); + for (size_t i = 0; i < bufsize; ++i) { + if (dotted_name[i] == '/') { + dotted_name[i] = '.'; + } + } + clazz = static_cast<jclass>( env->CallObjectMethod(g_class_loader.Get().obj(), g_class_loader_load_class_method_id, - ConvertUTF8ToJavaString(env, class_name).obj())); + ConvertUTF8ToJavaString(env, dotted_name).obj())); } else { clazz = env->FindClass(class_name); }
diff --git a/android/record_histogram.cc b/android/record_histogram.cc index 0df0487..8b7f7bd 100644 --- a/android/record_histogram.cc +++ b/android/record_histogram.cc
@@ -60,6 +60,31 @@ return InsertLocked(j_histogram_key, histogram); } + HistogramBase* CountHistogram(JNIEnv* env, + jstring j_histogram_name, + jint j_histogram_key) { + // These values are based on the hard-coded constants in the + // UMA_HISTOGRAM_COUNTS macro from base/metrics/histogram_macros.h. + const int histogram_min = 1; + const int histogram_max = 1000000; + const int histogram_num_buckets = 50; + + DCHECK(j_histogram_name); + DCHECK(j_histogram_key); + HistogramBase* histogram = FindLocked(j_histogram_key); + if (histogram) { + DCHECK(histogram->HasConstructionArguments(histogram_min, histogram_max, + histogram_num_buckets)); + return histogram; + } + + std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); + histogram = Histogram::FactoryGet(histogram_name, histogram_min, + histogram_max, histogram_num_buckets, + HistogramBase::kUmaTargetedHistogramFlag); + return InsertLocked(j_histogram_key, histogram); + } + HistogramBase* CustomTimesHistogram(JNIEnv* env, jstring j_histogram_name, jint j_histogram_key, @@ -133,6 +158,18 @@ ->Add(sample); } +void RecordCountHistogram(JNIEnv* env, + jclass clazz, + jstring j_histogram_name, + jint j_histogram_key, + jint j_sample) { + int sample = static_cast<int>(j_sample); + + g_histograms.Get() + .CountHistogram(env, j_histogram_name, j_histogram_key) + ->Add(sample); +} + void RecordCustomTimesHistogramMilliseconds(JNIEnv* env, jclass clazz, jstring j_histogram_name,
diff --git a/base.gyp b/base.gyp index 5f640d8..c7a2481 100644 --- a/base.gyp +++ b/base.gyp
@@ -541,7 +541,6 @@ 'mac/scoped_sending_event_unittest.mm', 'md5_unittest.cc', 'memory/aligned_memory_unittest.cc', - 'memory/discardable_memory_unittest.cc', 'memory/discardable_shared_memory_unittest.cc', 'memory/linked_ptr_unittest.cc', 'memory/ref_counted_memory_unittest.cc', @@ -976,6 +975,8 @@ 'test/simple_test_tick_clock.h', 'test/task_runner_test_template.cc', 'test/task_runner_test_template.h', + 'test/test_discardable_memory_shmem_allocator.cc', + 'test/test_discardable_memory_shmem_allocator.h', 'test/test_file_util.cc', 'test/test_file_util.h', 'test/test_file_util_android.cc',
diff --git a/base.gypi b/base.gypi index ebc7e3e..13cba85 100644 --- a/base.gypi +++ b/base.gypi
@@ -318,14 +318,10 @@ 'memory/aligned_memory.h', 'memory/discardable_memory.cc', 'memory/discardable_memory.h', - 'memory/discardable_memory_android.cc', - 'memory/discardable_memory_linux.cc', - 'memory/discardable_memory_mac.cc', 'memory/discardable_memory_shmem.cc', 'memory/discardable_memory_shmem.h', 'memory/discardable_memory_shmem_allocator.cc', 'memory/discardable_memory_shmem_allocator.h', - 'memory/discardable_memory_win.cc', 'memory/discardable_shared_memory.cc', 'memory/discardable_shared_memory.h', 'memory/linked_ptr.h', @@ -889,7 +885,6 @@ ['include', '^mac/scoped_mach_vm\\.'], ['include', '^mac/scoped_nsautorelease_pool\\.'], ['include', '^mac/scoped_nsobject\\.'], - ['include', '^memory/discardable_memory_mac\\.'], ['include', '^message_loop/message_pump_mac\\.'], ['include', '^strings/sys_string_conversions_mac\\.'], ['include', '^threading/platform_thread_mac\\.'],
diff --git a/base_paths_win.cc b/base_paths_win.cc index 5bef310..4ecb59d 100644 --- a/base_paths_win.cc +++ b/base_paths_win.cc
@@ -6,8 +6,10 @@ #include <shlobj.h> #include "base/base_paths.h" +#include "base/environment.h" #include "base/files/file_path.h" #include "base/path_service.h" +#include "base/strings/utf_string_conversions.h" #include "base/win/scoped_co_mem.h" #include "base/win/windows_version.h" @@ -65,6 +67,27 @@ return false; cur = FilePath(system_buffer); break; + case base::DIR_PROGRAM_FILES6432: +#if !defined(_WIN64) + if (base::win::OSInfo::GetInstance()->wow64_status() == + base::win::OSInfo::WOW64_ENABLED) { + scoped_ptr<base::Environment> env(base::Environment::Create()); + std::string programfiles_w6432; + // 32-bit process running in WOW64 sets ProgramW6432 environment + // variable. See + // https://msdn.microsoft.com/library/windows/desktop/aa384274.aspx. + if (!env->GetVar("ProgramW6432", &programfiles_w6432)) + return false; + // GetVar returns UTF8 - convert back to Wide. + cur = FilePath(UTF8ToWide(programfiles_w6432)); + break; + } +#endif + if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, + SHGFP_TYPE_CURRENT, system_buffer))) + return false; + cur = FilePath(system_buffer); + break; case base::DIR_IE_INTERNET_CACHE: if (FAILED(SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL, SHGFP_TYPE_CURRENT, system_buffer)))
diff --git a/base_paths_win.h b/base_paths_win.h index 032de34..4ab6af1 100644 --- a/base_paths_win.h +++ b/base_paths_win.h
@@ -16,8 +16,14 @@ DIR_WINDOWS, // Windows directory, usually "c:\windows" DIR_SYSTEM, // Usually c:\windows\system32" - DIR_PROGRAM_FILES, // Usually c:\program files - DIR_PROGRAM_FILESX86, // Usually c:\program files or c:\program files (x86) + // 32-bit 32-bit on 64-bit 64-bit on 64-bit + // DIR_PROGRAM_FILES 1 2 1 + // DIR_PROGRAM_FILESX86 1 2 2 + // DIR_PROGRAM_FILES6432 1 1 1 + // 1 - C:\Program Files 2 - C:\Program Files (x86) + DIR_PROGRAM_FILES, // See table above. + DIR_PROGRAM_FILESX86, // See table above. + DIR_PROGRAM_FILES6432, // See table above. DIR_IE_INTERNET_CACHE, // Temporary Internet Files directory. DIR_COMMON_START_MENU, // Usually "C:\Documents and Settings\All Users\
diff --git a/compiler_specific.h b/compiler_specific.h index 47ca977..034cf06 100644 --- a/compiler_specific.h +++ b/compiler_specific.h
@@ -175,9 +175,17 @@ // Mark a memory region fully initialized. // Use this to annotate code that deliberately reads uninitialized data, for // example a GC scavenging root set pointers from the stack. -#define MSAN_UNPOISON(p, s) __msan_unpoison(p, s) +#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size) + +// Check a memory region for initializedness, as if it was being used here. +// If any bits are uninitialized, crash with an MSan report. +// Use this to sanitize data which MSan won't be able to track, e.g. before +// passing data to another process via shared memory. +#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) \ + __msan_check_mem_is_initialized(p, size) #else // MEMORY_SANITIZER -#define MSAN_UNPOISON(p, s) +#define MSAN_UNPOISON(p, size) +#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) #endif // MEMORY_SANITIZER // Macro useful for writing cross-platform function pointers.
diff --git a/debug/BUILD.gn b/debug/BUILD.gn index 37a0ab2..8ed623b 100644 --- a/debug/BUILD.gn +++ b/debug/BUILD.gn
@@ -55,7 +55,7 @@ ] } - defines = [ "BASE_IMPLEMENTATION" ] + configs += [ "//base:base_implementation" ] deps = [ "//base/memory", @@ -63,6 +63,7 @@ ] if (is_linux) { + defines = [ "USE_SYMBOLIZE" ] deps += [ "//base/third_party/symbolize" ] }
diff --git a/files/file_posix.cc b/files/file_posix.cc index 245ea6a..663f099 100644 --- a/files/file_posix.cc +++ b/files/file_posix.cc
@@ -471,12 +471,15 @@ case EROFS: case EPERM: return FILE_ERROR_ACCESS_DENIED; + case EBUSY: #if !defined(OS_NACL) // ETXTBSY not defined by NaCl. case ETXTBSY: - return FILE_ERROR_IN_USE; #endif + return FILE_ERROR_IN_USE; case EEXIST: return FILE_ERROR_EXISTS; + case EIO: + return FILE_ERROR_IO; case ENOENT: return FILE_ERROR_NOT_FOUND; case EMFILE:
diff --git a/ios/weak_nsobject.h b/ios/weak_nsobject.h index a1984bb..fc3a7c3 100644 --- a/ios/weak_nsobject.h +++ b/ios/weak_nsobject.h
@@ -117,7 +117,9 @@ } WeakNSProtocol& operator=(const WeakNSProtocol<NST>& that) { - DCHECK(checker_.CalledOnValidThread()); + // A WeakNSProtocol object can be copied on one thread and used on + // another. + checker_.DetachFromThread(); container_ = that.container_; return *this; }
diff --git a/ios/weak_nsobject_unittest.mm b/ios/weak_nsobject_unittest.mm index 325dcd2..81de993 100644 --- a/ios/weak_nsobject_unittest.mm +++ b/ios/weak_nsobject_unittest.mm
@@ -109,8 +109,12 @@ // the weak object on its original thread. void CopyWeakNSObjectAndPost(const WeakNSObject<NSMutableData>& weak_object, scoped_refptr<SingleThreadTaskRunner> runner) { - WeakNSObject<NSMutableData> weak_copy(weak_object); - runner->PostTask(FROM_HERE, Bind(&TouchWeakData, weak_copy)); + // Copy using constructor. + WeakNSObject<NSMutableData> weak_copy1(weak_object); + runner->PostTask(FROM_HERE, Bind(&TouchWeakData, weak_copy1)); + // Copy using assignment operator. + WeakNSObject<NSMutableData> weak_copy2 = weak_object; + runner->PostTask(FROM_HERE, Bind(&TouchWeakData, weak_copy2)); } // Tests that the weak object can be copied on a different thread. @@ -128,8 +132,8 @@ other_thread.Stop(); loop.RunUntilIdle(); - // Check that TouchWeakData was called. - EXPECT_EQ(1u, [data length]); + // Check that TouchWeakData was called and the object touched twice. + EXPECT_EQ(2u, [data length]); } } // namespace
diff --git a/json/BUILD.gn b/json/BUILD.gn index 0310ea9..70830c1 100644 --- a/json/BUILD.gn +++ b/json/BUILD.gn
@@ -27,7 +27,7 @@ ] } - defines = [ "BASE_IMPLEMENTATION" ] + configs += [ "//base:base_implementation" ] deps = [ "//base/memory",
diff --git a/location.cc b/location.cc index 8b32b97..1333e6e 100644 --- a/location.cc +++ b/location.cc
@@ -31,6 +31,13 @@ program_counter_(NULL) { } +Location::Location(const Location& other) + : function_name_(other.function_name_), + file_name_(other.file_name_), + line_number_(other.line_number_), + program_counter_(other.program_counter_) { +} + std::string Location::ToString() const { return std::string(function_name_) + "@" + file_name_ + ":" + base::IntToString(line_number_);
diff --git a/location.h b/location.h index 05a4f66..477dc02 100644 --- a/location.h +++ b/location.h
@@ -5,10 +5,12 @@ #ifndef BASE_LOCATION_H_ #define BASE_LOCATION_H_ +#include <cassert> #include <string> #include "base/base_export.h" #include "base/basictypes.h" +#include "base/containers/hash_tables.h" namespace tracked_objects { @@ -27,18 +29,15 @@ // Provide a default constructor for easy of debugging. Location(); - // Comparison operator for insertion into a std::map<> hash tables. - // All we need is *some* (any) hashing distinction. Strings should already - // be unique, so we don't bother with strcmp or such. - // Use line number as the primary key (because it is fast, and usually gets us - // a difference), and then pointers as secondary keys (just to get some - // distinctions). - bool operator < (const Location& other) const { - if (line_number_ != other.line_number_) - return line_number_ < other.line_number_; - if (file_name_ != other.file_name_) - return file_name_ < other.file_name_; - return function_name_ < other.function_name_; + // Copy constructor. + Location(const Location& other); + + // Comparator for hash map insertion. + // No need to use |function_name_| since the other two fields uniquely + // identify this location. + bool operator==(const Location& other) const { + return line_number_ == other.line_number_ && + file_name_ == other.file_name_; } const char* function_name() const { return function_name_; } @@ -48,6 +47,26 @@ std::string ToString() const; + // Hash operator for hash maps. + struct Hash { + size_t operator()(const Location& location) const { + // Compute the hash value using file name pointer and line number. + // No need to use |function_name_| since the other two fields uniquely + // identify this location. + + // The file name will always be uniquely identified by its pointer since + // it comes from __FILE__, so no need to check the contents of the string. + // See the definition of FROM_HERE in location.h, and how it is used + // elsewhere. + + // Due to inconsistent definitions of uint64_t and uintptr_t, casting the + // file name pointer to a uintptr_t causes a compiler error for some + // platforms. The solution is to explicitly cast it to a uint64_t. + return base::HashPair(reinterpret_cast<uint64_t>(location.file_name()), + location.line_number()); + } + }; + // Translate the some of the state in this instance into a human readable // string with HTML characters in the function names escaped, and append that // string to |output|. Inclusion of the file_name_ and function_name_ are
diff --git a/mac/scoped_mach_port.h b/mac/scoped_mach_port.h index 9ef90d6..beb62b0 100644 --- a/mac/scoped_mach_port.h +++ b/mac/scoped_mach_port.h
@@ -20,7 +20,7 @@ return MACH_PORT_NULL; } - static void Free(mach_port_t port); + BASE_EXPORT static void Free(mach_port_t port); }; struct BASE_EXPORT ReceiveRightTraits { @@ -28,7 +28,7 @@ return MACH_PORT_NULL; } - static void Free(mach_port_t port); + BASE_EXPORT static void Free(mach_port_t port); }; struct PortSetTraits { @@ -36,7 +36,7 @@ return MACH_PORT_NULL; } - static void Free(mach_port_t port); + BASE_EXPORT static void Free(mach_port_t port); }; } // namespace internal
diff --git a/memory/BUILD.gn b/memory/BUILD.gn index 5d016ff..3d4c22c 100644 --- a/memory/BUILD.gn +++ b/memory/BUILD.gn
@@ -8,14 +8,10 @@ "aligned_memory.h", "discardable_memory.cc", "discardable_memory.h", - "discardable_memory_android.cc", - "discardable_memory_linux.cc", - "discardable_memory_mac.cc", "discardable_memory_shmem.cc", "discardable_memory_shmem.h", "discardable_memory_shmem_allocator.cc", "discardable_memory_shmem_allocator.h", - "discardable_memory_win.cc", "discardable_shared_memory.cc", "discardable_shared_memory.h", "linked_ptr.h", @@ -58,7 +54,7 @@ sources -= [ "shared_memory_nacl.cc" ] } - defines = [ "BASE_IMPLEMENTATION" ] + configs += [ "//base:base_implementation" ] visibility = [ "//base/*" ] }
diff --git a/memory/discardable_memory.cc b/memory/discardable_memory.cc index 7d19f9a..0e3b58a 100644 --- a/memory/discardable_memory.cc +++ b/memory/discardable_memory.cc
@@ -4,80 +4,14 @@ #include "base/memory/discardable_memory.h" -#include "base/lazy_instance.h" -#include "base/logging.h" +#include "base/memory/discardable_memory_shmem.h" namespace base { -namespace { - -const struct TypeNamePair { - DiscardableMemoryType type; - const char* name; -} kTypeNamePairs[] = { - { DISCARDABLE_MEMORY_TYPE_SHMEM, "shmem" } -}; - -DiscardableMemoryType g_preferred_type = DISCARDABLE_MEMORY_TYPE_NONE; - -struct DefaultPreferredType { - DefaultPreferredType() : value(DISCARDABLE_MEMORY_TYPE_NONE) { - std::vector<DiscardableMemoryType> supported_types; - DiscardableMemory::GetSupportedTypes(&supported_types); - DCHECK(!supported_types.empty()); - value = supported_types[0]; - } - DiscardableMemoryType value; -}; -LazyInstance<DefaultPreferredType>::Leaky g_default_preferred_type = - LAZY_INSTANCE_INITIALIZER; - -} // namespace - -// static -DiscardableMemoryType DiscardableMemory::GetNamedType( - const std::string& name) { - for (size_t i = 0; i < arraysize(kTypeNamePairs); ++i) { - if (name == kTypeNamePairs[i].name) - return kTypeNamePairs[i].type; - } - - return DISCARDABLE_MEMORY_TYPE_NONE; -} - -// static -const char* DiscardableMemory::GetTypeName(DiscardableMemoryType type) { - for (size_t i = 0; i < arraysize(kTypeNamePairs); ++i) { - if (type == kTypeNamePairs[i].type) - return kTypeNamePairs[i].name; - } - - return "unknown"; -} - -// static -void DiscardableMemory::SetPreferredType(DiscardableMemoryType type) { - // NONE is a reserved value and not a valid default type. - DCHECK_NE(DISCARDABLE_MEMORY_TYPE_NONE, type); - - // Make sure this function is only called once before the first call - // to GetPreferredType(). - DCHECK_EQ(DISCARDABLE_MEMORY_TYPE_NONE, g_preferred_type); - - g_preferred_type = type; -} - -// static -DiscardableMemoryType DiscardableMemory::GetPreferredType() { - if (g_preferred_type == DISCARDABLE_MEMORY_TYPE_NONE) - g_preferred_type = g_default_preferred_type.Get().value; - - return g_preferred_type; -} // static scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory( size_t size) { - return CreateLockedMemoryWithType(GetPreferredType(), size); + return make_scoped_ptr(new internal::DiscardableMemoryShmem(size)); } } // namespace base
diff --git a/memory/discardable_memory.h b/memory/discardable_memory.h index 4e5a9af..ce0f0bb 100644 --- a/memory/discardable_memory.h +++ b/memory/discardable_memory.h
@@ -15,11 +15,6 @@ namespace base { -enum DiscardableMemoryType { - DISCARDABLE_MEMORY_TYPE_NONE, - DISCARDABLE_MEMORY_TYPE_SHMEM -}; - // Platform abstraction for discardable memory. DiscardableMemory is used to // cache large objects without worrying about blowing out memory, both on mobile // devices where there is no swap, and desktop devices where unused free memory @@ -55,29 +50,7 @@ public: virtual ~DiscardableMemory() {} - // Gets the discardable memory type with a given name. - static DiscardableMemoryType GetNamedType(const std::string& name); - - // Gets the name of a discardable memory type. - static const char* GetTypeName(DiscardableMemoryType type); - - // Gets system supported discardable memory types. Default preferred type - // at the front of vector. - static void GetSupportedTypes(std::vector<DiscardableMemoryType>* types); - - // Sets the preferred discardable memory type. This overrides the default - // preferred type. Can only be called once prior to GetPreferredType() - // or CreateLockedMemory(). Caller is responsible for correct ordering. - static void SetPreferredType(DiscardableMemoryType type); - - // Gets the preferred discardable memory type. - static DiscardableMemoryType GetPreferredType(); - - // Create a DiscardableMemory instance with specified |type| and |size|. - static scoped_ptr<DiscardableMemory> CreateLockedMemoryWithType( - DiscardableMemoryType type, size_t size); - - // Create a DiscardableMemory instance with preferred type and |size|. + // Create a DiscardableMemory instance with |size|. static scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size); // Locks the memory so that it will not be purged by the system. Returns
diff --git a/memory/discardable_memory_android.cc b/memory/discardable_memory_android.cc deleted file mode 100644 index a36f54e..0000000 --- a/memory/discardable_memory_android.cc +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory.h" - -#include "base/logging.h" -#include "base/memory/discardable_memory_shmem.h" - -namespace base { - -// static -void DiscardableMemory::GetSupportedTypes( - std::vector<DiscardableMemoryType>* types) { - const DiscardableMemoryType supported_types[] = { - DISCARDABLE_MEMORY_TYPE_SHMEM - }; - types->assign(supported_types, supported_types + arraysize(supported_types)); -} - -// static -scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( - DiscardableMemoryType type, size_t size) { - switch (type) { - case DISCARDABLE_MEMORY_TYPE_SHMEM: - return make_scoped_ptr(new internal::DiscardableMemoryShmem(size)); - case DISCARDABLE_MEMORY_TYPE_NONE: - NOTREACHED(); - return nullptr; - } - - NOTREACHED(); - return nullptr; -} - -} // namespace base
diff --git a/memory/discardable_memory_linux.cc b/memory/discardable_memory_linux.cc deleted file mode 100644 index b394e07..0000000 --- a/memory/discardable_memory_linux.cc +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory.h" - -#include "base/logging.h" -#include "base/memory/discardable_memory_shmem.h" - -namespace base { - -// static -void DiscardableMemory::GetSupportedTypes( - std::vector<DiscardableMemoryType>* types) { - const DiscardableMemoryType supported_types[] = { - DISCARDABLE_MEMORY_TYPE_SHMEM - }; - types->assign(supported_types, supported_types + arraysize(supported_types)); -} - -// static -scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( - DiscardableMemoryType type, size_t size) { - switch (type) { - case DISCARDABLE_MEMORY_TYPE_SHMEM: - return make_scoped_ptr(new internal::DiscardableMemoryShmem(size)); - case DISCARDABLE_MEMORY_TYPE_NONE: - NOTREACHED(); - return nullptr; - } - - NOTREACHED(); - return nullptr; -} - -} // namespace base
diff --git a/memory/discardable_memory_mac.cc b/memory/discardable_memory_mac.cc deleted file mode 100644 index d7e6345..0000000 --- a/memory/discardable_memory_mac.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory.h" - -#include "base/logging.h" -#include "base/memory/discardable_memory_shmem.h" -#include "base/memory/scoped_ptr.h" - -namespace base { - -// static -void DiscardableMemory::GetSupportedTypes( - std::vector<DiscardableMemoryType>* types) { - const DiscardableMemoryType supported_types[] = { - DISCARDABLE_MEMORY_TYPE_SHMEM - }; - types->assign(supported_types, supported_types + arraysize(supported_types)); -} - -// static -scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( - DiscardableMemoryType type, size_t size) { - switch (type) { - case DISCARDABLE_MEMORY_TYPE_SHMEM: - return make_scoped_ptr(new internal::DiscardableMemoryShmem(size)); - case DISCARDABLE_MEMORY_TYPE_NONE: - NOTREACHED(); - return nullptr; - } - - NOTREACHED(); - return nullptr; -} - -} // namespace base
diff --git a/memory/discardable_memory_shmem_allocator.cc b/memory/discardable_memory_shmem_allocator.cc index 761204f..a87c58d 100644 --- a/memory/discardable_memory_shmem_allocator.cc +++ b/memory/discardable_memory_shmem_allocator.cc
@@ -11,45 +11,6 @@ namespace base { namespace { -class DiscardableMemoryShmemChunkImpl : public DiscardableMemoryShmemChunk { - public: - explicit DiscardableMemoryShmemChunkImpl( - scoped_ptr<DiscardableSharedMemory> shared_memory) - : shared_memory_(shared_memory.Pass()) {} - - // Overridden from DiscardableMemoryShmemChunk: - bool Lock() override { return false; } - void Unlock() override { - shared_memory_->Unlock(0, 0); - shared_memory_.reset(); - } - void* Memory() const override { return shared_memory_->memory(); } - - private: - scoped_ptr<DiscardableSharedMemory> shared_memory_; - - DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryShmemChunkImpl); -}; - -// Default allocator implementation that allocates in-process -// DiscardableSharedMemory instances. -class DiscardableMemoryShmemAllocatorImpl - : public DiscardableMemoryShmemAllocator { - public: - // Overridden from DiscardableMemoryShmemAllocator: - scoped_ptr<DiscardableMemoryShmemChunk> - AllocateLockedDiscardableMemory(size_t size) override { - scoped_ptr<DiscardableSharedMemory> memory(new DiscardableSharedMemory); - if (!memory->CreateAndMap(size)) - return nullptr; - - return make_scoped_ptr(new DiscardableMemoryShmemChunkImpl(memory.Pass())); - } -}; - -LazyInstance<DiscardableMemoryShmemAllocatorImpl>::Leaky g_default_allocator = - LAZY_INSTANCE_INITIALIZER; - DiscardableMemoryShmemAllocator* g_allocator = nullptr; } // namespace @@ -69,9 +30,7 @@ // static DiscardableMemoryShmemAllocator* DiscardableMemoryShmemAllocator::GetInstance() { - if (!g_allocator) - g_allocator = g_default_allocator.Pointer(); - + DCHECK(g_allocator); return g_allocator; }
diff --git a/memory/discardable_memory_unittest.cc b/memory/discardable_memory_unittest.cc deleted file mode 100644 index a769e17..0000000 --- a/memory/discardable_memory_unittest.cc +++ /dev/null
@@ -1,125 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory.h" - -#include <algorithm> - -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_ANDROID) -#include <limits> -#endif - -namespace base { -namespace { - -class DiscardableMemoryTest - : public testing::TestWithParam<DiscardableMemoryType> { - public: - DiscardableMemoryTest() {} - virtual ~DiscardableMemoryTest() { - } - - protected: - scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size) { - return DiscardableMemory::CreateLockedMemoryWithType( - GetParam(), size).Pass(); - } -}; - -const size_t kSize = 1024; - -TEST_P(DiscardableMemoryTest, IsNamed) { - std::string type_name(DiscardableMemory::GetTypeName(GetParam())); - EXPECT_NE("unknown", type_name); - EXPECT_EQ(GetParam(), DiscardableMemory::GetNamedType(type_name)); -} - -bool IsNativeType(DiscardableMemoryType type) { -#if defined(OS_ANDROID) - // SHMEM is backed by native discardable memory on Android. - return type == DISCARDABLE_MEMORY_TYPE_SHMEM; -#else - return false; -#endif -} - -TEST_P(DiscardableMemoryTest, SupportedNatively) { - std::vector<DiscardableMemoryType> supported_types; - DiscardableMemory::GetSupportedTypes(&supported_types); -#if defined(DISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY) - EXPECT_NE(0, std::count_if(supported_types.begin(), - supported_types.end(), - IsNativeType)); -#else - // If we ever have a platform that decides at runtime if it can support - // discardable memory natively, then we'll have to add a 'never supported - // natively' define for this case. At present, if it's not always supported - // natively, it's never supported. - EXPECT_EQ(0, std::count_if(supported_types.begin(), - supported_types.end(), - IsNativeType)); -#endif -} - -// Test Lock() and Unlock() functionalities. -TEST_P(DiscardableMemoryTest, LockAndUnLock) { - const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize)); - ASSERT_TRUE(memory); - void* addr = memory->Memory(); - EXPECT_NE(nullptr, addr); - memory->Unlock(); -} - -// Test delete a discardable memory while it is locked. -TEST_P(DiscardableMemoryTest, DeleteWhileLocked) { - const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize)); - ASSERT_TRUE(memory); -} - -#if !defined(NDEBUG) && !defined(OS_ANDROID) -// Death tests are not supported with Android APKs. -TEST_P(DiscardableMemoryTest, UnlockedMemoryAccessCrashesInDebugMode) { - const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize)); - ASSERT_TRUE(memory); - memory->Unlock(); - ASSERT_DEATH_IF_SUPPORTED( - { *static_cast<int*>(memory->Memory()) = 0xdeadbeef; }, ".*"); -} -#endif - -// Test behavior when creating enough instances that could use up a 32-bit -// address space. -// This is disabled under AddressSanitizer on Windows as it crashes (by design) -// on OOM. See http://llvm.org/PR22026 for the details. -#if !defined(ADDRESS_SANITIZER) || !defined(OS_WIN) -TEST_P(DiscardableMemoryTest, AddressSpace) { - const size_t kLargeSize = 4 * 1024 * 1024; // 4MiB. - const size_t kNumberOfInstances = 1024 + 1; // >4GiB total. - - scoped_ptr<DiscardableMemory> instances[kNumberOfInstances]; - for (auto& memory : instances) { - memory = CreateLockedMemory(kLargeSize); - ASSERT_TRUE(memory); - void* addr = memory->Memory(); - EXPECT_NE(nullptr, addr); - memory->Unlock(); - } -} -#endif - -std::vector<DiscardableMemoryType> GetSupportedDiscardableMemoryTypes() { - std::vector<DiscardableMemoryType> supported_types; - DiscardableMemory::GetSupportedTypes(&supported_types); - return supported_types; -} - -INSTANTIATE_TEST_CASE_P( - DiscardableMemoryTests, - DiscardableMemoryTest, - ::testing::ValuesIn(GetSupportedDiscardableMemoryTypes())); - -} // namespace -} // namespace base
diff --git a/memory/discardable_memory_win.cc b/memory/discardable_memory_win.cc deleted file mode 100644 index b394e07..0000000 --- a/memory/discardable_memory_win.cc +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory.h" - -#include "base/logging.h" -#include "base/memory/discardable_memory_shmem.h" - -namespace base { - -// static -void DiscardableMemory::GetSupportedTypes( - std::vector<DiscardableMemoryType>* types) { - const DiscardableMemoryType supported_types[] = { - DISCARDABLE_MEMORY_TYPE_SHMEM - }; - types->assign(supported_types, supported_types + arraysize(supported_types)); -} - -// static -scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( - DiscardableMemoryType type, size_t size) { - switch (type) { - case DISCARDABLE_MEMORY_TYPE_SHMEM: - return make_scoped_ptr(new internal::DiscardableMemoryShmem(size)); - case DISCARDABLE_MEMORY_TYPE_NONE: - NOTREACHED(); - return nullptr; - } - - NOTREACHED(); - return nullptr; -} - -} // namespace base
diff --git a/metrics/BUILD.gn b/metrics/BUILD.gn index 804e59b..0202637 100644 --- a/metrics/BUILD.gn +++ b/metrics/BUILD.gn
@@ -37,7 +37,7 @@ sources -= [ "field_trial.cc" ] } - defines = [ "BASE_IMPLEMENTATION" ] + configs += [ "//base:base_implementation" ] deps = [ "//base/debug",
diff --git a/path_service_unittest.cc b/path_service_unittest.cc index 543deb6..7551d67 100644 --- a/path_service_unittest.cc +++ b/path_service_unittest.cc
@@ -220,3 +220,55 @@ EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &new_user_data_dir)); EXPECT_EQ(original_user_data_dir, new_user_data_dir); } + +#if defined(OS_WIN) +TEST_F(PathServiceTest, GetProgramFiles) { + base::FilePath programfiles_dir; +#if defined(_WIN64) + // 64-bit on 64-bit. + EXPECT_TRUE(PathService::Get(base::DIR_PROGRAM_FILES, + &programfiles_dir)); + EXPECT_EQ(programfiles_dir.value(), + FILE_PATH_LITERAL("C:\\Program Files")); + EXPECT_TRUE(PathService::Get(base::DIR_PROGRAM_FILESX86, + &programfiles_dir)); + EXPECT_EQ(programfiles_dir.value(), + FILE_PATH_LITERAL("C:\\Program Files (x86)")); + EXPECT_TRUE(PathService::Get(base::DIR_PROGRAM_FILES6432, + &programfiles_dir)); + EXPECT_EQ(programfiles_dir.value(), + FILE_PATH_LITERAL("C:\\Program Files")); +#else + if (base::win::OSInfo::GetInstance()->wow64_status() == + base::win::OSInfo::WOW64_ENABLED) { + // 32-bit on 64-bit. + EXPECT_TRUE(PathService::Get(base::DIR_PROGRAM_FILES, + &programfiles_dir)); + EXPECT_EQ(programfiles_dir.value(), + FILE_PATH_LITERAL("C:\\Program Files (x86)")); + EXPECT_TRUE(PathService::Get(base::DIR_PROGRAM_FILESX86, + &programfiles_dir)); + EXPECT_EQ(programfiles_dir.value(), + FILE_PATH_LITERAL("C:\\Program Files (x86)")); + EXPECT_TRUE(PathService::Get(base::DIR_PROGRAM_FILES6432, + &programfiles_dir)); + EXPECT_EQ(programfiles_dir.value(), + FILE_PATH_LITERAL("C:\\Program Files")); + } else { + // 32-bit on 32-bit. + EXPECT_TRUE(PathService::Get(base::DIR_PROGRAM_FILES, + &programfiles_dir)); + EXPECT_EQ(programfiles_dir.value(), + FILE_PATH_LITERAL("C:\\Program Files")); + EXPECT_TRUE(PathService::Get(base::DIR_PROGRAM_FILESX86, + &programfiles_dir)); + EXPECT_EQ(programfiles_dir.value(), + FILE_PATH_LITERAL("C:\\Program Files")); + EXPECT_TRUE(PathService::Get(base::DIR_PROGRAM_FILES6432, + &programfiles_dir)); + EXPECT_EQ(programfiles_dir.value(), + FILE_PATH_LITERAL("C:\\Program Files")); + } +#endif +} +#endif
diff --git a/pickle.cc b/pickle.cc index 6eb207f..112ddc3 100644 --- a/pickle.cc +++ b/pickle.cc
@@ -358,6 +358,7 @@ inline void Pickle::WriteBytesCommon(const void* data, size_t length) { DCHECK_NE(kCapacityReadOnly, capacity_after_header_) << "oops: pickle is readonly"; + MSAN_CHECK_MEM_IS_INITIALIZED(data, length); size_t data_len = AlignInt(length, sizeof(uint32)); DCHECK_GE(data_len, length); #ifdef ARCH_CPU_64_BITS
diff --git a/process/BUILD.gn b/process/BUILD.gn index 125b451..e570647 100644 --- a/process/BUILD.gn +++ b/process/BUILD.gn
@@ -94,7 +94,7 @@ ] } - defines = [ "BASE_IMPLEMENTATION" ] + configs += [ "//base:base_implementation" ] deps = [ "//base/memory",
diff --git a/process/launch.cc b/process/launch.cc index 1c752bd..c179b2f 100644 --- a/process/launch.cc +++ b/process/launch.cc
@@ -27,6 +27,7 @@ #if defined(OS_LINUX) , clone_flags(0) , allow_new_privs(false) + , kill_on_parent_death(false) #endif // OS_LINUX #if defined(OS_POSIX) , pre_exec_delegate(NULL)
diff --git a/process/launch.h b/process/launch.h index 775e65c..56f27a8 100644 --- a/process/launch.h +++ b/process/launch.h
@@ -141,6 +141,9 @@ // By default, child processes will have the PR_SET_NO_NEW_PRIVS bit set. If // true, then this bit will not be set in the new child process. bool allow_new_privs; + + // Sets parent process death signal to SIGKILL. + bool kill_on_parent_death; #endif // defined(OS_LINUX) #if defined(OS_POSIX)
diff --git a/process/launch_posix.cc b/process/launch_posix.cc index f9963fa..77edc12 100644 --- a/process/launch_posix.cc +++ b/process/launch_posix.cc
@@ -523,6 +523,13 @@ RAW_LOG(FATAL, "prctl(PR_SET_NO_NEW_PRIVS) failed"); } } + + if (options.kill_on_parent_death) { + if (prctl(PR_SET_PDEATHSIG, SIGKILL) != 0) { + RAW_LOG(ERROR, "prctl(PR_SET_PDEATHSIG) failed"); + _exit(127); + } + } #endif if (current_directory != nullptr) {
diff --git a/process/process.h b/process/process.h index 41eef10..045f870 100644 --- a/process/process.h +++ b/process/process.h
@@ -55,7 +55,7 @@ // Returns a Process for the given |pid|. On Windows the handle is opened // with more access rights and must only be used by trusted code (can read the // address space and duplicate handles). - static Process OpenWithExtraPriviles(ProcessId pid); + static Process OpenWithExtraPrivileges(ProcessId pid); #if defined(OS_WIN) // Returns a Process for the given |pid|, using some |desired_access|.
diff --git a/process/process_posix.cc b/process/process_posix.cc index 1c4210b..a083123 100644 --- a/process/process_posix.cc +++ b/process/process_posix.cc
@@ -238,7 +238,7 @@ } // static -Process Process::OpenWithExtraPriviles(ProcessId pid) { +Process Process::OpenWithExtraPrivileges(ProcessId pid) { // On POSIX there are no privileges to set. return Open(pid); }
diff --git a/process/process_win.cc b/process/process_win.cc index 32da8ab..d72dd49 100644 --- a/process/process_win.cc +++ b/process/process_win.cc
@@ -54,7 +54,7 @@ } // static -Process Process::OpenWithExtraPriviles(ProcessId pid) { +Process Process::OpenWithExtraPrivileges(ProcessId pid) { DWORD access = kBasicProcessAccess | PROCESS_DUP_HANDLE | PROCESS_VM_READ; return Process(::OpenProcess(access, FALSE, pid)); }
diff --git a/test/BUILD.gn b/test/BUILD.gn index 55e710d..f5d2e4c 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn
@@ -81,6 +81,8 @@ "simple_test_tick_clock.h", "task_runner_test_template.cc", "task_runner_test_template.h", + "test_discardable_memory_shmem_allocator.cc", + "test_discardable_memory_shmem_allocator.h", "test_file_util.cc", "test_file_util.h", "test_file_util_android.cc",
diff --git a/test/launcher/test_launcher.cc b/test/launcher/test_launcher.cc index 667d1eb..1d48060 100644 --- a/test/launcher/test_launcher.cc +++ b/test/launcher/test_launcher.cc
@@ -383,6 +383,9 @@ } #elif defined(OS_POSIX) options.new_process_group = true; +#if defined(OS_LINUX) + options.kill_on_parent_death = true; +#endif // defined(OS_LINUX) FileHandleMappingVector fds_mapping; ScopedFD output_file_fd;
diff --git a/test/test_discardable_memory_shmem_allocator.cc b/test/test_discardable_memory_shmem_allocator.cc new file mode 100644 index 0000000..24185a2 --- /dev/null +++ b/test/test_discardable_memory_shmem_allocator.cc
@@ -0,0 +1,40 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/test_discardable_memory_shmem_allocator.h" + +#include <stdint.h> + +namespace base { +namespace { + +class DiscardableMemoryShmemChunkImpl : public DiscardableMemoryShmemChunk { + public: + explicit DiscardableMemoryShmemChunkImpl(size_t size) + : memory_(new uint8_t[size]) {} + + // Overridden from DiscardableMemoryShmemChunk: + bool Lock() override { return false; } + void Unlock() override {} + void* Memory() const override { return memory_.get(); } + + private: + scoped_ptr<uint8_t[]> memory_; +}; + +} // namespace + +TestDiscardableMemoryShmemAllocator::TestDiscardableMemoryShmemAllocator() { +} + +TestDiscardableMemoryShmemAllocator::~TestDiscardableMemoryShmemAllocator() { +} + +scoped_ptr<DiscardableMemoryShmemChunk> +TestDiscardableMemoryShmemAllocator::AllocateLockedDiscardableMemory( + size_t size) { + return make_scoped_ptr(new DiscardableMemoryShmemChunkImpl(size)); +} + +} // namespace base
diff --git a/test/test_discardable_memory_shmem_allocator.h b/test/test_discardable_memory_shmem_allocator.h new file mode 100644 index 0000000..a40960e --- /dev/null +++ b/test/test_discardable_memory_shmem_allocator.h
@@ -0,0 +1,28 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TEST_TEST_DISCARDABLE_MEMORY_SHMEM_ALLOCATOR_H_ +#define BASE_TEST_TEST_DISCARDABLE_MEMORY_SHMEM_ALLOCATOR_H_ + +#include "base/memory/discardable_memory_shmem_allocator.h" + +namespace base { + +class TestDiscardableMemoryShmemAllocator + : public DiscardableMemoryShmemAllocator { + public: + TestDiscardableMemoryShmemAllocator(); + ~TestDiscardableMemoryShmemAllocator() override; + + // Overridden from DiscardableMemoryShmemAllocator: + scoped_ptr<DiscardableMemoryShmemChunk> AllocateLockedDiscardableMemory( + size_t size) override; + + private: + DISALLOW_COPY_AND_ASSIGN(TestDiscardableMemoryShmemAllocator); +}; + +} // namespace base + +#endif // BASE_TEST_TEST_DISCARDABLE_MEMORY_SHMEM_ALLOCATOR_H_
diff --git a/third_party/nspr/BUILD.gn b/third_party/nspr/BUILD.gn index a67e168..034f37b 100644 --- a/third_party/nspr/BUILD.gn +++ b/third_party/nspr/BUILD.gn
@@ -12,7 +12,7 @@ # In GYP this project is part of base, so it uses the base implementation # define. TODO(brettw) rename this define. - defines = [ "BASE_IMPLEMENTATION" ] + configs += [ "//base:base_implementation" ] if (is_android && !is_debug) { configs -= [ "//build/config/compiler:optimize" ]
diff --git a/threading/sequenced_worker_pool.cc b/threading/sequenced_worker_pool.cc index f20d997..52b178b 100644 --- a/threading/sequenced_worker_pool.cc +++ b/threading/sequenced_worker_pool.cc
@@ -803,6 +803,20 @@ delete_these_outside_lock.clear(); break; } + + // No work was found, but there are tasks that need deletion. The + // deletion must happen outside of the lock. + if (delete_these_outside_lock.size()) { + AutoUnlock unlock(lock_); + delete_these_outside_lock.clear(); + + // Since the lock has been released, |status| may no longer be + // accurate. It might read GET_WORK_WAIT even if there are tasks + // ready to perform work. Jump to the top of the loop to recalculate + // |status|. + continue; + } + waiting_thread_count_++; switch (status) {
diff --git a/threading/sequenced_worker_pool_unittest.cc b/threading/sequenced_worker_pool_unittest.cc index c132731..5d0880c 100644 --- a/threading/sequenced_worker_pool_unittest.cc +++ b/threading/sequenced_worker_pool_unittest.cc
@@ -148,6 +148,17 @@ FROM_HERE, reposting_task, SequencedWorkerPool::SKIP_ON_SHUTDOWN); } + // This task reposts itself back onto the SequencedWorkerPool before it + // finishes running. + void PostRepostingBlockingTask( + const scoped_refptr<SequencedWorkerPool>& pool, + const SequencedWorkerPool::SequenceToken& token) { + Closure reposting_task = + base::Bind(&TestTracker::PostRepostingBlockingTask, this, pool, token); + pool->PostSequencedWorkerTaskWithShutdownBehavior(token, + FROM_HERE, reposting_task, SequencedWorkerPool::BLOCK_SHUTDOWN); + } + // Waits until the given number of tasks have started executing. void WaitUntilTasksBlocked(size_t count) { { @@ -795,6 +806,26 @@ pool()->Shutdown(); } +// Similar to the test AvoidsDeadlockOnShutdown, but there are now also +// sequenced, blocking tasks in the queue during shutdown. +TEST_F(SequencedWorkerPoolTest, + AvoidsDeadlockOnShutdownWithSequencedBlockingTasks) { + const std::string sequence_token_name("name"); + for (int i = 0; i < 4; ++i) { + scoped_refptr<DestructionDeadlockChecker> checker( + new DestructionDeadlockChecker(pool())); + tracker()->PostRepostingTask(pool(), checker); + + SequencedWorkerPool::SequenceToken token1 = + pool()->GetNamedSequenceToken(sequence_token_name); + tracker()->PostRepostingBlockingTask(pool(), token1); + } + + // Shutting down the pool should destroy the DestructionDeadlockCheckers, + // which in turn should not deadlock in their destructors. + pool()->Shutdown(); +} + // Verify that FlushForTesting works as intended. TEST_F(SequencedWorkerPoolTest, FlushForTesting) { // Should be fine to call on a new instance.
diff --git a/time/time.h b/time/time.h index b18c0b2..6a45b81 100644 --- a/time/time.h +++ b/time/time.h
@@ -233,13 +233,16 @@ // Represents a wall clock time in UTC. class BASE_EXPORT Time { public: + static const int64 kHoursPerDay = 24; static const int64 kMillisecondsPerSecond = 1000; + static const int64 kMillisecondsPerDay = kMillisecondsPerSecond * 60 * 60 * + kHoursPerDay; static const int64 kMicrosecondsPerMillisecond = 1000; static const int64 kMicrosecondsPerSecond = kMicrosecondsPerMillisecond * kMillisecondsPerSecond; static const int64 kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; static const int64 kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; - static const int64 kMicrosecondsPerDay = kMicrosecondsPerHour * 24; + static const int64 kMicrosecondsPerDay = kMicrosecondsPerHour * kHoursPerDay; static const int64 kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; static const int64 kNanosecondsPerMicrosecond = 1000; static const int64 kNanosecondsPerSecond = kNanosecondsPerMicrosecond *
diff --git a/trace_event/BUILD.gn b/trace_event/BUILD.gn index eec607b..10f7ec9 100644 --- a/trace_event/BUILD.gn +++ b/trace_event/BUILD.gn
@@ -41,7 +41,7 @@ ] } - defines = [ "BASE_IMPLEMENTATION" ] + configs += [ "//base:base_implementation" ] deps = [ "//base/debug",
diff --git a/trace_event/trace_event.h b/trace_event/trace_event.h index b90a3ea..9d8e7d1 100644 --- a/trace_event/trace_event.h +++ b/trace_event/trace_event.h
@@ -520,6 +520,27 @@ value1_name, static_cast<int>(value1_val), \ value2_name, static_cast<int>(value2_val)) +// TRACE_EVENT_SAMPLE_* events are injected by the sampling profiler. +#define TRACE_EVENT_SAMPLE_WITH_TID_AND_TIMESTAMP0(category_group, name, \ + thread_id, timestamp) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_SAMPLE, category_group, name, 0, thread_id, timestamp, \ + TRACE_EVENT_FLAG_NONE) + +#define TRACE_EVENT_SAMPLE_WITH_TID_AND_TIMESTAMP1( \ + category_group, name, thread_id, timestamp, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_SAMPLE, category_group, name, 0, thread_id, timestamp, \ + TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) + +#define TRACE_EVENT_SAMPLE_WITH_TID_AND_TIMESTAMP2(category_group, name, \ + thread_id, timestamp, \ + arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_SAMPLE, category_group, name, 0, thread_id, timestamp, \ + TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) + // ASYNC_STEP_* APIs should be only used by legacy code. New code should // consider using NESTABLE_ASYNC_* APIs to describe substeps within an async // event.
diff --git a/tracked_objects.h b/tracked_objects.h index 7840fec..34c3667 100644 --- a/tracked_objects.h +++ b/tracked_objects.h
@@ -14,6 +14,7 @@ #include "base/base_export.h" #include "base/basictypes.h" +#include "base/containers/hash_tables.h" #include "base/gtest_prod_util.h" #include "base/lazy_instance.h" #include "base/location.h" @@ -357,7 +358,7 @@ STATUS_LAST = PROFILING_CHILDREN_ACTIVE }; - typedef std::map<Location, Births*> BirthMap; + typedef base::hash_map<Location, Births*, Location::Hash> BirthMap; typedef std::map<const Births*, DeathData> DeathMap; typedef std::pair<const Births*, const Births*> ParentChildPair; typedef std::set<ParentChildPair> ParentChildSet;