static char RCSId[] = "$Id$"; static char Copyright[] = "Copyright Robert J. Amstadt, 1994"; #include #include #include #include "prototypes.h" #include "heap.h" #include "segmem.h" #ifdef HAVE_IPC static key_t MemoryKeys[SHMSEG]; /* Keep track of keys were using */ static int LinearInitialized = 0; #endif #ifdef HAVE_IPC /********************************************************************** * LinearFindSpace */ int LinearFindSpace(int n_segments) { int i, n; if (!LinearInitialized) { memset(MemoryKeys, -1, sizeof(MemoryKeys)); return 0; } for (i = 0, n = 0; i < SHMSEG, n != n_segments; i++) { if (MemoryKeys[i] < 0) n++; else n = 0; } if (n != n_segments) return -1; else return i - n; } #endif /* HAVE_IPC */ /********************************************************************** * GlobalLinearLock * * OK, this is an evil beast. We will do one of two things: * * 1. If the data item <= 64k, then just call GlobalLock(). * 2. If the data item > 64k, then map memory. */ void * GlobalLinearLock(unsigned int block) { GDESC *g, *g_first; int loc_idx; unsigned long addr; int i; /****************************************************************** * Get GDESC for this block. */ g_first = GlobalGetGDesc(block); if (g_first == NULL) return 0; /****************************************************************** * Is block less then 64k in length? */ if (g_first->sequence != 1 || g_first->length == 1) { return (void *) GlobalLock(block); } /****************************************************************** * If there is already a linear lock on this memory, then * just return a pointer to it. */ if (g_first->linear_count) { g_first->linear_count++; return g_first->linear_addr; } /****************************************************************** * No luck. We need to do the linear mapping right now. */ #ifdef HAVE_IPC loc_idx = LinearFindSpace(g_first->length); if (loc_idx < 0) return NULL; addr = (unsigned long) SHM_RANGE_START + (0x10000 * loc_idx); g = g_first; for (i = loc_idx; i < loc_idx + g_first->length; i++, addr += 0x10000, g = g->next) { if ((MemoryKeys[i] = IPCCopySelector(g->handle >> 3, addr, 0)) < 0) return NULL; g->linear_addr = (void *) addr; g->linear_count = 1; } #endif /* HAVE_IPC */ return g_first->linear_addr; } /********************************************************************** * GlobalLinearUnlock * */ unsigned int GlobalLinearUnlock(unsigned int block) { GDESC *g, *g_first; int loc_idx; int i; /****************************************************************** * Get GDESC for this block. */ g_first = GlobalGetGDesc(block); if (g_first == NULL) return block; /****************************************************************** * Is block less then 64k in length? */ if (g_first->sequence != 1 || g_first->length == 1) { return GlobalUnlock(block); } /****************************************************************** * Make sure we have a lock on this block. */ #ifdef HAVE_IPC if (g_first->linear_count > 1) { g_first->linear_count--; } else if (g_first->linear_count == 1) { g = g_first; loc_idx = (((unsigned int) g_first - (unsigned int) SHM_RANGE_START) / 0x10000); for (i = 0; i < g_first->length; i++, g = g->next) { shmdt(g->linear_addr); g->linear_addr = NULL; MemoryKeys[i] = -1; } g_first->linear_count = 0; return 0; } #endif /* HAVE_IPC */ return 0; } /**********************************************************************/ LinearTest() { #if 0 unsigned int handle; int *seg_ptr; int *lin_ptr; int seg, i; int *p; handle = GlobalAlloc(0, 0x40000); seg_ptr = GlobalLock(handle); lin_ptr = GlobalLinearLock(handle); for (seg = 0; seg < 4; seg++) { p = (int *) ((char *) seg_ptr + (0x80000 * seg)); for (i = 0; i < (0x10000 / sizeof(int)); i++, p++) *p = (seg * (0x10000 / sizeof(int))) + i; } p = lin_ptr; for (i = 0; i < (0x40000 / sizeof(int)); i++, p++) { if (*p != i) printf("lin_ptr[%x] = %x\n", i, *p); } #endif }