]>
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> | |
24 | #include <sys/mman.h> | |
f67539c2 | 25 | #include <sys/inotify.h> |
11fdf7f2 TL |
26 | |
27 | namespace seastar { | |
28 | ||
29 | file_desc | |
30 | file_desc::temporary(sstring directory) { | |
31 | // FIXME: add O_TMPFILE support one day | |
32 | directory += "/XXXXXX"; | |
33 | std::vector<char> templat(directory.c_str(), directory.c_str() + directory.size() + 1); | |
34 | int fd = ::mkstemp(templat.data()); | |
35 | throw_system_error_on(fd == -1); | |
36 | int r = ::unlink(templat.data()); | |
37 | throw_system_error_on(r == -1); // leaks created file, but what can we do? | |
38 | return file_desc(fd); | |
39 | } | |
40 | ||
f67539c2 TL |
41 | file_desc |
42 | file_desc::inotify_init(int flags) { | |
43 | int fd = ::inotify_init1(flags); | |
44 | throw_system_error_on(fd == -1, "could not create inotify instance"); | |
45 | return file_desc(fd); | |
46 | } | |
47 | ||
11fdf7f2 TL |
48 | void mmap_deleter::operator()(void* ptr) const { |
49 | ::munmap(ptr, _size); | |
50 | } | |
51 | ||
52 | mmap_area mmap_anonymous(void* addr, size_t length, int prot, int flags) { | |
53 | auto ret = ::mmap(addr, length, prot, flags | MAP_ANONYMOUS, -1, 0); | |
54 | throw_system_error_on(ret == MAP_FAILED); | |
55 | return mmap_area(reinterpret_cast<char*>(ret), mmap_deleter{length}); | |
56 | } | |
57 | ||
58 | void* posix_thread::start_routine(void* arg) noexcept { | |
59 | auto pfunc = reinterpret_cast<std::function<void ()>*>(arg); | |
60 | (*pfunc)(); | |
61 | return nullptr; | |
62 | } | |
63 | ||
64 | posix_thread::posix_thread(std::function<void ()> func) | |
65 | : posix_thread(attr{}, std::move(func)) { | |
66 | } | |
67 | ||
68 | posix_thread::posix_thread(attr a, std::function<void ()> func) | |
69 | : _func(std::make_unique<std::function<void ()>>(std::move(func))) { | |
70 | pthread_attr_t pa; | |
71 | auto r = pthread_attr_init(&pa); | |
72 | if (r) { | |
73 | throw std::system_error(r, std::system_category()); | |
74 | } | |
9f95a23c TL |
75 | |
76 | #ifndef SEASTAR_ASAN_ENABLED | |
11fdf7f2 TL |
77 | auto stack_size = a._stack_size.size; |
78 | if (!stack_size) { | |
79 | stack_size = 2 << 20; | |
80 | } | |
81 | // allocate guard area as well | |
82 | _stack = mmap_anonymous(nullptr, stack_size + (4 << 20), | |
83 | PROT_NONE, MAP_PRIVATE | MAP_NORESERVE); | |
84 | auto stack_start = align_up(_stack.get() + 1, 2 << 20); | |
85 | mmap_area real_stack = mmap_anonymous(stack_start, stack_size, | |
86 | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_STACK); | |
87 | real_stack.release(); // protected by @_stack | |
88 | ::madvise(stack_start, stack_size, MADV_HUGEPAGE); | |
89 | r = pthread_attr_setstack(&pa, stack_start, stack_size); | |
90 | if (r) { | |
91 | throw std::system_error(r, std::system_category()); | |
92 | } | |
9f95a23c TL |
93 | #endif |
94 | ||
11fdf7f2 TL |
95 | r = pthread_create(&_pthread, &pa, |
96 | &posix_thread::start_routine, _func.get()); | |
97 | if (r) { | |
98 | throw std::system_error(r, std::system_category()); | |
99 | } | |
100 | } | |
101 | ||
102 | posix_thread::posix_thread(posix_thread&& x) | |
103 | : _func(std::move(x._func)), _pthread(x._pthread), _valid(x._valid) | |
104 | , _stack(std::move(x._stack)) { | |
105 | x._valid = false; | |
106 | } | |
107 | ||
108 | posix_thread::~posix_thread() { | |
109 | assert(!_valid); | |
110 | } | |
111 | ||
112 | void posix_thread::join() { | |
113 | assert(_valid); | |
114 | pthread_join(_pthread, NULL); | |
115 | _valid = false; | |
116 | } | |
117 | ||
118 | } | |
119 |