d4a9b9d7d9d28384f27bbd130552fb7454e3f453
[gapil.git] / sources / SharedMem.c
1 /* SharedMem.c
2  * 
3  * Copyright (C) 2002 Simone Piccardi
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /***************************************************************
20  *
21  * File SharedMem.c 
22  * Routines for Shared Memory use. 
23  *
24  * Define two interfaces, the first one use SysV shared memory, the
25  * second POSIX shared memory.
26  *
27  * Author: S. Piccardi
28  *
29  * $Id: SharedMem.c,v 1.5 2003/02/26 21:37:36 piccardi Exp $
30  *
31  ***************************************************************/
32 #include <sys/shm.h>                  /* SysV IPC shared memory declarations */
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <stdio.h>                                 /* standard I/O functions */
36 #include <fcntl.h>
37 #include <signal.h>                          /* signal handling declarations */
38 #include <unistd.h>
39 #include <sys/mman.h>
40 #include <string.h>
41 #include <errno.h>
42
43 #include "macros.h"
44 /* *************************************************************************
45  *
46  *  Functions for SysV shared memory
47  *
48  * ************************************************************************* */
49 /*
50  * Function ShmCreate:
51  * Create and attach a SysV shared memory segment to the current process.
52  *
53  * First call get a shared memory segment with KEY key access and size SIZE,
54  * by creating it with R/W privilege for the user (this is the meaning of
55  * the ored flags). The function return an identifier shmid used for any 
56  * further reference to the shared memory segment. 
57  * Second call attach the shared memory segment to this process and return a
58  * pointer to it (of void * type). 
59  * Then initialize shared memory to the given value
60  *
61  * Input:  an IPC key value
62  *         the shared memory segment size
63  *         the permissions
64  *         the fill value
65  * Return: the address of the shared memory segment (NULL on error)
66  */
67 void * ShmCreate(key_t ipc_key, int shm_size, int perm, int fill) 
68 {
69     void * shm_ptr;
70     int shm_id;                       /* ID of the IPC shared memory segment */
71     shm_id = shmget(ipc_key, shm_size, IPC_CREAT|perm);        /* get shm ID */
72     if (shm_id < 0) { 
73         return NULL;
74     }
75     shm_ptr = shmat(shm_id, NULL, 0);                  /* map it into memory */
76     if (shm_ptr < 0) {
77         return NULL;
78     }
79     memset((void *)shm_ptr, fill, shm_size);                 /* fill segment */
80     return shm_ptr;
81 }
82 /*
83  * Function ShmFind:
84  * Find a SysV shared memory segment 
85  * Input:  an IPC key value
86  *         the shared memory segment size
87  * Return: the address of the segment (NULL on error)
88  */
89 void * ShmFind(key_t ipc_key, int shm_size) 
90 {
91     void * shm_ptr;
92     int shm_id;                      /* ID of the SysV shared memory segment */
93     shm_id = shmget(ipc_key, shm_size, 0);          /* find shared memory ID */
94     if (shm_id < 0) {
95         return NULL;
96     }
97     shm_ptr = shmat(shm_id, NULL, 0);                  /* map it into memory */
98     if (shm_ptr < 0) {
99         return NULL;
100     }
101     return shm_ptr;
102 }
103 /*
104  * Function ShmRemove:
105  * Schedule removal for a SysV shared memory segment 
106  * Input:  an IPC key value
107  *         the shared memory segment size
108  * Return: 0 on success, -1 on error
109  */
110 int ShmRemove(key_t ipc_key, void * shm_ptr) 
111 {
112     int shm_id;                      /* ID of the SysV shared memory segment */
113     /* first detach segment */
114     if (shmdt(shm_ptr) < 0) {
115         return -1;
116     }
117     /* schedule segment removal */
118     shm_id = shmget(ipc_key, 0, 0);                 /* find shared memory ID */
119     if (shm_id < 0) {
120         if (errno == EIDRM) return 0;
121         return -1;
122     }
123     if (shmctl(shm_id, IPC_RMID, NULL) < 0) {             /* ask for removal */
124         if (errno == EIDRM) return 0;
125         return -1;
126     }
127     return 0;
128 }
129 /* *************************************************************************
130  *
131  *  Functions for POSIX shared memory
132  *
133  * ************************************************************************* */
134 /*
135  * Function CreateShm:
136  * Create a POSIX shared memory segment and map it to the current process.
137  *
138  *
139  * Input:  a pathname
140  *         the shared memory segment size
141  *         the permissions
142  *         the fill value
143  * Return: the address of the shared memory segment (NULL on error)
144  */
145 void * CreateShm(char * shm_name, off_t shm_size, mode_t perm, int fill) 
146 {
147     void * shm_ptr;
148     int fd;
149     int flag;
150     /* first open the object, creating it if not existent */
151     flag = O_CREAT|O_EXCL|O_RDWR;
152     fd = shm_open(shm_name, flag, perm);    /* get object file descriptor */
153     if (fd < 0) { 
154         perror("errore in shm_open");
155         return NULL;
156     }
157     /* set the object size */
158     if (ftruncate(fd, shm_size)) {
159         perror("errore in ftruncate");
160         return NULL;
161     }
162     /* map it in the process address space */
163     shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
164     if (shm_ptr == MAP_FAILED) {
165         perror("errore in mmap");
166         return NULL;
167     }
168     memset((void *) shm_ptr, fill, shm_size);                /* fill segment */
169     return shm_ptr;
170 }
171 /*
172  * Function FindShm:
173  * Find a POSIX shared memory segment 
174  * Input:  a name
175  *         the shared memory segment size
176  * Return: the address of the segment (NULL on error)
177  */
178 void * FindShm(char * shm_name, off_t shm_size) 
179 {
180     void * shm_ptr;
181     int fd;                           /* ID of the IPC shared memory segment */
182     /* find shared memory ID */
183     if ((fd = shm_open(shm_name, O_RDWR|O_EXCL, 0)) < 0) {
184         debug("Cannot open %s\n", shm_name);
185         return NULL;
186     }
187     /* take the pointer to it */
188     shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
189     if (shm_ptr == MAP_FAILED) {
190         return NULL;
191     }
192     return shm_ptr;
193 }
194 /*
195  * Function RemoveShm:
196  * Remove a POSIX shared memory segment 
197  * Input:  the object name
198  * Return: 0 on success, -1 on error
199  */
200 int RemoveShm(char * shm_name)
201 {
202     shm_unlink(shm_name);
203     return 0;
204 }