1
// Copyright 2010, Google Inc.
2
// All rights reserved.
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above
11
// copyright notice, this list of conditions and the following disclaimer
12
// in the documentation and/or other materials provided with the
14
// * Neither the name of Google Inc. nor the names of its
15
// contributors may be used to endorse or promote products derived from
16
// this software without specific prior written permission.
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
#include "dictionary/dictionary_preloader.h"
32
#if defined(OS_WINDOWS)
35
#include <CommCtrl.h> // for CCSIZEOF_STRUCT
37
#include <pthread.h> // for pthread_create
41
#include <mach/mach_host.h>
44
#include "base/util.h"
45
#include "base/singleton.h"
46
#include "base/thread.h"
47
#include "session/config_handler.h"
48
#include "session/config.pb.h"
50
DEFINE_int32(preload_memory_factor, 5,
51
"A factor to be multiplied to the preload size "
52
"and compared with available system memory."
53
"Preload is enabled if available system memory is "
58
bool IsPreloadable(const char *image, size_t size) {
59
if (!GET_CONFIG(use_dictionary_suggest)) {
63
const int64 preload_size = size;
66
MEMORYSTATUSEX status;
67
::ZeroMemory(&status, sizeof(status));
68
status.dwLength = CCSIZEOF_STRUCT(MEMORYSTATUSEX, ullAvailExtendedVirtual);
69
if (!::GlobalMemoryStatusEx(&status)) {
71
"GlobalMemoryStatusEx failed. error = " << ::GetLastError();
75
return status.ullAvailPhys > preload_size * FLAGS_preload_memory_factor;
79
struct vm_statistics vm_info;
80
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
82
host_statistics(mach_host_self(), HOST_VM_INFO,
83
reinterpret_cast<host_info_t>(&vm_info), &count)) {
84
LOG(ERROR) << "host_statistics() failed: ";
88
const uint64 available_memory = vm_info.free_count * vm_page_size;
89
return available_memory > preload_size * FLAGS_preload_memory_factor;
93
// TOOD(taku): implement Linux version.
94
// Since Linux is installed into heterogeneous environment,
95
// we have to check the amount of available memory.
96
LOG(WARNING) << "Dictionary preloading is not implemented: " << preload_size;
102
// Note: this thread proc may be terminated by the end of main thread.
103
class PreloaderThread : public Thread {
105
PreloaderThread() : image_(NULL), size_(0) {}
111
void StartPreloader(const char *image, size_t size) {
113
LOG(WARNING) << "Preloader is already running";
123
// GetCurrentThread returns pseudo handle, which you need not
124
// to pass CloseHandle.
125
const HANDLE thread_handle = ::GetCurrentThread();
127
// Enter low priority mode.
128
if (Util::IsVistaOrLater()) {
129
// THREAD_MODE_BACKGROUND_BEGIN is beneficial for the preloader since
130
// all I/Os occurred in the background-mode thread are marked as
131
// "Low-Priority" so that the activity of the preloader is less likely
132
// to interrupt normal I/O tasks.
133
// Note that "all I/Os" includes implicit page-fault I/Os, which is
134
// what the preloader aims to do.
135
::SetThreadPriority(thread_handle, THREAD_MODE_BACKGROUND_BEGIN);
137
::SetThreadPriority(thread_handle, THREAD_PRIORITY_IDLE);
141
if (image_ == NULL || size_ == 0) {
142
LOG(ERROR) << "image is NULL or size is 0";
146
// Preleoad dictionary region.
147
// TODO(yukawa): determine the best region to load.
148
Util::PreloadMappedRegion(image_, size_, NULL);
150
VLOG(1) << "Preloader done!";
157
} // anonymous namespace
159
void DictionaryPreloader::PreloadIfApplicable(const char *image, size_t size) {
160
// On Windows, dictionary preloader is no longer enabled because
161
// GoogleIMEJaCacheService.exe is responsible for keeping the dictionary
162
// on-page (or freeing the memory in low-memory condition).
163
// See http://b/2354549 for details.
164
#if defined(OS_MACOSX) || defined(OS_LINUX)
165
if (!IsPreloadable(image, size)) {
169
Singleton<PreloaderThread>::get()->StartPreloader(image, size);
170
#endif // OS_MACOSX or OS_LINUX