1 /*		S H A R E D   M E M O R Y   D R I V E R
2 		=======================================
3 
4 		  by Jerzy.Borkowski@obs.unige.ch
5 
6 09-Mar-98 : initial version 1.0 released
7 23-Mar-98 : shared_malloc now accepts new handle as an argument
8 */
9 
10 
11 #include <sys/ipc.h>		/* this is necessary for Solaris/Linux */
12 #include <sys/shm.h>
13 #include <sys/sem.h>
14 
15 #ifdef _AIX
16 #include <fcntl.h>
17 #else
18 #include <sys/fcntl.h>
19 #endif
20 
21 		/* configuration parameters */
22 
23 #define	SHARED_MAXSEG	(16)		/* maximum number of shared memory blocks */
24 
25 #define	SHARED_KEYBASE	(14011963)	/* base for shared memory keys, may be overriden by getenv */
26 #define	SHARED_FDNAME	("/tmp/.shmem-lockfile") /* template for lock file name */
27 
28 #define	SHARED_ENV_KEYBASE ("SHMEM_LIB_KEYBASE") /* name of environment variable */
29 #define	SHARED_ENV_MAXSEG ("SHMEM_LIB_MAXSEG")	/* name of environment variable */
30 
31 		/* useful constants */
32 
33 #define	SHARED_RDONLY	(0)		/* flag for shared_(un)lock, lock for read */
34 #define	SHARED_RDWRITE	(1)		/* flag for shared_(un)lock, lock for write */
35 #define	SHARED_WAIT	(0)		/* flag for shared_lock, block if cannot lock immediate */
36 #define	SHARED_NOWAIT	(2)		/* flag for shared_lock, fail if cannot lock immediate */
37 #define	SHARED_NOLOCK	(0x100)		/* flag for shared_validate function */
38 
39 #define	SHARED_RESIZE	(4)		/* flag for shared_malloc, object is resizeable */
40 #define	SHARED_PERSIST	(8)		/* flag for shared_malloc, object is not deleted after last proc detaches */
41 
42 #define	SHARED_INVALID	(-1)		/* invalid handle for semaphore/shared memory */
43 
44 #define	SHARED_EMPTY	(0)		/* entries for shared_used table */
45 #define	SHARED_USED	(1)
46 
47 #define	SHARED_GRANUL	(16384)		/* granularity of shared_malloc allocation = phys page size, system dependent */
48 
49 
50 
51 		/* checkpoints in shared memory segments - might be omitted */
52 
53 #define	SHARED_ID_0	('J')		/* first byte of identifier in BLKHEAD */
54 #define	SHARED_ID_1	('B')		/* second byte of identifier in BLKHEAD */
55 
56 #define	BLOCK_REG	(0)		/* value for tflag member of BLKHEAD */
57 #define	BLOCK_SHARED	(1)		/* value for tflag member of BLKHEAD */
58 
59 		/* generic error codes */
60 
61 #define	SHARED_OK	(0)
62 
63 #define	SHARED_ERR_MIN_IDX	SHARED_BADARG
64 #define	SHARED_ERR_MAX_IDX	SHARED_NORESIZE
65 
66 
67 #define	DAL_SHM_FREE	(0)
68 #define	DAL_SHM_USED	(1)
69 
70 #define	DAL_SHM_ID0	('D')
71 #define	DAL_SHM_ID1	('S')
72 #define	DAL_SHM_ID2	('M')
73 
74 #define	DAL_SHM_SEGHEAD_ID	(0x19630114)
75 
76 
77 
78 		/* data types */
79 
80 /* BLKHEAD object is placed at the beginning of every memory segment (both
81   shared and regular) to allow automatic recognition of segments type */
82 
83 typedef union
84       { struct BLKHEADstruct
85 	      {	char	ID[2];		/* ID = 'JB', just as a checkpoint */
86 		char	tflag;		/* is it shared memory or regular one ? */
87 		int	handle;		/* this is not necessary, used only for non-resizeable objects via ptr */
88 	      } s;
89 	double	d;			/* for proper alignment on every machine */
90       } BLKHEAD;
91 
92 typedef void *SHARED_P;			/* generic type of shared memory pointer */
93 
94 typedef	struct SHARED_GTABstruct	/* data type used in global table */
95       {	int	sem;			/* access semaphore (1 field): process count */
96 	int	semkey;			/* key value used to generate semaphore handle */
97 	int	key;			/* key value used to generate shared memory handle (realloc changes it) */
98 	int	handle;			/* handle of shared memory segment */
99 	int	size;			/* size of shared memory segment */
100 	int	nprocdebug;		/* attached proc counter, helps remove zombie segments */
101 	char	attr;			/* attributes of shared memory object */
102       } SHARED_GTAB;
103 
104 typedef	struct SHARED_LTABstruct	/* data type used in local table */
105       {	BLKHEAD	*p;			/* pointer to segment (may be null) */
106 	int	tcnt;			/* number of threads in this process attached to segment */
107 	int	lkcnt;			/* >=0 <- number of read locks, -1 - write lock */
108 	long	seekpos;		/* current pointer position, read/write/seek operations change it */
109       } SHARED_LTAB;
110 
111 
112 	/* system dependent definitions */
113 
114 #ifndef HAVE_FLOCK_T
115 typedef struct flock flock_t;
116 #define HAVE_FLOCK_T
117 #endif
118 
119 #ifndef HAVE_UNION_SEMUN
120 union semun
121       {	int val;
122 	struct semid_ds *buf;
123 	unsigned short *array;
124       };
125 #define HAVE_UNION_SEMUN
126 #endif
127 
128 
129 typedef struct DAL_SHM_SEGHEAD_STRUCT	DAL_SHM_SEGHEAD;
130 
131 struct DAL_SHM_SEGHEAD_STRUCT
132       {	int	ID;			/* ID for debugging */
133 	int	h;			/* handle of sh. mem */
134 	int	size;			/* size of data area */
135 	int	nodeidx;		/* offset of root object (node struct typically) */
136       };
137 
138 		/* API routines */
139 
140 #ifdef __cplusplus
141 extern "C" {
142 #endif
143 
144 void	shared_cleanup(void);			/* must be called at exit/abort */
145 int	shared_init(int debug_msgs);		/* must be called before any other shared memory routine */
146 int	shared_recover(int id);			/* try to recover dormant segment(s) after applic crash */
147 int	shared_malloc(long size, int mode, int newhandle);	/* allocate n-bytes of shared memory */
148 int	shared_attach(int idx);			/* attach to segment given index to table */
149 int	shared_free(int idx);			/* release shared memory */
150 SHARED_P shared_lock(int idx, int mode);	/* lock segment for reading */
151 SHARED_P shared_realloc(int idx, long newsize);	/* reallocate n-bytes of shared memory (ON LOCKED SEGMENT ONLY) */
152 int	shared_size(int idx);			/* get size of attached shared memory segment (ON LOCKED SEGMENT ONLY) */
153 int	shared_attr(int idx);			/* get attributes of attached shared memory segment (ON LOCKED SEGMENT ONLY) */
154 int	shared_set_attr(int idx, int newattr);	/* set attributes of attached shared memory segment (ON LOCKED SEGMENT ONLY) */
155 int	shared_unlock(int idx);			/* unlock segment (ON LOCKED SEGMENT ONLY) */
156 int	shared_set_debug(int debug_msgs);	/* set/reset debug mode */
157 int	shared_set_createmode(int mode);	/* set/reset debug mode */
158 int	shared_list(int id);			/* list segment(s) */
159 int	shared_uncond_delete(int id);		/* uncondintionally delete (NOWAIT operation) segment(s) */
160 int	shared_getaddr(int id, char **address);	/* get starting address of FITS file in segment */
161 
162 int	smem_init(void);
163 int	smem_shutdown(void);
164 int	smem_setoptions(int options);
165 int	smem_getoptions(int *options);
166 int	smem_getversion(int *version);
167 int	smem_open(char *filename, int rwmode, int *driverhandle);
168 int	smem_create(char *filename, int *driverhandle);
169 int	smem_close(int driverhandle);
170 int	smem_remove(char *filename);
171 int	smem_size(int driverhandle, LONGLONG *size);
172 int	smem_flush(int driverhandle);
173 int	smem_seek(int driverhandle, LONGLONG offset);
174 int	smem_read(int driverhandle, void *buffer, long nbytes);
175 int	smem_write(int driverhandle, void *buffer, long nbytes);
176 
177 #ifdef __cplusplus
178 }
179 #endif
180