1 /*
2 * IPC SHM area manager
3 * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
4 *
5 * This library is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as
7 * published by the Free Software Foundation; either version 2.1 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 /**
22 * \file shmarea.c
23 * \ingroup Global
24 * \brief shared memory helpers
25 * \author Jaroslav Kysela <perex@perex.cz>
26 * \date 2001
27 *
28 * Shared memory helpers
29 */
30
31 #include "config.h"
32
33 /* These funcs are only used by pcm_mmap when sys/shm.h is available. */
34 #ifdef HAVE_SYS_SHM_H
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #if HAVE_MALLOC_H
39 #include <malloc.h>
40 #endif
41 #include <string.h>
42 #include <errno.h>
43 #include <poll.h>
44 #include <sys/mman.h>
45 #include <sys/shm.h>
46 #include "list.h"
47
48 #ifndef DOC_HIDDEN
49 struct snd_shm_area {
50 struct list_head list;
51 int shmid;
52 void *ptr;
53 int share;
54 };
55 #endif
56
57 static LIST_HEAD(shm_areas);
58
59 /**
60 * \brief Create a shm area record
61 * \param shmid IPC SHM ID
62 * \param ptr the shared area pointer
63 * \return The allocated shm area record, NULL if fail
64 *
65 * Allocates a shared area record with the given SHM ID and pointer.
66 * The record has a reference counter, which is initialized to 1 by this function.
67 */
snd_shm_area_create(int shmid,void * ptr)68 struct snd_shm_area *snd_shm_area_create(int shmid, void *ptr)
69 {
70 struct snd_shm_area *area = malloc(sizeof(*area));
71 if (area) {
72 area->shmid = shmid;
73 area->ptr = ptr;
74 area->share = 1;
75 list_add_tail(&area->list, &shm_areas);
76 }
77 return area;
78 }
79
80 /**
81 * \brief Increase the reference counter of shm area record
82 * \param area shm area record
83 * \return the shm area record (identical with the argument)
84 *
85 * Increases the reference counter of the given shared area record.
86 */
snd_shm_area_share(struct snd_shm_area * area)87 struct snd_shm_area *snd_shm_area_share(struct snd_shm_area *area)
88 {
89 if (area == NULL)
90 return NULL;
91 area->share++;
92 return area;
93 }
94
95 /**
96 * \brief Release the shared area record
97 * \param area the shared are record
98 * \return 0 if successful, or a negative error code
99 *
100 * Decreases the reference counter of the given shared area record, and
101 * releases the resources automaticall if it reaches to 0.
102 */
snd_shm_area_destroy(struct snd_shm_area * area)103 int snd_shm_area_destroy(struct snd_shm_area *area)
104 {
105 if (area == NULL)
106 return -ENOENT;
107 if (--area->share)
108 return 0;
109 list_del(&area->list);
110 shmdt(area->ptr);
111 free(area);
112 return 0;
113 }
114
115 #ifndef DOC_HIDDEN
116 void snd_shm_area_destructor(void) __attribute__ ((destructor));
117
snd_shm_area_destructor(void)118 void snd_shm_area_destructor(void)
119 {
120 struct list_head *pos;
121 struct snd_shm_area *area;
122
123 list_for_each(pos, &shm_areas) {
124 area = list_entry(pos, struct snd_shm_area, list);
125 shmdt(area->ptr);
126 }
127 }
128 #endif /* DOC_HIDDEN */
129
130 #endif
131