Authors: Paul Quinn <paulq@corel.ca>, Zygo Blaxell <zygob@corel.ca>
[wine/multimedia.git] / ipc / shm_main_blk.c
blob4458f5c219aebb8c6175958115a78b98ba9d644d
1 /***************************************************************************
2 * Copyright 1995, Technion, Israel Institute of Technology
3 * Electrical Eng, Software Lab.
4 * Author: Michael Veksler.
5 ***************************************************************************
6 * File: shm_main_blk.c
7 * Purpose: Main Wine's shared memory block
8 ***************************************************************************
9 */
10 #ifdef CONFIG_IPC
12 #define inline __inline__
13 #include <sys/types.h>
14 #include <sys/sem.h>
15 #include <time.h>
16 #include <assert.h>
17 #include <unistd.h>
18 #include <errno.h>
19 #include <signal.h>
20 #include "debug.h"
21 #include "shm_fragment.h"
22 #include "shm_block.h"
23 #include "shm_main_blk.h"
24 #include "shm_semaph.h"
26 #define WineKey ( 'W'+((int)'i'<<8)+((int)'n'<<16)+((int)'e'<<24) )
27 #define SHM_KEY_RANGE 8
29 /* main block (set during initialization) */
30 struct shm_main_block *main_block=NULL;
31 static char *shm_header="Wine - Windows emulator DDE mechanism";
32 static int main_shm_id;
34 static void shm_main_refresh();
36 /* for debugging only */
37 static void print_perm(struct ipc_perm *perm)
39 printf("Permission:\n");
40 /* FIXME: not portable
41 printf("\tKey=%d, mode=%03o, sequence #=%d\n",
42 (int)perm->key,perm->mode, perm->seq);
44 printf("\towner: uid=%d, gid=%d ;" ,perm->uid, perm->gid);
45 printf(" creator: uid=%d, gid=%d\n",perm->cuid,perm->cgid);
48 /* for debugging only */
49 /* print_shm_info: print shared memory descriptor info */
50 static void print_shm_info(int shm_id)
52 struct shmid_ds ds;
53 shmctl(shm_id, IPC_STAT, &ds );
55 printf("shm_id=%d, Size=0x%08x , Number of attaches=%d\n",
56 shm_id, ds.shm_segsz, (int)ds.shm_nattch);
57 if (ds.shm_atime)
58 printf("Last attach=%s",ctime(&ds.shm_atime));
59 if (ds.shm_dtime)
60 printf("Last detach=%s",ctime(&ds.shm_dtime));
61 printf("Last change=%s",ctime(&ds.shm_ctime));
62 printf("pid: creator=%d, last operator=%d\n",
63 (int)ds.shm_cpid,(int)ds.shm_lpid);
64 print_perm( &ds.shm_perm);
68 int proc_exist(pid_t pid)
70 if ( kill(pid,0) == 0) /* dummy signal to test existence */
71 return 1;
72 else if (errno==ESRCH) /* "no such process" */
73 return 0;
74 else
75 return 1;
78 /* setup a new main shm block (only construct a shm block object). */
79 static void shm_setup_main_block()
81 TRACE(shm,"creating data structure\n");
82 main_block->build_lock=1;
83 strcpy(main_block->magic, shm_header);
85 shm_setup_block(&main_block->block,sizeof(*main_block),SHM_MINBLOCK);
87 dde_proc_init(main_block->proc);
88 ATOM_GlobalInit();
89 shm_sem_init(&main_block->sem);
91 /* main block set and data structure is stable now */
92 main_block->build_lock=0;
95 /* Delete everything related to main_block */
96 void shm_delete_all(int shmid)
98 int proc_idx;
100 if (shmid == -1)
101 shmid= main_shm_id;
103 shmctl( shmid, IPC_RMID, NULL);
105 for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
106 dde_proc_done( &main_block->proc[proc_idx] );
108 shm_sem_done(&main_block->sem);
109 shmdt( (void *) main_block);
110 main_block= NULL;
113 int DDE_no_of_attached()
115 struct shmid_ds shm_info;
117 if (shmctl(main_shm_id, IPC_STAT, &shm_info) == -1)
118 return -1;
120 return shm_info.shm_nattch;
123 ** Test if shm_id is MainBlock and attach it (if it is),
124 ** Return 1 if ok, 0 otherwise.
126 static int attach_MainBlock(int shm_id)
128 struct shmid_ds shm_info;
130 if (shmctl(shm_id, IPC_STAT, &shm_info) == -1)
131 return 0;
133 /* Make sure we don't work on somebody else's block */
134 if (shm_info.shm_perm.cuid != getuid()) { /* creator is not me */
135 WARN(shm, "Creator is not me!\n");
136 return 0;
139 TRACE(shm,"shared memory exist, attaching anywhere\n");
140 main_block=(struct shm_main_block *)shmat(shm_id, 0, 0);
141 if ( (int)main_block==-1) {
142 WARN(shm, "Attach failed\n");
143 return 0;
146 if (strcmp(main_block->magic, shm_header) != 0) {
147 TRACE(shm,"Detaching, wrong magic\n");
148 shmdt((void *)main_block);
149 return 0;
152 if (TRACE_ON(shm))
153 print_shm_info(shm_id);
155 /* Is it an old unused block ? */
156 if (shm_info.shm_nattch == 0) {
157 TRACE(shm,"No attaches, deleting old data\n");
158 shm_delete_all(shm_id);
159 return 0;
162 /* Wait for data structure to stabilize */
163 while (main_block->build_lock)
164 usleep(10000);
166 main_shm_id= shm_id;
168 shm_main_refresh();
169 return 1;
172 /* (Function used by the constructor)
173 * Try to get existing shared memory with key="Wine", size=SHM_MINBLOCK
174 * complete user permission.
175 * If such block is found - return true (1), else return false (0)
177 static int shm_locate_MainBlock(key_t shm_key)
179 int shm_id; /* Descriptor to this shared memory */
180 int i;
182 TRACE(shm,"trying to attach, key=0x%x\n",
183 shm_key);
184 for (i=0 ; i < SHM_KEY_RANGE ; i++) {
185 TRACE(shm,"iteration=%d\n", i);
187 shm_id= shmget ( shm_key+i, SHM_MINBLOCK ,0700);
189 if (shm_id != -1) {
190 if ( attach_MainBlock(shm_id) ) {
191 return 1; /* success! */
193 } else {
194 switch(errno) {
195 #ifdef EIDRM
196 case EIDRM: /* segment destroyed */
197 #endif
198 case EACCES: /* no user permision */
199 break;
201 case ENOMEM: /* no free memory */
202 case ENOENT: /* this key does not exist */
203 default :
204 WARN(shm,"shmget failed, errno=%d, %s\n",
205 errno, strerror(errno) );
206 return 0; /* Failed */
208 } /* if .. else */
209 } /* for */
210 return 0;
213 /* (Function used by the constructor)
214 * Try to allocate new shared memory with key="Wine", size=SHM_MINBLOCK
215 * with complete user permission.
216 * If allocation succeeds - return true (1), else return false (0)
218 static int shm_create_MainBlock(key_t MainShmKey)
220 int shm_id;
221 int flags= 0700 | IPC_CREAT | IPC_EXCL;
222 int i;
224 TRACE(shm,"creating shared memory\n");
226 /* try to allocate shared memory with key="Wine", size=SHM_MINBLOCK, */
227 /* complete user permission */
228 for (i=0 ; i < SHM_KEY_RANGE ; i++) {
229 shm_id= shmget ( (key_t) MainShmKey, SHM_MINBLOCK, flags);
230 if (shm_id != -1)
231 break;
233 if (shm_id == -1) {
234 WARN(shm, "failed to create shared memory\n");
235 return 0;
237 TRACE(shm,"shared memory created, attaching\n");
238 main_block=(struct shm_main_block*) shmat(shm_id, 0,0);
239 if (TRACE_ON(shm))
240 print_shm_info(shm_id);
241 main_shm_id= shm_id;
242 shm_setup_main_block();
243 dde_wnd_setup();
244 return 1;
248 /* link to the dde shared memory block */
249 /* RETURN: 0 on success, non zero on failure */
250 int shm_init(void)
252 if ( !shm_locate_MainBlock(WineKey)
253 && !shm_create_MainBlock(WineKey)) {
254 ERR(shm, "Failed to init main shm block\n");
255 exit(1);
258 dde_proc_add(main_block->proc);
259 return 0;
262 static void shm_main_refresh()
264 int proc_idx;
266 for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
267 dde_proc_refresh( &main_block->proc[proc_idx] );
270 #endif /* CONFIG_IPC */