]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* |
2 | * This file is open source software, licensed to you under the terms | |
3 | * of the Apache License, Version 2.0 (the "License"). See the NOTICE file | |
4 | * distributed with this work for additional information regarding copyright | |
5 | * ownership. You may not use this file except in compliance with the License. | |
6 | * | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, | |
12 | * software distributed under the License is distributed on an | |
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | * KIND, either express or implied. See the License for the | |
15 | * specific language governing permissions and limitations | |
16 | * under the License. | |
17 | */ | |
18 | /* | |
19 | * Copyright (C) 2014 Cloudius Systems, Ltd. | |
20 | */ | |
21 | ||
22 | #include <seastar/core/posix.hh> | |
23 | #include <seastar/core/align.hh> | |
1e59de90 | 24 | #include <seastar/util/critical_alloc_section.hh> |
11fdf7f2 | 25 | #include <sys/mman.h> |
f67539c2 | 26 | #include <sys/inotify.h> |
11fdf7f2 TL |
27 | |
28 | namespace seastar { | |
29 | ||
30 | file_desc | |
31 | file_desc::temporary(sstring directory) { | |
32 | // FIXME: add O_TMPFILE support one day | |
33 | directory += "/XXXXXX"; | |
34 | std::vector<char> templat(directory.c_str(), directory.c_str() + directory.size() + 1); | |
35 | int fd = ::mkstemp(templat.data()); | |
36 | throw_system_error_on(fd == -1); | |
37 | int r = ::unlink(templat.data()); | |
38 | throw_system_error_on(r == -1); // leaks created file, but what can we do? | |
39 | return file_desc(fd); | |
40 | } | |
41 | ||
f67539c2 TL |
42 | file_desc |
43 | file_desc::inotify_init(int flags) { | |
44 | int fd = ::inotify_init1(flags); | |
45 | throw_system_error_on(fd == -1, "could not create inotify instance"); | |
46 | return file_desc(fd); | |
47 | } | |
48 | ||
1e59de90 TL |
49 | sstring file_desc::fdinfo() const noexcept { |
50 | memory::scoped_critical_alloc_section _; | |
51 | auto path = fmt::format("/proc/self/fd/{}", _fd); | |
52 | temporary_buffer<char> buf(64); | |
53 | auto ret = ::readlink(path.c_str(), buf.get_write(), buf.size()); | |
54 | if (ret > 0) { | |
55 | return sstring(buf.get(), ret); | |
56 | } else { | |
57 | return fmt::format("error({})", errno); | |
58 | } | |
59 | } | |
60 | ||
11fdf7f2 TL |
61 | void mmap_deleter::operator()(void* ptr) const { |
62 | ::munmap(ptr, _size); | |
63 | } | |
64 | ||
65 | mmap_area mmap_anonymous(void* addr, size_t length, int prot, int flags) { | |
66 | auto ret = ::mmap(addr, length, prot, flags | MAP_ANONYMOUS, -1, 0); | |
67 | throw_system_error_on(ret == MAP_FAILED); | |
68 | return mmap_area(reinterpret_cast<char*>(ret), mmap_deleter{length}); | |
69 | } | |
70 | ||
71 | void* posix_thread::start_routine(void* arg) noexcept { | |
72 | auto pfunc = reinterpret_cast<std::function<void ()>*>(arg); | |
73 | (*pfunc)(); | |
74 | return nullptr; | |
75 | } | |
76 | ||
77 | posix_thread::posix_thread(std::function<void ()> func) | |
78 | : posix_thread(attr{}, std::move(func)) { | |
79 | } | |
80 | ||
81 | posix_thread::posix_thread(attr a, std::function<void ()> func) | |
82 | : _func(std::make_unique<std::function<void ()>>(std::move(func))) { | |
83 | pthread_attr_t pa; | |
84 | auto r = pthread_attr_init(&pa); | |
85 | if (r) { | |
86 | throw std::system_error(r, std::system_category()); | |
87 | } | |
9f95a23c TL |
88 | |
89 | #ifndef SEASTAR_ASAN_ENABLED | |
11fdf7f2 TL |
90 | auto stack_size = a._stack_size.size; |
91 | if (!stack_size) { | |
92 | stack_size = 2 << 20; | |
93 | } | |
94 | // allocate guard area as well | |
95 | _stack = mmap_anonymous(nullptr, stack_size + (4 << 20), | |
96 | PROT_NONE, MAP_PRIVATE | MAP_NORESERVE); | |
97 | auto stack_start = align_up(_stack.get() + 1, 2 << 20); | |
98 | mmap_area real_stack = mmap_anonymous(stack_start, stack_size, | |
99 | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_STACK); | |
100 | real_stack.release(); // protected by @_stack | |
101 | ::madvise(stack_start, stack_size, MADV_HUGEPAGE); | |
102 | r = pthread_attr_setstack(&pa, stack_start, stack_size); | |
103 | if (r) { | |
104 | throw std::system_error(r, std::system_category()); | |
105 | } | |
9f95a23c TL |
106 | #endif |
107 | ||
11fdf7f2 TL |
108 | r = pthread_create(&_pthread, &pa, |
109 | &posix_thread::start_routine, _func.get()); | |
110 | if (r) { | |
111 | throw std::system_error(r, std::system_category()); | |
112 | } | |
113 | } | |
114 | ||
115 | posix_thread::posix_thread(posix_thread&& x) | |
116 | : _func(std::move(x._func)), _pthread(x._pthread), _valid(x._valid) | |
117 | , _stack(std::move(x._stack)) { | |
118 | x._valid = false; | |
119 | } | |
120 | ||
121 | posix_thread::~posix_thread() { | |
122 | assert(!_valid); | |
123 | } | |
124 | ||
125 | void posix_thread::join() { | |
126 | assert(_valid); | |
127 | pthread_join(_pthread, NULL); | |
128 | _valid = false; | |
129 | } | |
130 | ||
1e59de90 TL |
131 | std::set<unsigned> get_current_cpuset() { |
132 | cpu_set_t cs; | |
133 | auto r = pthread_getaffinity_np(pthread_self(), sizeof(cs), &cs); | |
134 | assert(r == 0); | |
135 | std::set<unsigned> ret; | |
136 | unsigned nr = CPU_COUNT(&cs); | |
137 | for (int cpu = 0; cpu < CPU_SETSIZE && ret.size() < nr; cpu++) { | |
138 | if (CPU_ISSET(cpu, &cs)) { | |
139 | ret.insert(cpu); | |
140 | } | |
141 | } | |
142 | return ret; | |
143 | } | |
144 | ||
11fdf7f2 TL |
145 | } |
146 |