/*************************************************************************** * Copyright 1995, Technion, Israel Institute of Technology * Electrical Eng, Software Lab. * Author: Michael Veksler. *************************************************************************** * File: dde_mem.c * Purpose : shared DDE memory functionality for DDE *************************************************************************** */ #ifdef CONFIG_IPC #include #include "debug.h" #include "ldt.h" #include "shm_main_blk.h" #include "shm_fragment.h" #include "shm_semaph.h" #include "dde_mem.h" #include "bit_array.h" DECLARE_DEBUG_CHANNEL(dde) DECLARE_DEBUG_CHANNEL(global) #define SEGPTR2HANDLE_INFO(sptr) ( (struct handle_info*)PTR_SEG_TO_LIN(sptr) ) #define HINFO2DATAPTR(h_info_ptr) ( (void*) ( (char*)h_info_ptr + \ sizeof(struct handle_info) ) ) #define DDE_MEM_IDX(handle) ((handle)& 0x7fff) #define DDE_MEM_HANDLE(idx) ((idx) | 0x8000) #define DDE_MEM_INFO(handle) (main_block->handles[ DDE_MEM_IDX(handle) ]) /* List of shared handles. * This entry resides on the shared memory, the data comes right * after the `handle_info'. * The entry is on the same block as the actual data. * The `next' field gives relative reference (relative to the start of * the blcok. */ struct handle_info { WORD lock_count; WORD flags; int size; /* size of the data (net)*/ }; static bit_array free_handles; int debug_last_handle_size= 0; /* for debugging purpose only */ /* locate_handle: * locate a shared memory handle. * Application: * The handle is first searched for in attached blocks. * At the beginning, only blocks owned by this process are * attached. * If a handle is not found, new blocks are attached. * Arguments: * h - the handle. * RETURN: pointer to handle info. */ static struct handle_info *locate_handle(HGLOBAL16 h, struct local_shm_map *map) { struct shm_block *block; TRACE(global,"shm: (0x%04x)\n", h); if (SampleBit( &free_handles, DDE_MEM_IDX(h)) == 0) { TRACE(global, "shm: return NULL\n"); return NULL; /* free!!! */ } block= shm_locate_block(DDE_MEM_INFO(h).shmid, map); if (block == NULL) { /* nothing found */ TRACE(global, "shm: return NULL\n"); return NULL; } return (struct handle_info *) REL2PTR(block, DDE_MEM_INFO(h).rel); } /* dde_alloc_handle: allocate shared DDE handle */ static HGLOBAL16 dde_alloc_handle() { int bit_nr; bit_nr= AllocateBit( &free_handles); if (bit_nr != -1) return DDE_MEM_HANDLE(bit_nr); TRACE(global,"dde_alloc_handle: no free DDE handle found\n"); return 0; } /********************************************************************** * DDE_malloc */ void * DDE_malloc(unsigned int flags, unsigned long size, SHMDATA *shmdata) { int shmid; struct shm_block *block; struct handle_info *h_info; struct local_shm_map *curr; HGLOBAL16 handle; TRACE(global,"DDE_malloc flags %4X, size %ld\n", flags, size); DDE_IPC_init(); /* make sure main shm block allocated */ shm_write_wait(main_block->proc[curr_proc_idx].sem); /* Try to find fragment big enough for `size' */ /* iterate through all local shm blocks, and try to allocate the fragment */ h_info= NULL; for (curr= shm_map ; curr != NULL ; curr= curr->next) { if (curr->proc_idx == curr_proc_idx) { h_info= (struct handle_info *) shm_FragPtrAlloc(curr->ptr, size+sizeof(struct handle_info)); if (h_info!=NULL) { shmid= curr->shm_id; break; } } } if (h_info == NULL) { block= shm_create_block(0, size+sizeof(struct handle_info), &shmid); if (block==NULL) { shm_write_signal(main_block->proc[curr_proc_idx].sem); return 0; } /* put the new block in the linked list */ block->next_shm_id= main_block->proc[curr_proc_idx].shmid; main_block->proc[curr_proc_idx].shmid= shmid; h_info= (struct handle_info *) shm_FragPtrAlloc(block, size+sizeof(struct handle_info)); if (h_info==NULL) { ERR(global,"BUG! unallocated fragment\n"); shm_write_signal(main_block->proc[curr_proc_idx].sem); return 0; } } else { block= curr->ptr; } /* Here we have an allocated fragment */ h_info->flags= flags; h_info->lock_count= 0; h_info->size= size; handle= dde_alloc_handle(); if (handle) { TRACE(global, "returning handle=0x%4x, ptr=0x%08lx\n", (int)handle, (long) HINFO2DATAPTR(h_info)); DDE_MEM_INFO(handle).rel= PTR2REL(block, h_info); DDE_MEM_INFO(handle).shmid= shmid; } else WARN(global, "failed\n"); shm_write_signal(main_block->proc[curr_proc_idx].sem); shmdata->handle= handle; return (char *)HINFO2DATAPTR(h_info); } HGLOBAL16 DDE_GlobalFree(HGLOBAL16 h) { struct handle_info *h_info; int handle_index= h & 0x7fff; struct local_shm_map map; TRACE(global,"(0x%04x)\n",h); if (h==0) return 0; h_info= locate_handle(h, &map); if (h_info == NULL) return h; shm_write_wait(main_block->proc[map.proc_idx].sem); shm_FragPtrFree(map.ptr, (struct shm_fragment *) h_info); AssignBit( &free_handles, handle_index, 0); /* FIXME: must free the shm block some day. */ shm_write_signal(main_block->proc[map.proc_idx].sem); return 0; } WORD DDE_SyncHandle(HGLOBAL16 handle, WORD sel) { struct handle_info *h_info; void *local_ptr; ldt_entry entry; h_info= locate_handle(handle, NULL); local_ptr= (void *)GET_SEL_BASE(sel); if (h_info == NULL) return 0; if (local_ptr == (void *) HINFO2DATAPTR(h_info)) return sel; /* need syncronization ! */ LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry ); entry.base= (unsigned long) HINFO2DATAPTR(h_info); LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry ); return sel; } /* * DDE_AttachHandle: * Attach shm memory (The data must not be already attached). * Parameters: * handle - the memory to attach. * segptr - in not null, return SEGPTR to the same block. * return value: * 32 bit pointer to the memory. */ void *DDE_AttachHandle(HGLOBAL16 handle, SEGPTR *segptr) { struct handle_info *h_info; SHMDATA shmdata; void *ptr; HGLOBAL16 hOwner = GetCurrentPDB16(); assert(is_dde_handle(handle)); if (segptr != NULL) *segptr=0; TRACE(global,"(%04x)\n",handle); h_info=locate_handle(handle, NULL); if (h_info == NULL) return NULL; if ( !(h_info->flags & GMEM_DDESHARE) ) { ERR(global,"Corrupted memory handle info\n"); return NULL; } TRACE(global,"h_info=%06lx\n",(long)h_info); shmdata.handle= handle; shmdata.shmid= DDE_MEM_INFO(handle).shmid; ptr= HINFO2DATAPTR(h_info); /* Allocate the selector(s) */ if (! GLOBAL_CreateBlock( h_info->flags, ptr, h_info->size, hOwner, FALSE, FALSE, FALSE, &shmdata)) return NULL; if (segptr != NULL) *segptr= (SEGPTR)MAKELONG( 0, shmdata.sel); if (TRACE_ON(dde)) debug_last_handle_size= h_info->size; TRACE(global,"DDE_AttachHandle returns ptr=0x%08lx\n", (long)ptr); return (LPSTR)ptr; } void DDE_mem_init() { int nr_of_bits; shm_init(); nr_of_bits= BITS_PER_BYTE * sizeof(main_block->free_handles); AssembleArray( &free_handles, main_block->free_handles, nr_of_bits); } #endif /* CONFIG_IPC */