summaryrefslogtreecommitdiff
path: root/src/base/sysinfo.h
blob: 77d956ea3f8b5126c6269aaeffa80e734b6ea4c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// All functions here are thread-hostile due to file caching unless
// commented otherwise.

#ifndef _SYSINFO_H_
#define _SYSINFO_H_

#include <config.h>

#include <time.h>
#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
#include <windows.h>   // for DWORD
#include <tlhelp32.h>  // for CreateToolhelp32Snapshot
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>    // for pid_t
#endif
#include <stddef.h>    // for size_t
#include <limits.h>    // for PATH_MAX
#include "base/basictypes.h"
#include "base/logging.h"   // for RawFD

// This getenv function is safe to call before the C runtime is initialized.
// On Windows, it utilizes GetEnvironmentVariable() and on unix it uses
// /proc/self/environ instead calling getenv().  It's intended to be used in
// routines that run before main(), when the state required for getenv() may
// not be set up yet.  In particular, errno isn't set up until relatively late
// (after the pthreads library has a chance to make it threadsafe), and
// getenv() doesn't work until then.
// On some platforms, this call will utilize the same, static buffer for
// repeated GetenvBeforeMain() calls. Callers should not expect pointers from
// this routine to be long lived.
// Note that on unix, /proc only has the environment at the time the
// application was started, so this routine ignores setenv() calls/etc.  Also
// note it only reads the first 16K of the environment.
extern const char* GetenvBeforeMain(const char* name);

// This takes as an argument an environment-variable name (like
// CPUPROFILE) whose value is supposed to be a file-path, and sets
// path to that path, and returns true.  Non-trivial for surprising
// reasons, as documented in sysinfo.cc.  path must have space PATH_MAX.
extern bool GetUniquePathFromEnv(const char* env_name, char* path);

extern int GetSystemCPUsCount();

//  Return true if we're running POSIX (e.g., NPTL on Linux) threads,
//  as opposed to a non-POSIX thread library.  The thing that we care
//  about is whether a thread's pid is the same as the thread that
//  spawned it.  If so, this function returns true.
//  Thread-safe.
//  Note: We consider false negatives to be OK.
bool HasPosixThreads();

#ifndef SWIG  // SWIG doesn't like struct Buffer and variable arguments.

// A ProcMapsIterator abstracts access to /proc/maps for a given
// process. Needs to be stack-allocatable and avoid using stdio/malloc
// so it can be used in the google stack dumper, heap-profiler, etc.
//
// On Windows and Mac OS X, this iterator iterates *only* over DLLs
// mapped into this process space.  For Linux, FreeBSD, and Solaris,
// it iterates over *all* mapped memory regions, including anonymous
// mmaps.  For other O/Ss, it is unlikely to work at all, and Valid()
// will always return false.  Also note: this routine only works on
// FreeBSD if procfs is mounted: make sure this is in your /etc/fstab:
//    proc            /proc   procfs  rw 0 0
class ProcMapsIterator {
 public:
  struct Buffer {
#ifdef __FreeBSD__
    // FreeBSD requires us to read all of the maps file at once, so
    // we have to make a buffer that's "always" big enough
    static const size_t kBufSize = 102400;
#else   // a one-line buffer is good enough
    static const size_t kBufSize = PATH_MAX + 1024;
#endif
    char buf_[kBufSize];
  };


  // Create a new iterator for the specified pid.  pid can be 0 for "self".
  explicit ProcMapsIterator(pid_t pid);

  // Create an iterator with specified storage (for use in signal
  // handler). "buffer" should point to a ProcMapsIterator::Buffer
  // buffer can be NULL in which case a bufer will be allocated.
  ProcMapsIterator(pid_t pid, Buffer *buffer);

  // Iterate through maps_backing instead of maps if use_maps_backing
  // is true.  Otherwise the same as above.  buffer can be NULL and
  // it will allocate a buffer itself.
  ProcMapsIterator(pid_t pid, Buffer *buffer,
                   bool use_maps_backing);

  // Returns true if the iterator successfully initialized;
  bool Valid() const;

  // Returns a pointer to the most recently parsed line. Only valid
  // after Next() returns true, and until the iterator is destroyed or
  // Next() is called again.  This may give strange results on non-Linux
  // systems.  Prefer FormatLine() if that may be a concern.
  const char *CurrentLine() const { return stext_; }

  // Writes the "canonical" form of the /proc/xxx/maps info for a single
  // line to the passed-in buffer. Returns the number of bytes written,
  // or 0 if it was not able to write the complete line.  (To guarantee
  // success, buffer should have size at least Buffer::kBufSize.)
  // Takes as arguments values set via a call to Next().  The
  // "canonical" form of the line (taken from linux's /proc/xxx/maps):
  //    <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)>   +
  //    <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the
  // eg
  //    08048000-0804c000 r-xp 00000000 03:01 3793678    /bin/cat
  // If you don't have the dev_t (dev), feel free to pass in 0.
  // (Next() doesn't return a dev_t, though NextExt does.)
  //
  // Note: if filename and flags were obtained via a call to Next(),
  // then the output of this function is only valid if Next() returned
  // true, and only until the iterator is destroyed or Next() is
  // called again.  (Since filename, at least, points into CurrentLine.)
  static int FormatLine(char* buffer, int bufsize,
                        uint64 start, uint64 end, const char *flags,
                        uint64 offset, int64 inode, const char *filename,
                        dev_t dev);

  // Find the next entry in /proc/maps; return true if found or false
  // if at the end of the file.
  //
  // Any of the result pointers can be NULL if you're not interested
  // in those values.
  //
  // If "flags" and "filename" are passed, they end up pointing to
  // storage within the ProcMapsIterator that is valid only until the
  // iterator is destroyed or Next() is called again. The caller may
  // modify the contents of these strings (up as far as the first NUL,
  // and only until the subsequent call to Next()) if desired.

  // The offsets are all uint64 in order to handle the case of a
  // 32-bit process running on a 64-bit kernel
  //
  // IMPORTANT NOTE: see top-of-class notes for details about what
  // mapped regions Next() iterates over, depending on O/S.
  // TODO(csilvers): make flags and filename const.
  bool Next(uint64 *start, uint64 *end, char **flags,
            uint64 *offset, int64 *inode, char **filename);

  bool NextExt(uint64 *start, uint64 *end, char **flags,
               uint64 *offset, int64 *inode, char **filename,
               uint64 *file_mapping, uint64 *file_pages,
               uint64 *anon_mapping, uint64 *anon_pages,
               dev_t *dev);

  ~ProcMapsIterator();

 private:
  void Init(pid_t pid, Buffer *buffer, bool use_maps_backing);

  char *ibuf_;        // input buffer
  char *stext_;       // start of text
  char *etext_;       // end of text
  char *nextline_;    // start of next line
  char *ebuf_;        // end of buffer (1 char for a nul)
#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
  HANDLE snapshot_;   // filehandle on dll info
  // In a change from the usual W-A pattern, there is no A variant of
  // MODULEENTRY32.  Tlhelp32.h #defines the W variant, but not the A.
  // We want the original A variants, and this #undef is the only
  // way I see to get them.  Redefining it when we're done prevents us
  // from affecting other .cc files.
# ifdef MODULEENTRY32  // Alias of W
#   undef MODULEENTRY32
  MODULEENTRY32 module_;   // info about current dll (and dll iterator)
#   define MODULEENTRY32 MODULEENTRY32W
# else  // It's the ascii, the one we want.
  MODULEENTRY32 module_;   // info about current dll (and dll iterator)
# endif
#elif defined(__MACH__)
  int current_image_; // dll's are called "images" in macos parlance
  int current_load_cmd_;   // the segment of this dll we're examining
#elif defined(__sun__)     // Solaris
  int fd_;
  char current_filename_[PATH_MAX];
#else
  int fd_;            // filehandle on /proc/*/maps
#endif
  pid_t pid_;
  char flags_[10];
  Buffer* dynamic_buffer_;  // dynamically-allocated Buffer
  bool using_maps_backing_; // true if we are looking at maps_backing instead of maps.
};

#endif  /* #ifndef SWIG */

// Helper routines

namespace tcmalloc {
int FillProcSelfMaps(char buf[], int size, bool* wrote_all);
void DumpProcSelfMaps(RawFD fd);
}

#endif   /* #ifndef _SYSINFO_H_ */