1 /***************************************************************************
2 * Copyright 1995, Technion, Israel Institute of Technology
3 * Electrical Eng, Software Lab.
4 * Author: Michael Veksler.
5 ***************************************************************************
7 * Purpose : shared DDE memory functionality for DDE
8 ***************************************************************************
17 #include "shm_main_blk.h"
18 #include "shm_fragment.h"
19 #include "shm_semaph.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
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 */
48 * locate a shared memory handle.
50 * The handle is first searched for in attached blocks.
51 * At the beginning, only blocks owned by this process are
53 * If a handle is not found, new blocks are attached.
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
);
73 dprintf_global(stddeb
, "shm:locate_handle: return NULL\n");
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()
86 bit_nr
= AllocateBit( &free_handles
);
89 return DDE_MEM_HANDLE(bit_nr
);
91 dprintf_global(stddeb
,"dde_alloc_handle: no free DDE handle found\n");
94 /**********************************************************************
98 DDE_malloc(unsigned int flags
, unsigned long size
, SHMDATA
*shmdata
)
101 struct shm_block
*block
;
102 struct handle_info
*h_info
;
103 struct local_shm_map
*curr
;
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
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
));
127 if (h_info
== NULL
) {
129 block
= shm_create_block(0, size
+sizeof(struct handle_info
), &shmid
);
131 shm_write_signal(main_block
->proc
[curr_proc_idx
].sem
);
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
));
140 fprintf(stderr
,"DDE_malloc: BUG! unallocated fragment\n");
141 shm_write_signal(main_block
->proc
[curr_proc_idx
].sem
);
148 /* Here we have an allocated fragment */
149 h_info
->flags
= flags
;
150 h_info
->lock_count
= 0;
152 handle
= dde_alloc_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
;
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
);
181 h_info
= locate_handle(h
, &map
);
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
);
196 WORD
DDE_SyncHandle(HGLOBAL handle
, WORD sel
)
199 struct handle_info
*h_info
;
203 h_info
= locate_handle(handle
, NULL
);
204 local_ptr
= (void *)GET_SEL_BASE(sel
);
210 if (local_ptr
== (void *) HINFO2DATAPTR(h_info
))
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
);
223 * Attach shm memory (The data must not be already attached).
225 * handle - the memory to attach.
226 * segptr - in not null, return SEGPTR to the same block.
228 * 32 bit pointer to the memory.
231 void *DDE_AttachHandle(HGLOBAL handle
, SEGPTR
*segptr
)
233 struct handle_info
*h_info
;
236 HGLOBAL hOwner
= GetCurrentPDB();
238 assert(is_dde_handle(handle
));
242 dprintf_global(stddeb
,"DDE_AttachHandle(%04x)\n",handle
);
243 h_info
=locate_handle(handle
, NULL
);
248 if ( !(h_info
->flags
& GMEM_DDESHARE
) ) {
249 fprintf(stderr
,"DDE_AttachHandle: Corrupted memory handle info\n");
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
))
265 *segptr
= (SEGPTR
)MAKELONG( 0, shmdata
.sel
);
268 debug_last_handle_size
= h_info
->size
;
270 dprintf_global(stddeb
,"DDE_AttachHandle returns ptr=0x%08lx\n", (long)ptr
);
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 */