1 /*
2 * @file SharedMemoryAllocator.c
3 *
4 * ============================================================================
5 *
6 */
7 /*
8 * Copyright (c) 2012, Texas Instruments Incorporated
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * * Neither the name of Texas Instruments Incorporated nor the names of
22 * its contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
32 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * Contact information for paper mail:
37 * Texas Instruments
38 * Post Office Box 655303
39 * Dallas, Texas 75265
40 * Contact information:
41 * http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
42 * DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
43 * ============================================================================
44 *
45 */
47 #include "ti/shmemallocator/SharedMemoryAllocator.h"
48 #include <sys/select.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/ioctl.h>
52 #include <sys/mman.h>
53 #include <sys/slog.h>
54 #include <fcntl.h>
55 #include <errno.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <stdlib.h>
59 #include <unistd.h>
60 #include <pthread.h>
61 #include <time.h>
63 #define SHAREDMEMALLOCATOR_DRIVER_NAME "/dev/shmemallocator"
65 #if defined (__cplusplus)
66 extern "C" {
67 #endif /* defined (__cplusplus) */
69 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
70 static int shmHandler = -1;
71 static int ref_cnt = 0;
73 int initSHMHandler(int *SHMAllocatorDrv_handle)
74 {
75 int status = 0;
77 pthread_mutex_lock(&mutex);
78 if (ref_cnt++ == 0) {
79 *SHMAllocatorDrv_handle = open (SHAREDMEMALLOCATOR_DRIVER_NAME,
80 O_SYNC | O_RDWR);
81 if (*SHMAllocatorDrv_handle < 0) {
82 slogf (42, _SLOG_DEBUG1, "\ninitSHMHandler: couldn't open shmemallocator device\n");
83 ref_cnt--;
84 status = -errno;
85 } else {
86 status = fcntl (*SHMAllocatorDrv_handle, F_SETFD, FD_CLOEXEC);
87 if (status != 0) {
88 slogf (42, _SLOG_DEBUG1, "\ninitSHMHandler: Failed to set file descriptor flags\n");
89 status = -errno;
90 }
91 }
92 }
94 pthread_mutex_unlock(&mutex);
95 return status;
96 }
98 void deinitSHMHandler(int SHMAllocatorDrv_handle)
99 {
100 if(SHMAllocatorDrv_handle < 0){
101 slogf (42, _SLOG_DEBUG1, "invalid SHMAllocatorDrv_handle value %d",SHMAllocatorDrv_handle);
102 return;
103 }
105 pthread_mutex_lock(&mutex);
107 if (--ref_cnt == 0) {
108 close (SHMAllocatorDrv_handle);
109 }
110 pthread_mutex_unlock(&mutex);
111 }
113 int SHM_alloc(int size, shm_buf *buf)
114 {
115 int status = 0;
116 SHMAllocatorDrv_CmdArgs cmdArgs;
118 if(buf == NULL || size <= 0){
119 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc: Invalid arguments\n");
120 return -1;
121 }
122 buf->phy_addr = NULL;
123 buf->vir_addr = NULL;
124 buf->blockID = -1;
125 buf->size = 0;
127 status = initSHMHandler(&shmHandler);
129 if (status < 0) {
130 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc: initSHMHandler Failed\n");
131 return status;
132 }
134 cmdArgs.size = size;
135 cmdArgs.blockID = 0;
136 cmdArgs.alignment = 0;
137 cmdArgs.result.phy_addr = 0;
138 cmdArgs.result.vir_addr = 0;
140 ioctl (shmHandler, CMD_SHMALLOCATOR_ALLOC, &cmdArgs);
141 status = cmdArgs.apiStatus;
142 if (status < 0) {
143 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc: IOCTL Failed \n");
144 deinitSHMHandler(shmHandler);
145 return status;
146 }
147 else {
148 buf->phy_addr = cmdArgs.result.phy_addr;
149 buf->vir_addr = cmdArgs.result.vir_addr;
150 buf->blockID = cmdArgs.result.blockID;
151 buf->size = cmdArgs.result.size;
152 }
154 return (status);
155 }
157 int SHM_alloc_aligned(int size, uint alignment, shm_buf *buf)
158 {
159 int status = 0;
160 SHMAllocatorDrv_CmdArgs cmdArgs;
162 if(buf == NULL || size <= 0 || alignment == 0){
163 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc: Invalid arguments\n");
164 return -1;
165 }
166 buf->phy_addr = NULL;
167 buf->vir_addr = NULL;
168 buf->blockID = -1;
169 buf->size = 0;
171 status = initSHMHandler(&shmHandler);
173 if (status < 0) {
174 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc_aligned: initSHMHandler Failed\n");
175 return status;
176 }
178 cmdArgs.size = size;
179 cmdArgs.blockID = 0;
180 cmdArgs.alignment = alignment;
181 cmdArgs.result.phy_addr = 0;
182 cmdArgs.result.vir_addr = 0;
184 ioctl (shmHandler, CMD_SHMALLOCATOR_ALLOC, &cmdArgs);
185 status = cmdArgs.apiStatus;
186 if (status < 0) {
187 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc_aligned: IOCTL Failed \n");
188 deinitSHMHandler(shmHandler);
189 return status;
190 }
191 else {
192 buf->phy_addr = cmdArgs.result.phy_addr;
193 buf->vir_addr = cmdArgs.result.vir_addr;
194 buf->blockID = cmdArgs.result.blockID;
195 buf->size = cmdArgs.result.size;
196 }
198 return (status);
199 }
201 int SHM_alloc_fromBlock(int size, int blockID, shm_buf *buf)
202 {
203 int status = 0;
204 SHMAllocatorDrv_CmdArgs cmdArgs;
206 buf->phy_addr = NULL;
207 buf->vir_addr = NULL;
208 buf->blockID = -1;
209 buf->size = 0;
211 if(buf == NULL || size <= 0 || blockID < MIN_BLOCKS_IDX || blockID > MAX_BLOCKS_IDX){
212 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc: Invalid arguments\n");
213 return -1;
214 }
216 status = initSHMHandler(&shmHandler);
218 if (status < 0) {
219 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc_fromBlock: initSHMHandler Failed\n");
220 return status;
221 }
223 cmdArgs.size = size;
224 cmdArgs.blockID = blockID;
225 cmdArgs.alignment = 0;
226 cmdArgs.result.phy_addr = 0;
227 cmdArgs.result.vir_addr = 0;
229 ioctl (shmHandler, CMD_SHMALLOCATOR_ALLOC, &cmdArgs);
230 status = cmdArgs.apiStatus;
231 if (status < 0) {
232 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc_fromBlock: IOCTL Failed \n");
233 deinitSHMHandler(shmHandler);
234 return status;
235 }
236 else {
237 buf->phy_addr = cmdArgs.result.phy_addr;
238 buf->vir_addr = cmdArgs.result.vir_addr;
239 buf->blockID = cmdArgs.result.blockID;
240 buf->size = cmdArgs.result.size;
241 }
243 return (status);
244 }
246 int SHM_alloc_aligned_fromBlock(int size, uint alignment, int blockID,
247 shm_buf *buf)
248 {
249 int status = 0;
250 SHMAllocatorDrv_CmdArgs cmdArgs;
252 buf->phy_addr = NULL;
253 buf->vir_addr = NULL;
254 buf->blockID = -1;
255 buf->size = 0;
257 if(buf == NULL || size <= 0 || alignment == 0 || blockID < MIN_BLOCKS_IDX || blockID > MAX_BLOCKS_IDX){
258 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc: Invalid arguments\n");
259 return -1;
260 }
262 status = initSHMHandler(&shmHandler);
264 if (status < 0) {
265 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc_aligned_fromBlock: initSHMHandler Failed\n");
266 return status;
267 }
269 cmdArgs.size = size;
270 cmdArgs.blockID = blockID;
271 cmdArgs.alignment = alignment;
272 cmdArgs.result.phy_addr = 0;
273 cmdArgs.result.vir_addr = 0;
275 ioctl (shmHandler, CMD_SHMALLOCATOR_ALLOC, &cmdArgs);
276 status = cmdArgs.apiStatus;
277 if (status < 0) {
278 slogf (42, _SLOG_DEBUG1, "\nSHM_alloc: IOCTL Failed \n");
279 deinitSHMHandler(shmHandler);
280 return status;
281 }
282 buf->phy_addr = cmdArgs.result.phy_addr;
283 buf->vir_addr = cmdArgs.result.vir_addr;
284 buf->blockID = cmdArgs.result.blockID;
285 buf->size = cmdArgs.result.size;
287 return (status);
288 }
290 /*!
291 * @brief This function triggers the buffer release in the kernel.
292 *
293 * @param buf Pointer to the buffer address information
294 *
295 * @return 0 Success.
296 * -1 Failure in ioctl call.
297 *
298 */
299 int SHM_release(shm_buf *buf)
301 {
302 int status = 0;
303 SHMAllocatorDrv_CmdArgs cmdArgs;
305 if(buf == NULL){
306 slogf (42, _SLOG_DEBUG1, "\nSHM_release: Invalid arguments\n");
307 return -1;
308 }
309 if(buf->blockID < MIN_BLOCKS_IDX || buf->blockID > MAX_BLOCKS_IDX || buf->vir_addr == NULL){
310 slogf (42, _SLOG_DEBUG1, "\nSHM_release: Invalid arguments\n");
311 return -1;
312 }
313 cmdArgs.result.phy_addr = buf->phy_addr;
314 cmdArgs.result.vir_addr = buf->vir_addr;
315 cmdArgs.blockID = buf->blockID;
317 ioctl (shmHandler, CMD_SHMALLOCATOR_RELEASE, &cmdArgs);
318 status = cmdArgs.apiStatus;
320 if (status < 0) {
321 slogf (42, _SLOG_DEBUG1, "\nRELEASE IOCTL failed\n");
322 }
324 deinitSHMHandler (shmHandler);
326 return (status);
327 }
329 #if defined (__cplusplus)
330 }
331 #endif /* defined (__cplusplus) */