Coverage Report

Created: 2025-07-23 08:18

/src/x265/source/common/ringmem.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * Copyright (C) 2013-2017 MulticoreWare, Inc
3
 *
4
 * Authors: liwei <liwei@multicorewareinc.com>
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
19
 *
20
 * This program is also available under a commercial proprietary license.
21
 * For more information, contact us at license @ x265.com
22
 *****************************************************************************/
23
24
#include "ringmem.h"
25
26
#ifndef _WIN32
27
#include <sys/mman.h>
28
#endif ////< _WIN32
29
30
#ifdef _WIN32
31
#define X265_SHARED_MEM_NAME                    "Local\\_x265_shr_mem_"
32
#define X265_SEMAPHORE_RINGMEM_WRITER_NAME      "_x265_semW_"
33
#define X265_SEMAPHORE_RINGMEM_READER_NAME      "_x265_semR_"
34
#else /* POSIX / pthreads */
35
0
#define X265_SHARED_MEM_NAME                    "/tmp/_x265_shr_mem_"
36
0
#define X265_SEMAPHORE_RINGMEM_WRITER_NAME      "/tmp/_x265_semW_"
37
0
#define X265_SEMAPHORE_RINGMEM_READER_NAME      "/tmp/_x265_semR_"
38
#endif
39
40
0
#define RINGMEM_ALLIGNMENT                       64
41
42
namespace X265_NS {
43
    RingMem::RingMem() 
44
0
        : m_initialized(false)
45
0
        , m_protectRW(false)
46
0
        , m_itemSize(0)
47
0
        , m_itemCnt(0)
48
        , m_dataPool(NULL)
49
        , m_shrMem(NULL)
50
#ifdef _WIN32
51
        , m_handle(NULL)
52
#else //_WIN32
53
        , m_filepath(NULL)
54
#endif //_WIN32
55
        , m_writeSem(NULL)
56
        , m_readSem(NULL)
57
0
    {
58
0
    }
59
60
61
    RingMem::~RingMem()
62
0
    {
63
0
    }
64
65
0
    bool RingMem::skipRead(int32_t cnt) {
66
0
        if (!m_initialized)
67
0
        {
68
0
            return false;
69
0
        }
70
71
0
        if (m_protectRW)
72
0
        {
73
0
            for (int i = 0; i < cnt; i++)
74
0
            {
75
0
                m_readSem->take();
76
0
            }
77
0
        }
78
        
79
0
        ATOMIC_ADD(&m_shrMem->m_read, cnt);
80
81
0
        if (m_protectRW)
82
0
        {
83
0
            m_writeSem->give(cnt);
84
0
        }
85
86
0
        return true;
87
0
    }
88
89
0
    bool RingMem::skipWrite(int32_t cnt) {
90
0
        if (!m_initialized)
91
0
        {
92
0
            return false;
93
0
        }
94
95
0
        if (m_protectRW)
96
0
        {
97
0
            for (int i = 0; i < cnt; i++)
98
0
            {
99
0
                m_writeSem->take();
100
0
            }
101
0
        }
102
103
0
        ATOMIC_ADD(&m_shrMem->m_write, cnt);
104
105
0
        if (m_protectRW)
106
0
        {
107
0
            m_readSem->give(cnt);
108
0
        }
109
110
0
        return true;
111
0
    }
112
113
    ///< initialize
114
    bool RingMem::init(int32_t itemSize, int32_t itemCnt, const char *name, bool protectRW)
115
0
    {
116
        ///< check parameters
117
0
        if (itemSize <= 0 || itemCnt <= 0 || NULL == name)
118
0
        {
119
            ///< invalid parameters 
120
0
            return false;
121
0
        }
122
123
0
        if (!m_initialized)
124
0
        {
125
            ///< formating names
126
0
            char nameBuf[MAX_SHR_NAME_LEN] = { 0 };
127
128
            ///< shared memory name
129
0
            snprintf(nameBuf, sizeof(nameBuf) - 1, "%s%s", X265_SHARED_MEM_NAME, name);
130
131
            ///< create or open shared memory
132
0
            bool newCreated = false;
133
134
            ///< calculate the size of the shared memory
135
0
            int32_t shrMemSize = (itemSize * itemCnt + sizeof(ShrMemCtrl) + RINGMEM_ALLIGNMENT - 1) & ~(RINGMEM_ALLIGNMENT - 1);
136
137
#ifdef _WIN32
138
            HANDLE h = OpenFileMappingA(FILE_MAP_WRITE | FILE_MAP_READ, FALSE, nameBuf);
139
            if (!h)
140
            {
141
                h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, shrMemSize, nameBuf);
142
143
                if (!h)
144
                {
145
                    return false;
146
                }
147
148
                newCreated = true;
149
            }
150
151
            void *pool = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);
152
153
            ///< should not close the handle here, otherwise the OpenFileMapping would fail
154
            //CloseHandle(h);
155
            m_handle = h;
156
157
            if (!pool)
158
            {
159
                return false;
160
            }
161
162
#else /* POSIX / pthreads */
163
0
            mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
164
0
            int flag = O_RDWR;
165
0
            int shrfd = -1;
166
0
            if ((shrfd = open(nameBuf, flag, mode)) < 0)
167
0
            {
168
0
                flag |= O_CREAT;
169
                
170
0
                shrfd = open(nameBuf, flag, mode);
171
0
                if (shrfd < 0)
172
0
                {
173
0
                    return false;
174
0
                }
175
0
                newCreated = true;
176
177
0
                lseek(shrfd, shrMemSize - 1, SEEK_SET);
178
179
0
                if (-1 == write(shrfd, "\0", 1))
180
0
                {
181
0
                    close(shrfd);
182
0
                    return false;
183
0
                }
184
185
0
                if (lseek(shrfd, 0, SEEK_END) < shrMemSize)
186
0
                {
187
0
                    close(shrfd);
188
0
                    return false;
189
0
                }
190
0
            }
191
192
0
            void *pool = mmap(0,
193
0
                shrMemSize,
194
0
                PROT_READ | PROT_WRITE,
195
0
                MAP_SHARED,
196
0
                shrfd,
197
0
                0);
198
199
0
            close(shrfd);
200
0
            if (pool == MAP_FAILED)
201
0
            {               
202
0
                return false;
203
0
            }
204
205
0
            m_filepath = strdup(nameBuf);
206
0
#endif ///< _WIN32
207
208
0
            if (newCreated)
209
0
            {
210
0
                memset(pool, 0, shrMemSize);
211
0
            }
212
            
213
0
            m_shrMem = reinterpret_cast<ShrMemCtrl *>(pool);
214
0
            m_dataPool = reinterpret_cast<uint8_t *>(pool) + sizeof(ShrMemCtrl);
215
0
            m_itemSize = itemSize;
216
0
            m_itemCnt = itemCnt;
217
0
            m_initialized = true;
218
219
0
            if (protectRW)
220
0
            {
221
0
                m_protectRW = true;
222
0
                m_writeSem = new NamedSemaphore();
223
0
                if (!m_writeSem)
224
0
                {
225
0
                    release();
226
0
                    return false;
227
0
                }
228
229
                ///< shared memory name
230
0
                snprintf(nameBuf, sizeof(nameBuf) - 1, "%s%s", X265_SEMAPHORE_RINGMEM_WRITER_NAME, name);
231
0
                if (!m_writeSem->create(nameBuf, m_itemCnt, m_itemCnt))
232
0
                {
233
0
                    release();
234
0
                    return false;
235
0
                }
236
237
0
                m_readSem = new NamedSemaphore();
238
0
                if (!m_readSem)
239
0
                {
240
0
                    release();
241
0
                    return false;
242
0
                }
243
244
                ///< shared memory name
245
0
                snprintf(nameBuf, sizeof(nameBuf) - 1, "%s%s", X265_SEMAPHORE_RINGMEM_READER_NAME, name);
246
0
                if (!m_readSem->create(nameBuf, 0, m_itemCnt))
247
0
                {
248
0
                    release();
249
0
                    return false;
250
0
                }
251
0
            }
252
0
        }
253
254
0
        return true;
255
0
    }
256
    ///< finalize
257
    void RingMem::release()
258
0
    {
259
0
        if (m_initialized)
260
0
        {
261
0
            m_initialized = false;
262
263
0
            if (m_shrMem)
264
0
            {
265
#ifdef _WIN32
266
                UnmapViewOfFile(m_shrMem);
267
                CloseHandle(m_handle);
268
                m_handle = NULL;
269
#else /* POSIX / pthreads */
270
0
                int32_t shrMemSize = (m_itemSize * m_itemCnt + sizeof(ShrMemCtrl) + RINGMEM_ALLIGNMENT - 1) & (~RINGMEM_ALLIGNMENT - 1);
271
0
                munmap(m_shrMem, shrMemSize);
272
0
                unlink(m_filepath);
273
0
                free(m_filepath);
274
0
                m_filepath = NULL;
275
0
#endif ///< _WIN32
276
0
                m_shrMem = NULL;
277
0
                m_dataPool = NULL;
278
0
                m_itemSize = 0;
279
0
                m_itemCnt = 0;
280
0
            }
281
            
282
0
            if (m_protectRW)
283
0
            {
284
0
                m_protectRW = false;
285
0
                if (m_writeSem)
286
0
                {
287
0
                    m_writeSem->release();
288
289
0
                    delete m_writeSem;
290
0
                    m_writeSem = NULL;
291
0
                }
292
293
0
                if (m_readSem)
294
0
                {
295
0
                    m_readSem->release();
296
297
0
                    delete m_readSem;
298
0
                    m_readSem = NULL;
299
0
                }
300
0
            }
301
302
0
        }
303
0
    }
304
305
    ///< data read
306
    bool RingMem::readNext(void* dst, fnRWSharedData callback)
307
0
    {
308
0
        if (!m_initialized || !callback || !dst)
309
0
        {
310
0
            return false;
311
0
        }
312
313
0
        if (m_protectRW)
314
0
        {
315
0
            if (!m_readSem->take())
316
0
            {
317
0
                return false;
318
0
            }
319
0
        }
320
321
0
        int32_t index = ATOMIC_ADD(&m_shrMem->m_read, 1) % m_itemCnt;
322
0
        (*callback)(dst, reinterpret_cast<uint8_t *>(m_dataPool) + index * m_itemSize, m_itemSize);
323
324
0
        if (m_protectRW)
325
0
        {
326
0
            m_writeSem->give(1);
327
0
        }
328
329
0
        return true;
330
0
    }
331
    ///< data write
332
    bool RingMem::writeData(void *data, fnRWSharedData callback)
333
0
    {
334
0
        if (!m_initialized || !data || !callback)
335
0
        {
336
0
            return false;
337
0
        }
338
339
0
        if (m_protectRW)
340
0
        {
341
0
            if (!m_writeSem->take())
342
0
            {
343
0
                return false;
344
0
            }
345
0
        }
346
347
0
        int32_t index = ATOMIC_ADD(&m_shrMem->m_write, 1) % m_itemCnt;
348
0
        (*callback)(reinterpret_cast<uint8_t *>(m_dataPool) + index * m_itemSize, data, m_itemSize);
349
350
0
        if (m_protectRW)
351
0
        {
352
0
            m_readSem->give(1);
353
0
        }
354
355
0
        return true;
356
0
    }
357
}