Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1805 yogev_ezra 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 *allocmem( Dword reqsize )
44
{
45
  MemBlock *BlockForCheck;
46
  MemBlock *LastKnownGood;
47
  Dword tail;
48
  Byte *address;
49
 
50
  //подровняем размер
51
  if( ( tail = reqsize % SIZE_ALIGN ) != 0 )
52
  {
53
    reqsize += SIZE_ALIGN - tail;
54
  }
55
 
56
  LastKnownGood = NULL;
57
 
58
  // ждём освобождения мьютекса
59
  while ( rtlInterlockedExchange( &mmMutex, TRUE ) )
60
  {
61
	  //
62
	  kos_Pause( 1 );
63
  }
64
 
65
  //ищем подходящий свободный блок
66
  if( rootfree != NULL )
67
  {
68
    for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next )
69
    {
70
      if ( BlockForCheck->Size >= reqsize )
71
      {
72
        //нашли
73
        if ( LastKnownGood != NULL )
74
        {
75
          if ( LastKnownGood->Size >= BlockForCheck->Size )
76
            LastKnownGood = BlockForCheck;
77
        }
78
        else
79
          LastKnownGood = BlockForCheck;
80
        if ( LastKnownGood->Size == reqsize )
81
          break;
82
      }
83
      if ( BlockForCheck->Next == NULL )
84
        break;
85
    }
86
  }
87
 
88
  if ( LastKnownGood != NULL )
89
  {
90
    //проверим найденный блок на возможность деления
91
    tail = LastKnownGood->Size - reqsize;
92
    if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) )
93
    {
94
      //будем разбивать
95
      BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail );
96
      BlockForCheck->Size = reqsize;
97
      //вставим занятый блок в начало списка занатых блоков
98
      if( rootuser != NULL )
99
      {
100
        BlockForCheck->Next = rootuser;
101
        rootuser->Previous = BlockForCheck;
102
        BlockForCheck->Previous = NULL;
103
        rootuser = BlockForCheck;
104
      }
105
      else
106
      {
107
        rootuser = BlockForCheck;
108
        BlockForCheck->Next = NULL;
109
        BlockForCheck->Previous = NULL;
110
      }
111
 
112
      //изменим размер оставшейся части
113
      LastKnownGood->Size = tail - sizeof(MemBlock);
114
      address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock);
115
 
116
	  // отпустим мьютекс
117
      rtlInterlockedExchange( &mmMutex, FALSE );
118
 
119
      return address;
120
    }
121
    else
122
    {
123
      //перемести блок из очереди свободных в начало очереди занятых
124
      //сначала выкинем его из очереди свободных
125
      if ( LastKnownGood->Previous != NULL )
126
      {
127
        LastKnownGood->Previous->Next = LastKnownGood->Next;
128
      }
129
      else
130
      {
131
        //блок стоит в начале очереди
132
        rootfree = LastKnownGood->Next;
133
      }
134
      if( LastKnownGood->Next != NULL )
135
      {
136
        LastKnownGood->Next->Previous = LastKnownGood->Previous;
137
      }
138
      //теперь вставим его в очередь занятых
139
      if( rootuser != NULL )
140
      {
141
        LastKnownGood->Next = rootuser;
142
        rootuser->Previous = LastKnownGood;
143
        LastKnownGood->Previous = NULL;
144
        rootuser = LastKnownGood;
145
      }
146
      else
147
      {
148
        rootuser = LastKnownGood;
149
        LastKnownGood->Next = NULL;
150
        LastKnownGood->Previous = NULL;
151
      }
152
	  //
153
      address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock);
154
 
155
	  // отпустим мьютекс
156
      rtlInterlockedExchange( &mmMutex, FALSE );
157
 
158
      return address;
159
    }
160
  }
161
  else
162
  {
163
	// надо получить ещё блок памяти
164
	LastKnownGood = (MemBlock *)kos_malloc(
165
		(reqsize > 0x10000 - sizeof(MemBlock)) ? (reqsize + sizeof(MemBlock)) : 0x10000);
166
	if (LastKnownGood != NULL)
167
	{
168
		LastKnownGood->Size = reqsize;
169
		// теперь вставим его в очередь занятых
170
		LastKnownGood->Next = rootuser;
171
		LastKnownGood->Previous = NULL;
172
		if (rootuser != NULL)
173
			rootuser->Previous = LastKnownGood;
174
		rootuser = LastKnownGood;
175
		// а также добавим хвост свежевыделенного большого блока в список свободных
176
		if (reqsize < 0x10000 - sizeof(MemBlock))
177
		{
178
			MemBlock* free = (MemBlock*)((Byte*)LastKnownGood + sizeof(MemBlock) + reqsize);
179
			free->Next = rootfree;
180
			free->Previous = NULL;
181
			if (rootfree != NULL)
182
				rootfree->Previous = free;
183
			rootfree = free;
184
		}
185
		address = (Byte*)LastKnownGood + sizeof(MemBlock);
186
		// отпустим мьютекс
187
		rtlInterlockedExchange(&mmMutex, FALSE);
188
 
189
		return address;
190
	}
191
  }
192
 
193
  // отпустим мьютекс
194
  rtlInterlockedExchange( &mmMutex, FALSE );
195
 
196
  //
197
  rtlDebugOutString( "allocmem failed." );
198
  kos_ExitApp();
199
  //
200
  return NULL;
201
}
202
 
203
//
204
Dword freemem( void *vaddress )
205
{
206
  Dword result;
207
 
208
  Byte *checknext, *address = (Byte *)vaddress;
209
 
210
  // ждём освобождения мьютекса
211
  while ( rtlInterlockedExchange( &mmMutex, TRUE ) )
212
  {
213
	  //
214
	  kos_Pause( 1 );
215
  }
216
 
217
  MemBlock *released = (MemBlock *)( address - sizeof(MemBlock) );
218
 
219
  result = released->Size;
220
 
221
  //убираем блок из списка занятых
222
  if ( released->Previous != NULL )
223
  {
224
    released->Previous->Next = released->Next;
225
  }
226
  else
227
  {
228
    rootuser = released->Next;
229
  }
230
  if ( released->Next != NULL )
231
  {
232
    released->Next->Previous = released->Previous;
233
  }
234
  //закинем теперь этот блок в список свободных
235
  released->Next = rootfree;
236
  released->Previous = NULL;
237
  rootfree = released;
238
  if ( released->Next != NULL )
239
  {
240
    released->Next->Previous = released;
241
  }
242
 
243
  //теперь поищем смежные свободные блоки
244
  checknext = (Byte *)(rootfree) + ( rootfree->Size + sizeof(MemBlock) );
245
  //
246
  for ( released = rootfree->Next; released != NULL; released = released->Next )
247
  {
248
    if ( checknext == (Byte *)released )
249
    {
250
      //собираем блоки вместе
251
      //сначала выкинем из очереди свободных
252
      released->Previous->Next = released->Next;
253
      if( released->Next != NULL )
254
      {
255
        released->Next->Previous = released->Previous;
256
      }
257
      //теперь увеличим размер корневого блока
258
      rootfree->Size += released->Size + sizeof(MemBlock);
259
      break;
260
    }
261
  }
262
  //если надо, поищем блоки перед текщим.
263
  checknext = (Byte *)(rootfree);
264
  //
265
  if ( released == NULL )
266
  {
267
    for ( released = rootfree->Next; released != NULL; released = released->Next )
268
    {
269
      if ( checknext == (Byte *)released + ( released->Size + sizeof(MemBlock) ) )
270
      {
271
        //собираем блоки вместе
272
        //увеличим размер блока
273
        released->Size += rootfree->Size + sizeof(MemBlock);
274
        //теперь выкинем из очереди свободных
275
        released->Previous->Next = released->Next;
276
        if ( released->Next != NULL )
277
        {
278
          released->Next->Previous = released->Previous;
279
        }
280
        //и закинем его в начало очереди вместо присоединённого блока из корня списка
281
        if ( rootfree->Next != NULL )
282
        {
283
          rootfree->Next->Previous = released;
284
        }
285
        released->Next = rootfree->Next;
286
        released->Previous = NULL;
287
        rootfree = released;
288
        break;
289
      }
290
    }
291
  }
292
 
293
  // отпустим мьютекс
294
  rtlInterlockedExchange( &mmMutex, FALSE );
295
 
296
  return result;
297
}
298