Thrill  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
porting.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * thrill/common/porting.cpp
3  *
4  * Part of Project Thrill - http://project-thrill.org
5  *
6  * Copyright (C) 2015 Alexander Noe <[email protected]>
7  * Copyright (C) 2015 Timo Bingmann <[email protected]>
8  *
9  * All rights reserved. Published under the BSD-2 license in the LICENSE file.
10  ******************************************************************************/
11 
15 #include <thrill/common/string.hpp>
17 
18 #include <tlx/string/replace.hpp>
19 #include <tlx/unused.hpp>
20 
21 #include <fcntl.h>
22 
23 #include <fstream>
24 #include <mutex>
25 #include <sstream>
26 #include <string>
27 #include <vector>
28 
29 #if !defined(_MSC_VER)
30 
31 #include <unistd.h>
32 
33 #else
34 
35 #include <io.h>
36 
37 #endif
38 
39 namespace thrill {
40 namespace common {
41 
42 void PortSetCloseOnExec(int fd) {
43 #if !defined(_MSC_VER)
44  if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
45  throw ErrnoException("Error setting FD_CLOEXEC on file descriptor");
46  }
47 #else
48  tlx::unused(fd);
49 #endif
50 }
51 
52 void MakePipe(int out_pipefds[2]) {
53 #if THRILL_HAVE_PIPE2
54  if (pipe2(out_pipefds, O_CLOEXEC) != 0)
55  throw ErrnoException("Error creating pipe");
56 #elif defined(_MSC_VER)
57  if (_pipe(out_pipefds, 256, O_BINARY) != 0)
58  throw ErrnoException("Error creating pipe");
59 #else
60  if (pipe(out_pipefds) != 0)
61  throw ErrnoException("Error creating pipe");
62 
63  PortSetCloseOnExec(out_pipefds[0]);
64  PortSetCloseOnExec(out_pipefds[1]);
65 #endif
66 }
67 
69 #if __linux__
70  // read cmdline from /proc/<pid>/cmdline
71  pid_t mypid = getpid();
72 
73  std::ifstream proc("/proc/" + std::to_string(mypid) + "/cmdline");
74  if (!proc.good()) return;
75 
76  std::vector<std::string> args;
77  std::string arg;
78  while (std::getline(proc, arg, '\0'))
79  args.emplace_back(arg);
80 
81  std::string prog;
82  if (!args.empty()) {
83  prog = args[0];
84  std::string::size_type slashpos = prog.rfind('/');
85  if (slashpos != std::string::npos)
86  prog = prog.substr(slashpos + 1);
87  }
88 
89  std::ostringstream cmdline;
90  for (size_t i = 0; i < args.size(); ++i) {
91  if (i != 0)
92  cmdline << ' ';
93 
94  arg = args[i];
95  // escape " -> \"
96  if (arg.find('"') != std::string::npos)
97  tlx::replace_all(arg, "\"", "\\\"");
98  cmdline << arg;
99  }
100 
101  logger << "class" << "Cmdline"
102  << "event" << "start"
103  << "program" << prog
104  << "argv" << args
105  << "cmdline" << cmdline.str();
106 #else
107  tlx::unused(logger);
108 #endif
109 }
110 
111 void SetCpuAffinity(std::thread& thread, size_t cpu_id) {
112 #if __linux__ && !THRILL_ON_TRAVIS
113  cpu_set_t cpuset;
114  CPU_ZERO(&cpuset);
115  CPU_SET(cpu_id % std::thread::hardware_concurrency(), &cpuset);
116  int rc = pthread_setaffinity_np(
117  thread.native_handle(), sizeof(cpu_set_t), &cpuset);
118  if (rc != 0) {
119  LOG1 << "Error calling pthread_setaffinity_np(): "
120  << rc << ": " << strerror(errno);
121  }
122 #else
123  tlx::unused(thread);
124  tlx::unused(cpu_id);
125 #endif
126 }
127 
128 void SetCpuAffinity(size_t cpu_id) {
129 #if __linux__ && !THRILL_ON_TRAVIS
130  cpu_set_t cpuset;
131  CPU_ZERO(&cpuset);
132  CPU_SET(cpu_id % std::thread::hardware_concurrency(), &cpuset);
133  int rc = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
134  if (rc != 0) {
135  LOG1 << "Error calling pthread_setaffinity_np(): "
136  << rc << ": " << strerror(errno);
137  }
138 #else
139  tlx::unused(cpu_id);
140 #endif
141 }
142 
144 #if __linux__
145  char buffer[64];
146  gethostname(buffer, 64);
147  return buffer;
148 #else
149  return "<unknown host>";
150 #endif
151 }
152 
153 struct dirent * ts_readdir(DIR* dirp) {
154  static std::mutex s_mutex;
155  std::unique_lock<std::mutex> lock(s_mutex);
156  return ::readdir(dirp);
157 }
158 
159 } // namespace common
160 } // namespace thrill
161 
162 /******************************************************************************/
void LogCmdlineParams(JsonLogger &logger)
Definition: porting.cpp:68
#define LOG1
Definition: logger.hpp:28
An Exception which is thrown on system errors and contains errno information.
void PortSetCloseOnExec(int fd)
set FD_CLOEXEC on file descriptor (if possible)
Definition: porting.cpp:42
void MakePipe(int out_pipefds[2])
create a pair of pipe file descriptors
Definition: porting.cpp:52
static by_string to_string(int val)
convert to string
void unused(Types &&...)
Definition: unused.hpp:20
std::string & replace_all(std::string *str, const std::string &needle, const std::string &instead)
Replace all occurrences of needle in str.
Definition: replace.cpp:141
std::string GetHostname()
get hostname
Definition: porting.cpp:143
struct dirent * ts_readdir(DIR *dirp)
mutex-locked readdir() call
Definition: porting.cpp:153
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
Definition: allocator.hpp:220
JsonLogger is a receiver of JSON output objects for logging.
Definition: json_logger.hpp:69
#define O_BINARY
Definition: sys_file.cpp:34
void SetCpuAffinity(std::thread &thread, size_t cpu_id)
set cpu/core affinity of a thread
Definition: porting.cpp:111