Release 940405
[wine/gsoc-2012-control.git] / memory / linear.c
blob1bceeaacb52b6feaf2b7592f704341c63b0c607c
1 static char RCSId[] = "$Id$";
2 static char Copyright[] = "Copyright Robert J. Amstadt, 1994";
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "prototypes.h"
8 #include "heap.h"
9 #include "segmem.h"
11 #ifdef HAVE_IPC
12 static key_t MemoryKeys[SHMSEG]; /* Keep track of keys were using */
13 static int LinearInitialized = 0;
14 #endif
17 #ifdef HAVE_IPC
18 /**********************************************************************
19 * LinearFindSpace
21 int
22 LinearFindSpace(int n_segments)
24 int i, n;
26 if (!LinearInitialized)
28 memset(MemoryKeys, -1, sizeof(MemoryKeys));
29 return 0;
32 for (i = 0, n = 0; i < SHMSEG, n != n_segments; i++)
34 if (MemoryKeys[i] < 0)
35 n++;
36 else
37 n = 0;
40 if (n != n_segments)
41 return -1;
42 else
43 return i - n;
45 #endif /* HAVE_IPC */
47 /**********************************************************************
48 * GlobalLinearLock
50 * OK, this is an evil beast. We will do one of two things:
52 * 1. If the data item <= 64k, then just call GlobalLock().
53 * 2. If the data item > 64k, then map memory.
55 void *
56 GlobalLinearLock(unsigned int block)
58 GDESC *g, *g_first;
59 int loc_idx;
60 unsigned long addr;
61 int i;
63 /******************************************************************
64 * Get GDESC for this block.
66 g_first = GlobalGetGDesc(block);
67 if (g_first == NULL)
68 return 0;
70 /******************************************************************
71 * Is block less then 64k in length?
73 if (g_first->sequence != 1 || g_first->length == 1)
75 return (void *) GlobalLock(block);
78 /******************************************************************
79 * If there is already a linear lock on this memory, then
80 * just return a pointer to it.
82 if (g_first->linear_count)
84 g_first->linear_count++;
85 return g_first->linear_addr;
88 /******************************************************************
89 * No luck. We need to do the linear mapping right now.
91 #ifdef HAVE_IPC
92 loc_idx = LinearFindSpace(g_first->length);
93 if (loc_idx < 0)
94 return NULL;
96 addr = (unsigned long) SHM_RANGE_START + (0x10000 * loc_idx);
97 g = g_first;
98 for (i = loc_idx;
99 i < loc_idx + g_first->length;
100 i++, addr += 0x10000, g = g->next)
102 if ((MemoryKeys[i] = IPCCopySelector(g->handle >> 3, addr, 0)) < 0)
103 return NULL;
104 g->linear_addr = (void *) addr;
105 g->linear_count = 1;
107 #endif /* HAVE_IPC */
109 return g_first->linear_addr;
112 /**********************************************************************
113 * GlobalLinearUnlock
116 unsigned int
117 GlobalLinearUnlock(unsigned int block)
119 GDESC *g, *g_first;
120 int loc_idx;
121 int i;
123 /******************************************************************
124 * Get GDESC for this block.
126 g_first = GlobalGetGDesc(block);
127 if (g_first == NULL)
128 return block;
130 /******************************************************************
131 * Is block less then 64k in length?
133 if (g_first->sequence != 1 || g_first->length == 1)
135 return GlobalUnlock(block);
138 /******************************************************************
139 * Make sure we have a lock on this block.
141 #ifdef HAVE_IPC
142 if (g_first->linear_count > 1)
144 g_first->linear_count--;
146 else if (g_first->linear_count == 1)
148 g = g_first;
149 loc_idx = (((unsigned int) g_first - (unsigned int) SHM_RANGE_START)
150 / 0x10000);
151 for (i = 0; i < g_first->length; i++, g = g->next)
153 shmdt(g->linear_addr);
154 g->linear_addr = NULL;
155 MemoryKeys[i] = -1;
158 g_first->linear_count = 0;
159 return 0;
161 #endif /* HAVE_IPC */
163 return 0;
165 /**********************************************************************/
167 LinearTest()
169 #if 0
170 unsigned int handle;
171 int *seg_ptr;
172 int *lin_ptr;
173 int seg, i;
174 int *p;
176 handle = GlobalAlloc(0, 0x40000);
177 seg_ptr = GlobalLock(handle);
178 lin_ptr = GlobalLinearLock(handle);
180 for (seg = 0; seg < 4; seg++)
182 p = (int *) ((char *) seg_ptr + (0x80000 * seg));
183 for (i = 0; i < (0x10000 / sizeof(int)); i++, p++)
184 *p = (seg * (0x10000 / sizeof(int))) + i;
187 p = lin_ptr;
188 for (i = 0; i < (0x40000 / sizeof(int)); i++, p++)
190 if (*p != i)
191 printf("lin_ptr[%x] = %x\n", i, *p);
193 #endif