195 lines
4.3 KiB
C
195 lines
4.3 KiB
C
static char RCSId[] = "$Id$";
|
||
static char Copyright[] = "Copyright Robert J. Amstadt, 1994";
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#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
|
||
}
|