Subversion Repositories Kolibri OS

Rev

Rev 5596 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5596 Rev 6339
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
7
 
8
$Revision: 5596 $
8
$Revision: 6339 $
9
 
9
 
10
 
10
 
11
struct  MEM_BLOCK
11
struct  MEM_BLOCK
12
        list            LHEAD
12
        list            LHEAD
13
        next_block      dd ? ;+8
13
        next_block      dd ? ;+8
14
        prev_block      dd ? ;+4
14
        prev_block      dd ? ;+4
15
        base            dd ? ;+16
15
        base            dd ? ;+16
16
        size            dd ? ;+20
16
        size            dd ? ;+20
17
        flags           dd ? ;+24
17
        flags           dd ? ;+24
18
        handle          dd ? ;+28
18
        handle          dd ? ;+28
19
ends
19
ends
20
 
20
 
21
FREE_BLOCK      equ  4
21
FREE_BLOCK      equ  4
22
USED_BLOCK      equ  8
22
USED_BLOCK      equ  8
23
DONT_FREE_BLOCK equ  10h
23
DONT_FREE_BLOCK equ  10h
24
 
24
 
25
 
25
 
26
block_next   equ MEM_BLOCK.next_block
26
block_next   equ MEM_BLOCK.next_block
27
block_prev   equ MEM_BLOCK.prev_block
27
block_prev   equ MEM_BLOCK.prev_block
28
list_fd      equ MEM_BLOCK.list.next
28
list_fd      equ MEM_BLOCK.list.next
29
list_bk      equ MEM_BLOCK.list.prev
29
list_bk      equ MEM_BLOCK.list.prev
30
block_base   equ MEM_BLOCK.base
30
block_base   equ MEM_BLOCK.base
31
block_size   equ MEM_BLOCK.size
31
block_size   equ MEM_BLOCK.size
32
block_flags  equ MEM_BLOCK.flags
32
block_flags  equ MEM_BLOCK.flags
33
 
33
 
34
macro calc_index op
34
macro calc_index op
35
{          shr op, 12
35
{          shr op, 12
36
        dec     op
36
        dec     op
37
        cmp     op, 63
37
        cmp     op, 63
38
        jna     @f
38
        jna     @f
39
        mov     op, 63
39
        mov     op, 63
40
@@:
40
@@:
41
}
41
}
42
 
42
 
43
align 4
43
align 4
44
md:
44
md:
45
.add_to_used:
45
.add_to_used:
46
        mov     eax, [esi+block_base]
46
        mov     eax, [esi+block_base]
47
        mov     ebx, [esi+block_base]
47
        mov     ebx, [esi+block_base]
48
        shr     ebx, 6
48
        shr     ebx, 6
49
        add     eax, ebx
49
        add     eax, ebx
50
        shr     ebx, 6
50
        shr     ebx, 6
51
        add     eax, ebx
51
        add     eax, ebx
52
        shr     eax, 12
52
        shr     eax, 12
53
        and     eax, 63
53
        and     eax, 63
54
        inc     [mem_hash_cnt+eax*4]
54
        inc     [mem_hash_cnt+eax*4]
55
 
55
 
56
        lea     ecx, [mem_used_list+eax*8]
56
        lea     ecx, [mem_used_list+eax*8]
57
        list_add esi, ecx
57
        list_add esi, ecx
58
        mov     [esi+block_flags], USED_BLOCK
58
        mov     [esi+block_flags], USED_BLOCK
59
        mov     eax, [esi+block_size]
59
        mov     eax, [esi+block_size]
60
        sub     [heap_free], eax
60
        sub     [heap_free], eax
61
        ret
61
        ret
62
align 4
62
align 4
63
.find_used:
63
.find_used:
64
        mov     ecx, eax
64
        mov     ecx, eax
65
        mov     ebx, eax
65
        mov     ebx, eax
66
        shr     ebx, 6
66
        shr     ebx, 6
67
        add     ecx, ebx
67
        add     ecx, ebx
68
        shr     ebx, 6
68
        shr     ebx, 6
69
        add     ecx, ebx
69
        add     ecx, ebx
70
        shr     ecx, 12
70
        shr     ecx, 12
71
        and     ecx, 63
71
        and     ecx, 63
72
 
72
 
73
        lea     ebx, [mem_used_list+ecx*8]
73
        lea     ebx, [mem_used_list+ecx*8]
74
        mov     esi, ebx
74
        mov     esi, ebx
75
.next:
75
.next:
76
        mov     esi, [esi+list_fd]
76
        mov     esi, [esi+list_fd]
77
        cmp     esi, ebx
77
        cmp     esi, ebx
78
        je      .fail
78
        je      .fail
79
 
79
 
80
        cmp     eax, [esi+block_base]
80
        cmp     eax, [esi+block_base]
81
        jne     .next
81
        jne     .next
82
 
82
 
83
        ret
83
        ret
84
.fail:
84
.fail:
85
        xor     esi, esi
85
        xor     esi, esi
86
        ret
86
        ret
87
 
87
 
88
align 4
88
align 4
89
.del_from_used:
89
.del_from_used:
90
        call    .find_used
90
        call    .find_used
91
        test    esi, esi
91
        test    esi, esi
92
        jz      .done
92
        jz      .done
93
 
93
 
94
        cmp     [esi+block_flags], USED_BLOCK
94
        cmp     [esi+block_flags], USED_BLOCK
95
        jne     .fatal
95
        jne     .fatal
96
 
96
 
97
        dec     [mem_hash_cnt+ecx*4]
97
        dec     [mem_hash_cnt+ecx*4]
98
        list_del esi
98
        list_del esi
99
.done:
99
.done:
100
        ret
100
        ret
101
.fatal:                            ;FIXME panic here
101
.fatal:                            ;FIXME panic here
102
        xor     esi, esi
102
        xor     esi, esi
103
        ret
103
        ret
104
 
104
 
105
;Initial heap state
105
;Initial heap state
106
;
106
;
107
;+heap_size               terminator        USED_BLOCK
107
;+heap_size               terminator        USED_BLOCK
108
;+4096*MEM_BLOCK.sizeof   free space        FREE_BLOCK
108
;+4096*MEM_BLOCK.sizeof   free space        FREE_BLOCK
109
;HEAP_BASE                heap_descriptors  USED_BLOCK
109
;HEAP_BASE                heap_descriptors  USED_BLOCK
110
;
110
;
111
 
111
 
112
align 4
112
align 4
113
proc init_kernel_heap
113
proc init_kernel_heap
114
 
114
 
115
        mov     ecx, 64
115
        mov     ecx, 64
116
        mov     edi, mem_block_list
116
        mov     edi, mem_block_list
117
@@:
117
@@:
118
        mov     eax, edi
118
        mov     eax, edi
119
        stosd
119
        stosd
120
        stosd
120
        stosd
121
        loop    @B
121
        loop    @B
122
 
122
 
123
        mov     ecx, 64
123
        mov     ecx, 64
124
        mov     edi, mem_used_list
124
        mov     edi, mem_used_list
125
@@:
125
@@:
126
        mov     eax, edi
126
        mov     eax, edi
127
        stosd
127
        stosd
128
        stosd
128
        stosd
129
        loop    @B
129
        loop    @B
130
 
130
 
131
        stdcall alloc_pages, dword 32
131
        stdcall alloc_pages, dword 32
132
 
132
 
133
        or      eax, PG_SWR
133
        or      eax, PG_SWR
134
        mov     ebx, HEAP_BASE
134
        mov     ebx, HEAP_BASE
135
        mov     ecx, 32
135
        mov     ecx, 32
136
        call    commit_pages
136
        call    commit_pages
137
 
137
 
138
        mov     edi, HEAP_BASE                     ;descriptors
138
        mov     edi, HEAP_BASE                     ;descriptors
139
        mov     ebx, HEAP_BASE+sizeof.MEM_BLOCK      ;free space
139
        mov     ebx, HEAP_BASE+sizeof.MEM_BLOCK      ;free space
140
        mov     ecx, HEAP_BASE+sizeof.MEM_BLOCK*2    ;terminator
140
        mov     ecx, HEAP_BASE+sizeof.MEM_BLOCK*2    ;terminator
141
 
141
 
142
        xor     eax, eax
142
        xor     eax, eax
143
        mov     [edi+block_next], ebx
143
        mov     [edi+block_next], ebx
144
        mov     [edi+block_prev], eax
144
        mov     [edi+block_prev], eax
145
        mov     [edi+list_fd], eax
145
        mov     [edi+list_fd], eax
146
        mov     [edi+list_bk], eax
146
        mov     [edi+list_bk], eax
147
        mov     [edi+block_base], HEAP_BASE
147
        mov     [edi+block_base], HEAP_BASE
148
        mov     [edi+block_size], 4096*sizeof.MEM_BLOCK
148
        mov     [edi+block_size], 4096*sizeof.MEM_BLOCK
149
        mov     [edi+block_flags], USED_BLOCK
149
        mov     [edi+block_flags], USED_BLOCK
150
 
150
 
151
        mov     [ecx+block_next], eax
151
        mov     [ecx+block_next], eax
152
        mov     [ecx+block_prev], ebx
152
        mov     [ecx+block_prev], ebx
153
        mov     [ecx+list_fd], eax
153
        mov     [ecx+list_fd], eax
154
        mov     [ecx+list_bk], eax
154
        mov     [ecx+list_bk], eax
155
        mov     [ecx+block_base], eax
155
        mov     [ecx+block_base], eax
156
        mov     [ecx+block_size], eax
156
        mov     [ecx+block_size], eax
157
        mov     [ecx+block_flags], USED_BLOCK
157
        mov     [ecx+block_flags], USED_BLOCK
158
 
158
 
159
        mov     [ebx+block_next], ecx
159
        mov     [ebx+block_next], ecx
160
        mov     [ebx+block_prev], edi
160
        mov     [ebx+block_prev], edi
161
        mov     [ebx+block_base], HEAP_BASE+4096*sizeof.MEM_BLOCK
161
        mov     [ebx+block_base], HEAP_BASE+4096*sizeof.MEM_BLOCK
162
 
162
 
163
        mov     ecx, [pg_data.kernel_pages]
163
        mov     ecx, [pg_data.kernel_pages]
164
        shl     ecx, 12
164
        shl     ecx, 12
165
        sub     ecx, HEAP_BASE-OS_BASE+4096*sizeof.MEM_BLOCK
165
        sub     ecx, HEAP_BASE-OS_BASE+4096*sizeof.MEM_BLOCK
166
        mov     [heap_size], ecx
166
        mov     [heap_size], ecx
167
        mov     [heap_free], ecx
167
        mov     [heap_free], ecx
168
        mov     [ebx+block_size], ecx
168
        mov     [ebx+block_size], ecx
169
        mov     [ebx+block_flags], FREE_BLOCK
169
        mov     [ebx+block_flags], FREE_BLOCK
170
 
170
 
171
        mov     [mem_block_mask], eax
171
        mov     [mem_block_mask], eax
172
        mov     [mem_block_mask+4], 0x80000000
172
        mov     [mem_block_mask+4], 0x80000000
173
 
173
 
174
        mov     ecx, mem_block_list+63*8
174
        mov     ecx, mem_block_list+63*8
175
        list_add ebx, ecx
175
        list_add ebx, ecx
176
 
176
 
177
        mov     ecx, 4096-3-1
177
        mov     ecx, 4096-3-1
178
        mov     eax, HEAP_BASE+sizeof.MEM_BLOCK*4
178
        mov     eax, HEAP_BASE+sizeof.MEM_BLOCK*4
179
 
179
 
180
        mov     [next_memblock], HEAP_BASE+sizeof.MEM_BLOCK *3
180
        mov     [next_memblock], HEAP_BASE+sizeof.MEM_BLOCK *3
181
@@:
181
@@:
182
        mov     [eax-sizeof.MEM_BLOCK], eax
182
        mov     [eax-sizeof.MEM_BLOCK], eax
183
        add     eax, sizeof.MEM_BLOCK
183
        add     eax, sizeof.MEM_BLOCK
184
        loop    @B
184
        loop    @B
185
 
185
 
186
        mov     [eax-sizeof.MEM_BLOCK], dword 0
186
        mov     [eax-sizeof.MEM_BLOCK], dword 0
187
 
187
 
188
        mov     ecx, heap_mutex
188
        mov     ecx, heap_mutex
189
        call    mutex_init
189
        call    mutex_init
190
        mov     [heap_blocks], 4094
190
        mov     [heap_blocks], 4094
191
        mov     [free_blocks], 4093
191
        mov     [free_blocks], 4093
192
        ret
192
        ret
193
endp
193
endp
194
 
194
 
195
; param
195
; param
196
;  eax= required size
196
;  eax= required size
197
;
197
;
198
; retval
198
; retval
199
;  edi= memory block descriptor
199
;  edi= memory block descriptor
200
;  ebx= descriptor index
200
;  ebx= descriptor index
201
 
201
 
202
align 4
202
align 4
203
get_small_block:
203
get_small_block:
204
        mov     ecx, eax
204
        mov     ecx, eax
205
        shr     ecx, 12
205
        shr     ecx, 12
206
        dec     ecx
206
        dec     ecx
207
        cmp     ecx, 63
207
        cmp     ecx, 63
208
        jle     .get_index
208
        jle     .get_index
209
        mov     ecx, 63
209
        mov     ecx, 63
210
.get_index:
210
.get_index:
211
        lea     esi, [mem_block_mask]
211
        lea     esi, [mem_block_mask]
212
        xor     ebx, ebx
212
        xor     ebx, ebx
213
        or      edx, -1
213
        or      edx, -1
214
 
214
 
215
        cmp     ecx, 32
215
        cmp     ecx, 32
216
        jb      .bit_test
216
        jb      .bit_test
217
 
217
 
218
        sub     ecx, 32
218
        sub     ecx, 32
219
        add     ebx, 32
219
        add     ebx, 32
220
        add     esi, 4
220
        add     esi, 4
221
.bit_test:
221
.bit_test:
222
        shl     edx, cl
222
        shl     edx, cl
223
        and     edx, [esi]
223
        and     edx, [esi]
224
.find:
224
.find:
225
        bsf     edi, edx
225
        bsf     edi, edx
226
        jz      .high_mask
226
        jz      .high_mask
227
        add     ebx, edi
227
        add     ebx, edi
228
        lea     ecx, [mem_block_list+ebx*8]
228
        lea     ecx, [mem_block_list+ebx*8]
229
        mov     edi, ecx
229
        mov     edi, ecx
230
.next:
230
.next:
231
        mov     edi, [edi+list_fd]
231
        mov     edi, [edi+list_fd]
232
        cmp     edi, ecx
232
        cmp     edi, ecx
233
        je      .err
233
        je      .err
234
        cmp     eax, [edi+block_size]
234
        cmp     eax, [edi+block_size]
235
        ja      .next
235
        ja      .next
236
        ret
236
        ret
237
.err:
237
.err:
238
        xor     edi, edi
238
        xor     edi, edi
239
        ret
239
        ret
240
 
240
 
241
.high_mask:
241
.high_mask:
242
        add     esi, 4
242
        add     esi, 4
243
        cmp     esi, mem_block_mask+8
243
        cmp     esi, mem_block_mask+8
244
        jae     .err
244
        jae     .err
245
        add     ebx, 32
245
        add     ebx, 32
246
        mov     edx, [esi]
246
        mov     edx, [esi]
247
        jmp     .find
247
        jmp     .find
248
 
248
 
249
 
249
 
250
align 4
250
align 4
251
free_mem_block:
251
free_mem_block:
252
        mov     ebx, [next_memblock]
252
        mov     ebx, [next_memblock]
253
        mov     [eax], ebx
253
        mov     [eax], ebx
254
        mov     [next_memblock], eax
254
        mov     [next_memblock], eax
255
        xor     ebx, ebx
255
        xor     ebx, ebx
256
 
256
 
257
        mov     dword [eax+4], ebx
257
        mov     dword [eax+4], ebx
258
        mov     dword [eax+8], ebx
258
        mov     dword [eax+8], ebx
259
        mov     dword [eax+12], ebx
259
        mov     dword [eax+12], ebx
260
        mov     dword [eax+16], ebx
260
        mov     dword [eax+16], ebx
261
;           mov dword [eax+20], 0     ;don't clear block size
261
;           mov dword [eax+20], 0     ;don't clear block size
262
        mov     dword [eax+24], ebx
262
        mov     dword [eax+24], ebx
263
        mov     dword [eax+28], ebx
263
        mov     dword [eax+28], ebx
264
        inc     [free_blocks]
264
        inc     [free_blocks]
265
        ret
265
        ret
266
 
266
 
267
align 4
267
align 4
268
proc alloc_kernel_space stdcall, size:dword
268
proc alloc_kernel_space stdcall, size:dword
269
           local block_ind:DWORD
269
           local block_ind:DWORD
270
 
270
 
271
        push    ebx
271
        push    ebx
272
        push    esi
272
        push    esi
273
        push    edi
273
        push    edi
274
 
274
 
275
        mov     eax, [size]
275
        mov     eax, [size]
276
        add     eax, 4095
276
        add     eax, 4095
277
        and     eax, not 4095
277
        and     eax, not 4095
278
        mov     [size], eax
278
        mov     [size], eax
279
 
279
 
280
        cmp     eax, [heap_free]
280
        cmp     eax, [heap_free]
281
        ja      .error
281
        ja      .error
282
 
282
 
283
        spin_lock_irqsave heap_mutex
283
        spin_lock_irqsave heap_mutex
284
 
284
 
285
        mov     eax, [size]
285
        mov     eax, [size]
286
 
286
 
287
        call    get_small_block ; eax
287
        call    get_small_block ; eax
288
        test    edi, edi
288
        test    edi, edi
289
        jz      .error_unlock
289
        jz      .error_unlock
290
 
290
 
291
        cmp     [edi+block_flags], FREE_BLOCK
291
        cmp     [edi+block_flags], FREE_BLOCK
292
        jne     .error_unlock
292
        jne     .error_unlock
293
 
293
 
294
        mov     [block_ind], ebx  ;index of allocated block
294
        mov     [block_ind], ebx  ;index of allocated block
295
 
295
 
296
        mov     eax, [edi+block_size]
296
        mov     eax, [edi+block_size]
297
        cmp     eax, [size]
297
        cmp     eax, [size]
298
        je      .m_eq_size
298
        je      .m_eq_size
299
 
299
 
300
        mov     esi, [next_memblock]    ;new memory block
300
        mov     esi, [next_memblock]    ;new memory block
301
        test    esi, esi
301
        test    esi, esi
302
        jz      .error_unlock
302
        jz      .error_unlock
303
 
303
 
304
        dec     [free_blocks]
304
        dec     [free_blocks]
305
        mov     eax, [esi]
305
        mov     eax, [esi]
306
        mov     [next_memblock], eax
306
        mov     [next_memblock], eax
307
 
307
 
308
        mov     [esi+block_next], edi
308
        mov     [esi+block_next], edi
309
        mov     eax, [edi+block_prev]
309
        mov     eax, [edi+block_prev]
310
        mov     [esi+block_prev], eax
310
        mov     [esi+block_prev], eax
311
        mov     [edi+block_prev], esi
311
        mov     [edi+block_prev], esi
312
        mov     [esi+list_fd], 0
312
        mov     [esi+list_fd], 0
313
        mov     [esi+list_bk], 0
313
        mov     [esi+list_bk], 0
314
        mov     [eax+block_next], esi
314
        mov     [eax+block_next], esi
315
 
315
 
316
        mov     ebx, [edi+block_base]
316
        mov     ebx, [edi+block_base]
317
        mov     [esi+block_base], ebx
317
        mov     [esi+block_base], ebx
318
        mov     edx, [size]
318
        mov     edx, [size]
319
        mov     [esi+block_size], edx
319
        mov     [esi+block_size], edx
320
        add     [edi+block_base], edx
320
        add     [edi+block_base], edx
321
        sub     [edi+block_size], edx
321
        sub     [edi+block_size], edx
322
 
322
 
323
        mov     eax, [edi+block_size]
323
        mov     eax, [edi+block_size]
324
        calc_index eax
324
        calc_index eax
325
        cmp     eax, [block_ind]
325
        cmp     eax, [block_ind]
326
        je      .add_used
326
        je      .add_used
327
 
327
 
328
        list_del edi
328
        list_del edi
329
 
329
 
330
        mov     ecx, [block_ind]
330
        mov     ecx, [block_ind]
331
        lea     edx, [mem_block_list+ecx*8]
331
        lea     edx, [mem_block_list+ecx*8]
332
        cmp     edx, [edx]
332
        cmp     edx, [edx]
333
        jnz     @f
333
        jnz     @f
334
        btr     [mem_block_mask], ecx
334
        btr     [mem_block_mask], ecx
335
@@:
335
@@:
336
        bts     [mem_block_mask], eax
336
        bts     [mem_block_mask], eax
337
        lea     edx, [mem_block_list+eax*8]  ;edx= list head
337
        lea     edx, [mem_block_list+eax*8]  ;edx= list head
338
        list_add edi, edx
338
        list_add edi, edx
339
.add_used:
339
.add_used:
340
 
340
 
341
        call    md.add_to_used
341
        call    md.add_to_used
342
 
342
 
343
        spin_unlock_irqrestore heap_mutex
343
        spin_unlock_irqrestore heap_mutex
344
        mov     eax, [esi+block_base]
344
        mov     eax, [esi+block_base]
345
        pop     edi
345
        pop     edi
346
        pop     esi
346
        pop     esi
347
        pop     ebx
347
        pop     ebx
348
        ret
348
        ret
349
 
349
 
350
.m_eq_size:
350
.m_eq_size:
351
        list_del edi
351
        list_del edi
352
        lea     edx, [mem_block_list+ebx*8]
352
        lea     edx, [mem_block_list+ebx*8]
353
        cmp     edx, [edx]
353
        cmp     edx, [edx]
354
        jnz     @f
354
        jnz     @f
355
        btr     [mem_block_mask], ebx
355
        btr     [mem_block_mask], ebx
356
@@:
356
@@:
357
        mov     esi, edi
357
        mov     esi, edi
358
        jmp     .add_used
358
        jmp     .add_used
359
 
359
 
360
.error_unlock:
360
.error_unlock:
361
        spin_unlock_irqrestore heap_mutex
361
        spin_unlock_irqrestore heap_mutex
362
.error:
362
.error:
363
        xor     eax, eax
363
        xor     eax, eax
364
        pop     edi
364
        pop     edi
365
        pop     esi
365
        pop     esi
366
        pop     ebx
366
        pop     ebx
367
        ret
367
        ret
368
endp
368
endp
369
 
369
 
370
align 4
370
align 4
371
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
371
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
372
 
372
 
373
        spin_lock_irqsave heap_mutex
373
        spin_lock_irqsave heap_mutex
374
 
374
 
375
        mov     eax, [base]
375
        mov     eax, [base]
376
 
376
 
377
        call    md.del_from_used
377
        call    md.del_from_used
378
        test    esi, esi
378
        test    esi, esi
379
        jz      .fail
379
        jz      .fail
380
 
380
 
381
        mov     eax, [esi+block_size]
381
        mov     eax, [esi+block_size]
382
        add     [heap_free], eax
382
        add     [heap_free], eax
383
 
383
 
384
        mov     edi, [esi+block_next]
384
        mov     edi, [esi+block_next]
385
        cmp     [edi+block_flags], FREE_BLOCK
385
        cmp     [edi+block_flags], FREE_BLOCK
386
        jne     .prev
386
        jne     .prev
387
 
387
 
388
        list_del edi
388
        list_del edi
389
 
389
 
390
        mov     edx, [edi+block_next]
390
        mov     edx, [edi+block_next]
391
        mov     [esi+block_next], edx
391
        mov     [esi+block_next], edx
392
        mov     [edx+block_prev], esi
392
        mov     [edx+block_prev], esi
393
        mov     ecx, [edi+block_size]
393
        mov     ecx, [edi+block_size]
394
        add     [esi+block_size], ecx
394
        add     [esi+block_size], ecx
395
 
395
 
396
        calc_index ecx
396
        calc_index ecx
397
 
397
 
398
        lea     edx, [mem_block_list+ecx*8]
398
        lea     edx, [mem_block_list+ecx*8]
399
        cmp     edx, [edx]
399
        cmp     edx, [edx]
400
        jne     @F
400
        jne     @F
401
        btr     [mem_block_mask], ecx
401
        btr     [mem_block_mask], ecx
402
@@:
402
@@:
403
        mov     eax, edi
403
        mov     eax, edi
404
        call    free_mem_block
404
        call    free_mem_block
405
.prev:
405
.prev:
406
        mov     edi, [esi+block_prev]
406
        mov     edi, [esi+block_prev]
407
        cmp     [edi+block_flags], FREE_BLOCK
407
        cmp     [edi+block_flags], FREE_BLOCK
408
        jne     .insert
408
        jne     .insert
409
 
409
 
410
        mov     edx, [esi+block_next]
410
        mov     edx, [esi+block_next]
411
        mov     [edi+block_next], edx
411
        mov     [edi+block_next], edx
412
        mov     [edx+block_prev], edi
412
        mov     [edx+block_prev], edi
413
 
413
 
414
        mov     eax, esi
414
        mov     eax, esi
415
        call    free_mem_block
415
        call    free_mem_block
416
 
416
 
417
        mov     ecx, [edi+block_size]
417
        mov     ecx, [edi+block_size]
418
        mov     eax, [esi+block_size]
418
        mov     eax, [esi+block_size]
419
        add     eax, ecx
419
        add     eax, ecx
420
        mov     [edi+block_size], eax
420
        mov     [edi+block_size], eax
421
 
421
 
422
        calc_index eax                     ;new index
422
        calc_index eax                     ;new index
423
        calc_index ecx                     ;old index
423
        calc_index ecx                     ;old index
424
        cmp     eax, ecx
424
        cmp     eax, ecx
425
        je      .m_eq
425
        je      .m_eq
426
 
426
 
427
        push    ecx
427
        push    ecx
428
        list_del edi
428
        list_del edi
429
        pop     ecx
429
        pop     ecx
430
 
430
 
431
        lea     edx, [mem_block_list+ecx*8]
431
        lea     edx, [mem_block_list+ecx*8]
432
        cmp     edx, [edx]
432
        cmp     edx, [edx]
433
        jne     .add_block
433
        jne     .add_block
434
        btr     [mem_block_mask], ecx
434
        btr     [mem_block_mask], ecx
435
 
435
 
436
.add_block:
436
.add_block:
437
        bts     [mem_block_mask], eax
437
        bts     [mem_block_mask], eax
438
        lea     edx, [mem_block_list+eax*8]
438
        lea     edx, [mem_block_list+eax*8]
439
        list_add edi, edx
439
        list_add edi, edx
440
.m_eq:
440
.m_eq:
441
        spin_unlock_irqrestore heap_mutex
441
        spin_unlock_irqrestore heap_mutex
442
        xor     eax, eax
442
        xor     eax, eax
443
        not     eax
443
        not     eax
444
        ret
444
        ret
445
.insert:
445
.insert:
446
        mov     [esi+block_flags], FREE_BLOCK
446
        mov     [esi+block_flags], FREE_BLOCK
447
        mov     eax, [esi+block_size]
447
        mov     eax, [esi+block_size]
448
        calc_index eax
448
        calc_index eax
449
        mov     edi, esi
449
        mov     edi, esi
450
        jmp     .add_block
450
        jmp     .add_block
451
 
451
 
452
.fail:
452
.fail:
453
        spin_unlock_irqrestore heap_mutex
453
        spin_unlock_irqrestore heap_mutex
454
        xor     eax, eax
454
        xor     eax, eax
455
        ret
455
        ret
456
endp
456
endp
457
 
457
 
458
align 4
458
align 4
459
proc kernel_alloc stdcall, size:dword
459
proc kernel_alloc stdcall, size:dword
460
        locals
460
        locals
461
          lin_addr    dd ?
461
          lin_addr    dd ?
462
          pages_count dd ?
462
          pages_count dd ?
463
        endl
463
        endl
464
 
464
 
465
        push    ebx
465
        push    ebx
466
        push    edi
466
        push    edi
467
 
467
 
468
        mov     eax, [size]
468
        mov     eax, [size]
469
        add     eax, 4095
469
        add     eax, 4095
470
        and     eax, not 4095;
470
        and     eax, not 4095;
471
        mov     [size], eax
471
        mov     [size], eax
472
        and     eax, eax
472
        and     eax, eax
473
        jz      .err
473
        jz      .err
474
        mov     ebx, eax
474
        mov     ebx, eax
475
        shr     ebx, 12
475
        shr     ebx, 12
476
        mov     [pages_count], ebx
476
        mov     [pages_count], ebx
477
 
477
 
478
        stdcall alloc_kernel_space, eax
478
        stdcall alloc_kernel_space, eax
479
        mov     [lin_addr], eax
479
        mov     [lin_addr], eax
480
        mov     ebx, [pages_count]
480
        mov     ebx, [pages_count]
481
        test    eax, eax
481
        test    eax, eax
482
        jz      .err
482
        jz      .err
483
 
483
 
484
        mov     edx, eax
484
        mov     edx, eax
485
 
485
 
486
        shr     ebx, 3
486
        shr     ebx, 3
487
        jz      .tail
487
        jz      .tail
488
 
488
 
489
        shl     ebx, 3
489
        shl     ebx, 3
490
        stdcall alloc_pages, ebx
490
        stdcall alloc_pages, ebx
491
        test    eax, eax
491
        test    eax, eax
492
        jz      .err
492
        jz      .err
493
 
493
 
494
        mov     ecx, ebx
494
        mov     ecx, ebx
495
        or      eax, PG_GLOBAL+PG_SWR
495
        or      eax, PG_GLOBAL+PG_SWR
496
        mov     ebx, [lin_addr]
496
        mov     ebx, [lin_addr]
497
        call    commit_pages
497
        call    commit_pages
498
 
498
 
499
        mov     edx, ebx                    ; this dirty hack
499
        mov     edx, ebx                    ; this dirty hack
500
.tail:
500
.tail:
501
        mov     ebx, [pages_count]
501
        mov     ebx, [pages_count]
502
        and     ebx, 7
502
        and     ebx, 7
503
        jz      .end
503
        jz      .end
504
@@:
504
@@:
505
        call    alloc_page
505
        call    alloc_page
506
        test    eax, eax
506
        test    eax, eax
507
        jz      .err
507
        jz      .err
508
 
508
 
509
        stdcall map_page, edx, eax, dword (PG_GLOBAL+PG_SWR)
509
        stdcall map_page, edx, eax, dword (PG_GLOBAL+PG_SWR)
510
        add     edx, 0x1000
510
        add     edx, 0x1000
511
        dec     ebx
511
        dec     ebx
512
        jnz     @B
512
        jnz     @B
513
.end:
513
.end:
514
        mov     eax, [lin_addr]
514
        mov     eax, [lin_addr]
515
        pop     edi
515
        pop     edi
516
        pop     ebx
516
        pop     ebx
517
        ret
517
        ret
518
.err:
518
.err:
519
        xor     eax, eax
519
        xor     eax, eax
520
        pop     edi
520
        pop     edi
521
        pop     ebx
521
        pop     ebx
522
        ret
522
        ret
523
endp
523
endp
524
 
524
 
525
align 4
525
align 4
526
proc kernel_free stdcall, base:dword
526
proc kernel_free stdcall, base:dword
527
 
527
 
528
        push    ebx esi
528
        push    ebx esi
529
 
529
 
530
        spin_lock_irqsave heap_mutex
530
        spin_lock_irqsave heap_mutex
531
 
531
 
532
        mov     eax, [base]
532
        mov     eax, [base]
533
        call    md.find_used
533
        call    md.find_used
534
 
534
 
535
        cmp     [esi+block_flags], USED_BLOCK
535
        cmp     [esi+block_flags], USED_BLOCK
536
        jne     .fail
536
        jne     .fail
537
 
537
 
538
        spin_unlock_irqrestore heap_mutex
538
        spin_unlock_irqrestore heap_mutex
539
 
539
 
540
        mov     eax, [esi+block_base]
540
        mov     eax, [esi+block_base]
541
        mov     ecx, [esi+block_size]
541
        mov     ecx, [esi+block_size]
542
        shr     ecx, 12
542
        shr     ecx, 12
543
        call    release_pages   ;eax, ecx
543
        call    release_pages   ;eax, ecx
544
        stdcall free_kernel_space, [base]
544
        stdcall free_kernel_space, [base]
545
        pop     esi ebx
545
        pop     esi ebx
546
        ret
546
        ret
547
.fail:
547
.fail:
548
        spin_unlock_irqrestore heap_mutex
548
        spin_unlock_irqrestore heap_mutex
549
        xor     eax, eax
549
        xor     eax, eax
550
        pop     esi ebx
550
        pop     esi ebx
551
        ret
551
        ret
552
endp
552
endp
553
 
553
 
554
restore block_next
554
restore block_next
555
restore block_prev
555
restore block_prev
556
restore block_list
556
restore block_list
557
restore block_base
557
restore block_base
558
restore block_size
558
restore block_size
559
restore block_flags
559
restore block_flags
560
 
560
 
561
;;;;;;;;;;;;;;      USER HEAP     ;;;;;;;;;;;;;;;;;
561
;;;;;;;;;;;;;;      USER HEAP     ;;;;;;;;;;;;;;;;;
562
 
562
 
563
HEAP_TOP  equ 0x80000000
563
HEAP_TOP  equ 0x80000000
564
 
564
 
565
align 4
565
align 4
566
proc init_heap
566
proc init_heap
567
 
567
 
568
        mov     ebx, [current_process]
568
        mov     ebx, [current_process]
569
        mov     eax, [ebx+PROC.heap_top]
569
        mov     eax, [ebx+PROC.heap_top]
570
        test    eax, eax
570
        test    eax, eax
571
        jz      @F
571
        jz      @F
572
        sub     eax, [ebx+PROC.heap_base]
572
        sub     eax, [ebx+PROC.heap_base]
573
        sub     eax, PAGE_SIZE
573
        sub     eax, PAGE_SIZE
574
        ret
574
        ret
575
@@:
575
@@:
576
        lea     ecx, [ebx+PROC.heap_lock]
576
        lea     ecx, [ebx+PROC.heap_lock]
577
        call    mutex_init
577
        call    mutex_init
578
 
578
 
579
        mov     esi, [ebx+PROC.mem_used]
579
        mov     esi, [ebx+PROC.mem_used]
580
        add     esi, 4095
580
        add     esi, 4095
581
        and     esi, not 4095
581
        and     esi, not 4095
582
        mov     [ebx+PROC.mem_used], esi
582
        mov     [ebx+PROC.mem_used], esi
583
        mov     eax, HEAP_TOP
583
        mov     eax, HEAP_TOP
584
        mov     [ebx+PROC.heap_base], esi
584
        mov     [ebx+PROC.heap_base], esi
585
        mov     [ebx+PROC.heap_top], eax
585
        mov     [ebx+PROC.heap_top], eax
586
 
586
 
587
        sub     eax, esi
587
        sub     eax, esi
588
        shr     esi, 10
588
        shr     esi, 9
589
        mov     ecx, eax
589
        mov     ecx, eax
590
        sub     eax, PAGE_SIZE
590
        sub     eax, PAGE_SIZE
591
        or      ecx, FREE_BLOCK
591
        or      ecx, FREE_BLOCK
592
        mov     [page_tabs+esi], ecx
592
        mov     [page_tabs+esi], ecx
593
        ret
593
        ret
594
endp
594
endp
595
 
595
 
596
align 4
596
align 4
597
proc user_alloc stdcall, alloc_size:dword
597
proc user_alloc stdcall, alloc_size:dword
598
 
598
 
599
        push    ebx
599
        push    ebx
600
        push    esi
600
        push    esi
601
        push    edi
601
        push    edi
602
 
602
 
603
        mov     ebx, [current_process]
603
        mov     ebx, [current_process]
604
        lea     ecx, [ebx+PROC.heap_lock]
604
        lea     ecx, [ebx+PROC.heap_lock]
605
        call    mutex_lock
605
        call    mutex_lock
606
 
606
 
607
        mov     ecx, [alloc_size]
607
        mov     ecx, [alloc_size]
608
        add     ecx, (4095+PAGE_SIZE)
608
        add     ecx, (4095+PAGE_SIZE)
609
        and     ecx, not 4095
609
        and     ecx, not 4095
610
 
610
 
611
        mov     esi, dword [ebx+PROC.heap_base] ; heap_base
611
        mov     esi, dword [ebx+PROC.heap_base] ; heap_base
612
        mov     edi, dword [ebx+PROC.heap_top]  ; heap_top
612
        mov     edi, dword [ebx+PROC.heap_top]  ; heap_top
613
.scan:
613
.scan:
614
        cmp     esi, edi
614
        cmp     esi, edi
615
        jae     .m_exit
615
        jae     .m_exit
616
 
616
 
617
        mov     ebx, esi
617
        mov     ebx, esi
618
        shr     ebx, 12
618
        shr     ebx, 12
619
        mov     eax, [page_tabs+ebx*4]
619
        mov     eax, [page_tabs+ebx*8]
620
        test    al, FREE_BLOCK
620
        test    al, FREE_BLOCK
621
        jz      .test_used
621
        jz      .test_used
622
        and     eax, 0xFFFFF000
622
        and     eax, 0xFFFFF000
623
        cmp     eax, ecx   ;alloc_size
623
        cmp     eax, ecx   ;alloc_size
624
        jb      .m_next
624
        jb      .m_next
625
        jz      @f
625
        jz      @f
626
 
626
 
627
        lea     edx, [esi+ecx]
627
        lea     edx, [esi+ecx]
628
        sub     eax, ecx
628
        sub     eax, ecx
629
        or      al, FREE_BLOCK
629
        or      al, FREE_BLOCK
630
        shr     edx, 12
630
        shr     edx, 12
631
        mov     [page_tabs+edx*4], eax
631
        mov     [page_tabs+edx*8], eax
632
@@:
632
@@:
633
        or      ecx, USED_BLOCK
633
        or      ecx, USED_BLOCK
634
        mov     [page_tabs+ebx*4], ecx
634
        mov     [page_tabs+ebx*8], ecx
635
        shr     ecx, 12
635
        shr     ecx, 12
636
        inc     ebx
636
        inc     ebx
637
        dec     ecx
637
        dec     ecx
638
        jz      .no
638
        jz      .no
639
@@:
639
@@:
640
        mov     dword [page_tabs+ebx*4], 2
640
        mov     dword [page_tabs+ebx*8], 2
641
        inc     ebx
641
        inc     ebx
642
        dec     ecx
642
        dec     ecx
643
        jnz     @B
643
        jnz     @B
644
.no:
644
.no:
645
 
645
 
646
        mov     edx, [current_process]
646
        mov     edx, [current_process]
647
        mov     ebx, [alloc_size]
647
        mov     ebx, [alloc_size]
648
        add     ebx, 0xFFF
648
        add     ebx, 0xFFF
649
        and     ebx, not 0xFFF
649
        and     ebx, not 0xFFF
650
        add     [edx+PROC.mem_used], ebx
650
        add     [edx+PROC.mem_used], ebx
651
 
651
 
652
        lea     ecx, [edx+PROC.heap_lock]
652
        lea     ecx, [edx+PROC.heap_lock]
653
        call    mutex_unlock
653
        call    mutex_unlock
654
 
654
 
655
        lea     eax, [esi+4096]
655
        lea     eax, [esi+4096]
656
 
656
 
657
        pop     edi
657
        pop     edi
658
        pop     esi
658
        pop     esi
659
        pop     ebx
659
        pop     ebx
660
        ret
660
        ret
661
.test_used:
661
.test_used:
662
        test    al, USED_BLOCK
662
        test    al, USED_BLOCK
663
        jz      .m_exit
663
        jz      .m_exit
664
 
664
 
665
        and     eax, 0xFFFFF000
665
        and     eax, 0xFFFFF000
666
.m_next:
666
.m_next:
667
        add     esi, eax
667
        add     esi, eax
668
        jmp     .scan
668
        jmp     .scan
669
.m_exit:
669
.m_exit:
670
        mov     ecx, [current_process]
670
        mov     ecx, [current_process]
671
        lea     ecx, [ecx+PROC.heap_lock]
671
        lea     ecx, [ecx+PROC.heap_lock]
672
        call    mutex_unlock
672
        call    mutex_unlock
673
 
673
 
674
        xor     eax, eax
674
        xor     eax, eax
675
        pop     edi
675
        pop     edi
676
        pop     esi
676
        pop     esi
677
        pop     ebx
677
        pop     ebx
678
        ret
678
        ret
679
endp
679
endp
680
 
680
 
681
align 4
681
align 4
682
proc user_alloc_at stdcall, address:dword, alloc_size:dword
682
proc user_alloc_at stdcall, address:dword, alloc_size:dword
683
 
683
 
684
        push    ebx
684
        push    ebx
685
        push    esi
685
        push    esi
686
        push    edi
686
        push    edi
687
 
687
 
688
        mov     ebx, [current_process]
688
        mov     ebx, [current_process]
689
        lea     ecx, [ebx+PROC.heap_lock]
689
        lea     ecx, [ebx+PROC.heap_lock]
690
        call    mutex_lock
690
        call    mutex_lock
691
 
691
 
692
        mov     edx, [address]
692
        mov     edx, [address]
693
        and     edx, not 0xFFF
693
        and     edx, not 0xFFF
694
        mov     [address], edx
694
        mov     [address], edx
695
        sub     edx, 0x1000
695
        sub     edx, 0x1000
696
        jb      .error
696
        jb      .error
697
        mov     esi, [ebx+PROC.heap_base]
697
        mov     esi, [ebx+PROC.heap_base]
698
        mov     edi, [ebx+PROC.heap_top]
698
        mov     edi, [ebx+PROC.heap_top]
699
        cmp     edx, esi
699
        cmp     edx, esi
700
        jb      .error
700
        jb      .error
701
.scan:
701
.scan:
702
        cmp     esi, edi
702
        cmp     esi, edi
703
        jae     .error
703
        jae     .error
704
        mov     ebx, esi
704
        mov     ebx, esi
705
        shr     ebx, 12
705
        shr     ebx, 12
706
        mov     eax, [page_tabs+ebx*4]
706
        mov     eax, [page_tabs+ebx*8]
707
        mov     ecx, eax
707
        mov     ecx, eax
708
        and     ecx, 0xFFFFF000
708
        and     ecx, 0xFFFFF000
709
        add     ecx, esi
709
        add     ecx, esi
710
        cmp     edx, ecx
710
        cmp     edx, ecx
711
        jb      .found
711
        jb      .found
712
        mov     esi, ecx
712
        mov     esi, ecx
713
        jmp     .scan
713
        jmp     .scan
714
.error:
714
.error:
715
        mov     ecx, [current_process]
715
        mov     ecx, [current_process]
716
        lea     ecx, [ecx+PROC.heap_lock]
716
        lea     ecx, [ecx+PROC.heap_lock]
717
        call    mutex_unlock
717
        call    mutex_unlock
718
 
718
 
719
        xor     eax, eax
719
        xor     eax, eax
720
        pop     edi
720
        pop     edi
721
        pop     esi
721
        pop     esi
722
        pop     ebx
722
        pop     ebx
723
        ret
723
        ret
724
.found:
724
.found:
725
        test    al, FREE_BLOCK
725
        test    al, FREE_BLOCK
726
        jz      .error
726
        jz      .error
727
        mov     eax, ecx
727
        mov     eax, ecx
728
        sub     eax, edx
728
        sub     eax, edx
729
        sub     eax, 0x1000
729
        sub     eax, 0x1000
730
        cmp     eax, [alloc_size]
730
        cmp     eax, [alloc_size]
731
        jb      .error
731
        jb      .error
732
 
732
 
733
; Here we have 1 big free block which includes requested area.
733
; Here we have 1 big free block which includes requested area.
734
; In general, 3 other blocks must be created instead:
734
; In general, 3 other blocks must be created instead:
735
; free at [esi, edx);
735
; free at [esi, edx);
736
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
736
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
737
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
737
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
738
; First or third block (or both) may be absent.
738
; First or third block (or both) may be absent.
739
        mov     eax, edx
739
        mov     eax, edx
740
        sub     eax, esi
740
        sub     eax, esi
741
        jz      .nofirst
741
        jz      .nofirst
742
        or      al, FREE_BLOCK
742
        or      al, FREE_BLOCK
743
        mov     [page_tabs+ebx*4], eax
743
        mov     [page_tabs+ebx*8], eax
744
.nofirst:
744
.nofirst:
745
        mov     eax, [alloc_size]
745
        mov     eax, [alloc_size]
746
        add     eax, 0x1FFF
746
        add     eax, 0x1FFF
747
        and     eax, not 0xFFF
747
        and     eax, not 0xFFF
748
        mov     ebx, edx
748
        mov     ebx, edx
749
        add     edx, eax
749
        add     edx, eax
750
        shr     ebx, 12
750
        shr     ebx, 12
751
        or      al, USED_BLOCK
751
        or      al, USED_BLOCK
752
        mov     [page_tabs+ebx*4], eax
752
        mov     [page_tabs+ebx*8], eax
753
        shr     eax, 12
753
        shr     eax, 12
754
        dec     eax
754
        dec     eax
755
        jz      .second_nofill
755
        jz      .second_nofill
756
        inc     ebx
756
        inc     ebx
757
.fill:
757
.fill:
758
        mov     dword [page_tabs+ebx*4], 2
758
        mov     dword [page_tabs+ebx*8], 2
759
        inc     ebx
759
        inc     ebx
760
        dec     eax
760
        dec     eax
761
        jnz     .fill
761
        jnz     .fill
762
 
762
 
763
.second_nofill:
763
.second_nofill:
764
        sub     ecx, edx
764
        sub     ecx, edx
765
        jz      .nothird
765
        jz      .nothird
766
        or      cl, FREE_BLOCK
766
        or      cl, FREE_BLOCK
767
        mov     [page_tabs+ebx*4], ecx
767
        mov     [page_tabs+ebx*8], ecx
768
 
768
 
769
.nothird:
769
.nothird:
770
        mov     edx, [current_process]
770
        mov     edx, [current_process]
771
        mov     ebx, [alloc_size]
771
        mov     ebx, [alloc_size]
772
        add     ebx, 0xFFF
772
        add     ebx, 0xFFF
773
        and     ebx, not 0xFFF
773
        and     ebx, not 0xFFF
774
        add     [edx+PROC.mem_used], ebx
774
        add     [edx+PROC.mem_used], ebx
775
 
775
 
776
        lea     ecx, [edx+PROC.heap_lock]
776
        lea     ecx, [edx+PROC.heap_lock]
777
        call    mutex_unlock
777
        call    mutex_unlock
778
 
778
 
779
        mov     eax, [address]
779
        mov     eax, [address]
780
 
780
 
781
        pop     edi
781
        pop     edi
782
        pop     esi
782
        pop     esi
783
        pop     ebx
783
        pop     ebx
784
        ret
784
        ret
785
endp
785
endp
786
 
786
 
787
align 4
787
align 4
788
proc user_free stdcall, base:dword
788
proc user_free stdcall, base:dword
789
 
789
 
790
        push    esi
790
        push    esi
791
 
791
 
792
        mov     esi, [base]
792
        mov     esi, [base]
793
        test    esi, esi
793
        test    esi, esi
794
        jz      .fail
794
        jz      .fail
795
 
795
 
796
        push    ebx
796
        push    ebx
797
 
797
 
798
        mov     ebx, [current_process]
798
        mov     ebx, [current_process]
799
        lea     ecx, [ebx+PROC.heap_lock]
799
        lea     ecx, [ebx+PROC.heap_lock]
800
        call    mutex_lock
800
        call    mutex_lock
801
 
801
 
802
        xor     ebx, ebx
802
        xor     ebx, ebx
803
        shr     esi, 12
803
        shr     esi, 12
804
        mov     eax, [page_tabs+(esi-1)*4]
804
        mov     eax, [page_tabs+(esi-1)*8]
805
        test    al, USED_BLOCK
805
        test    al, USED_BLOCK
806
        jz      .cantfree
806
        jz      .cantfree
807
        test    al, DONT_FREE_BLOCK
807
        test    al, DONT_FREE_BLOCK
808
        jnz     .cantfree
808
        jnz     .cantfree
809
 
809
 
810
        and     eax, not 4095
810
        and     eax, not 4095
811
        mov     ecx, eax
811
        mov     ecx, eax
812
        or      al, FREE_BLOCK
812
        or      al, FREE_BLOCK
813
        mov     [page_tabs+(esi-1)*4], eax
813
        mov     [page_tabs+(esi-1)*8], eax
814
        sub     ecx, 4096
814
        sub     ecx, 4096
815
        mov     ebx, ecx
815
        mov     ebx, ecx
816
        shr     ecx, 12
816
        shr     ecx, 12
817
        jz      .released
817
        jz      .released
818
.release:
818
.release:
819
        xor     eax, eax
819
        xor     eax, eax
820
        xchg    eax, [page_tabs+esi*4]
820
        xchg    eax, [page_tabs+esi*8]
821
        test    al, 1
821
        test    al, 1
822
        jz      @F
822
        jz      @F
823
        test    eax, PG_SHARED
823
        test    eax, PG_SHARED
824
        jnz     @F
824
        jnz     @F
825
        call    free_page
825
        call    free_page
826
        mov     eax, esi
826
        mov     eax, esi
827
        shl     eax, 12
827
        shl     eax, 12
828
        invlpg  [eax]
828
        invlpg  [eax]
829
@@:
829
@@:
830
        inc     esi
830
        inc     esi
831
        dec     ecx
831
        dec     ecx
832
        jnz     .release
832
        jnz     .release
833
 
833
 
834
.released:
834
.released:
835
        push    edi
835
        push    edi
836
 
836
 
837
        mov     edx, [current_process]
837
        mov     edx, [current_process]
838
        lea     ecx, [edx+PROC.heap_lock]
838
        lea     ecx, [edx+PROC.heap_lock]
839
        mov     esi, dword [edx+PROC.heap_base]
839
        mov     esi, dword [edx+PROC.heap_base]
840
        mov     edi, dword [edx+PROC.heap_top]
840
        mov     edi, dword [edx+PROC.heap_top]
841
        sub     ebx, [edx+PROC.mem_used]
841
        sub     ebx, [edx+PROC.mem_used]
842
        neg     ebx
842
        neg     ebx
843
        mov     [edx+PROC.mem_used], ebx
843
        mov     [edx+PROC.mem_used], ebx
844
        call    user_normalize
844
        call    user_normalize
845
        pop     edi
845
        pop     edi
846
.exit:
846
.exit:
847
        call    mutex_unlock
847
        call    mutex_unlock
848
 
848
 
849
        xor     eax, eax
849
        xor     eax, eax
850
        inc     eax
850
        inc     eax
851
        pop     ebx
851
        pop     ebx
852
        pop     esi
852
        pop     esi
853
        ret
853
        ret
854
 
854
 
855
.cantfree:
855
.cantfree:
856
        mov     ecx, [current_process]
856
        mov     ecx, [current_process]
857
        lea     ecx, [ecx+PROC.heap_lock]
857
        lea     ecx, [ecx+PROC.heap_lock]
858
        jmp     .exit
858
        jmp     .exit
859
.fail:
859
.fail:
860
        xor     eax, eax
860
        xor     eax, eax
861
        pop     esi
861
        pop     esi
862
        ret
862
        ret
863
endp
863
endp
864
 
864
 
865
 
865
 
866
align 4
866
align 4
867
proc user_unmap stdcall, base:dword, offset:dword, size:dword
867
proc user_unmap stdcall, base:dword, offset:dword, size:dword
868
 
868
 
869
        push    ebx
869
        push    ebx
870
 
870
 
871
        mov     ebx, [base]             ; must be valid pointer
871
        mov     ebx, [base]             ; must be valid pointer
872
        test    ebx, ebx
872
        test    ebx, ebx
873
        jz      .error
873
        jz      .error
874
 
874
 
875
        mov     edx, [offset]           ; check offset
875
        mov     edx, [offset]           ; check offset
876
        add     edx, ebx                ; must be below 2Gb app limit
876
        add     edx, ebx                ; must be below 2Gb app limit
877
        js      .error
877
        js      .error
878
 
878
 
879
        shr     ebx, 12                 ; chek block attributes
879
        shr     ebx, 12                 ; chek block attributes
880
        lea     ebx, [page_tabs+ebx*4]
880
        lea     ebx, [page_tabs+ebx*8]
881
        mov     eax, [ebx-4]            ; block attributes
881
        mov     eax, [ebx-4]            ; block attributes
882
        test    al, USED_BLOCK
882
        test    al, USED_BLOCK
883
        jz      .error
883
        jz      .error
884
        test    al, DONT_FREE_BLOCK
884
        test    al, DONT_FREE_BLOCK
885
        jnz     .error
885
        jnz     .error
886
 
886
 
887
        shr     edx, 12
887
        shr     edx, 12
888
        lea     edx, [page_tabs+edx*4]  ; unmap offset
888
        lea     edx, [page_tabs+edx*8]  ; unmap offset
889
 
889
 
890
        mov     ecx, [size]
890
        mov     ecx, [size]
891
        add     ecx, 4095
891
        add     ecx, 4095
892
        shr     ecx, 12                 ; unmap size in pages
892
        shr     ecx, 12                 ; unmap size in pages
893
 
893
 
894
        shr     eax, 12                 ; block size + 1 page
894
        shr     eax, 12                 ; block size + 1 page
895
        lea     ebx, [ebx+eax*4-4]      ; block end ptr
895
        lea     ebx, [ebx+eax*8-8]      ; block end ptr
896
        lea     eax, [edx+ecx*4]        ; unmap end ptr
896
        lea     eax, [edx+ecx*8]        ; unmap end ptr
897
 
897
 
898
        cmp     eax, ebx                ; check for overflow
898
        cmp     eax, ebx                ; check for overflow
899
        ja      .error
899
        ja      .error
900
 
900
 
901
        mov     ebx, [offset]
901
        mov     ebx, [offset]
902
        and     ebx, not 4095           ; is it required ?
902
        and     ebx, not 4095           ; is it required ?
903
        add     ebx, [base]
903
        add     ebx, [base]
904
 
904
 
905
.unmap:
905
.unmap:
906
        mov     eax, [edx]              ; get page addres
906
        mov     eax, [edx]              ; get page addres
907
        test    al, 1                   ; page mapped ?
907
        test    al, 1                   ; page mapped ?
908
        jz      @F
908
        jz      @F
909
        test    eax, PG_SHARED          ; page shared ?
909
        test    eax, PG_SHARED          ; page shared ?
910
        jnz     @F
910
        jnz     @F
911
        mov     [edx], dword 2
911
        mov     [edx], dword 2
912
                                        ; mark page as reserved
912
                                        ; mark page as reserved
913
        invlpg  [ebx]                   ; when we start using
913
        invlpg  [ebx]                   ; when we start using
914
        call    free_page               ; empty c-o-w page instead this ?
914
        call    free_page               ; empty c-o-w page instead this ?
915
@@:
915
@@:
916
        add     ebx, 4096
916
        add     ebx, 4096
917
        add     edx, 4
917
        add     edx, 8
918
        dec     ecx
918
        dec     ecx
919
        jnz     .unmap
919
        jnz     .unmap
920
 
920
 
921
        pop     ebx
921
        pop     ebx
922
        or      al, 1                   ; return non zero on success
922
        or      al, 1                   ; return non zero on success
923
        ret
923
        ret
924
.error:
924
.error:
925
        pop     ebx
925
        pop     ebx
926
        xor     eax, eax                ; something wrong
926
        xor     eax, eax                ; something wrong
927
        ret
927
        ret
928
endp
928
endp
929
 
929
 
930
align 4
930
align 4
931
user_normalize:
931
user_normalize:
932
; in: esi=heap_base, edi=heap_top
932
; in: esi=heap_base, edi=heap_top
933
; out: eax=0 <=> OK
933
; out: eax=0 <=> OK
934
; destroys: ebx,edx,esi,edi
934
; destroys: ebx,edx,esi,edi
935
        shr     esi, 12
935
        shr     esi, 12
936
        shr     edi, 12
936
        shr     edi, 12
937
@@:
937
@@:
938
        mov     eax, [page_tabs+esi*4]
938
        mov     eax, [page_tabs+esi*8]
939
        test    al, USED_BLOCK
939
        test    al, USED_BLOCK
940
        jz      .test_free
940
        jz      .test_free
941
        shr     eax, 12
941
        shr     eax, 12
942
        add     esi, eax
942
        add     esi, eax
943
        jmp     @B
943
        jmp     @B
944
.test_free:
944
.test_free:
945
        test    al, FREE_BLOCK
945
        test    al, FREE_BLOCK
946
        jz      .err
946
        jz      .err
947
        mov     edx, eax
947
        mov     edx, eax
948
        shr     edx, 12
948
        shr     edx, 12
949
        add     edx, esi
949
        add     edx, esi
950
        cmp     edx, edi
950
        cmp     edx, edi
951
        jae     .exit
951
        jae     .exit
952
 
952
 
953
        mov     ebx, [page_tabs+edx*4]
953
        mov     ebx, [page_tabs+edx*8]
954
        test    bl, USED_BLOCK
954
        test    bl, USED_BLOCK
955
        jz      .next_free
955
        jz      .next_free
956
 
956
 
957
        shr     ebx, 12
957
        shr     ebx, 12
958
        add     edx, ebx
958
        add     edx, ebx
959
        mov     esi, edx
959
        mov     esi, edx
960
        jmp     @B
960
        jmp     @B
961
.next_free:
961
.next_free:
962
        test    bl, FREE_BLOCK
962
        test    bl, FREE_BLOCK
963
        jz      .err
963
        jz      .err
964
        and     dword [page_tabs+edx*4], 0
964
        and     dword [page_tabs+edx*8], 0
965
        add     eax, ebx
965
        add     eax, ebx
966
        and     eax, not 4095
966
        and     eax, not 4095
967
        or      eax, FREE_BLOCK
967
        or      eax, FREE_BLOCK
968
        mov     [page_tabs+esi*4], eax
968
        mov     [page_tabs+esi*8], eax
969
        jmp     @B
969
        jmp     @B
970
.exit:
970
.exit:
971
        xor     eax, eax
971
        xor     eax, eax
972
        inc     eax
972
        inc     eax
973
        ret
973
        ret
974
.err:
974
.err:
975
        xor     eax, eax
975
        xor     eax, eax
976
        ret
976
        ret
977
 
977
 
978
user_realloc:
978
user_realloc:
979
; in: eax = pointer, ebx = new size
979
; in: eax = pointer, ebx = new size
980
; out: eax = new pointer or NULL
980
; out: eax = new pointer or NULL
981
        test    eax, eax
981
        test    eax, eax
982
        jnz     @f
982
        jnz     @f
983
; realloc(NULL,sz) - same as malloc(sz)
983
; realloc(NULL,sz) - same as malloc(sz)
984
        push    ebx
984
        push    ebx
985
        call    user_alloc
985
        call    user_alloc
986
        ret
986
        ret
987
@@:
987
@@:
988
        push    ecx edx
988
        push    ecx edx
989
 
989
 
990
        push    eax
990
        push    eax
991
        mov     ecx, [current_process]
991
        mov     ecx, [current_process]
992
        lea     ecx, [ecx+PROC.heap_lock]
992
        lea     ecx, [ecx+PROC.heap_lock]
993
        call    mutex_lock
993
        call    mutex_lock
994
        pop     eax
994
        pop     eax
995
 
995
 
996
        lea     ecx, [eax - 0x1000]
996
        lea     ecx, [eax - 0x1000]
997
        shr     ecx, 12
997
        shr     ecx, 12
998
        mov     edx, [page_tabs+ecx*4]
998
        mov     edx, [page_tabs+ecx*8]
999
        test    dl, USED_BLOCK
999
        test    dl, USED_BLOCK
1000
        jnz     @f
1000
        jnz     @f
1001
; attempt to realloc invalid pointer
1001
; attempt to realloc invalid pointer
1002
.ret0:
1002
.ret0:
1003
        mov     ecx, [current_process]
1003
        mov     ecx, [current_process]
1004
        lea     ecx, [ecx+PROC.heap_lock]
1004
        lea     ecx, [ecx+PROC.heap_lock]
1005
        call    mutex_unlock
1005
        call    mutex_unlock
1006
 
1006
 
1007
        pop     edx ecx
1007
        pop     edx ecx
1008
        xor     eax, eax
1008
        xor     eax, eax
1009
        ret
1009
        ret
1010
@@:
1010
@@:
1011
        test    dl, DONT_FREE_BLOCK
1011
        test    dl, DONT_FREE_BLOCK
1012
        jnz     .ret0
1012
        jnz     .ret0
1013
        add     ebx, 0x1FFF
1013
        add     ebx, 0x1FFF
1014
        shr     edx, 12
1014
        shr     edx, 12
1015
        shr     ebx, 12
1015
        shr     ebx, 12
1016
; edx = allocated size, ebx = new size
1016
; edx = allocated size, ebx = new size
1017
        add     edx, ecx
1017
        add     edx, ecx
1018
        add     ebx, ecx
1018
        add     ebx, ecx
1019
        cmp     edx, ebx
1019
        cmp     edx, ebx
1020
        jb      .realloc_add
1020
        jb      .realloc_add
1021
; release part of allocated memory
1021
; release part of allocated memory
1022
.loop:
1022
.loop:
1023
        cmp     edx, ebx
1023
        cmp     edx, ebx
1024
        jz      .release_done
1024
        jz      .release_done
1025
        dec     edx
1025
        dec     edx
1026
        xor     eax, eax
1026
        xor     eax, eax
1027
        xchg    eax, [page_tabs+edx*4]
1027
        xchg    eax, [page_tabs+edx*8]
1028
        test    al, 1
1028
        test    al, 1
1029
        jz      .loop
1029
        jz      .loop
1030
        call    free_page
1030
        call    free_page
1031
        mov     eax, edx
1031
        mov     eax, edx
1032
        shl     eax, 12
1032
        shl     eax, 12
1033
        invlpg  [eax]
1033
        invlpg  [eax]
1034
        jmp     .loop
1034
        jmp     .loop
1035
.release_done:
1035
.release_done:
1036
        sub     ebx, ecx
1036
        sub     ebx, ecx
1037
        cmp     ebx, 1
1037
        cmp     ebx, 1
1038
        jnz     .nofreeall
1038
        jnz     .nofreeall
1039
        mov     eax, [page_tabs+ecx*4]
1039
        mov     eax, [page_tabs+ecx*8]
1040
        and     eax, not 0xFFF
1040
        and     eax, not 0xFFF
1041
        mov     edx, [current_process]
1041
        mov     edx, [current_process]
1042
        mov     ebx, [edx+PROC.mem_used]
1042
        mov     ebx, [edx+PROC.mem_used]
1043
        sub     ebx, eax
1043
        sub     ebx, eax
1044
        add     ebx, 0x1000
1044
        add     ebx, 0x1000
1045
        or      al, FREE_BLOCK
1045
        or      al, FREE_BLOCK
1046
        mov     [page_tabs+ecx*4], eax
1046
        mov     [page_tabs+ecx*8], eax
1047
        push    esi edi
1047
        push    esi edi
1048
        mov     esi, [edx+PROC.heap_base]
1048
        mov     esi, [edx+PROC.heap_base]
1049
        mov     edi, [edx+PROC.heap_top]
1049
        mov     edi, [edx+PROC.heap_top]
1050
        mov     [edx+PROC.mem_used], ebx
1050
        mov     [edx+PROC.mem_used], ebx
1051
        call    user_normalize
1051
        call    user_normalize
1052
        pop     edi esi
1052
        pop     edi esi
1053
        jmp     .ret0   ; all freed
1053
        jmp     .ret0   ; all freed
1054
.nofreeall:
1054
.nofreeall:
1055
        sub     edx, ecx
1055
        sub     edx, ecx
1056
        shl     ebx, 12
1056
        shl     ebx, 12
1057
        or      ebx, USED_BLOCK
1057
        or      ebx, USED_BLOCK
1058
        xchg    [page_tabs+ecx*4], ebx
1058
        xchg    [page_tabs+ecx*8], ebx
1059
        shr     ebx, 12
1059
        shr     ebx, 12
1060
        sub     ebx, edx
1060
        sub     ebx, edx
1061
        push    ebx ecx edx
1061
        push    ebx ecx edx
1062
        mov     edx, [current_process]
1062
        mov     edx, [current_process]
1063
        shl     ebx, 12
1063
        shl     ebx, 12
1064
        sub     ebx, [edx+PROC.mem_used]
1064
        sub     ebx, [edx+PROC.mem_used]
1065
        neg     ebx
1065
        neg     ebx
1066
        mov     [edx+PROC.mem_used], ebx
1066
        mov     [edx+PROC.mem_used], ebx
1067
        pop     edx ecx ebx
1067
        pop     edx ecx ebx
1068
        lea     eax, [ecx+1]
1068
        lea     eax, [ecx+1]
1069
        shl     eax, 12
1069
        shl     eax, 12
1070
        push    eax
1070
        push    eax
1071
        add     ecx, edx
1071
        add     ecx, edx
1072
        lea     edx, [ecx+ebx]
1072
        lea     edx, [ecx+ebx]
1073
        shl     ebx, 12
1073
        shl     ebx, 12
1074
        jz      .ret
1074
        jz      .ret
1075
        push    esi
1075
        push    esi
1076
        mov     esi, [current_process]
1076
        mov     esi, [current_process]
1077
        mov     esi, [esi+PROC.heap_top]
1077
        mov     esi, [esi+PROC.heap_top]
1078
        shr     esi, 12
1078
        shr     esi, 12
1079
@@:
1079
@@:
1080
        cmp     edx, esi
1080
        cmp     edx, esi
1081
        jae     .merge_done
1081
        jae     .merge_done
1082
        mov     eax, [page_tabs+edx*4]
1082
        mov     eax, [page_tabs+edx*8]
1083
        test    al, USED_BLOCK
1083
        test    al, USED_BLOCK
1084
        jnz     .merge_done
1084
        jnz     .merge_done
1085
        and     dword [page_tabs+edx*4], 0
1085
        and     dword [page_tabs+edx*8], 0
1086
        shr     eax, 12
1086
        shr     eax, 12
1087
        add     edx, eax
1087
        add     edx, eax
1088
        shl     eax, 12
1088
        shl     eax, 12
1089
        add     ebx, eax
1089
        add     ebx, eax
1090
        jmp     @b
1090
        jmp     @b
1091
.merge_done:
1091
.merge_done:
1092
        pop     esi
1092
        pop     esi
1093
        or      ebx, FREE_BLOCK
1093
        or      ebx, FREE_BLOCK
1094
        mov     [page_tabs+ecx*4], ebx
1094
        mov     [page_tabs+ecx*8], ebx
1095
.ret:
1095
.ret:
1096
        mov     ecx, [current_process]
1096
        mov     ecx, [current_process]
1097
        lea     ecx, [ecx+PROC.heap_lock]
1097
        lea     ecx, [ecx+PROC.heap_lock]
1098
        call    mutex_unlock
1098
        call    mutex_unlock
1099
        pop     eax edx ecx
1099
        pop     eax edx ecx
1100
        ret
1100
        ret
1101
 
1101
 
1102
.realloc_add:
1102
.realloc_add:
1103
; get some additional memory
1103
; get some additional memory
1104
        mov     eax, [current_process]
1104
        mov     eax, [current_process]
1105
        mov     eax, [eax+PROC.heap_top]
1105
        mov     eax, [eax+PROC.heap_top]
1106
        shr     eax, 12
1106
        shr     eax, 12
1107
        cmp     edx, eax
1107
        cmp     edx, eax
1108
        jae     .cant_inplace
1108
        jae     .cant_inplace
1109
        mov     eax, [page_tabs+edx*4]
1109
        mov     eax, [page_tabs+edx*8]
1110
        test    al, FREE_BLOCK
1110
        test    al, FREE_BLOCK
1111
        jz      .cant_inplace
1111
        jz      .cant_inplace
1112
        shr     eax, 12
1112
        shr     eax, 12
1113
        add     eax, edx
1113
        add     eax, edx
1114
        sub     eax, ebx
1114
        sub     eax, ebx
1115
        jb      .cant_inplace
1115
        jb      .cant_inplace
1116
        jz      @f
1116
        jz      @f
1117
        shl     eax, 12
1117
        shl     eax, 12
1118
        or      al, FREE_BLOCK
1118
        or      al, FREE_BLOCK
1119
        mov     [page_tabs+ebx*4], eax
1119
        mov     [page_tabs+ebx*8], eax
1120
@@:
1120
@@:
1121
        mov     eax, ebx
1121
        mov     eax, ebx
1122
        sub     eax, ecx
1122
        sub     eax, ecx
1123
        shl     eax, 12
1123
        shl     eax, 12
1124
        or      al, USED_BLOCK
1124
        or      al, USED_BLOCK
1125
        mov     [page_tabs+ecx*4], eax
1125
        mov     [page_tabs+ecx*8], eax
1126
        lea     eax, [ecx+1]
1126
        lea     eax, [ecx+1]
1127
        shl     eax, 12
1127
        shl     eax, 12
1128
        push    eax
1128
        push    eax
1129
        push    edi
1129
        push    edi
1130
        lea     edi, [page_tabs+edx*4]
1130
        lea     edi, [page_tabs+edx*8]
1131
        mov     eax, 2
1131
        mov     eax, 2
1132
        sub     ebx, edx
1132
        sub     ebx, edx
1133
        mov     ecx, ebx
1133
        mov     ecx, ebx
1134
        cld
1134
        cld
1135
        rep stosd
1135
        rep stosd
1136
        pop     edi
1136
        pop     edi
1137
        mov     edx, [current_process]
1137
        mov     edx, [current_process]
1138
        shl     ebx, 12
1138
        shl     ebx, 12
1139
        add     [edx+PROC.mem_used], ebx
1139
        add     [edx+PROC.mem_used], ebx
1140
 
1140
 
1141
        mov     ecx, [current_process]
1141
        mov     ecx, [current_process]
1142
        lea     ecx, [ecx+PROC.heap_lock]
1142
        lea     ecx, [ecx+PROC.heap_lock]
1143
        call    mutex_unlock
1143
        call    mutex_unlock
1144
        pop     eax edx ecx
1144
        pop     eax edx ecx
1145
        ret
1145
        ret
1146
 
1146
 
1147
.cant_inplace:
1147
.cant_inplace:
1148
        push    esi edi
1148
        push    esi edi
1149
        mov     eax, [current_process]
1149
        mov     eax, [current_process]
1150
        mov     esi, [eax+PROC.heap_base]
1150
        mov     esi, [eax+PROC.heap_base]
1151
        mov     edi, [eax+PROC.heap_top]
1151
        mov     edi, [eax+PROC.heap_top]
1152
        shr     esi, 12
1152
        shr     esi, 12
1153
        shr     edi, 12
1153
        shr     edi, 12
1154
        sub     ebx, ecx
1154
        sub     ebx, ecx
1155
.find_place:
1155
.find_place:
1156
        cmp     esi, edi
1156
        cmp     esi, edi
1157
        jae     .place_not_found
1157
        jae     .place_not_found
1158
        mov     eax, [page_tabs+esi*4]
1158
        mov     eax, [page_tabs+esi*8]
1159
        test    al, FREE_BLOCK
1159
        test    al, FREE_BLOCK
1160
        jz      .next_place
1160
        jz      .next_place
1161
        shr     eax, 12
1161
        shr     eax, 12
1162
        cmp     eax, ebx
1162
        cmp     eax, ebx
1163
        jae     .place_found
1163
        jae     .place_found
1164
        add     esi, eax
1164
        add     esi, eax
1165
        jmp     .find_place
1165
        jmp     .find_place
1166
.next_place:
1166
.next_place:
1167
        shr     eax, 12
1167
        shr     eax, 12
1168
        add     esi, eax
1168
        add     esi, eax
1169
        jmp     .find_place
1169
        jmp     .find_place
1170
.place_not_found:
1170
.place_not_found:
1171
        pop     edi esi
1171
        pop     edi esi
1172
        jmp     .ret0
1172
        jmp     .ret0
1173
.place_found:
1173
.place_found:
1174
        sub     eax, ebx
1174
        sub     eax, ebx
1175
        jz      @f
1175
        jz      @f
1176
        push    esi
1176
        push    esi
1177
        add     esi, ebx
1177
        add     esi, ebx
1178
        shl     eax, 12
1178
        shl     eax, 12
1179
        or      al, FREE_BLOCK
1179
        or      al, FREE_BLOCK
1180
        mov     [page_tabs+esi*4], eax
1180
        mov     [page_tabs+esi*8], eax
1181
        pop     esi
1181
        pop     esi
1182
@@:
1182
@@:
1183
        mov     eax, ebx
1183
        mov     eax, ebx
1184
        shl     eax, 12
1184
        shl     eax, 12
1185
        or      al, USED_BLOCK
1185
        or      al, USED_BLOCK
1186
        mov     [page_tabs+esi*4], eax
1186
        mov     [page_tabs+esi*8], eax
1187
        inc     esi
1187
        inc     esi
1188
        mov     eax, esi
1188
        mov     eax, esi
1189
        shl     eax, 12
1189
        shl     eax, 12
1190
        push    eax
1190
        push    eax
1191
        mov     eax, [page_tabs+ecx*4]
1191
        mov     eax, [page_tabs+ecx*8]
1192
        and     eax, not 0xFFF
1192
        and     eax, not 0xFFF
1193
        or      al, FREE_BLOCK
1193
        or      al, FREE_BLOCK
1194
        sub     edx, ecx
1194
        sub     edx, ecx
1195
        mov     [page_tabs+ecx*4], eax
1195
        mov     [page_tabs+ecx*8], eax
1196
        inc     ecx
1196
        inc     ecx
1197
        dec     ebx
1197
        dec     ebx
1198
        dec     edx
1198
        dec     edx
1199
        jz      .no
1199
        jz      .no
1200
@@:
1200
@@:
1201
        xor     eax, eax
1201
        xor     eax, eax
1202
        xchg    eax, [page_tabs+ecx*4]
1202
        xchg    eax, [page_tabs+ecx*8]
1203
        mov     [page_tabs+esi*4], eax
1203
        mov     [page_tabs+esi*8], eax
1204
        mov     eax, ecx
1204
        mov     eax, ecx
1205
        shl     eax, 12
1205
        shl     eax, 12
1206
        invlpg  [eax]
1206
        invlpg  [eax]
1207
        inc     esi
1207
        inc     esi
1208
        inc     ecx
1208
        inc     ecx
1209
        dec     ebx
1209
        dec     ebx
1210
        dec     edx
1210
        dec     edx
1211
        jnz     @b
1211
        jnz     @b
1212
.no:
1212
.no:
1213
        push    ebx
1213
        push    ebx
1214
        mov     edx, [current_process]
1214
        mov     edx, [current_process]
1215
        shl     ebx, 12
1215
        shl     ebx, 12
1216
        add     [edx+PROC.mem_used], ebx
1216
        add     [edx+PROC.mem_used], ebx
1217
        pop     ebx
1217
        pop     ebx
1218
@@:
1218
@@:
1219
        mov     dword [page_tabs+esi*4], 2
1219
        mov     dword [page_tabs+esi*8], 2
1220
        inc     esi
1220
        inc     esi
1221
        dec     ebx
1221
        dec     ebx
1222
        jnz     @b
1222
        jnz     @b
1223
 
1223
 
1224
        mov     ecx, [current_process]
1224
        mov     ecx, [current_process]
1225
        lea     ecx, [ecx+PROC.heap_lock]
1225
        lea     ecx, [ecx+PROC.heap_lock]
1226
        call    mutex_unlock
1226
        call    mutex_unlock
1227
        pop     eax edi esi edx ecx
1227
        pop     eax edi esi edx ecx
1228
        ret
1228
        ret
1229
 
1229
 
1230
 
1230
 
1231
 
1231
 
1232
;;;;;;;;;;;;;;      SHARED MEMORY     ;;;;;;;;;;;;;;;;;
1232
;;;;;;;;;;;;;;      SHARED MEMORY     ;;;;;;;;;;;;;;;;;
1233
 
1233
 
1234
 
1234
 
1235
; param
1235
; param
1236
;  eax= shm_map object
1236
;  eax= shm_map object
1237
 
1237
 
1238
align 4
1238
align 4
1239
destroy_smap:
1239
destroy_smap:
1240
 
1240
 
1241
        pushfd
1241
        pushfd
1242
        cli
1242
        cli
1243
 
1243
 
1244
        push    esi
1244
        push    esi
1245
        push    edi
1245
        push    edi
1246
 
1246
 
1247
        mov     edi, eax
1247
        mov     edi, eax
1248
        mov     esi, [eax+SMAP.parent]
1248
        mov     esi, [eax+SMAP.parent]
1249
        test    esi, esi
1249
        test    esi, esi
1250
        jz      .done
1250
        jz      .done
1251
 
1251
 
1252
        lock dec [esi+SMEM.refcount]
1252
        lock dec [esi+SMEM.refcount]
1253
        jnz     .done
1253
        jnz     .done
1254
 
1254
 
1255
        mov     ecx, [esi+SMEM.bk]
1255
        mov     ecx, [esi+SMEM.bk]
1256
        mov     edx, [esi+SMEM.fd]
1256
        mov     edx, [esi+SMEM.fd]
1257
 
1257
 
1258
        mov     [ecx+SMEM.fd], edx
1258
        mov     [ecx+SMEM.fd], edx
1259
        mov     [edx+SMEM.bk], ecx
1259
        mov     [edx+SMEM.bk], ecx
1260
 
1260
 
1261
        stdcall kernel_free, [esi+SMEM.base]
1261
        stdcall kernel_free, [esi+SMEM.base]
1262
        mov     eax, esi
1262
        mov     eax, esi
1263
        call    free
1263
        call    free
1264
.done:
1264
.done:
1265
        mov     eax, edi
1265
        mov     eax, edi
1266
        call    destroy_kernel_object
1266
        call    destroy_kernel_object
1267
 
1267
 
1268
        pop     edi
1268
        pop     edi
1269
        pop     esi
1269
        pop     esi
1270
        popfd
1270
        popfd
1271
 
1271
 
1272
        ret
1272
        ret
1273
 
1273
 
1274
E_NOTFOUND      equ  5
1274
E_NOTFOUND      equ  5
1275
E_ACCESS        equ 10
1275
E_ACCESS        equ 10
1276
E_NOMEM         equ 30
1276
E_NOMEM         equ 30
1277
E_PARAM         equ 33
1277
E_PARAM         equ 33
1278
 
1278
 
1279
SHM_READ        equ 0
1279
SHM_READ        equ 0
1280
SHM_WRITE       equ 1
1280
SHM_WRITE       equ 1
1281
 
1281
 
1282
SHM_ACCESS_MASK equ 3
1282
SHM_ACCESS_MASK equ 3
1283
 
1283
 
1284
SHM_OPEN        equ (0 shl 2)
1284
SHM_OPEN        equ (0 shl 2)
1285
SHM_OPEN_ALWAYS equ (1 shl 2)
1285
SHM_OPEN_ALWAYS equ (1 shl 2)
1286
SHM_CREATE      equ (2 shl 2)
1286
SHM_CREATE      equ (2 shl 2)
1287
 
1287
 
1288
SHM_OPEN_MASK   equ (3 shl 2)
1288
SHM_OPEN_MASK   equ (3 shl 2)
1289
 
1289
 
1290
align 4
1290
align 4
1291
proc shmem_open stdcall name:dword, size:dword, access:dword
1291
proc shmem_open stdcall name:dword, size:dword, access:dword
1292
        locals
1292
        locals
1293
           action         dd ?
1293
           action         dd ?
1294
           owner_access   dd ?
1294
           owner_access   dd ?
1295
           mapped         dd ?
1295
           mapped         dd ?
1296
        endl
1296
        endl
1297
 
1297
 
1298
        push    ebx
1298
        push    ebx
1299
        push    esi
1299
        push    esi
1300
        push    edi
1300
        push    edi
1301
 
1301
 
1302
        mov     [mapped], 0
1302
        mov     [mapped], 0
1303
        mov     [owner_access], 0
1303
        mov     [owner_access], 0
1304
 
1304
 
1305
        pushfd                         ;mutex required
1305
        pushfd                         ;mutex required
1306
        cli
1306
        cli
1307
 
1307
 
1308
        mov     eax, [access]
1308
        mov     eax, [access]
1309
        and     eax, SHM_OPEN_MASK
1309
        and     eax, SHM_OPEN_MASK
1310
        mov     [action], eax
1310
        mov     [action], eax
1311
 
1311
 
1312
        mov     ebx, [name]
1312
        mov     ebx, [name]
1313
        test    ebx, ebx
1313
        test    ebx, ebx
1314
        mov     edx, E_PARAM
1314
        mov     edx, E_PARAM
1315
        jz      .fail
1315
        jz      .fail
1316
 
1316
 
1317
        mov     esi, [shmem_list.fd]
1317
        mov     esi, [shmem_list.fd]
1318
align 4
1318
align 4
1319
@@:
1319
@@:
1320
        cmp     esi, shmem_list
1320
        cmp     esi, shmem_list
1321
        je      .not_found
1321
        je      .not_found
1322
 
1322
 
1323
        lea     edx, [esi+SMEM.name]; link , base, size
1323
        lea     edx, [esi+SMEM.name]; link , base, size
1324
        stdcall strncmp, edx, ebx, 32
1324
        stdcall strncmp, edx, ebx, 32
1325
        test    eax, eax
1325
        test    eax, eax
1326
        je      .found
1326
        je      .found
1327
 
1327
 
1328
        mov     esi, [esi+SMEM.fd]
1328
        mov     esi, [esi+SMEM.fd]
1329
        jmp     @B
1329
        jmp     @B
1330
 
1330
 
1331
.not_found:
1331
.not_found:
1332
        mov     eax, [action]
1332
        mov     eax, [action]
1333
 
1333
 
1334
        cmp     eax, SHM_OPEN
1334
        cmp     eax, SHM_OPEN
1335
        mov     edx, E_NOTFOUND
1335
        mov     edx, E_NOTFOUND
1336
        je      .fail
1336
        je      .fail
1337
 
1337
 
1338
        cmp     eax, SHM_CREATE
1338
        cmp     eax, SHM_CREATE
1339
        mov     edx, E_PARAM
1339
        mov     edx, E_PARAM
1340
        je      .create_shm
1340
        je      .create_shm
1341
 
1341
 
1342
        cmp     eax, SHM_OPEN_ALWAYS
1342
        cmp     eax, SHM_OPEN_ALWAYS
1343
        jne     .fail
1343
        jne     .fail
1344
 
1344
 
1345
.create_shm:
1345
.create_shm:
1346
 
1346
 
1347
        mov     ecx, [size]
1347
        mov     ecx, [size]
1348
        test    ecx, ecx
1348
        test    ecx, ecx
1349
        jz      .fail
1349
        jz      .fail
1350
 
1350
 
1351
        add     ecx, 4095
1351
        add     ecx, 4095
1352
        and     ecx, -4096
1352
        and     ecx, -4096
1353
        mov     [size], ecx
1353
        mov     [size], ecx
1354
 
1354
 
1355
        mov     eax, sizeof.SMEM
1355
        mov     eax, sizeof.SMEM
1356
        call    malloc
1356
        call    malloc
1357
        test    eax, eax
1357
        test    eax, eax
1358
        mov     esi, eax
1358
        mov     esi, eax
1359
        mov     edx, E_NOMEM
1359
        mov     edx, E_NOMEM
1360
        jz      .fail
1360
        jz      .fail
1361
 
1361
 
1362
        stdcall kernel_alloc, [size]
1362
        stdcall kernel_alloc, [size]
1363
        test    eax, eax
1363
        test    eax, eax
1364
        mov     [mapped], eax
1364
        mov     [mapped], eax
1365
        mov     edx, E_NOMEM
1365
        mov     edx, E_NOMEM
1366
        jz      .cleanup
1366
        jz      .cleanup
1367
 
1367
 
1368
        mov     ecx, [size]
1368
        mov     ecx, [size]
1369
        mov     edx, [access]
1369
        mov     edx, [access]
1370
        and     edx, SHM_ACCESS_MASK
1370
        and     edx, SHM_ACCESS_MASK
1371
 
1371
 
1372
        mov     [esi+SMEM.base], eax
1372
        mov     [esi+SMEM.base], eax
1373
        mov     [esi+SMEM.size], ecx
1373
        mov     [esi+SMEM.size], ecx
1374
        mov     [esi+SMEM.access], edx
1374
        mov     [esi+SMEM.access], edx
1375
        mov     [esi+SMEM.refcount], 0
1375
        mov     [esi+SMEM.refcount], 0
1376
        mov     [esi+SMEM.name+28], 0
1376
        mov     [esi+SMEM.name+28], 0
1377
 
1377
 
1378
        lea     eax, [esi+SMEM.name]
1378
        lea     eax, [esi+SMEM.name]
1379
        stdcall strncpy, eax, [name], 31
1379
        stdcall strncpy, eax, [name], 31
1380
 
1380
 
1381
        mov     eax, [shmem_list.fd]
1381
        mov     eax, [shmem_list.fd]
1382
        mov     [esi+SMEM.bk], shmem_list
1382
        mov     [esi+SMEM.bk], shmem_list
1383
        mov     [esi+SMEM.fd], eax
1383
        mov     [esi+SMEM.fd], eax
1384
 
1384
 
1385
        mov     [eax+SMEM.bk], esi
1385
        mov     [eax+SMEM.bk], esi
1386
        mov     [shmem_list.fd], esi
1386
        mov     [shmem_list.fd], esi
1387
 
1387
 
1388
        mov     [action], SHM_OPEN
1388
        mov     [action], SHM_OPEN
1389
        mov     [owner_access], SHM_WRITE
1389
        mov     [owner_access], SHM_WRITE
1390
 
1390
 
1391
.found:
1391
.found:
1392
        mov     eax, [action]
1392
        mov     eax, [action]
1393
 
1393
 
1394
        cmp     eax, SHM_CREATE
1394
        cmp     eax, SHM_CREATE
1395
        mov     edx, E_ACCESS
1395
        mov     edx, E_ACCESS
1396
        je      .exit
1396
        je      .exit
1397
 
1397
 
1398
        cmp     eax, SHM_OPEN
1398
        cmp     eax, SHM_OPEN
1399
        mov     edx, E_PARAM
1399
        mov     edx, E_PARAM
1400
        je      .create_map
1400
        je      .create_map
1401
 
1401
 
1402
        cmp     eax, SHM_OPEN_ALWAYS
1402
        cmp     eax, SHM_OPEN_ALWAYS
1403
        jne     .fail
1403
        jne     .fail
1404
 
1404
 
1405
.create_map:
1405
.create_map:
1406
 
1406
 
1407
        mov     eax, [access]
1407
        mov     eax, [access]
1408
        and     eax, SHM_ACCESS_MASK
1408
        and     eax, SHM_ACCESS_MASK
1409
        cmp     eax, [esi+SMEM.access]
1409
        cmp     eax, [esi+SMEM.access]
1410
        mov     [access], eax
1410
        mov     [access], eax
1411
        mov     edx, E_ACCESS
1411
        mov     edx, E_ACCESS
1412
        ja      .fail
1412
        ja      .fail
1413
 
1413
 
1414
        mov     ebx, [CURRENT_TASK]
1414
        mov     ebx, [CURRENT_TASK]
1415
        shl     ebx, 5
1415
        shl     ebx, 5
1416
        mov     ebx, [CURRENT_TASK+ebx+4]
1416
        mov     ebx, [CURRENT_TASK+ebx+4]
1417
        mov     eax, sizeof.SMAP
1417
        mov     eax, sizeof.SMAP
1418
 
1418
 
1419
        call    create_kernel_object
1419
        call    create_kernel_object
1420
        test    eax, eax
1420
        test    eax, eax
1421
        mov     edi, eax
1421
        mov     edi, eax
1422
        mov     edx, E_NOMEM
1422
        mov     edx, E_NOMEM
1423
        jz      .fail
1423
        jz      .fail
1424
 
1424
 
1425
        inc     [esi+SMEM.refcount]
1425
        inc     [esi+SMEM.refcount]
1426
 
1426
 
1427
        mov     [edi+SMAP.magic], 'SMAP'
1427
        mov     [edi+SMAP.magic], 'SMAP'
1428
        mov     [edi+SMAP.destroy], destroy_smap
1428
        mov     [edi+SMAP.destroy], destroy_smap
1429
        mov     [edi+SMAP.parent], esi
1429
        mov     [edi+SMAP.parent], esi
1430
        mov     [edi+SMAP.base], 0
1430
        mov     [edi+SMAP.base], 0
1431
 
1431
 
1432
        stdcall user_alloc, [esi+SMEM.size]
1432
        stdcall user_alloc, [esi+SMEM.size]
1433
        test    eax, eax
1433
        test    eax, eax
1434
        mov     [mapped], eax
1434
        mov     [mapped], eax
1435
        mov     edx, E_NOMEM
1435
        mov     edx, E_NOMEM
1436
        jz      .cleanup2
1436
        jz      .cleanup2
1437
 
1437
 
1438
        mov     [edi+SMAP.base], eax
1438
        mov     [edi+SMAP.base], eax
1439
 
1439
 
1440
        mov     ecx, [esi+SMEM.size]
1440
        mov     ecx, [esi+SMEM.size]
1441
        mov     [size], ecx
1441
        mov     [size], ecx
1442
 
1442
 
1443
        shr     ecx, 12
1443
        shr     ecx, 12
1444
        shr     eax, 10
1444
        shr     eax, 9
1445
 
1445
 
1446
        mov     esi, [esi+SMEM.base]
1446
        mov     esi, [esi+SMEM.base]
1447
        shr     esi, 10
1447
        shr     esi, 9
1448
        lea     edi, [page_tabs+eax]
1448
        lea     edi, [page_tabs+eax]
1449
        add     esi, page_tabs
1449
        add     esi, page_tabs
1450
 
1450
 
1451
        mov     edx, [access]
1451
        mov     edx, [access]
1452
        or      edx, [owner_access]
1452
        or      edx, [owner_access]
1453
        shl     edx, 1
1453
        shl     edx, 1
1454
        or      edx, PG_SHARED+PG_UR
1454
        or      edx, PG_SHARED+PG_UR
1455
@@:
1455
@@:
1456
        lodsd
1456
        lodsd
1457
        and     eax, 0xFFFFF000
1457
        and     eax, 0xFFFFF000
1458
        or      eax, edx
1458
        or      eax, edx
1459
        stosd
1459
        stosd
-
 
1460
        movsd
1460
        loop    @B
1461
        loop    @B
1461
 
1462
 
1462
        xor     edx, edx
1463
        xor     edx, edx
1463
 
1464
 
1464
        cmp     [owner_access], 0
1465
        cmp     [owner_access], 0
1465
        jne     .fail
1466
        jne     .fail
1466
.exit:
1467
.exit:
1467
        mov     edx, [size]
1468
        mov     edx, [size]
1468
.fail:
1469
.fail:
1469
        mov     eax, [mapped]
1470
        mov     eax, [mapped]
1470
 
1471
 
1471
        popfd
1472
        popfd
1472
        pop     edi
1473
        pop     edi
1473
        pop     esi
1474
        pop     esi
1474
        pop     ebx
1475
        pop     ebx
1475
        ret
1476
        ret
1476
.cleanup:
1477
.cleanup:
1477
        mov     [size], edx
1478
        mov     [size], edx
1478
        mov     eax, esi
1479
        mov     eax, esi
1479
        call    free
1480
        call    free
1480
        jmp     .exit
1481
        jmp     .exit
1481
 
1482
 
1482
.cleanup2:
1483
.cleanup2:
1483
        mov     [size], edx
1484
        mov     [size], edx
1484
        mov     eax, edi
1485
        mov     eax, edi
1485
        call    destroy_smap
1486
        call    destroy_smap
1486
        jmp     .exit
1487
        jmp     .exit
1487
endp
1488
endp
1488
 
1489
 
1489
align 4
1490
align 4
1490
proc shmem_close stdcall, name:dword
1491
proc shmem_close stdcall, name:dword
1491
 
1492
 
1492
        mov     eax, [name]
1493
        mov     eax, [name]
1493
        test    eax, eax
1494
        test    eax, eax
1494
        jz      .fail
1495
        jz      .fail
1495
 
1496
 
1496
        push    esi
1497
        push    esi
1497
        push    edi
1498
        push    edi
1498
        pushfd
1499
        pushfd
1499
        cli
1500
        cli
1500
 
1501
 
1501
        mov     esi, [current_slot]
1502
        mov     esi, [current_slot]
1502
        add     esi, APP_OBJ_OFFSET
1503
        add     esi, APP_OBJ_OFFSET
1503
.next:
1504
.next:
1504
        mov     eax, [esi+APPOBJ.fd]
1505
        mov     eax, [esi+APPOBJ.fd]
1505
        test    eax, eax
1506
        test    eax, eax
1506
        jz      @F
1507
        jz      @F
1507
 
1508
 
1508
        cmp     eax, esi
1509
        cmp     eax, esi
1509
        mov     esi, eax
1510
        mov     esi, eax
1510
        je      @F
1511
        je      @F
1511
 
1512
 
1512
        cmp     [eax+SMAP.magic], 'SMAP'
1513
        cmp     [eax+SMAP.magic], 'SMAP'
1513
        jne     .next
1514
        jne     .next
1514
 
1515
 
1515
        mov     edi, [eax+SMAP.parent]
1516
        mov     edi, [eax+SMAP.parent]
1516
        test    edi, edi
1517
        test    edi, edi
1517
        jz      .next
1518
        jz      .next
1518
 
1519
 
1519
        lea     edi, [edi+SMEM.name]
1520
        lea     edi, [edi+SMEM.name]
1520
        stdcall strncmp, [name], edi, 32
1521
        stdcall strncmp, [name], edi, 32
1521
        test    eax, eax
1522
        test    eax, eax
1522
        jne     .next
1523
        jne     .next
1523
 
1524
 
1524
        stdcall user_free, [esi+SMAP.base]
1525
        stdcall user_free, [esi+SMAP.base]
1525
 
1526
 
1526
        mov     eax, esi
1527
        mov     eax, esi
1527
        call    [esi+APPOBJ.destroy]
1528
        call    [esi+APPOBJ.destroy]
1528
@@:
1529
@@:
1529
        popfd
1530
        popfd
1530
        pop     edi
1531
        pop     edi
1531
        pop     esi
1532
        pop     esi
1532
.fail:
1533
.fail:
1533
        ret
1534
        ret
1534
endp
1535
endp