Merge branch 'master' of ssh://gapil.gnulinux.it/srv/git/gapil
[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  ***************************************************************/
30 #include <sys/shm.h>     /* SysV shared memory */
31 #include <sys/types.h>   /* primitive system data types */
32 #include <sys/stat.h>    /* file characteristics constants and functions */
33 #include <stdio.h>       /* standard I/O library */
34 #include <fcntl.h>       /* file control functions */
35 #include <signal.h>      /* signal constants, types and functions */
36 #include <unistd.h>      /* unix standard library */
37 #include <sys/mman.h>
38 #include <string.h>      /* C strings library */
39 #include <errno.h>       /* error definitions and routines */
40
41 #include "macros.h"
42 /* *************************************************************************
43  *
44  *  Functions for SysV shared memory
45  *
46  * ************************************************************************* */
47 /*
48  * Function ShmCreate:
49  * Create and attach a SysV shared memory segment to the current process.
50  *
51  * First call get a shared memory segment with KEY key access and size SIZE,
52  * by creating it with R/W privilege for the user (this is the meaning of
53  * the ored flags). The function return an identifier shmid used for any 
54  * further reference to the shared memory segment. 
55  * Second call attach the shared memory segment to this process and return a
56  * pointer to it (of void * type). 
57  * Then initialize shared memory to the given value
58  *
59  * Input:  an IPC key value
60  *         the shared memory segment size
61  *         the permissions
62  *         the fill value
63  * Return: the address of the shared memory segment (NULL on error)
64  */
65 void * ShmCreate(key_t ipc_key, int shm_size, int perm, int fill) 
66 {
67     void * shm_ptr;
68     int shm_id;                       /* ID of the IPC shared memory segment */
69     shm_id = shmget(ipc_key, shm_size, IPC_CREAT|perm);        /* get shm ID */
70     if (shm_id < 0) { 
71         return NULL;
72     }
73     shm_ptr = shmat(shm_id, NULL, 0);                  /* map it into memory */
74     if (shm_ptr < 0) {
75         return NULL;
76     }
77     memset((void *)shm_ptr, fill, shm_size);                 /* fill segment */
78     return shm_ptr;
79 }
80 /*
81  * Function ShmFind:
82  * Find a SysV shared memory segment 
83  * Input:  an IPC key value
84  *         the shared memory segment size
85  * Return: the address of the segment (NULL on error)
86  */
87 void * ShmFind(key_t ipc_key, int shm_size) 
88 {
89     void * shm_ptr;
90     int shm_id;                      /* ID of the SysV shared memory segment */
91     shm_id = shmget(ipc_key, shm_size, 0);          /* find shared memory ID */
92     if (shm_id < 0) {
93         return NULL;
94     }
95     shm_ptr = shmat(shm_id, NULL, 0);                  /* map it into memory */
96     if (shm_ptr < 0) {
97         return NULL;
98     }
99     return shm_ptr;
100 }
101 /*
102  * Function ShmRemove:
103  * Schedule removal for a SysV shared memory segment 
104  * Input:  an IPC key value
105  *         the shared memory segment size
106  * Return: 0 on success, -1 on error
107  */
108 int ShmRemove(key_t ipc_key, void * shm_ptr) 
109 {
110     int shm_id;                      /* ID of the SysV shared memory segment */
111     /* first detach segment */
112     if (shmdt(shm_ptr) < 0) {
113         return -1;
114     }
115     /* schedule segment removal */
116     shm_id = shmget(ipc_key, 0, 0);                 /* find shared memory ID */
117     if (shm_id < 0) {
118         if (errno == EIDRM) return 0;
119         return -1;
120     }
121     if (shmctl(shm_id, IPC_RMID, NULL) < 0) {             /* ask for removal */
122         if (errno == EIDRM) return 0;
123         return -1;
124     }
125     return 0;
126 }
127 /* *************************************************************************
128  *
129  *  Functions for POSIX shared memory
130  *
131  * ************************************************************************* */
132 /*
133  * Function CreateShm:
134  * Create a POSIX shared memory segment and map it to the current process.
135  *
136  *
137  * Input:  a pathname
138  *         the shared memory segment size
139  *         the permissions
140  *         the fill value
141  * Return: the address of the shared memory segment (NULL on error)
142  */
143 void * CreateShm(char * shm_name, off_t shm_size, mode_t perm, int fill) 
144 {
145     void * shm_ptr;
146     int fd;
147     int flag;
148     /* first open the object, creating it if not existent */
149     flag = O_CREAT|O_EXCL|O_RDWR;
150     fd = shm_open(shm_name, flag, perm);    /* get object file descriptor */
151     if (fd < 0) { 
152         perror("errore in shm_open");
153         return NULL;
154     }
155     /* set the object size */
156     if (ftruncate(fd, shm_size)) {
157         perror("errore in ftruncate");
158         return NULL;
159     }
160     /* map it in the process address space */
161     shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
162     if (shm_ptr == MAP_FAILED) {
163         perror("errore in mmap");
164         return NULL;
165     }
166     memset((void *) shm_ptr, fill, shm_size);                /* fill segment */
167     return shm_ptr;
168 }
169 /*
170  * Function FindShm:
171  * Find a POSIX shared memory segment 
172  * Input:  a name
173  *         the shared memory segment size
174  * Return: the address of the segment (NULL on error)
175  */
176 void * FindShm(char * shm_name, off_t shm_size) 
177 {
178     void * shm_ptr;
179     int fd;                           /* ID of the IPC shared memory segment */
180     /* find shared memory ID */
181     if ((fd = shm_open(shm_name, O_RDWR|O_EXCL, 0)) < 0) {
182         debug("Cannot open %s\n", shm_name);
183         return NULL;
184     }
185     /* take the pointer to it */
186     shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
187     if (shm_ptr == MAP_FAILED) {
188         return NULL;
189     }
190     return shm_ptr;
191 }
192 /*
193  * Function RemoveShm:
194  * Remove a POSIX shared memory segment 
195  * Input:  the object name
196  * Return: 0 on success, -1 on error
197  */
198 int RemoveShm(char * shm_name)
199 {
200     return shm_unlink(shm_name);
201 }