1// Copyright (c) 2006, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
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
13// distribution.
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.
17//
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.
29
30// All functions here are thread-hostile due to file caching unless
31// commented otherwise.
32
33#ifndef _SYSINFO_H_
34#define _SYSINFO_H_
35
36#include <config.h>
37
38#include <time.h>
39#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
40#include <windows.h>   // for DWORD
41#include <TlHelp32.h>  // for CreateToolhelp32Snapshot
42#endif
43#ifdef HAVE_UNISTD_H
44#include <unistd.h>    // for pid_t
45#endif
46#include <stddef.h>    // for size_t
47#include <limits.h>    // for PATH_MAX
48#include "base/basictypes.h"
49#include "base/logging.h"   // for RawFD
50
51// This getenv function is safe to call before the C runtime is initialized.
52// On Windows, it utilizes GetEnvironmentVariable() and on unix it uses
53// /proc/self/environ instead calling getenv().  It's intended to be used in
54// routines that run before main(), when the state required for getenv() may
55// not be set up yet.  In particular, errno isn't set up until relatively late
56// (after the pthreads library has a chance to make it threadsafe), and
57// getenv() doesn't work until then.
58// On some platforms, this call will utilize the same, static buffer for
59// repeated GetenvBeforeMain() calls. Callers should not expect pointers from
60// this routine to be long lived.
61// Note that on unix, /proc only has the environment at the time the
62// application was started, so this routine ignores setenv() calls/etc.  Also
63// note it only reads the first 16K of the environment.
64extern const char* GetenvBeforeMain(const char* name);
65
66// This takes as an argument an environment-variable name (like
67// CPUPROFILE) whose value is supposed to be a file-path, and sets
68// path to that path, and returns true.  Non-trivial for surprising
69// reasons, as documented in sysinfo.cc.  path must have space PATH_MAX.
70extern bool GetUniquePathFromEnv(const char* env_name, char* path);
71
72extern int NumCPUs();
73
74void SleepForMilliseconds(int milliseconds);
75
76// processor cycles per second of each processor.  Thread-safe.
77extern double CyclesPerSecond(void);
78
79
80//  Return true if we're running POSIX (e.g., NPTL on Linux) threads,
81//  as opposed to a non-POSIX thread libary.  The thing that we care
82//  about is whether a thread's pid is the same as the thread that
83//  spawned it.  If so, this function returns true.
84//  Thread-safe.
85//  Note: We consider false negatives to be OK.
86bool HasPosixThreads();
87
88#ifndef SWIG  // SWIG doesn't like struct Buffer and variable arguments.
89
90// A ProcMapsIterator abstracts access to /proc/maps for a given
91// process. Needs to be stack-allocatable and avoid using stdio/malloc
92// so it can be used in the google stack dumper, heap-profiler, etc.
93//
94// On Windows and Mac OS X, this iterator iterates *only* over DLLs
95// mapped into this process space.  For Linux, FreeBSD, and Solaris,
96// it iterates over *all* mapped memory regions, including anonymous
97// mmaps.  For other O/Ss, it is unlikely to work at all, and Valid()
98// will always return false.  Also note: this routine only works on
99// FreeBSD if procfs is mounted: make sure this is in your /etc/fstab:
100//    proc            /proc   procfs  rw 0 0
101class ProcMapsIterator {
102 public:
103  struct Buffer {
104#ifdef __FreeBSD__
105    // FreeBSD requires us to read all of the maps file at once, so
106    // we have to make a buffer that's "always" big enough
107    static const size_t kBufSize = 102400;
108#else   // a one-line buffer is good enough
109    static const size_t kBufSize = PATH_MAX + 1024;
110#endif
111    char buf_[kBufSize];
112  };
113
114
115  // Create a new iterator for the specified pid.  pid can be 0 for "self".
116  explicit ProcMapsIterator(pid_t pid);
117
118  // Create an iterator with specified storage (for use in signal
119  // handler). "buffer" should point to a ProcMapsIterator::Buffer
120  // buffer can be NULL in which case a bufer will be allocated.
121  ProcMapsIterator(pid_t pid, Buffer *buffer);
122
123  // Iterate through maps_backing instead of maps if use_maps_backing
124  // is true.  Otherwise the same as above.  buffer can be NULL and
125  // it will allocate a buffer itself.
126  ProcMapsIterator(pid_t pid, Buffer *buffer,
127                   bool use_maps_backing);
128
129  // Returns true if the iterator successfully initialized;
130  bool Valid() const;
131
132  // Returns a pointer to the most recently parsed line. Only valid
133  // after Next() returns true, and until the iterator is destroyed or
134  // Next() is called again.  This may give strange results on non-Linux
135  // systems.  Prefer FormatLine() if that may be a concern.
136  const char *CurrentLine() const { return stext_; }
137
138  // Writes the "canonical" form of the /proc/xxx/maps info for a single
139  // line to the passed-in buffer. Returns the number of bytes written,
140  // or 0 if it was not able to write the complete line.  (To guarantee
141  // success, buffer should have size at least Buffer::kBufSize.)
142  // Takes as arguments values set via a call to Next().  The
143  // "canonical" form of the line (taken from linux's /proc/xxx/maps):
144  //    <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)>   +
145  //    <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the
146  // eg
147  //    08048000-0804c000 r-xp 00000000 03:01 3793678    /bin/cat
148  // If you don't have the dev_t (dev), feel free to pass in 0.
149  // (Next() doesn't return a dev_t, though NextExt does.)
150  //
151  // Note: if filename and flags were obtained via a call to Next(),
152  // then the output of this function is only valid if Next() returned
153  // true, and only until the iterator is destroyed or Next() is
154  // called again.  (Since filename, at least, points into CurrentLine.)
155  static int FormatLine(char* buffer, int bufsize,
156                        uint64 start, uint64 end, const char *flags,
157                        uint64 offset, int64 inode, const char *filename,
158                        dev_t dev);
159
160  // Find the next entry in /proc/maps; return true if found or false
161  // if at the end of the file.
162  //
163  // Any of the result pointers can be NULL if you're not interested
164  // in those values.
165  //
166  // If "flags" and "filename" are passed, they end up pointing to
167  // storage within the ProcMapsIterator that is valid only until the
168  // iterator is destroyed or Next() is called again. The caller may
169  // modify the contents of these strings (up as far as the first NUL,
170  // and only until the subsequent call to Next()) if desired.
171
172  // The offsets are all uint64 in order to handle the case of a
173  // 32-bit process running on a 64-bit kernel
174  //
175  // IMPORTANT NOTE: see top-of-class notes for details about what
176  // mapped regions Next() iterates over, depending on O/S.
177  // TODO(csilvers): make flags and filename const.
178  bool Next(uint64 *start, uint64 *end, char **flags,
179            uint64 *offset, int64 *inode, char **filename);
180
181  bool NextExt(uint64 *start, uint64 *end, char **flags,
182               uint64 *offset, int64 *inode, char **filename,
183               uint64 *file_mapping, uint64 *file_pages,
184               uint64 *anon_mapping, uint64 *anon_pages,
185               dev_t *dev);
186
187  ~ProcMapsIterator();
188
189 private:
190  void Init(pid_t pid, Buffer *buffer, bool use_maps_backing);
191
192  char *ibuf_;        // input buffer
193  char *stext_;       // start of text
194  char *etext_;       // end of text
195  char *nextline_;    // start of next line
196  char *ebuf_;        // end of buffer (1 char for a nul)
197#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
198  HANDLE snapshot_;   // filehandle on dll info
199  // In a change from the usual W-A pattern, there is no A variant of
200  // MODULEENTRY32.  Tlhelp32.h #defines the W variant, but not the A.
201  // We want the original A variants, and this #undef is the only
202  // way I see to get them.  Redefining it when we're done prevents us
203  // from affecting other .cc files.
204# ifdef MODULEENTRY32  // Alias of W
205#   undef MODULEENTRY32
206  MODULEENTRY32 module_;   // info about current dll (and dll iterator)
207#   define MODULEENTRY32 MODULEENTRY32W
208# else  // It's the ascii, the one we want.
209  MODULEENTRY32 module_;   // info about current dll (and dll iterator)
210# endif
211#elif defined(__MACH__)
212  int current_image_; // dll's are called "images" in macos parlance
213  int current_load_cmd_;   // the segment of this dll we're examining
214#elif defined(__sun__)     // Solaris
215  int fd_;
216  char current_filename_[PATH_MAX];
217#else
218  int fd_;            // filehandle on /proc/*/maps
219#endif
220  pid_t pid_;
221  char flags_[10];
222  Buffer* dynamic_buffer_;  // dynamically-allocated Buffer
223  bool using_maps_backing_; // true if we are looking at maps_backing instead of maps.
224};
225
226#endif  /* #ifndef SWIG */
227
228// Helper routines
229
230namespace tcmalloc {
231int FillProcSelfMaps(char buf[], int size, bool* wrote_all);
232void DumpProcSelfMaps(RawFD fd);
233}
234
235#endif   /* #ifndef _SYSINFO_H_ */
236