Subversion Repositories Kolibri OS

Rev

Rev 864 | Rev 888 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 864 Rev 886
Line 11... Line 11...
11
   link_t adj;
11
   link_t adj;
12
   addr_t base;
12
   addr_t base;
13
   size_t size;
13
   size_t size;
14
   void*  parent;
14
   void*  parent;
15
   u32_t  reserved;
15
   u32_t  state;
16
}md_t;
16
}md_t;
17
 
17
 
Line -... Line 18...
-
 
18
#define   MD_FREE    1
-
 
19
#define   MD_USED    2
-
 
20
 
18
typedef struct {
21
typedef struct {
19
   SPINLOCK_DECLARE(lock);   /**< this lock protects everything below */
22
    SPINLOCK_DECLARE(lock);   /**< this lock protects everything below */
Line 20... Line 23...
20
 
23
 
21
   u32_t  availmask;
24
    u32_t  availmask;
-
 
25
    link_t free[32];
-
 
26
 
22
   link_t list[32];
27
    link_t used;
Line -... Line 28...
-
 
28
}heap_t;
23
}heap_t;
29
 
24
 
30
 
Line -... Line 31...
-
 
31
slab_cache_t *md_slab;
25
slab_cache_t *md_slab;
32
slab_cache_t *phm_slab;
26
slab_cache_t *phm_slab;
33
 
Line -... Line 34...
-
 
34
 
-
 
35
heap_t        lheap;
27
 
36
heap_t        sheap;
28
heap_t lheap;
37
 
Line 29... Line 38...
29
heap_t sheap;
38
 
30
 
39
 
Line 31... Line 40...
31
static inline void _set_lmask(count_t idx)
40
static inline void _set_lmask(count_t idx)
32
{ asm volatile ("bts DWORD PTR [_lheap], %0"::"r"(idx):"cc"); }
41
{ asm volatile ("bts %0, _lheap"::"r"(idx):"cc"); }
Line 33... Line 42...
33
 
42
 
34
static inline void _reset_lmask(count_t idx)
43
static inline void _reset_lmask(count_t idx)
Line 35... Line 44...
35
{ asm volatile ("btr DWORD PTR [_lheap], %0"::"r"(idx):"cc"); }
44
{ asm volatile ("btr %0, _lheap"::"r"(idx):"cc"); }
36
 
45
 
37
static inline void _set_smask(count_t idx)
46
static inline void _set_smask(count_t idx)
Line 52... Line 61...
52
   ASSERT((size & 0x3FFFFF) == 0);
61
   ASSERT((size & 0x3FFFFF) == 0);
53
 
62
 
Line 54... Line 63...
54
   for (i = 0; i < 32; i++)
63
   for (i = 0; i < 32; i++)
55
   {
64
   {
56
     list_initialize(&lheap.list[i]);
65
     list_initialize(&lheap.free[i]);
57
     list_initialize(&sheap.list[i]);
66
     list_initialize(&sheap.free[i]);
58
   };
67
   };
Line -... Line 68...
-
 
68
 
-
 
69
   list_initialize(&lheap.used);
-
 
70
   list_initialize(&sheap.used);
-
 
71
 
59
 
72
 
Line 60... Line 73...
60
   md_slab = slab_cache_create(sizeof(md_t), 32,NULL,NULL,SLAB_CACHE_MAGDEFERRED);
73
   md_slab = slab_cache_create(sizeof(md_t), 32,NULL,NULL,SLAB_CACHE_MAGDEFERRED);
Line 61... Line 74...
61
 
74
 
62
   md = (md_t*)slab_alloc(md_slab,0);
75
   md = (md_t*)slab_alloc(md_slab,0);
63
 
76
 
64
   list_initialize(&md->adj);
77
   list_initialize(&md->adj);
65
   md->base = base;
78
   md->base = base;
Line 66... Line 79...
66
   md->size = size;
79
   md->size = size;
67
   md->parent = NULL;
80
   md->parent = NULL;
68
   md->reserved = 0;
81
   md->state = MD_FREE;
Line 69... Line 82...
69
 
82
 
Line 91... Line 104...
91
   if(mask)
104
   if(mask)
92
   {
105
   {
93
     if(idx0 == 31)
106
     if(idx0 == 31)
94
     {
107
     {
95
        md_t *tmp = (md_t*)lheap.list[31].next;
108
        md_t *tmp = (md_t*)lheap.free[31].next;
96
        while((link_t*)tmp != &lheap.list[31])
109
        while((link_t*)tmp != &lheap.free[31])
97
        {
110
        {
98
          if(tmp->size >= size)
111
          if(tmp->size >= size)
99
          {
112
          {
100
            DBG("remove large tmp %x\n", tmp);
113
            DBG("remove large tmp %x\n", tmp);
Line 108... Line 121...
108
     else
121
     else
109
     {
122
     {
110
       idx0 = _bsf(mask);
123
       idx0 = _bsf(mask);
111
 
124
 
Line 112... Line 125...
112
       ASSERT( !list_empty(&lheap.list[idx0]))
125
       ASSERT( !list_empty(&lheap.free[idx0]))
Line 113... Line 126...
113
 
126
 
114
       md = (md_t*)lheap.list[idx0].next;
127
       md = (md_t*)lheap.free[idx0].next;
115
     };
128
     };
116
   }
129
   }
117
   else
130
   else
Line -... Line 131...
-
 
131
     return NULL;
-
 
132
 
118
     return NULL;
133
   ASSERT(md->state == MD_FREE);
119
 
134
 
120
   list_remove((link_t*)md);
135
   list_remove((link_t*)md);
Line 121... Line 136...
121
   if(list_empty(&lheap.list[idx0]))
136
   if(list_empty(&lheap.free[idx0]))
122
     _reset_lmask(idx0);
137
     _reset_lmask(idx0);
123
 
138
 
124
   if(md->size > size)
139
   if(md->size > size)
Line 125... Line 140...
125
   {
140
   {
126
     count_t idx1;
141
     count_t idx1;
Line 127... Line 142...
127
     md_t *new_md = (md_t*)slab_alloc(md_slab,0);
142
     md_t *new_md = (md_t*)slab_alloc(md_slab,0);         /* FIXME check */
128
 
143
 
-
 
144
     link_initialize(&new_md->link);
Line 129... Line 145...
129
     link_initialize(&new_md->link);
145
     list_insert(&new_md->adj, &md->adj);
130
     list_insert(&new_md->adj, &md->adj);
146
 
Line 131... Line 147...
131
 
147
     new_md->base = md->base;
Line 132... Line 148...
132
     new_md->base = md->base;
148
     new_md->size = size;
133
     new_md->size = size;
149
     new_md->state = MD_USED;
Line 134... Line 150...
134
 
150
 
135
     md->base+= size;
151
     md->base+= size;
-
 
152
     md->size-= size;
-
 
153
 
136
     md->size-= size;
154
     idx1 = (md->size>>22) - 1 < 32 ? (md->size>>22) - 1 : 31;
137
 
155
 
Line 138... Line 156...
138
     idx1 = (md->size>>22) - 1 < 32 ? (md->size>>22) - 1 : 31;
156
     list_prepend(&md->link, &lheap.free[idx1]);
139
 
157
     _set_lmask(idx1);
Line 166... Line 184...
166
   if(mask)
184
    if(mask)
167
   {
185
    {
168
     if(idx0 == 31)
186
        if(idx0 == 31)
169
     {
187
        {
-
 
188
            ASSERT( !list_empty(&sheap.free[31]));
-
 
189
 
170
        md_t *tmp = (md_t*)sheap.list[31].next;
190
            md_t *tmp = (md_t*)sheap.free[31].next;
171
        while((link_t*)tmp != &sheap.list[31])
191
            while((link_t*)tmp != &sheap.free[31])
172
        {
192
            {
173
          if(tmp->size >= size)
193
                if(tmp->size >= size)
174
          {
194
                {
175
             md = tmp;
195
                    md = tmp;
176
             break;
196
                    break;
Line 180... Line 200...
180
     }
200
        }
181
     else
201
        else
182
     {
202
        {
183
       idx0 = _bsf(mask);
203
            idx0 = _bsf(mask);
184
       ASSERT( !list_empty(&sheap.list[idx0]))
204
 
-
 
205
            ASSERT( !list_empty(&sheap.free[idx0]));
185
       md = (md_t*)sheap.list[idx0].next;
206
 
-
 
207
            md = (md_t*)sheap.free[idx0].next;
186
     }
208
        }
187
   };
209
    };
188
 
210
 
Line 189... Line 211...
189
   if(md)
211
    if(md)
190
   {
212
    {
191
     DBG("remove md %x\n", md);
213
        DBG("remove md %x\n", md);
Line -... Line 214...
-
 
214
 
-
 
215
        ASSERT(md->state==MD_FREE);
192
 
216
 
193
     list_remove((link_t*)md);
217
        list_remove((link_t*)md);
194
     if(list_empty(&sheap.list[idx0]))
218
        if(list_empty(&sheap.free[idx0]))
195
       _reset_smask(idx0);
219
            _reset_smask(idx0);
196
   }
220
    }
197
   else
221
    else
198
   {
222
    {
Line 206... Line 230...
206
       safe_sti(efl);
230
            safe_sti(efl);
207
       return NULL;
231
            return NULL;
208
     };
232
        };
209
 
233
 
Line 210... Line 234...
210
     md = (md_t*)slab_alloc(md_slab,0);
234
        md = (md_t*)slab_alloc(md_slab,0);    /* FIXME check */
-
 
235
 
211
     link_initialize(&md->link);
236
        link_initialize(&md->link);
212
     list_initialize(&md->adj);
237
        list_initialize(&md->adj);
213
     md->base = lmd->base;
238
        md->base = lmd->base;
214
     md->size = lmd->size;
239
        md->size = lmd->size;
215
     md->parent  = lmd;
240
        md->parent  = lmd;
216
     md->reserved = 0;
241
        md->state = MD_USED;
217
   };
242
    };
Line 218... Line 243...
218
 
243
 
219
   if(md->size > size)
244
    if(md->size > size)
220
   {
245
    {
221
     count_t idx1;
246
        count_t idx1;
Line 222... Line 247...
222
     md_t *new_md = (md_t*)slab_alloc(md_slab,0);
247
        md_t *new_md = (md_t*)slab_alloc(md_slab,0);    /* FIXME check */
223
 
248
 
Line 224... Line 249...
224
     link_initialize(&new_md->link);
249
        link_initialize(&new_md->link);
225
     list_insert(&new_md->adj, &md->adj);
250
        list_insert(&new_md->adj, &md->adj);
226
 
251
 
227
     new_md->base = md->base;
252
        new_md->base = md->base;
Line 228... Line 253...
228
     new_md->size = size;
253
        new_md->size = size;
229
     new_md->parent = md->parent;
254
        new_md->parent = md->parent;
-
 
255
        new_md->state = MD_USED;
Line 230... Line 256...
230
     new_md->reserved = 0;
256
 
Line 231... Line 257...
231
 
257
        md->base+= size;
Line 232... Line 258...
232
     md->base+= size;
258
        md->size-= size;
233
     md->size-= size;
259
        md->state = MD_FREE;
234
 
260
 
235
     idx1 = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31;
261
        idx1 = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31;
236
 
262
 
237
     DBG("insert md %x, base %x size %x idx %x\n", md,md->base, md->size,idx1);
263
        DBG("insert md %x, base %x size %x idx %x\n", md,md->base, md->size,idx1);
238
 
264
 
239
     if( idx1 < 31)
265
        if( idx1 < 31)
240
       list_prepend(&md->link, &sheap.list[idx1]);
266
          list_prepend(&md->link, &sheap.free[idx1]);
Line 241... Line 267...
241
     else
267
        else
242
     {
268
        {
243
       if( list_empty(&sheap.list[31]))
269
            if( list_empty(&sheap.free[31]))
244
         list_prepend(&md->link, &sheap.list[31]);
270
                list_prepend(&md->link, &sheap.free[31]);
245
       else
271
            else
246
       {
272
            {
Line 260... Line 286...
260
 
286
 
Line 261... Line 287...
261
     safe_sti(efl);
287
        safe_sti(efl);
Line 262... Line 288...
262
 
288
 
263
     return new_md;
289
        return new_md;
-
 
290
    };
-
 
291
 
-
 
292
    md->state = MD_USED;
264
   }
293
 
-
 
294
    safe_sti(efl);
265
   safe_sti(efl);
295
 
266
   return md;
296
    return md;
Line -... Line 297...
-
 
297
}
-
 
298
 
-
 
299
void __fastcall free_small_md(md_t *md)
-
 
300
{
-
 
301
    eflags_t  efl ;
-
 
302
    md_t     *fd;
-
 
303
    md_t     *bk;
-
 
304
    count_t   idx;
-
 
305
 
-
 
306
    efl = safe_cli();
-
 
307
    spinlock_lock(&sheap.lock);
-
 
308
 
-
 
309
    if( !list_empty(&md->adj))
-
 
310
    {
-
 
311
        bk = (md_t*)md->adj.prev;
-
 
312
        fd = (md_t*)md->adj.next;
-
 
313
 
-
 
314
        if(fd->state == MD_FREE)
-
 
315
        {
-
 
316
            idx = (fd->size>>12) - 1 < 32 ? (fd->size>>12) - 1 : 31;
-
 
317
 
-
 
318
            list_remove((link_t*)fd);
-
 
319
            if(list_empty(&sheap.free[idx]))
-
 
320
                _reset_smask(idx);
-
 
321
 
-
 
322
            md->size+= fd->size;
-
 
323
            md->adj.next = fd->adj.next;
-
 
324
            md->adj.next->prev = (link_t*)md;
-
 
325
            slab_free(md_slab, fd);
-
 
326
        };
-
 
327
        if(bk->state == MD_FREE)
-
 
328
        {
-
 
329
            idx = (bk->size>>12) - 1 < 32 ? (bk->size>>12) - 1 : 31;
-
 
330
 
-
 
331
            list_remove((link_t*)bk);
-
 
332
            if(list_empty(&sheap.free[idx]))
-
 
333
                _reset_smask(idx);
-
 
334
 
-
 
335
            bk->size+= md->size;
-
 
336
            bk->adj.next = md->adj.next;
-
 
337
            bk->adj.next->prev = (link_t*)bk;
-
 
338
            slab_free(md_slab, md);
-
 
339
            md = fd;
-
 
340
        };
-
 
341
    };
-
 
342
 
-
 
343
    md->state = MD_FREE;
-
 
344
 
-
 
345
    idx = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31;
-
 
346
 
-
 
347
    _set_smask(idx);
-
 
348
 
-
 
349
    if( idx < 31)
-
 
350
        list_prepend(&md->link, &sheap.free[idx]);
-
 
351
    else
-
 
352
    {
-
 
353
        if( list_empty(&sheap.free[31]))
-
 
354
            list_prepend(&md->link, &sheap.free[31]);
-
 
355
        else
-
 
356
        {
-
 
357
            md_t *tmp = (md_t*)sheap.free[31].next;
-
 
358
 
-
 
359
            while((link_t*)tmp != &sheap.free[31])
-
 
360
            {
-
 
361
                if(md->base < tmp->base)
-
 
362
                    break;
-
 
363
                tmp = (md_t*)tmp->link.next;
-
 
364
            }
-
 
365
            list_insert(&md->link, &tmp->link);
-
 
366
        };
-
 
367
    };
-
 
368
    spinlock_unlock(&sheap.lock);
-
 
369
    safe_sti(efl);
-
 
370
 
-
 
371
};
-
 
372
 
-
 
373
 
-
 
374
#define page_tabs 0xDF800000
267
}
375
 
268
 
376
/*
269
phismem_t* __fastcall phis_alloc(count_t count)
377
phismem_t* __fastcall phis_alloc(count_t count)
270
{
378
{
271
   phismem_t *phm;
379
   phismem_t *phm;
Line 287... Line 395...
287
 
395
 
Line 288... Line 396...
288
   return phm;
396
   return phm;
289
}
397
}
Line 290... Line -...
290
 
-
 
291
#define page_tabs 0xDF800000
-
 
292
 
398
 
293
void map_phm(addr_t base, phismem_t *phm, u32_t mapflags)
399
void map_phm(addr_t base, phismem_t *phm, u32_t mapflags)
294
{
400
{
295
   count_t count;
401
   count_t count;
Line 315... Line 421...
315
       frame+= 4096;
421
       frame+= 4096;
316
     }
422
     }
317
   }
423
   }
318
};
424
};
319
 
425
*/
-
 
426
 
Line 320... Line 427...
320
void* __fastcall mem_alloc(size_t size, u32_t flags)
427
void * __fastcall mem_alloc(size_t size, u32_t flags)
321
{
428
{
322
   md_t *md;
-
 
323
   phismem_t *phm;
429
    eflags_t efl;
Line 324... Line 430...
324
 
430
 
Line 325... Line -...
325
   size = (size+4095)&~4095;
-
 
326
 
-
 
327
   md = find_small_md(size);
-
 
328
   if( md )
-
 
329
   {
431
    md_t *md;
330
     phm = phis_alloc(size>>12);
-
 
331
     map_phm(md->base , phm, flags);
-
 
332
     return (void*)md->base;
-
 
333
   }
-
 
Line 334... Line -...
334
   return NULL;
-
 
335
};
-
 
336
 
432
 
Line 337... Line 433...
337
void * __fastcall heap_alloc(size_t size, u32_t flags)
433
    DBG("\nmem_alloc: %x bytes\n", size);
Line 338... Line 434...
338
{
434
 
Line 339... Line 435...
339
   md_t *md;
435
    ASSERT(size != 0);
340
 
436
 
-
 
437
    size = (size+4095)&~4095;
-
 
438
 
341
   size = (size+4095)&~4095;
439
    md = find_small_md(size);
342
 
440
 
343
   md = find_small_md(size);
441
    if( md )
344
 
442
    {
Line 354... Line 452...
354
         u32_t  order;
452
                u32_t  order;
355
         addr_t frame;
453
                addr_t frame;
356
         size_t size;
454
                size_t size;
357
 
455
 
Line 358... Line 456...
358
         asm volatile ("bsr %0, %1":"=&r"(order):"r"(tmp):"cc");
456
                asm volatile ("bsr %1, %0":"=&r"(order):"r"(tmp):"cc");
359
         asm volatile ("btr %0, %1" :"=r"(tmp):"r"(order):"cc");
457
                asm volatile ("btr %1, %0" :"=r"(tmp):"r"(order):"cc");
Line 360... Line 458...
360
 
458
 
Line 361... Line 459...
361
         frame = core_alloc(order) | flags;
459
                frame = core_alloc(order) | flags;         /* FIXME check */
362
 
460
 
363
         size = (1 << order);
461
                size = (1 << order);
364
         while(size--)
462
                while(size--)
365
         {
463
                {
366
           *pte++ = frame;
464
                    *pte++ = frame;
367
           frame+= 4096;
465
                    frame+= 4096;
368
         };
466
                };
-
 
467
            };
-
 
468
        };
-
 
469
 
-
 
470
        efl = safe_cli();
-
 
471
        spinlock_lock(&sheap.lock);
-
 
472
 
-
 
473
        if( list_empty(&sheap.used) )
-
 
474
            list_prepend(&md->link, &sheap.used);
-
 
475
        else
-
 
476
        {
-
 
477
            md_t *tmp = (md_t*)sheap.used.next;
-
 
478
 
-
 
479
            while((link_t*)tmp != &sheap.used)
-
 
480
            {
-
 
481
                if(md->base < tmp->base)
-
 
482
                    break;
-
 
483
                tmp = (md_t*)tmp->link.next;
-
 
484
            }
-
 
485
            list_insert(&md->link, &tmp->link);
-
 
486
        };
-
 
487
 
-
 
488
        spinlock_unlock(&sheap.lock);
369
       };
489
        safe_sti(efl);
370
     };
490
 
371
     DBG("alloc_heap: %x size %x\n\n",md->base, size);
491
        DBG("allocate: %x size %x\n\n",md->base, size);
372
     return (void*)md->base;
492
        return (void*)md->base;
373
   };
493
    };
Line -... Line 494...
-
 
494
    return NULL;
-
 
495
};
-
 
496
 
-
 
497
void __fastcall mem_free(void *mem)
-
 
498
{
-
 
499
    eflags_t efl;
-
 
500
 
-
 
501
    md_t *tmp;
-
 
502
    md_t *md = NULL;
-
 
503
 
-
 
504
    DBG("mem_free: %x\n",mem);
-
 
505
 
-
 
506
    ASSERT( mem != 0 );
-
 
507
    ASSERT( ((addr_t)mem & 0xFFF) == 0 );
-
 
508
    ASSERT( ! list_empty(&sheap.used));
-
 
509
 
-
 
510
    efl = safe_cli();
-
 
511
 
-
 
512
    tmp = (md_t*)sheap.used.next;
-
 
513
 
-
 
514
    while((link_t*)tmp != &sheap.used)
-
 
515
    {
-
 
516
        if( tmp->base == (addr_t)mem )
-
 
517
        {
-
 
518
            md = tmp;
-
 
519
            break;
Line -... Line 520...
-
 
520
        };
-
 
521
        tmp = (md_t*)tmp->link.next;
-
 
522
    }
-
 
523
 
-
 
524
    if( md )
-
 
525
    {
-
 
526
        DBG("\tmd: %x base: %x size: %x\n",md, md->base, md->size);
-
 
527
 
-
 
528
        ASSERT(md->state == MD_USED);
-
 
529
 
-
 
530
        count_t tmp  = md->size >> 12;
-
 
531
        addr_t  *pte = &((addr_t*)page_tabs)[md->base>>12];
-
 
532
 
-
 
533
        while(tmp--)
-
 
534
        {
-
 
535
            *pte++ = 0;
-
 
536
            asm volatile (
-
 
537
                "invlpg (%0)"
-
 
538
                :
-
 
539
                :"r" (mem) );
-
 
540
            mem+= 4096;
-
 
541
        };
-
 
542
        list_remove((link_t*)md);
-
 
543
        free_small_md( md );
-
 
544
    }
-
 
545
    else
-
 
546
    {
-
 
547
        DBG("\tERROR: invalid base address: %x\n", mem);