[WTF] Move currentCPUTime and sleep(Seconds) to CPUTime.h and Seconds.h respectively
[WebKit-https.git] / Source / WebKit / Platform / unix / SharedMemoryUnix.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (c) 2010 University of Szeged
4  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #if USE(UNIX_DOMAIN_SOCKETS)
30 #include "SharedMemory.h"
31
32 #include "Decoder.h"
33 #include "Encoder.h"
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <stdlib.h>
37 #include <sys/mman.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 #include <wtf/Assertions.h>
42 #include <wtf/RandomNumber.h>
43 #include <wtf/UniStdExtras.h>
44 #include <wtf/text/CString.h>
45 #include <wtf/text/WTFString.h>
46
47 namespace WebKit {
48
49 SharedMemory::Handle::Handle()
50 {
51 }
52
53 SharedMemory::Handle::~Handle()
54 {
55 }
56
57 void SharedMemory::Handle::clear()
58 {
59     m_attachment = IPC::Attachment();
60 }
61
62 bool SharedMemory::Handle::isNull() const
63 {
64     return m_attachment.fileDescriptor() == -1;
65 }
66
67 void SharedMemory::Handle::encode(IPC::Encoder& encoder) const
68 {
69     encoder << releaseAttachment();
70 }
71
72 bool SharedMemory::Handle::decode(IPC::Decoder& decoder, Handle& handle)
73 {
74     ASSERT_ARG(handle, handle.isNull());
75
76     IPC::Attachment attachment;
77     if (!decoder.decode(attachment))
78         return false;
79
80     handle.adoptAttachment(WTFMove(attachment));
81     return true;
82 }
83
84 IPC::Attachment SharedMemory::Handle::releaseAttachment() const
85 {
86     return WTFMove(m_attachment);
87 }
88
89 void SharedMemory::Handle::adoptAttachment(IPC::Attachment&& attachment)
90 {
91     ASSERT(isNull());
92
93     m_attachment = WTFMove(attachment);
94 }
95
96 static inline int accessModeMMap(SharedMemory::Protection protection)
97 {
98     switch (protection) {
99     case SharedMemory::Protection::ReadOnly:
100         return PROT_READ;
101     case SharedMemory::Protection::ReadWrite:
102         return PROT_READ | PROT_WRITE;
103     }
104
105     ASSERT_NOT_REACHED();
106     return PROT_READ | PROT_WRITE;
107 }
108
109 RefPtr<SharedMemory> SharedMemory::create(void* address, size_t size, Protection protection)
110 {
111     CString tempName;
112
113     int fileDescriptor = -1;
114     for (int tries = 0; fileDescriptor == -1 && tries < 10; ++tries) {
115         String name = String("/WK2SharedMemory.") + String::number(static_cast<unsigned>(WTF::randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)));
116         tempName = name.utf8();
117
118         do {
119             fileDescriptor = shm_open(tempName.data(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
120         } while (fileDescriptor == -1 && errno == EINTR);
121     }
122     if (fileDescriptor == -1) {
123         WTFLogAlways("Failed to create shared memory file %s: %s", tempName.data(), strerror(errno));
124         return nullptr;
125     }
126
127     while (ftruncate(fileDescriptor, size) == -1) {
128         if (errno != EINTR) {
129             closeWithRetry(fileDescriptor);
130             shm_unlink(tempName.data());
131             return nullptr;
132         }
133     }
134
135     void* data = mmap(address, size, accessModeMMap(protection), MAP_SHARED, fileDescriptor, 0);
136     if (data == MAP_FAILED) {
137         closeWithRetry(fileDescriptor);
138         shm_unlink(tempName.data());
139         return nullptr;
140     }
141
142     shm_unlink(tempName.data());
143
144     RefPtr<SharedMemory> instance = adoptRef(new SharedMemory());
145     instance->m_data = data;
146     instance->m_fileDescriptor = fileDescriptor;
147     instance->m_size = size;
148     return instance;
149 }
150
151 RefPtr<SharedMemory> SharedMemory::allocate(size_t size)
152 {
153     return SharedMemory::create(nullptr, size, SharedMemory::Protection::ReadWrite);
154 }
155
156 RefPtr<SharedMemory> SharedMemory::map(const Handle& handle, Protection protection)
157 {
158     ASSERT(!handle.isNull());
159
160     int fd = handle.m_attachment.releaseFileDescriptor();
161     void* data = mmap(0, handle.m_attachment.size(), accessModeMMap(protection), MAP_SHARED, fd, 0);
162     closeWithRetry(fd);
163     if (data == MAP_FAILED)
164         return nullptr;
165
166     RefPtr<SharedMemory> instance = wrapMap(data, handle.m_attachment.size(), -1);
167     instance->m_fileDescriptor = std::nullopt;
168     instance->m_isWrappingMap = false;
169     return instance;
170 }
171
172 RefPtr<SharedMemory> SharedMemory::wrapMap(void* data, size_t size, int fileDescriptor)
173 {
174     RefPtr<SharedMemory> instance = adoptRef(new SharedMemory());
175     instance->m_data = data;
176     instance->m_size = size;
177     instance->m_fileDescriptor = fileDescriptor;
178     instance->m_isWrappingMap = true;
179     return instance;
180 }
181
182 SharedMemory::~SharedMemory()
183 {
184     if (m_isWrappingMap)
185         return;
186
187     munmap(m_data, m_size);
188     if (m_fileDescriptor)
189         closeWithRetry(m_fileDescriptor.value());
190 }
191
192 bool SharedMemory::createHandle(Handle& handle, Protection)
193 {
194     ASSERT_ARG(handle, handle.isNull());
195     ASSERT(m_fileDescriptor);
196
197     // FIXME: Handle the case where the passed Protection is ReadOnly.
198     // See https://bugs.webkit.org/show_bug.cgi?id=131542.
199
200     int duplicatedHandle = dupCloseOnExec(m_fileDescriptor.value());
201     if (duplicatedHandle == -1) {
202         ASSERT_NOT_REACHED();
203         return false;
204     }
205     handle.m_attachment = IPC::Attachment(duplicatedHandle, m_size);
206     return true;
207 }
208
209 unsigned SharedMemory::systemPageSize()
210 {
211     static unsigned pageSize = 0;
212
213     if (!pageSize)
214         pageSize = getpagesize();
215
216     return pageSize;
217 }
218
219 } // namespace WebKit
220
221 #endif
222