Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
968 leency 1
// memman.cpp : Defines the entry point for the console application.
2
//
3
 
4
#include "kosSyst.h"
5
#include "mcsmemm.h"
6
 
7
 
8
void * __cdecl operator new ( size_t count, size_t element_size )
9
{
10
	return allocmem( (Dword)(count * element_size) );
11
}
12
 
13
void * __cdecl operator new [] ( size_t amount )
14
{
15
	return allocmem( (Dword)amount );
16
}
17
 
18
void * __cdecl operator new ( size_t amount )
19
{
20
	return allocmem( (Dword)amount );
21
}
22
 
23
void __cdecl operator delete ( void *pointer )
24
{
25
	if ( pointer != NULL ) freemem( pointer );
26
}
27
 
28
void __cdecl operator delete [] ( void *pointer )
29
{
30
	if ( pointer != NULL ) freemem( pointer );
31
}
32
 
33
 
34
//
35
Dword mmMutex = FALSE;
36
MemBlock *rootfree = NULL;
37
MemBlock *rootuser = NULL;
38
bool mmInitialized = false;
39
Byte *mmHeapTop = NULL;
40
 
41
 
42
//
43
Byte * AllocMemFromSystem( Dword reqSize )
44
{
45
	Byte *result;
46
	sProcessInfo pInfo;
47
 
48
	//
49
	if ( mmInitialized )
50
	{
51
		result = mmHeapTop;
52
	}
53
	else
54
	{
55
		//
56
		kos_ProcessInfo( &pInfo );
57
		//
58
		result = (Byte *)(pInfo.processInfo.used_memory + 1);
59
		//
60
		mmInitialized = true;
61
	}
62
	//
63
	if ( ! kos_ApplicationMemoryResize( ((Dword)result) + reqSize ) )
64
	{
65
		result = NULL;
66
	}
67
	//
68
	mmHeapTop = result + reqSize;
69
	//
70
	return result;
71
}
72
 
73
 
74
//
75
Byte *allocmem( Dword reqsize )
76
{
77
  MemBlock *BlockForCheck;
78
  MemBlock *LastKnownGood;
79
  Dword tail;
80
  Byte *address;
81
 
82
  //подровняем размер
83
  if( ( tail = reqsize % SIZE_ALIGN ) != 0 )
84
  {
85
    reqsize += SIZE_ALIGN - tail;
86
  }
87
 
88
  LastKnownGood = NULL;
89
 
90
  // ждём освобождения мьютекса
91
  while ( rtlInterlockedExchange( &mmMutex, TRUE ) )
92
  {
93
	  //
94
	  kos_Pause( 1 );
95
  }
96
 
97
  //ищем подходящий свободный блок
98
  if( rootfree != NULL )
99
  {
100
    for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next )
101
    {
102
      if ( BlockForCheck->Size >= reqsize )
103
      {
104
        //нашли
105
        if ( LastKnownGood != NULL )
106
        {
107
          if ( LastKnownGood->Size >= BlockForCheck->Size )
108
            LastKnownGood = BlockForCheck;
109
        }
110
        else
111
          LastKnownGood = BlockForCheck;
112
        if ( LastKnownGood->Size == reqsize )
113
          break;
114
      }
115
      if ( BlockForCheck->Next == NULL )
116
        break;
117
    }
118
  }
119
 
120
  if ( LastKnownGood != NULL )
121
  {
122
    //проверим найденный блок на возможность деления
123
    tail = LastKnownGood->Size - reqsize;
124
    if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) )
125
    {
126
      //будем разбивать
127
      BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail );
128
      BlockForCheck->Size = reqsize;
129
      //вставим занятый блок в начало списка занатых блоков
130
      if( rootuser != NULL )
131
      {
132
        BlockForCheck->Next = rootuser;
133
        rootuser->Previous = BlockForCheck;
134
        BlockForCheck->Previous = NULL;
135
        rootuser = BlockForCheck;
136
      }
137
      else
138
      {
139
        rootuser = BlockForCheck;
140
        BlockForCheck->Next = NULL;
141
        BlockForCheck->Previous = NULL;
142
      }
143
 
144
      //изменим размер оставшейся части
145
      LastKnownGood->Size = tail - sizeof(MemBlock);
146
      address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock);
147
 
148
	  // отпустим мьютекс
149
      rtlInterlockedExchange( &mmMutex, FALSE );
150
 
151
      return address;
152
    }
153
    else
154
    {
155
      //перемести блок из очереди свободных в начало очереди занятых
156
      //сначала выкинем его из очереди свободных
157
      if ( LastKnownGood->Previous != NULL )
158
      {
159
        LastKnownGood->Previous->Next = LastKnownGood->Next;
160
      }
161
      else
162
      {
163
        //блок стоит в начале очереди
164
        rootfree = LastKnownGood->Next;
165
      }
166
      if( LastKnownGood->Next != NULL )
167
      {
168
        LastKnownGood->Next->Previous = LastKnownGood->Previous;
169
      }
170
      //теперь вставим его в очередь занятых
171
      if( rootuser != NULL )
172
      {
173
        LastKnownGood->Next = rootuser;
174
        rootuser->Previous = LastKnownGood;
175
        LastKnownGood->Previous = NULL;
176
        rootuser = LastKnownGood;
177
      }
178
      else
179
      {
180
        rootuser = LastKnownGood;
181
        LastKnownGood->Next = NULL;
182
        LastKnownGood->Previous = NULL;
183
      }
184
	  //
185
      address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock);
186
 
187
	  // отпустим мьютекс
188
      rtlInterlockedExchange( &mmMutex, FALSE );
189
 
190
      return address;
191
    }
192
  }
193
  else
194
  {
195
    //надо получить ещё кусочек памяти
196
    LastKnownGood = (MemBlock *)AllocMemFromSystem( reqsize + sizeof(MemBlock) );
197
	//
198
    if( LastKnownGood != NULL )
199
    {
200
      LastKnownGood->Size = reqsize;
201
      //теперь вставим его в очередь занятых
202
      if( rootuser != NULL )
203
      {
204
        LastKnownGood->Next = rootuser;
205
        rootuser->Previous = LastKnownGood;
206
        LastKnownGood->Previous = NULL;
207
        rootuser = LastKnownGood;
208
      }
209
      else
210
      {
211
        rootuser = LastKnownGood;
212
        LastKnownGood->Next = NULL;
213
        LastKnownGood->Previous = NULL;
214
      }
215
      address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock);
216
 
217
	  // отпустим мьютекс
218
      rtlInterlockedExchange( &mmMutex, FALSE );
219
 
220
      return address;
221
    }
222
  }
223
 
224
  // отпустим мьютекс
225
  rtlInterlockedExchange( &mmMutex, FALSE );
226
 
227
  //
228
  rtlDebugOutString( "allocmem failed." );
229
  kos_ExitApp();
230
  //
231
  return NULL;
232
}
233
 
234
//
235
Dword freemem( void *vaddress )
236
{
237
  Dword result;
238
 
239
  Byte *checknext, *address = (Byte *)vaddress;
240
 
241
  // ждём освобождения мьютекса
242
  while ( rtlInterlockedExchange( &mmMutex, TRUE ) )
243
  {
244
	  //
245
	  kos_Pause( 1 );
246
  }
247
 
248
  MemBlock *released = (MemBlock *)( address - sizeof(MemBlock) );
249
 
250
  result = released->Size;
251
 
252
  //убираем блок из списка занятых
253
  if ( released->Previous != NULL )
254
  {
255
    released->Previous->Next = released->Next;
256
  }
257
  else
258
  {
259
    rootuser = released->Next;
260
  }
261
  if ( released->Next != NULL )
262
  {
263
    released->Next->Previous = released->Previous;
264
  }
265
  //закинем теперь этот блок в список свободных
266
  released->Next = rootfree;
267
  released->Previous = NULL;
268
  rootfree = released;
269
  if ( released->Next != NULL )
270
  {
271
    released->Next->Previous = released;
272
  }
273
 
274
  //теперь поищем смежные свободные блоки
275
  checknext = (Byte *)(rootfree) + ( rootfree->Size + sizeof(MemBlock) );
276
  //
277
  for ( released = rootfree->Next; released != NULL; released = released->Next )
278
  {
279
    if ( checknext == (Byte *)released )
280
    {
281
      //собираем блоки вместе
282
      //сначала выкинем из очереди свободных
283
      released->Previous->Next = released->Next;
284
      if( released->Next != NULL )
285
      {
286
        released->Next->Previous = released->Previous;
287
      }
288
      //теперь увеличим размер корневого блока
289
      rootfree->Size += released->Size + sizeof(MemBlock);
290
      break;
291
    }
292
  }
293
  //если надо, поищем блоки перед текщим.
294
  checknext = (Byte *)(rootfree);
295
  //
296
  if ( released == NULL )
297
  {
298
    for ( released = rootfree->Next; released != NULL; released = released->Next )
299
    {
300
      if ( checknext == (Byte *)released + ( released->Size + sizeof(MemBlock) ) )
301
      {
302
        //собираем блоки вместе
303
        //увеличим размер блока
304
        released->Size += rootfree->Size + sizeof(MemBlock);
305
        //теперь выкинем из очереди свободных
306
        released->Previous->Next = released->Next;
307
        if ( released->Next != NULL )
308
        {
309
          released->Next->Previous = released->Previous;
310
        }
311
        //и закинем его в начало очереди вместо присоединённого блока из корня списка
312
        if ( rootfree->Next != NULL )
313
        {
314
          rootfree->Next->Previous = released;
315
        }
316
        released->Next = rootfree->Next;
317
        released->Previous = NULL;
318
        rootfree = released;
319
        break;
320
      }
321
    }
322
  }
323
 
324
  // отпустим мьютекс
325
  rtlInterlockedExchange( &mmMutex, FALSE );
326
 
327
  return result;
328
}
329