Release 950216
[wine.git] / memory / linear.c
blob1d09b14aa740d2e0b34d6929d4a97722ef68f2f9
1 /*
2 static char RCSId[] = "$Id$";
3 static char Copyright[] = "Copyright Robert J. Amstadt, 1994";
4 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "prototypes.h"
9 #include "heap.h"
10 #include "segmem.h"
12 #ifdef HAVE_IPC
13 static key_t MemoryKeys[SHMSEG]; /* Keep track of keys were using */
14 static int LinearInitialized = 0;
15 #endif
18 #ifdef HAVE_IPC
19 /**********************************************************************
20 * LinearFindSpace
22 int
23 LinearFindSpace(int n_segments)
25 int i, n;
27 if (!LinearInitialized)
29 memset(MemoryKeys, -1, sizeof(MemoryKeys));
30 return 0;
33 for (i = 0, n = 0; i < SHMSEG, n != n_segments; i++)
35 if (MemoryKeys[i] < 0)
36 n++;
37 else
38 n = 0;
41 if (n != n_segments)
42 return -1;
43 else
44 return i - n;
46 #endif /* HAVE_IPC */
48 /**********************************************************************
49 * GlobalLinearLock
51 * OK, this is an evil beast. We will do one of two things:
53 * 1. If the data item <= 64k, then just call GlobalLock().
54 * 2. If the data item > 64k, then map memory.
56 void *
57 GlobalLinearLock(unsigned int block)
59 GDESC *g, *g_first;
60 int loc_idx;
61 unsigned long addr;
62 int i;
64 /******************************************************************
65 * Get GDESC for this block.
67 g_first = GlobalGetGDesc(block);
68 if (g_first == NULL)
69 return 0;
71 /******************************************************************
72 * Is block less then 64k in length?
74 if (g_first->sequence != 1 || g_first->length == 1)
76 return (void *) GlobalLock(block);
79 /******************************************************************
80 * If there is already a linear lock on this memory, then
81 * just return a pointer to it.
83 if (g_first->linear_count)
85 g_first->linear_count++;
86 return g_first->linear_addr;
89 /******************************************************************
90 * No luck. We need to do the linear mapping right now.
92 #ifdef HAVE_IPC
93 loc_idx = LinearFindSpace(g_first->length);
94 if (loc_idx < 0)
95 return NULL;
97 addr = (unsigned long) SHM_RANGE_START + (0x10000 * loc_idx);
98 g = g_first;
99 for (i = loc_idx;
100 i < loc_idx + g_first->length;
101 i++, addr += 0x10000, g = g->next)
103 if ((MemoryKeys[i] = IPCCopySelector(g->handle >> __AHSHIFT,
104 addr, 0)) < 0)
105 return NULL;
106 g->linear_addr = (void *) addr;
107 g->linear_count = 1;
109 #endif /* HAVE_IPC */
111 return g_first->linear_addr;
114 /**********************************************************************
115 * GlobalLinearUnlock
118 unsigned int
119 GlobalLinearUnlock(unsigned int block)
121 GDESC *g, *g_first;
122 int loc_idx;
123 int i;
125 /******************************************************************
126 * Get GDESC for this block.
128 g_first = GlobalGetGDesc(block);
129 if (g_first == NULL)
130 return block;
132 /******************************************************************
133 * Is block less then 64k in length?
135 if (g_first->sequence != 1 || g_first->length == 1)
137 return GlobalUnlock(block);
140 /******************************************************************
141 * Make sure we have a lock on this block.
143 #ifdef HAVE_IPC
144 if (g_first->linear_count > 1)
146 g_first->linear_count--;
148 else if (g_first->linear_count == 1)
150 g = g_first;
151 loc_idx = (((unsigned int) g_first - (unsigned int) SHM_RANGE_START)
152 / 0x10000);
153 for (i = 0; i < g_first->length; i++, g = g->next)
155 shmdt(g->linear_addr);
156 g->linear_addr = NULL;
157 MemoryKeys[i] = -1;
160 g_first->linear_count = 0;
161 return 0;
163 #endif /* HAVE_IPC */
165 return 0;
167 /**********************************************************************/
169 void LinearTest()
171 #if 0
172 unsigned int handle;
173 int *seg_ptr;
174 int *lin_ptr;
175 int seg, i;
176 int *p;
178 handle = GlobalAlloc(0, 0x40000);
179 seg_ptr = GlobalLock(handle);
180 lin_ptr = GlobalLinearLock(handle);
182 for (seg = 0; seg < 4; seg++)
184 p = (int *) ((char *) seg_ptr + (0x80000 * seg));
185 for (i = 0; i < (0x10000 / sizeof(int)); i++, p++)
186 *p = (seg * (0x10000 / sizeof(int))) + i;
189 p = lin_ptr;
190 for (i = 0; i < (0x40000 / sizeof(int)); i++, p++)
192 if (*p != i)
193 printf("lin_ptr[%x] = %x\n", i, *p);
195 #endif