Release 980913
[wine/multimedia.git] / ipc / dde_mem.c
blobecfd164ca3fd312a8449ad48345ce13fccf29ca9
1 /***************************************************************************
2 * Copyright 1995, Technion, Israel Institute of Technology
3 * Electrical Eng, Software Lab.
4 * Author: Michael Veksler.
5 ***************************************************************************
6 * File: dde_mem.c
7 * Purpose : shared DDE memory functionality for DDE
8 ***************************************************************************
9 */
10 #ifdef CONFIG_IPC
12 #include <assert.h>
13 #include "debug.h"
14 #include "ldt.h"
15 #include "shm_main_blk.h"
16 #include "shm_fragment.h"
17 #include "shm_semaph.h"
18 #include "dde_mem.h"
19 #include "bit_array.h"
21 #define SEGPTR2HANDLE_INFO(sptr) ( (struct handle_info*)PTR_SEG_TO_LIN(sptr) )
23 #define HINFO2DATAPTR(h_info_ptr) ( (void*) ( (char*)h_info_ptr + \
24 sizeof(struct handle_info) ) )
25 #define DDE_MEM_IDX(handle) ((handle)& 0x7fff)
26 #define DDE_MEM_HANDLE(idx) ((idx) | 0x8000)
27 #define DDE_MEM_INFO(handle) (main_block->handles[ DDE_MEM_IDX(handle) ])
28 /* List of shared handles.
29 * This entry resides on the shared memory, the data comes right
30 * after the `handle_info'.
31 * The entry is on the same block as the actual data.
32 * The `next' field gives relative reference (relative to the start of
33 * the blcok.
35 struct handle_info {
36 WORD lock_count;
37 WORD flags;
38 int size; /* size of the data (net)*/
41 static bit_array free_handles;
42 int debug_last_handle_size= 0; /* for debugging purpose only */
45 /* locate_handle:
46 * locate a shared memory handle.
47 * Application:
48 * The handle is first searched for in attached blocks.
49 * At the beginning, only blocks owned by this process are
50 * attached.
51 * If a handle is not found, new blocks are attached.
52 * Arguments:
53 * h - the handle.
54 * RETURN: pointer to handle info.
56 static struct handle_info *locate_handle(HGLOBAL16 h, struct local_shm_map *map)
58 struct shm_block *block;
60 TRACE(global,"shm: (0x%04x)\n", h);
63 if (SampleBit( &free_handles, DDE_MEM_IDX(h)) == 0) {
64 TRACE(global, "shm: return NULL\n");
65 return NULL; /* free!!! */
68 block= shm_locate_block(DDE_MEM_INFO(h).shmid, map);
69 if (block == NULL) {
70 /* nothing found */
71 TRACE(global, "shm: return NULL\n");
72 return NULL;
75 return (struct handle_info *) REL2PTR(block, DDE_MEM_INFO(h).rel);
79 /* dde_alloc_handle: allocate shared DDE handle */
80 static HGLOBAL16 dde_alloc_handle()
82 int bit_nr;
84 bit_nr= AllocateBit( &free_handles);
86 if (bit_nr != -1)
87 return DDE_MEM_HANDLE(bit_nr);
89 TRACE(global,"dde_alloc_handle: no free DDE handle found\n");
90 return 0;
92 /**********************************************************************
93 * DDE_malloc
95 void *
96 DDE_malloc(unsigned int flags, unsigned long size, SHMDATA *shmdata)
98 int shmid;
99 struct shm_block *block;
100 struct handle_info *h_info;
101 struct local_shm_map *curr;
102 HGLOBAL16 handle;
104 TRACE(global,"DDE_malloc flags %4X, size %ld\n", flags, size);
105 DDE_IPC_init(); /* make sure main shm block allocated */
107 shm_write_wait(main_block->proc[curr_proc_idx].sem);
109 /* Try to find fragment big enough for `size' */
110 /* iterate through all local shm blocks, and try to allocate
111 the fragment */
113 h_info= NULL;
114 for (curr= shm_map ; curr != NULL ; curr= curr->next) {
115 if (curr->proc_idx == curr_proc_idx) {
116 h_info= (struct handle_info *)
117 shm_FragPtrAlloc(curr->ptr, size+sizeof(struct handle_info));
118 if (h_info!=NULL) {
119 shmid= curr->shm_id;
120 break;
125 if (h_info == NULL) {
127 block= shm_create_block(0, size+sizeof(struct handle_info), &shmid);
128 if (block==NULL) {
129 shm_write_signal(main_block->proc[curr_proc_idx].sem);
130 return 0;
132 /* put the new block in the linked list */
133 block->next_shm_id= main_block->proc[curr_proc_idx].shmid;
134 main_block->proc[curr_proc_idx].shmid= shmid;
135 h_info= (struct handle_info *)
136 shm_FragPtrAlloc(block, size+sizeof(struct handle_info));
137 if (h_info==NULL) {
138 ERR(global,"BUG! unallocated fragment\n");
139 shm_write_signal(main_block->proc[curr_proc_idx].sem);
140 return 0;
142 } else {
143 block= curr->ptr;
146 /* Here we have an allocated fragment */
147 h_info->flags= flags;
148 h_info->lock_count= 0;
149 h_info->size= size;
150 handle= dde_alloc_handle();
152 if (handle) {
153 TRACE(global, "returning handle=0x%4x, ptr=0x%08lx\n",
154 (int)handle, (long) HINFO2DATAPTR(h_info));
155 DDE_MEM_INFO(handle).rel= PTR2REL(block, h_info);
156 DDE_MEM_INFO(handle).shmid= shmid;
158 else
159 WARN(global, "failed\n");
161 shm_write_signal(main_block->proc[curr_proc_idx].sem);
163 shmdata->handle= handle;
164 return (char *)HINFO2DATAPTR(h_info);
167 HGLOBAL16 DDE_GlobalFree(HGLOBAL16 h)
169 struct handle_info *h_info;
170 int handle_index= h & 0x7fff;
171 struct local_shm_map map;
173 TRACE(global,"(0x%04x)\n",h);
175 if (h==0)
176 return 0;
178 h_info= locate_handle(h, &map);
179 if (h_info == NULL)
180 return h;
182 shm_write_wait(main_block->proc[map.proc_idx].sem);
184 shm_FragPtrFree(map.ptr, (struct shm_fragment *) h_info);
186 AssignBit( &free_handles, handle_index, 0);
188 /* FIXME: must free the shm block some day. */
189 shm_write_signal(main_block->proc[map.proc_idx].sem);
190 return 0;
193 WORD DDE_SyncHandle(HGLOBAL16 handle, WORD sel)
196 struct handle_info *h_info;
197 void *local_ptr;
198 ldt_entry entry;
200 h_info= locate_handle(handle, NULL);
201 local_ptr= (void *)GET_SEL_BASE(sel);
204 if (h_info == NULL)
205 return 0;
207 if (local_ptr == (void *) HINFO2DATAPTR(h_info))
208 return sel;
210 /* need syncronization ! */
211 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
212 entry.base= (unsigned long) HINFO2DATAPTR(h_info);
213 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
215 return sel;
219 * DDE_AttachHandle:
220 * Attach shm memory (The data must not be already attached).
221 * Parameters:
222 * handle - the memory to attach.
223 * segptr - in not null, return SEGPTR to the same block.
224 * return value:
225 * 32 bit pointer to the memory.
228 void *DDE_AttachHandle(HGLOBAL16 handle, SEGPTR *segptr)
230 struct handle_info *h_info;
231 SHMDATA shmdata;
232 void *ptr;
233 HGLOBAL16 hOwner = GetCurrentPDB();
235 assert(is_dde_handle(handle));
236 if (segptr != NULL)
237 *segptr=0;
239 TRACE(global,"(%04x)\n",handle);
240 h_info=locate_handle(handle, NULL);
242 if (h_info == NULL)
243 return NULL;
245 if ( !(h_info->flags & GMEM_DDESHARE) ) {
246 ERR(global,"Corrupted memory handle info\n");
247 return NULL;
250 TRACE(global,"h_info=%06lx\n",(long)h_info);
252 shmdata.handle= handle;
253 shmdata.shmid= DDE_MEM_INFO(handle).shmid;
255 ptr= HINFO2DATAPTR(h_info);
256 /* Allocate the selector(s) */
257 if (! GLOBAL_CreateBlock( h_info->flags, ptr, h_info->size, hOwner,
258 FALSE, FALSE, FALSE, &shmdata))
259 return NULL;
261 if (segptr != NULL)
262 *segptr= (SEGPTR)MAKELONG( 0, shmdata.sel);
264 if (TRACE_ON(dde))
265 debug_last_handle_size= h_info->size;
267 TRACE(global,"DDE_AttachHandle returns ptr=0x%08lx\n", (long)ptr);
269 return (LPSTR)ptr;
273 void DDE_mem_init()
275 int nr_of_bits;
277 shm_init();
279 nr_of_bits= BITS_PER_BYTE * sizeof(main_block->free_handles);
280 AssembleArray( &free_handles, main_block->free_handles, nr_of_bits);
283 #endif /* CONFIG_IPC */