Release 960314
[wine.git] / ipc / dde_mem.c
blob5e9c03d8366534de979c47df18901b62e0fe3260
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 <stdio.h>
13 #include <stddebug.h>
14 #include <debug.h>
15 #include <assert.h>
16 #include "ldt.h"
17 #include "shm_main_blk.h"
18 #include "shm_fragment.h"
19 #include "shm_semaph.h"
20 #include "dde_mem.h"
21 #include "bit_array.h"
23 #define SEGPTR2HANDLE_INFO(sptr) ( (struct handle_info*)PTR_SEG_TO_LIN(sptr) )
25 #define HINFO2DATAPTR(h_info_ptr) ( (void*) ( (char*)h_info_ptr + \
26 sizeof(struct handle_info) ) )
27 #define DDE_MEM_IDX(handle) ((handle)& 0x7fff)
28 #define DDE_MEM_HANDLE(idx) ((idx) | 0x8000)
29 #define DDE_MEM_INFO(handle) (main_block->handles[ DDE_MEM_IDX(handle) ])
30 /* List of shared handles.
31 * This entry resides on the shared memory, the data comes right
32 * after the `handle_info'.
33 * The entry is on the same block as the actual data.
34 * The `next' field gives relative reference (relative to the start of
35 * the blcok.
37 struct handle_info {
38 WORD lock_count;
39 WORD flags;
40 int size; /* size of the data (net)*/
43 static bit_array free_handles;
44 int debug_last_handle_size= 0; /* for debugging purpose only */
47 /* locate_handle:
48 * locate a shared memory handle.
49 * Application:
50 * The handle is first searched for in attached blocks.
51 * At the beginning, only blocks owned by this process are
52 * attached.
53 * If a handle is not found, new blocks are attached.
54 * Arguments:
55 * h - the handle.
56 * RETURN: pointer to handle info.
58 static struct handle_info *locate_handle(HGLOBAL h, struct local_shm_map *map)
60 struct shm_block *block;
62 dprintf_global(stddeb,"shm:locate_handle(0x%04x)\n", h);
65 if (SampleBit( &free_handles, DDE_MEM_IDX(h)) == 0) {
66 dprintf_global(stddeb, "shm:locate_handle: return NULL\n");
67 return NULL; /* free!!! */
70 block= shm_locate_block(DDE_MEM_INFO(h).shmid, map);
71 if (block == NULL) {
72 /* nothing found */
73 dprintf_global(stddeb, "shm:locate_handle: return NULL\n");
74 return NULL;
77 return (struct handle_info *) REL2PTR(block, DDE_MEM_INFO(h).rel);
81 /* dde_alloc_handle: allocate shared DDE handle */
82 static HGLOBAL dde_alloc_handle()
84 int bit_nr;
86 bit_nr= AllocateBit( &free_handles);
88 if (bit_nr != -1)
89 return DDE_MEM_HANDLE(bit_nr);
91 dprintf_global(stddeb,"dde_alloc_handle: no free DDE handle found\n");
92 return 0;
94 /**********************************************************************
95 * DDE_malloc
97 void *
98 DDE_malloc(unsigned int flags, unsigned long size, SHMDATA *shmdata)
100 int shmid;
101 struct shm_block *block;
102 struct handle_info *h_info;
103 struct local_shm_map *curr;
104 HGLOBAL handle;
106 dprintf_global(stddeb,"DDE_malloc flags %4X, size %ld\n", flags, size);
107 DDE_IPC_init(); /* make sure main shm block allocated */
109 shm_write_wait(main_block->proc[curr_proc_idx].sem);
111 /* Try to find fragment big enough for `size' */
112 /* iterate through all local shm blocks, and try to allocate
113 the fragment */
115 h_info= NULL;
116 for (curr= shm_map ; curr != NULL ; curr= curr->next) {
117 if (curr->proc_idx == curr_proc_idx) {
118 h_info= (struct handle_info *)
119 shm_FragPtrAlloc(curr->ptr, size+sizeof(struct handle_info));
120 if (h_info!=NULL) {
121 shmid= curr->shm_id;
122 break;
127 if (h_info == NULL) {
129 block= shm_create_block(0, size+sizeof(struct handle_info), &shmid);
130 if (block==NULL) {
131 shm_write_signal(main_block->proc[curr_proc_idx].sem);
132 return 0;
134 /* put the new block in the linked list */
135 block->next_shm_id= main_block->proc[curr_proc_idx].shmid;
136 main_block->proc[curr_proc_idx].shmid= shmid;
137 h_info= (struct handle_info *)
138 shm_FragPtrAlloc(block, size+sizeof(struct handle_info));
139 if (h_info==NULL) {
140 fprintf(stderr,"DDE_malloc: BUG! unallocated fragment\n");
141 shm_write_signal(main_block->proc[curr_proc_idx].sem);
142 return 0;
144 } else {
145 block= curr->ptr;
148 /* Here we have an allocated fragment */
149 h_info->flags= flags;
150 h_info->lock_count= 0;
151 h_info->size= size;
152 handle= dde_alloc_handle();
154 if (handle) {
155 dprintf_global(stddeb,
156 "DDE_malloc returning handle=0x%4x, ptr=0x%08lx\n",
157 (int)handle, (long) HINFO2DATAPTR(h_info));
158 DDE_MEM_INFO(handle).rel= PTR2REL(block, h_info);
159 DDE_MEM_INFO(handle).shmid= shmid;
161 else
162 dprintf_global(stddeb,"DDE_malloc failed\n");
164 shm_write_signal(main_block->proc[curr_proc_idx].sem);
166 shmdata->handle= handle;
167 return (char *)HINFO2DATAPTR(h_info);
170 HGLOBAL DDE_GlobalFree(HGLOBAL h)
172 struct handle_info *h_info;
173 int handle_index= h & 0x7fff;
174 struct local_shm_map map;
176 dprintf_global(stddeb,"DDE_GlobalFree(0x%04x)\n",h);
178 if (h==0)
179 return 0;
181 h_info= locate_handle(h, &map);
182 if (h_info == NULL)
183 return h;
185 shm_write_wait(main_block->proc[map.proc_idx].sem);
187 shm_FragPtrFree(map.ptr, (struct shm_fragment *) h_info);
189 AssignBit( &free_handles, handle_index, 0);
191 /* FIXME: must free the shm block some day. */
192 shm_write_signal(main_block->proc[map.proc_idx].sem);
193 return 0;
196 WORD DDE_SyncHandle(HGLOBAL handle, WORD sel)
199 struct handle_info *h_info;
200 void *local_ptr;
201 ldt_entry entry;
203 h_info= locate_handle(handle, NULL);
204 local_ptr= (void *)GET_SEL_BASE(sel);
207 if (h_info == NULL)
208 return 0;
210 if (local_ptr == (void *) HINFO2DATAPTR(h_info))
211 return sel;
213 /* need syncronization ! */
214 LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
215 entry.base= (unsigned long) HINFO2DATAPTR(h_info);
216 LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
218 return sel;
222 * DDE_AttachHandle:
223 * Attach shm memory (The data must not be already attached).
224 * Parameters:
225 * handle - the memory to attach.
226 * segptr - in not null, return SEGPTR to the same block.
227 * return value:
228 * 32 bit pointer to the memory.
231 void *DDE_AttachHandle(HGLOBAL handle, SEGPTR *segptr)
233 struct handle_info *h_info;
234 SHMDATA shmdata;
235 void *ptr;
236 HGLOBAL hOwner = GetCurrentPDB();
238 assert(is_dde_handle(handle));
239 if (segptr != NULL)
240 *segptr=0;
242 dprintf_global(stddeb,"DDE_AttachHandle(%04x)\n",handle);
243 h_info=locate_handle(handle, NULL);
245 if (h_info == NULL)
246 return NULL;
248 if ( !(h_info->flags & GMEM_DDESHARE) ) {
249 fprintf(stderr,"DDE_AttachHandle: Corrupted memory handle info\n");
250 return NULL;
253 dprintf_global(stddeb,"DDE_AttachHandle: h_info=%06lx\n",(long)h_info);
255 shmdata.handle= handle;
256 shmdata.shmid= DDE_MEM_INFO(handle).shmid;
258 ptr= HINFO2DATAPTR(h_info);
259 /* Allocate the selector(s) */
260 if (! GLOBAL_CreateBlock( h_info->flags, ptr, h_info->size, hOwner,
261 FALSE, FALSE, FALSE, &shmdata))
262 return NULL;
264 if (segptr != NULL)
265 *segptr= (SEGPTR)MAKELONG( 0, shmdata.sel);
267 if (debugging_dde)
268 debug_last_handle_size= h_info->size;
270 dprintf_global(stddeb,"DDE_AttachHandle returns ptr=0x%08lx\n", (long)ptr);
272 return (LPSTR)ptr;
276 void DDE_mem_init()
278 int nr_of_bits;
280 shm_init();
282 nr_of_bits= BITS_PER_BYTE * sizeof(main_block->free_handles);
283 AssembleArray( &free_handles, main_block->free_handles, nr_of_bits);
286 #endif /* CONFIG_IPC */