Subversion Repositories Kolibri OS

Rev

Rev 6893 | Rev 7136 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6893 Rev 6974
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: 6893 $
8
$Revision: 6974 $
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, 10
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
        push    ebx esi edi
598
        push    ebx esi edi
599
        call    init_heap
599
        mov     ebx, [current_process]
600
        lea     ecx, [ebx+PROC.heap_lock]
600
        lea     ecx, [ebx+PROC.heap_lock]
601
        call    mutex_lock
601
        call    mutex_lock
602
        mov     ecx, [alloc_size]
602
        mov     ecx, [alloc_size]
603
        add     ecx, (4095+PAGE_SIZE)
603
        add     ecx, (4095+PAGE_SIZE)
604
        and     ecx, not 4095
604
        and     ecx, not 4095
605
        mov     esi, dword [ebx+PROC.heap_base] ; heap_base
605
        mov     esi, dword [ebx+PROC.heap_base] ; heap_base
606
        mov     edi, dword [ebx+PROC.heap_top]  ; heap_top
606
        mov     edi, dword [ebx+PROC.heap_top]  ; heap_top
607
.scan:
607
.scan:
608
        cmp     esi, edi
608
        cmp     esi, edi
609
        jae     .m_exit
609
        jae     .m_exit
610
 
610
 
611
        mov     ebx, esi
611
        mov     ebx, esi
612
        shr     ebx, 12
612
        shr     ebx, 12
613
        mov     eax, [page_tabs+ebx*4]
613
        mov     eax, [page_tabs+ebx*4]
614
        test    al, FREE_BLOCK
614
        test    al, FREE_BLOCK
615
        jz      .test_used
615
        jz      .test_used
616
        and     eax, 0xFFFFF000
616
        and     eax, 0xFFFFF000
617
        cmp     eax, ecx   ;alloc_size
617
        cmp     eax, ecx   ;alloc_size
618
        jb      .m_next
618
        jb      .m_next
619
        jz      @f
619
        jz      @f
620
 
620
 
621
        lea     edx, [esi+ecx]
621
        lea     edx, [esi+ecx]
622
        sub     eax, ecx
622
        sub     eax, ecx
623
        or      al, FREE_BLOCK
623
        or      al, FREE_BLOCK
624
        shr     edx, 12
624
        shr     edx, 12
625
        mov     [page_tabs+edx*4], eax
625
        mov     [page_tabs+edx*4], eax
626
@@:
626
@@:
627
        or      ecx, USED_BLOCK
627
        or      ecx, USED_BLOCK
628
        mov     [page_tabs+ebx*4], ecx
628
        mov     [page_tabs+ebx*4], ecx
629
        shr     ecx, 12
629
        shr     ecx, 12
630
        inc     ebx
630
        inc     ebx
631
        dec     ecx
631
        dec     ecx
632
        jz      .no
632
        jz      .no
633
@@:
633
@@:
634
        mov     dword [page_tabs+ebx*4], 2
634
        mov     dword [page_tabs+ebx*4], 2
635
        inc     ebx
635
        inc     ebx
636
        dec     ecx
636
        dec     ecx
637
        jnz     @B
637
        jnz     @B
638
.no:
638
.no:
639
 
639
 
640
        mov     edx, [current_process]
640
        mov     edx, [current_process]
641
        mov     ebx, [alloc_size]
641
        mov     ebx, [alloc_size]
642
        add     ebx, 0xFFF
642
        add     ebx, 0xFFF
643
        and     ebx, not 0xFFF
643
        and     ebx, not 0xFFF
644
        add     [edx+PROC.mem_used], ebx
644
        add     [edx+PROC.mem_used], ebx
645
 
645
 
646
        lea     ecx, [edx+PROC.heap_lock]
646
        lea     ecx, [edx+PROC.heap_lock]
647
        call    mutex_unlock
647
        call    mutex_unlock
648
 
648
 
649
        lea     eax, [esi+4096]
649
        lea     eax, [esi+4096]
650
 
650
 
651
        pop     edi
651
        pop     edi
652
        pop     esi
652
        pop     esi
653
        pop     ebx
653
        pop     ebx
654
        ret
654
        ret
655
.test_used:
655
.test_used:
656
        test    al, USED_BLOCK
656
        test    al, USED_BLOCK
657
        jz      .m_exit
657
        jz      .m_exit
658
 
658
 
659
        and     eax, 0xFFFFF000
659
        and     eax, 0xFFFFF000
660
.m_next:
660
.m_next:
661
        add     esi, eax
661
        add     esi, eax
662
        jmp     .scan
662
        jmp     .scan
663
.m_exit:
663
.m_exit:
664
        mov     ecx, [current_process]
664
        mov     ecx, [current_process]
665
        lea     ecx, [ecx+PROC.heap_lock]
665
        lea     ecx, [ecx+PROC.heap_lock]
666
        call    mutex_unlock
666
        call    mutex_unlock
667
 
667
 
668
        xor     eax, eax
668
        xor     eax, eax
669
        pop     edi
669
        pop     edi
670
        pop     esi
670
        pop     esi
671
        pop     ebx
671
        pop     ebx
672
        ret
672
        ret
673
endp
673
endp
674
 
674
 
675
align 4
675
align 4
676
proc user_alloc_at stdcall, address:dword, alloc_size:dword
676
proc user_alloc_at stdcall, address:dword, alloc_size:dword
677
 
677
 
678
        push    ebx
678
        push    ebx
679
        push    esi
679
        push    esi
680
        push    edi
680
        push    edi
681
 
681
 
682
        mov     ebx, [current_process]
682
        mov     ebx, [current_process]
683
        lea     ecx, [ebx+PROC.heap_lock]
683
        lea     ecx, [ebx+PROC.heap_lock]
684
        call    mutex_lock
684
        call    mutex_lock
685
 
685
 
686
        mov     edx, [address]
686
        mov     edx, [address]
687
        and     edx, not 0xFFF
687
        and     edx, not 0xFFF
688
        mov     [address], edx
688
        mov     [address], edx
689
        sub     edx, 0x1000
689
        sub     edx, 0x1000
690
        jb      .error
690
        jb      .error
691
        mov     esi, [ebx+PROC.heap_base]
691
        mov     esi, [ebx+PROC.heap_base]
692
        mov     edi, [ebx+PROC.heap_top]
692
        mov     edi, [ebx+PROC.heap_top]
693
        cmp     edx, esi
693
        cmp     edx, esi
694
        jb      .error
694
        jb      .error
695
.scan:
695
.scan:
696
        cmp     esi, edi
696
        cmp     esi, edi
697
        jae     .error
697
        jae     .error
698
        mov     ebx, esi
698
        mov     ebx, esi
699
        shr     ebx, 12
699
        shr     ebx, 12
700
        mov     eax, [page_tabs+ebx*4]
700
        mov     eax, [page_tabs+ebx*4]
701
        mov     ecx, eax
701
        mov     ecx, eax
702
        and     ecx, 0xFFFFF000
702
        and     ecx, 0xFFFFF000
703
        add     ecx, esi
703
        add     ecx, esi
704
        cmp     edx, ecx
704
        cmp     edx, ecx
705
        jb      .found
705
        jb      .found
706
        mov     esi, ecx
706
        mov     esi, ecx
707
        jmp     .scan
707
        jmp     .scan
708
.error:
708
.error:
709
        mov     ecx, [current_process]
709
        mov     ecx, [current_process]
710
        lea     ecx, [ecx+PROC.heap_lock]
710
        lea     ecx, [ecx+PROC.heap_lock]
711
        call    mutex_unlock
711
        call    mutex_unlock
712
 
712
 
713
        xor     eax, eax
713
        xor     eax, eax
714
        pop     edi
714
        pop     edi
715
        pop     esi
715
        pop     esi
716
        pop     ebx
716
        pop     ebx
717
        ret
717
        ret
718
.found:
718
.found:
719
        test    al, FREE_BLOCK
719
        test    al, FREE_BLOCK
720
        jz      .error
720
        jz      .error
721
        mov     eax, ecx
721
        mov     eax, ecx
722
        sub     eax, edx
722
        sub     eax, edx
723
        sub     eax, 0x1000
723
        sub     eax, 0x1000
724
        cmp     eax, [alloc_size]
724
        cmp     eax, [alloc_size]
725
        jb      .error
725
        jb      .error
726
 
726
 
727
; Here we have 1 big free block which includes requested area.
727
; Here we have 1 big free block which includes requested area.
728
; In general, 3 other blocks must be created instead:
728
; In general, 3 other blocks must be created instead:
729
; free at [esi, edx);
729
; free at [esi, edx);
730
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
730
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
731
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
731
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
732
; First or third block (or both) may be absent.
732
; First or third block (or both) may be absent.
733
        mov     eax, edx
733
        mov     eax, edx
734
        sub     eax, esi
734
        sub     eax, esi
735
        jz      .nofirst
735
        jz      .nofirst
736
        or      al, FREE_BLOCK
736
        or      al, FREE_BLOCK
737
        mov     [page_tabs+ebx*4], eax
737
        mov     [page_tabs+ebx*4], eax
738
.nofirst:
738
.nofirst:
739
        mov     eax, [alloc_size]
739
        mov     eax, [alloc_size]
740
        add     eax, 0x1FFF
740
        add     eax, 0x1FFF
741
        and     eax, not 0xFFF
741
        and     eax, not 0xFFF
742
        mov     ebx, edx
742
        mov     ebx, edx
743
        add     edx, eax
743
        add     edx, eax
744
        shr     ebx, 12
744
        shr     ebx, 12
745
        or      al, USED_BLOCK
745
        or      al, USED_BLOCK
746
        mov     [page_tabs+ebx*4], eax
746
        mov     [page_tabs+ebx*4], eax
747
        shr     eax, 12
747
        shr     eax, 12
748
        dec     eax
748
        dec     eax
749
        jz      .second_nofill
749
        jz      .second_nofill
750
        inc     ebx
750
        inc     ebx
751
.fill:
751
.fill:
752
        mov     dword [page_tabs+ebx*4], 2
752
        mov     dword [page_tabs+ebx*4], 2
753
        inc     ebx
753
        inc     ebx
754
        dec     eax
754
        dec     eax
755
        jnz     .fill
755
        jnz     .fill
756
 
756
 
757
.second_nofill:
757
.second_nofill:
758
        sub     ecx, edx
758
        sub     ecx, edx
759
        jz      .nothird
759
        jz      .nothird
760
        or      cl, FREE_BLOCK
760
        or      cl, FREE_BLOCK
761
        mov     [page_tabs+ebx*4], ecx
761
        mov     [page_tabs+ebx*4], ecx
762
 
762
 
763
.nothird:
763
.nothird:
764
        mov     edx, [current_process]
764
        mov     edx, [current_process]
765
        mov     ebx, [alloc_size]
765
        mov     ebx, [alloc_size]
766
        add     ebx, 0xFFF
766
        add     ebx, 0xFFF
767
        and     ebx, not 0xFFF
767
        and     ebx, not 0xFFF
768
        add     [edx+PROC.mem_used], ebx
768
        add     [edx+PROC.mem_used], ebx
769
 
769
 
770
        lea     ecx, [edx+PROC.heap_lock]
770
        lea     ecx, [edx+PROC.heap_lock]
771
        call    mutex_unlock
771
        call    mutex_unlock
772
 
772
 
773
        mov     eax, [address]
773
        mov     eax, [address]
774
 
774
 
775
        pop     edi
775
        pop     edi
776
        pop     esi
776
        pop     esi
777
        pop     ebx
777
        pop     ebx
778
        ret
778
        ret
779
endp
779
endp
780
 
780
 
781
align 4
781
align 4
782
proc user_free stdcall, base:dword
782
proc user_free stdcall, base:dword
783
 
783
 
784
        push    esi
784
        push    esi
785
 
785
 
786
        mov     esi, [base]
786
        mov     esi, [base]
787
        test    esi, esi
787
        test    esi, esi
788
        jz      .fail
788
        jz      .fail
789
 
789
 
790
        push    ebx
790
        push    ebx
791
 
791
 
792
        mov     ebx, [current_process]
792
        mov     ebx, [current_process]
793
        lea     ecx, [ebx+PROC.heap_lock]
793
        lea     ecx, [ebx+PROC.heap_lock]
794
        call    mutex_lock
794
        call    mutex_lock
795
 
795
 
796
        xor     ebx, ebx
796
        xor     ebx, ebx
797
        shr     esi, 12
797
        shr     esi, 12
798
        mov     eax, [page_tabs+(esi-1)*4]
798
        mov     eax, [page_tabs+(esi-1)*4]
799
        test    al, USED_BLOCK
799
        test    al, USED_BLOCK
800
        jz      .cantfree
800
        jz      .cantfree
801
        test    al, DONT_FREE_BLOCK
801
        test    al, DONT_FREE_BLOCK
802
        jnz     .cantfree
802
        jnz     .cantfree
803
 
803
 
804
        and     eax, not 4095
804
        and     eax, not 4095
805
        mov     ecx, eax
805
        mov     ecx, eax
806
        or      al, FREE_BLOCK
806
        or      al, FREE_BLOCK
807
        mov     [page_tabs+(esi-1)*4], eax
807
        mov     [page_tabs+(esi-1)*4], eax
808
        sub     ecx, 4096
808
        sub     ecx, 4096
809
        mov     ebx, ecx
809
        mov     ebx, ecx
810
        shr     ecx, 12
810
        shr     ecx, 12
811
        jz      .released
811
        jz      .released
812
.release:
812
.release:
813
        xor     eax, eax
813
        xor     eax, eax
814
        xchg    eax, [page_tabs+esi*4]
814
        xchg    eax, [page_tabs+esi*4]
815
        test    al, 1
815
        test    al, 1
816
        jz      @F
816
        jz      @F
817
        test    eax, PG_SHARED
817
        test    eax, PG_SHARED
818
        jnz     @F
818
        jnz     @F
819
        call    free_page
819
        call    free_page
820
        mov     eax, esi
820
        mov     eax, esi
821
        shl     eax, 12
821
        shl     eax, 12
822
        invlpg  [eax]
822
        invlpg  [eax]
823
@@:
823
@@:
824
        inc     esi
824
        inc     esi
825
        dec     ecx
825
        dec     ecx
826
        jnz     .release
826
        jnz     .release
827
 
827
 
828
.released:
828
.released:
829
        push    edi
829
        push    edi
830
 
830
 
831
        mov     edx, [current_process]
831
        mov     edx, [current_process]
832
        lea     ecx, [edx+PROC.heap_lock]
832
        lea     ecx, [edx+PROC.heap_lock]
833
        mov     esi, dword [edx+PROC.heap_base]
833
        mov     esi, dword [edx+PROC.heap_base]
834
        mov     edi, dword [edx+PROC.heap_top]
834
        mov     edi, dword [edx+PROC.heap_top]
835
        sub     ebx, [edx+PROC.mem_used]
835
        sub     ebx, [edx+PROC.mem_used]
836
        neg     ebx
836
        neg     ebx
837
        mov     [edx+PROC.mem_used], ebx
837
        mov     [edx+PROC.mem_used], ebx
838
        call    user_normalize
838
        call    user_normalize
839
        pop     edi
839
        pop     edi
840
.exit:
840
.exit:
841
        call    mutex_unlock
841
        call    mutex_unlock
842
 
842
 
843
        xor     eax, eax
843
        xor     eax, eax
844
        inc     eax
844
        inc     eax
845
        pop     ebx
845
        pop     ebx
846
        pop     esi
846
        pop     esi
847
        ret
847
        ret
848
 
848
 
849
.cantfree:
849
.cantfree:
850
        mov     ecx, [current_process]
850
        mov     ecx, [current_process]
851
        lea     ecx, [ecx+PROC.heap_lock]
851
        lea     ecx, [ecx+PROC.heap_lock]
852
        jmp     .exit
852
        jmp     .exit
853
.fail:
853
.fail:
854
        xor     eax, eax
854
        xor     eax, eax
855
        pop     esi
855
        pop     esi
856
        ret
856
        ret
857
endp
857
endp
858
 
858
 
859
 
859
 
860
align 4
860
align 4
861
proc user_unmap stdcall, base:dword, offset:dword, size:dword
861
proc user_unmap stdcall, base:dword, offset:dword, size:dword
862
 
862
 
863
        push    ebx
863
        push    ebx
864
 
864
 
865
        mov     ebx, [base]             ; must be valid pointer
865
        mov     ebx, [base]             ; must be valid pointer
866
        test    ebx, ebx
866
        test    ebx, ebx
867
        jz      .error
867
        jz      .error
868
 
868
 
869
        mov     edx, [offset]           ; check offset
869
        mov     edx, [offset]           ; check offset
870
        add     edx, ebx                ; must be below 2Gb app limit
870
        add     edx, ebx                ; must be below 2Gb app limit
871
        js      .error
871
        js      .error
872
 
872
 
873
        shr     ebx, 12                 ; chek block attributes
873
        shr     ebx, 12                 ; chek block attributes
874
        lea     ebx, [page_tabs+ebx*4]
874
        lea     ebx, [page_tabs+ebx*4]
875
        mov     eax, [ebx-4]            ; block attributes
875
        mov     eax, [ebx-4]            ; block attributes
876
        test    al, USED_BLOCK
876
        test    al, USED_BLOCK
877
        jz      .error
877
        jz      .error
878
        test    al, DONT_FREE_BLOCK
878
        test    al, DONT_FREE_BLOCK
879
        jnz     .error
879
        jnz     .error
880
 
880
 
881
        shr     edx, 12
881
        shr     edx, 12
882
        lea     edx, [page_tabs+edx*4]  ; unmap offset
882
        lea     edx, [page_tabs+edx*4]  ; unmap offset
883
 
883
 
884
        mov     ecx, [size]
884
        mov     ecx, [size]
885
        add     ecx, 4095
885
        add     ecx, 4095
886
        shr     ecx, 12                 ; unmap size in pages
886
        shr     ecx, 12                 ; unmap size in pages
887
 
887
 
888
        shr     eax, 12                 ; block size + 1 page
888
        shr     eax, 12                 ; block size + 1 page
889
        lea     ebx, [ebx+eax*4-4]      ; block end ptr
889
        lea     ebx, [ebx+eax*4-4]      ; block end ptr
890
        lea     eax, [edx+ecx*4]        ; unmap end ptr
890
        lea     eax, [edx+ecx*4]        ; unmap end ptr
891
 
891
 
892
        cmp     eax, ebx                ; check for overflow
892
        cmp     eax, ebx                ; check for overflow
893
        ja      .error
893
        ja      .error
894
 
894
 
895
        mov     ebx, [offset]
895
        mov     ebx, [offset]
896
        and     ebx, not 4095           ; is it required ?
896
        and     ebx, not 4095           ; is it required ?
897
        add     ebx, [base]
897
        add     ebx, [base]
898
 
898
 
899
.unmap:
899
.unmap:
900
        mov     eax, [edx]              ; get page addres
900
        mov     eax, [edx]              ; get page addres
901
        test    al, 1                   ; page mapped ?
901
        test    al, 1                   ; page mapped ?
902
        jz      @F
902
        jz      @F
903
        test    eax, PG_SHARED          ; page shared ?
903
        test    eax, PG_SHARED          ; page shared ?
904
        jnz     @F
904
        jnz     @F
905
        mov     [edx], dword 2
905
        mov     [edx], dword 2
906
                                        ; mark page as reserved
906
                                        ; mark page as reserved
907
        invlpg  [ebx]                   ; when we start using
907
        invlpg  [ebx]                   ; when we start using
908
        call    free_page               ; empty c-o-w page instead this ?
908
        call    free_page               ; empty c-o-w page instead this ?
909
@@:
909
@@:
910
        add     ebx, 4096
910
        add     ebx, 4096
911
        add     edx, 4
911
        add     edx, 4
912
        dec     ecx
912
        dec     ecx
913
        jnz     .unmap
913
        jnz     .unmap
914
 
914
 
915
        pop     ebx
915
        pop     ebx
916
        or      al, 1                   ; return non zero on success
916
        or      al, 1                   ; return non zero on success
917
        ret
917
        ret
918
.error:
918
.error:
919
        pop     ebx
919
        pop     ebx
920
        xor     eax, eax                ; something wrong
920
        xor     eax, eax                ; something wrong
921
        ret
921
        ret
922
endp
922
endp
923
 
923
 
924
align 4
924
align 4
925
user_normalize:
925
user_normalize:
926
; in: esi=heap_base, edi=heap_top
926
; in: esi=heap_base, edi=heap_top
927
; out: eax=0 <=> OK
927
; out: eax=0 <=> OK
928
; destroys: ebx,edx,esi,edi
928
; destroys: ebx,edx,esi,edi
929
        shr     esi, 12
929
        shr     esi, 12
930
        shr     edi, 12
930
        shr     edi, 12
931
@@:
931
@@:
932
        mov     eax, [page_tabs+esi*4]
932
        mov     eax, [page_tabs+esi*4]
933
        test    al, USED_BLOCK
933
        test    al, USED_BLOCK
934
        jz      .test_free
934
        jz      .test_free
935
        shr     eax, 12
935
        shr     eax, 12
936
        add     esi, eax
936
        add     esi, eax
937
        jmp     @B
937
        jmp     @B
938
.test_free:
938
.test_free:
939
        test    al, FREE_BLOCK
939
        test    al, FREE_BLOCK
940
        jz      .err
940
        jz      .err
941
        mov     edx, eax
941
        mov     edx, eax
942
        shr     edx, 12
942
        shr     edx, 12
943
        add     edx, esi
943
        add     edx, esi
944
        cmp     edx, edi
944
        cmp     edx, edi
945
        jae     .exit
945
        jae     .exit
946
 
946
 
947
        mov     ebx, [page_tabs+edx*4]
947
        mov     ebx, [page_tabs+edx*4]
948
        test    bl, USED_BLOCK
948
        test    bl, USED_BLOCK
949
        jz      .next_free
949
        jz      .next_free
950
 
950
 
951
        shr     ebx, 12
951
        shr     ebx, 12
952
        add     edx, ebx
952
        add     edx, ebx
953
        mov     esi, edx
953
        mov     esi, edx
954
        jmp     @B
954
        jmp     @B
955
.next_free:
955
.next_free:
956
        test    bl, FREE_BLOCK
956
        test    bl, FREE_BLOCK
957
        jz      .err
957
        jz      .err
958
        and     dword [page_tabs+edx*4], 0
958
        and     dword [page_tabs+edx*4], 0
959
        add     eax, ebx
959
        add     eax, ebx
960
        and     eax, not 4095
960
        and     eax, not 4095
961
        or      eax, FREE_BLOCK
961
        or      eax, FREE_BLOCK
962
        mov     [page_tabs+esi*4], eax
962
        mov     [page_tabs+esi*4], eax
963
        jmp     @B
963
        jmp     @B
964
.exit:
964
.exit:
965
        xor     eax, eax
965
        xor     eax, eax
966
        inc     eax
966
        inc     eax
967
        ret
967
        ret
968
.err:
968
.err:
969
        xor     eax, eax
969
        xor     eax, eax
970
        ret
970
        ret
971
 
971
 
972
user_realloc:
972
user_realloc:
973
; in: eax = pointer, ebx = new size
973
; in: eax = pointer, ebx = new size
974
; out: eax = new pointer or NULL
974
; out: eax = new pointer or NULL
975
        test    eax, eax
975
        test    eax, eax
976
        jnz     @f
976
        jnz     @f
977
; realloc(NULL,sz) - same as malloc(sz)
977
; realloc(NULL,sz) - same as malloc(sz)
978
        push    ebx
978
        push    ebx
979
        call    user_alloc
979
        call    user_alloc
980
        ret
980
        ret
981
@@:
981
@@:
982
        push    ecx edx
982
        push    ecx edx
983
 
983
 
984
        push    eax
984
        push    eax
985
        mov     ecx, [current_process]
985
        mov     ecx, [current_process]
986
        lea     ecx, [ecx+PROC.heap_lock]
986
        lea     ecx, [ecx+PROC.heap_lock]
987
        call    mutex_lock
987
        call    mutex_lock
988
        pop     eax
988
        pop     eax
989
 
989
 
990
        lea     ecx, [eax - 0x1000]
990
        lea     ecx, [eax - 0x1000]
991
        shr     ecx, 12
991
        shr     ecx, 12
992
        mov     edx, [page_tabs+ecx*4]
992
        mov     edx, [page_tabs+ecx*4]
993
        test    dl, USED_BLOCK
993
        test    dl, USED_BLOCK
994
        jnz     @f
994
        jnz     @f
995
; attempt to realloc invalid pointer
995
; attempt to realloc invalid pointer
996
.ret0:
996
.ret0:
997
        mov     ecx, [current_process]
997
        mov     ecx, [current_process]
998
        lea     ecx, [ecx+PROC.heap_lock]
998
        lea     ecx, [ecx+PROC.heap_lock]
999
        call    mutex_unlock
999
        call    mutex_unlock
1000
 
1000
 
1001
        pop     edx ecx
1001
        pop     edx ecx
1002
        xor     eax, eax
1002
        xor     eax, eax
1003
        ret
1003
        ret
1004
@@:
1004
@@:
1005
        test    dl, DONT_FREE_BLOCK
1005
        test    dl, DONT_FREE_BLOCK
1006
        jnz     .ret0
1006
        jnz     .ret0
1007
        add     ebx, 0x1FFF
1007
        add     ebx, 0x1FFF
1008
        shr     edx, 12
1008
        shr     edx, 12
1009
        shr     ebx, 12
1009
        shr     ebx, 12
1010
; edx = allocated size, ebx = new size
1010
; edx = allocated size, ebx = new size
1011
        add     edx, ecx
1011
        add     edx, ecx
1012
        add     ebx, ecx
1012
        add     ebx, ecx
1013
        cmp     edx, ebx
1013
        cmp     edx, ebx
1014
        jb      .realloc_add
1014
        jb      .realloc_add
1015
; release part of allocated memory
1015
; release part of allocated memory
1016
.loop:
1016
.loop:
1017
        cmp     edx, ebx
1017
        cmp     edx, ebx
1018
        jz      .release_done
1018
        jz      .release_done
1019
        dec     edx
1019
        dec     edx
1020
        xor     eax, eax
1020
        xor     eax, eax
1021
        xchg    eax, [page_tabs+edx*4]
1021
        xchg    eax, [page_tabs+edx*4]
1022
        test    al, 1
1022
        test    al, 1
1023
        jz      .loop
1023
        jz      .loop
1024
        call    free_page
1024
        call    free_page
1025
        mov     eax, edx
1025
        mov     eax, edx
1026
        shl     eax, 12
1026
        shl     eax, 12
1027
        invlpg  [eax]
1027
        invlpg  [eax]
1028
        jmp     .loop
1028
        jmp     .loop
1029
.release_done:
1029
.release_done:
1030
        sub     ebx, ecx
1030
        sub     ebx, ecx
1031
        cmp     ebx, 1
1031
        cmp     ebx, 1
1032
        jnz     .nofreeall
1032
        jnz     .nofreeall
1033
        mov     eax, [page_tabs+ecx*4]
1033
        mov     eax, [page_tabs+ecx*4]
1034
        and     eax, not 0xFFF
1034
        and     eax, not 0xFFF
1035
        mov     edx, [current_process]
1035
        mov     edx, [current_process]
1036
        mov     ebx, [edx+PROC.mem_used]
1036
        mov     ebx, [edx+PROC.mem_used]
1037
        sub     ebx, eax
1037
        sub     ebx, eax
1038
        add     ebx, 0x1000
1038
        add     ebx, 0x1000
1039
        or      al, FREE_BLOCK
1039
        or      al, FREE_BLOCK
1040
        mov     [page_tabs+ecx*4], eax
1040
        mov     [page_tabs+ecx*4], eax
1041
        push    esi edi
1041
        push    esi edi
1042
        mov     esi, [edx+PROC.heap_base]
1042
        mov     esi, [edx+PROC.heap_base]
1043
        mov     edi, [edx+PROC.heap_top]
1043
        mov     edi, [edx+PROC.heap_top]
1044
        mov     [edx+PROC.mem_used], ebx
1044
        mov     [edx+PROC.mem_used], ebx
1045
        call    user_normalize
1045
        call    user_normalize
1046
        pop     edi esi
1046
        pop     edi esi
1047
        jmp     .ret0   ; all freed
1047
        jmp     .ret0   ; all freed
1048
.nofreeall:
1048
.nofreeall:
1049
        sub     edx, ecx
1049
        sub     edx, ecx
1050
        shl     ebx, 12
1050
        shl     ebx, 12
1051
        or      ebx, USED_BLOCK
1051
        or      ebx, USED_BLOCK
1052
        xchg    [page_tabs+ecx*4], ebx
1052
        xchg    [page_tabs+ecx*4], ebx
1053
        shr     ebx, 12
1053
        shr     ebx, 12
1054
        sub     ebx, edx
1054
        sub     ebx, edx
1055
        push    ebx ecx edx
1055
        push    ebx ecx edx
1056
        mov     edx, [current_process]
1056
        mov     edx, [current_process]
1057
        shl     ebx, 12
1057
        shl     ebx, 12
1058
        sub     ebx, [edx+PROC.mem_used]
1058
        sub     ebx, [edx+PROC.mem_used]
1059
        neg     ebx
1059
        neg     ebx
1060
        mov     [edx+PROC.mem_used], ebx
1060
        mov     [edx+PROC.mem_used], ebx
1061
        pop     edx ecx ebx
1061
        pop     edx ecx ebx
1062
        lea     eax, [ecx+1]
1062
        lea     eax, [ecx+1]
1063
        shl     eax, 12
1063
        shl     eax, 12
1064
        push    eax
1064
        push    eax
1065
        add     ecx, edx
1065
        add     ecx, edx
1066
        lea     edx, [ecx+ebx]
1066
        lea     edx, [ecx+ebx]
1067
        shl     ebx, 12
1067
        shl     ebx, 12
1068
        jz      .ret
1068
        jz      .ret
1069
        push    esi
1069
        push    esi
1070
        mov     esi, [current_process]
1070
        mov     esi, [current_process]
1071
        mov     esi, [esi+PROC.heap_top]
1071
        mov     esi, [esi+PROC.heap_top]
1072
        shr     esi, 12
1072
        shr     esi, 12
1073
@@:
1073
@@:
1074
        cmp     edx, esi
1074
        cmp     edx, esi
1075
        jae     .merge_done
1075
        jae     .merge_done
1076
        mov     eax, [page_tabs+edx*4]
1076
        mov     eax, [page_tabs+edx*4]
1077
        test    al, USED_BLOCK
1077
        test    al, USED_BLOCK
1078
        jnz     .merge_done
1078
        jnz     .merge_done
1079
        and     dword [page_tabs+edx*4], 0
1079
        and     dword [page_tabs+edx*4], 0
1080
        shr     eax, 12
1080
        shr     eax, 12
1081
        add     edx, eax
1081
        add     edx, eax
1082
        shl     eax, 12
1082
        shl     eax, 12
1083
        add     ebx, eax
1083
        add     ebx, eax
1084
        jmp     @b
1084
        jmp     @b
1085
.merge_done:
1085
.merge_done:
1086
        pop     esi
1086
        pop     esi
1087
        or      ebx, FREE_BLOCK
1087
        or      ebx, FREE_BLOCK
1088
        mov     [page_tabs+ecx*4], ebx
1088
        mov     [page_tabs+ecx*4], ebx
1089
.ret:
1089
.ret:
1090
        mov     ecx, [current_process]
1090
        mov     ecx, [current_process]
1091
        lea     ecx, [ecx+PROC.heap_lock]
1091
        lea     ecx, [ecx+PROC.heap_lock]
1092
        call    mutex_unlock
1092
        call    mutex_unlock
1093
        pop     eax edx ecx
1093
        pop     eax edx ecx
1094
        ret
1094
        ret
1095
 
1095
 
1096
.realloc_add:
1096
.realloc_add:
1097
; get some additional memory
1097
; get some additional memory
1098
        mov     eax, [current_process]
1098
        mov     eax, [current_process]
1099
        mov     eax, [eax+PROC.heap_top]
1099
        mov     eax, [eax+PROC.heap_top]
1100
        shr     eax, 12
1100
        shr     eax, 12
1101
        cmp     edx, eax
1101
        cmp     edx, eax
1102
        jae     .cant_inplace
1102
        jae     .cant_inplace
1103
        mov     eax, [page_tabs+edx*4]
1103
        mov     eax, [page_tabs+edx*4]
1104
        test    al, FREE_BLOCK
1104
        test    al, FREE_BLOCK
1105
        jz      .cant_inplace
1105
        jz      .cant_inplace
1106
        shr     eax, 12
1106
        shr     eax, 12
1107
        add     eax, edx
1107
        add     eax, edx
1108
        sub     eax, ebx
1108
        sub     eax, ebx
1109
        jb      .cant_inplace
1109
        jb      .cant_inplace
1110
        jz      @f
1110
        jz      @f
1111
        shl     eax, 12
1111
        shl     eax, 12
1112
        or      al, FREE_BLOCK
1112
        or      al, FREE_BLOCK
1113
        mov     [page_tabs+ebx*4], eax
1113
        mov     [page_tabs+ebx*4], eax
1114
@@:
1114
@@:
1115
        mov     eax, ebx
1115
        mov     eax, ebx
1116
        sub     eax, ecx
1116
        sub     eax, ecx
1117
        shl     eax, 12
1117
        shl     eax, 12
1118
        or      al, USED_BLOCK
1118
        or      al, USED_BLOCK
1119
        mov     [page_tabs+ecx*4], eax
1119
        mov     [page_tabs+ecx*4], eax
1120
        lea     eax, [ecx+1]
1120
        lea     eax, [ecx+1]
1121
        shl     eax, 12
1121
        shl     eax, 12
1122
        push    eax
1122
        push    eax
1123
        push    edi
1123
        push    edi
1124
        lea     edi, [page_tabs+edx*4]
1124
        lea     edi, [page_tabs+edx*4]
1125
        mov     eax, 2
1125
        mov     eax, 2
1126
        sub     ebx, edx
1126
        sub     ebx, edx
1127
        mov     ecx, ebx
1127
        mov     ecx, ebx
1128
        cld
1128
        cld
1129
        rep stosd
1129
        rep stosd
1130
        pop     edi
1130
        pop     edi
1131
        mov     edx, [current_process]
1131
        mov     edx, [current_process]
1132
        shl     ebx, 12
1132
        shl     ebx, 12
1133
        add     [edx+PROC.mem_used], ebx
1133
        add     [edx+PROC.mem_used], ebx
1134
 
1134
 
1135
        mov     ecx, [current_process]
1135
        mov     ecx, [current_process]
1136
        lea     ecx, [ecx+PROC.heap_lock]
1136
        lea     ecx, [ecx+PROC.heap_lock]
1137
        call    mutex_unlock
1137
        call    mutex_unlock
1138
        pop     eax edx ecx
1138
        pop     eax edx ecx
1139
        ret
1139
        ret
1140
 
1140
 
1141
.cant_inplace:
1141
.cant_inplace:
1142
        push    esi edi
1142
        push    esi edi
1143
        mov     eax, [current_process]
1143
        mov     eax, [current_process]
1144
        mov     esi, [eax+PROC.heap_base]
1144
        mov     esi, [eax+PROC.heap_base]
1145
        mov     edi, [eax+PROC.heap_top]
1145
        mov     edi, [eax+PROC.heap_top]
1146
        shr     esi, 12
1146
        shr     esi, 12
1147
        shr     edi, 12
1147
        shr     edi, 12
1148
        sub     ebx, ecx
1148
        sub     ebx, ecx
1149
.find_place:
1149
.find_place:
1150
        cmp     esi, edi
1150
        cmp     esi, edi
1151
        jae     .place_not_found
1151
        jae     .place_not_found
1152
        mov     eax, [page_tabs+esi*4]
1152
        mov     eax, [page_tabs+esi*4]
1153
        test    al, FREE_BLOCK
1153
        test    al, FREE_BLOCK
1154
        jz      .next_place
1154
        jz      .next_place
1155
        shr     eax, 12
1155
        shr     eax, 12
1156
        cmp     eax, ebx
1156
        cmp     eax, ebx
1157
        jae     .place_found
1157
        jae     .place_found
1158
        add     esi, eax
1158
        add     esi, eax
1159
        jmp     .find_place
1159
        jmp     .find_place
1160
.next_place:
1160
.next_place:
1161
        shr     eax, 12
1161
        shr     eax, 12
1162
        add     esi, eax
1162
        add     esi, eax
1163
        jmp     .find_place
1163
        jmp     .find_place
1164
.place_not_found:
1164
.place_not_found:
1165
        pop     edi esi
1165
        pop     edi esi
1166
        jmp     .ret0
1166
        jmp     .ret0
1167
.place_found:
1167
.place_found:
1168
        sub     eax, ebx
1168
        sub     eax, ebx
1169
        jz      @f
1169
        jz      @f
1170
        push    esi
1170
        push    esi
1171
        add     esi, ebx
1171
        add     esi, ebx
1172
        shl     eax, 12
1172
        shl     eax, 12
1173
        or      al, FREE_BLOCK
1173
        or      al, FREE_BLOCK
1174
        mov     [page_tabs+esi*4], eax
1174
        mov     [page_tabs+esi*4], eax
1175
        pop     esi
1175
        pop     esi
1176
@@:
1176
@@:
1177
        mov     eax, ebx
1177
        mov     eax, ebx
1178
        shl     eax, 12
1178
        shl     eax, 12
1179
        or      al, USED_BLOCK
1179
        or      al, USED_BLOCK
1180
        mov     [page_tabs+esi*4], eax
1180
        mov     [page_tabs+esi*4], eax
1181
        inc     esi
1181
        inc     esi
1182
        mov     eax, esi
1182
        mov     eax, esi
1183
        shl     eax, 12
1183
        shl     eax, 12
1184
        push    eax
1184
        push    eax
1185
        mov     eax, [page_tabs+ecx*4]
1185
        mov     eax, [page_tabs+ecx*4]
1186
        and     eax, not 0xFFF
1186
        and     eax, not 0xFFF
1187
        or      al, FREE_BLOCK
1187
        or      al, FREE_BLOCK
1188
        sub     edx, ecx
1188
        sub     edx, ecx
1189
        mov     [page_tabs+ecx*4], eax
1189
        mov     [page_tabs+ecx*4], eax
1190
        inc     ecx
1190
        inc     ecx
1191
        dec     ebx
1191
        dec     ebx
1192
        dec     edx
1192
        dec     edx
1193
        jz      .no
1193
        jz      .no
1194
@@:
1194
@@:
1195
        xor     eax, eax
1195
        xor     eax, eax
1196
        xchg    eax, [page_tabs+ecx*4]
1196
        xchg    eax, [page_tabs+ecx*4]
1197
        mov     [page_tabs+esi*4], eax
1197
        mov     [page_tabs+esi*4], eax
1198
        mov     eax, ecx
1198
        mov     eax, ecx
1199
        shl     eax, 12
1199
        shl     eax, 12
1200
        invlpg  [eax]
1200
        invlpg  [eax]
1201
        inc     esi
1201
        inc     esi
1202
        inc     ecx
1202
        inc     ecx
1203
        dec     ebx
1203
        dec     ebx
1204
        dec     edx
1204
        dec     edx
1205
        jnz     @b
1205
        jnz     @b
1206
.no:
1206
.no:
1207
        push    ebx
1207
        push    ebx
1208
        mov     edx, [current_process]
1208
        mov     edx, [current_process]
1209
        shl     ebx, 12
1209
        shl     ebx, 12
1210
        add     [edx+PROC.mem_used], ebx
1210
        add     [edx+PROC.mem_used], ebx
1211
        pop     ebx
1211
        pop     ebx
1212
@@:
1212
@@:
1213
        mov     dword [page_tabs+esi*4], 2
1213
        mov     dword [page_tabs+esi*4], 2
1214
        inc     esi
1214
        inc     esi
1215
        dec     ebx
1215
        dec     ebx
1216
        jnz     @b
1216
        jnz     @b
1217
 
1217
 
1218
        mov     ecx, [current_process]
1218
        mov     ecx, [current_process]
1219
        lea     ecx, [ecx+PROC.heap_lock]
1219
        lea     ecx, [ecx+PROC.heap_lock]
1220
        call    mutex_unlock
1220
        call    mutex_unlock
1221
        pop     eax edi esi edx ecx
1221
        pop     eax edi esi edx ecx
1222
        ret
1222
        ret
1223
 
1223
 
1224
 
1224
 
1225
 
1225
 
1226
;;;;;;;;;;;;;;      SHARED MEMORY     ;;;;;;;;;;;;;;;;;
1226
;;;;;;;;;;;;;;      SHARED MEMORY     ;;;;;;;;;;;;;;;;;
1227
 
1227
 
1228
 
1228
 
1229
; param
1229
; param
1230
;  eax= shm_map object
1230
;  eax= shm_map object
1231
 
1231
 
1232
align 4
1232
align 4
1233
destroy_smap:
1233
destroy_smap:
1234
 
1234
 
1235
        pushfd
1235
        pushfd
1236
        cli
1236
        cli
1237
 
1237
 
1238
        push    esi
1238
        push    esi
1239
        push    edi
1239
        push    edi
1240
 
1240
 
1241
        mov     edi, eax
1241
        mov     edi, eax
1242
        mov     esi, [eax+SMAP.parent]
1242
        mov     esi, [eax+SMAP.parent]
1243
        test    esi, esi
1243
        test    esi, esi
1244
        jz      .done
1244
        jz      .done
1245
 
1245
 
1246
        lock dec [esi+SMEM.refcount]
1246
        lock dec [esi+SMEM.refcount]
1247
        jnz     .done
1247
        jnz     .done
1248
 
1248
 
1249
        mov     ecx, [esi+SMEM.bk]
1249
        mov     ecx, [esi+SMEM.bk]
1250
        mov     edx, [esi+SMEM.fd]
1250
        mov     edx, [esi+SMEM.fd]
1251
 
1251
 
1252
        mov     [ecx+SMEM.fd], edx
1252
        mov     [ecx+SMEM.fd], edx
1253
        mov     [edx+SMEM.bk], ecx
1253
        mov     [edx+SMEM.bk], ecx
1254
 
1254
 
1255
        stdcall kernel_free, [esi+SMEM.base]
1255
        stdcall kernel_free, [esi+SMEM.base]
1256
        mov     eax, esi
1256
        mov     eax, esi
1257
        call    free
1257
        call    free
1258
.done:
1258
.done:
1259
        mov     eax, edi
1259
        mov     eax, edi
1260
        call    destroy_kernel_object
1260
        call    destroy_kernel_object
1261
 
1261
 
1262
        pop     edi
1262
        pop     edi
1263
        pop     esi
1263
        pop     esi
1264
        popfd
1264
        popfd
1265
 
1265
 
1266
        ret
1266
        ret
1267
 
1267
 
1268
E_NOTFOUND      equ  5
1268
E_NOTFOUND      equ  5
1269
E_ACCESS        equ 10
1269
E_ACCESS        equ 10
1270
E_NOMEM         equ 30
1270
E_NOMEM         equ 30
1271
E_PARAM         equ 33
1271
E_PARAM         equ 33
1272
 
1272
 
1273
SHM_READ        equ 0
1273
SHM_READ        equ 0
1274
SHM_WRITE       equ 1
1274
SHM_WRITE       equ 1
1275
 
1275
 
1276
SHM_ACCESS_MASK equ 3
1276
SHM_ACCESS_MASK equ 3
1277
 
1277
 
1278
SHM_OPEN        equ (0 shl 2)
1278
SHM_OPEN        equ (0 shl 2)
1279
SHM_OPEN_ALWAYS equ (1 shl 2)
1279
SHM_OPEN_ALWAYS equ (1 shl 2)
1280
SHM_CREATE      equ (2 shl 2)
1280
SHM_CREATE      equ (2 shl 2)
1281
 
1281
 
1282
SHM_OPEN_MASK   equ (3 shl 2)
1282
SHM_OPEN_MASK   equ (3 shl 2)
1283
 
1283
 
1284
align 4
1284
align 4
1285
proc shmem_open stdcall name:dword, size:dword, access:dword
1285
proc shmem_open stdcall name:dword, size:dword, access:dword
1286
        locals
1286
        locals
1287
           action         dd ?
1287
           action         dd ?
1288
           owner_access   dd ?
1288
           owner_access   dd ?
1289
           mapped         dd ?
1289
           mapped         dd ?
1290
        endl
1290
        endl
1291
 
1291
 
1292
        push    ebx
1292
        push    ebx
1293
        push    esi
1293
        push    esi
1294
        push    edi
1294
        push    edi
1295
 
1295
 
1296
        mov     [mapped], 0
1296
        mov     [mapped], 0
1297
        mov     [owner_access], 0
1297
        mov     [owner_access], 0
1298
 
1298
 
1299
        pushfd                         ;mutex required
1299
        pushfd                         ;mutex required
1300
        cli
1300
        cli
1301
 
1301
 
1302
        mov     eax, [access]
1302
        mov     eax, [access]
1303
        and     eax, SHM_OPEN_MASK
1303
        and     eax, SHM_OPEN_MASK
1304
        mov     [action], eax
1304
        mov     [action], eax
1305
 
1305
 
1306
        mov     ebx, [name]
1306
        mov     ebx, [name]
1307
        test    ebx, ebx
1307
        test    ebx, ebx
1308
        mov     edx, E_PARAM
1308
        mov     edx, E_PARAM
1309
        jz      .fail
1309
        jz      .fail
1310
 
1310
 
1311
        mov     esi, [shmem_list.fd]
1311
        mov     esi, [shmem_list.fd]
1312
align 4
1312
align 4
1313
@@:
1313
@@:
1314
        cmp     esi, shmem_list
1314
        cmp     esi, shmem_list
1315
        je      .not_found
1315
        je      .not_found
1316
 
1316
 
1317
        lea     edx, [esi+SMEM.name]; link , base, size
1317
        lea     edx, [esi+SMEM.name]; link , base, size
1318
        stdcall strncmp, edx, ebx, 32
1318
        stdcall strncmp, edx, ebx, 32
1319
        test    eax, eax
1319
        test    eax, eax
1320
        je      .found
1320
        je      .found
1321
 
1321
 
1322
        mov     esi, [esi+SMEM.fd]
1322
        mov     esi, [esi+SMEM.fd]
1323
        jmp     @B
1323
        jmp     @B
1324
 
1324
 
1325
.not_found:
1325
.not_found:
1326
        mov     eax, [action]
1326
        mov     eax, [action]
1327
 
1327
 
1328
        cmp     eax, SHM_OPEN
1328
        cmp     eax, SHM_OPEN
1329
        mov     edx, E_NOTFOUND
1329
        mov     edx, E_NOTFOUND
1330
        je      .fail
1330
        je      .fail
1331
 
1331
 
1332
        cmp     eax, SHM_CREATE
1332
        cmp     eax, SHM_CREATE
1333
        mov     edx, E_PARAM
1333
        mov     edx, E_PARAM
1334
        je      .create_shm
1334
        je      .create_shm
1335
 
1335
 
1336
        cmp     eax, SHM_OPEN_ALWAYS
1336
        cmp     eax, SHM_OPEN_ALWAYS
1337
        jne     .fail
1337
        jne     .fail
1338
 
1338
 
1339
.create_shm:
1339
.create_shm:
1340
 
1340
 
1341
        mov     ecx, [size]
1341
        mov     ecx, [size]
1342
        test    ecx, ecx
1342
        test    ecx, ecx
1343
        jz      .fail
1343
        jz      .fail
1344
 
1344
 
1345
        add     ecx, 4095
1345
        add     ecx, 4095
1346
        and     ecx, -4096
1346
        and     ecx, -4096
1347
        mov     [size], ecx
1347
        mov     [size], ecx
1348
 
1348
 
1349
        mov     eax, sizeof.SMEM
1349
        mov     eax, sizeof.SMEM
1350
        call    malloc
1350
        call    malloc
1351
        test    eax, eax
1351
        test    eax, eax
1352
        mov     esi, eax
1352
        mov     esi, eax
1353
        mov     edx, E_NOMEM
1353
        mov     edx, E_NOMEM
1354
        jz      .fail
1354
        jz      .fail
1355
 
1355
 
1356
        stdcall kernel_alloc, [size]
1356
        stdcall kernel_alloc, [size]
1357
        test    eax, eax
1357
        test    eax, eax
1358
        mov     [mapped], eax
1358
        mov     [mapped], eax
1359
        mov     edx, E_NOMEM
1359
        mov     edx, E_NOMEM
1360
        jz      .cleanup
1360
        jz      .cleanup
1361
 
1361
 
1362
        mov     ecx, [size]
1362
        mov     ecx, [size]
1363
        mov     edx, [access]
1363
        mov     edx, [access]
1364
        and     edx, SHM_ACCESS_MASK
1364
        and     edx, SHM_ACCESS_MASK
1365
 
1365
 
1366
        mov     [esi+SMEM.base], eax
1366
        mov     [esi+SMEM.base], eax
1367
        mov     [esi+SMEM.size], ecx
1367
        mov     [esi+SMEM.size], ecx
1368
        mov     [esi+SMEM.access], edx
1368
        mov     [esi+SMEM.access], edx
1369
        mov     [esi+SMEM.refcount], 0
1369
        mov     [esi+SMEM.refcount], 0
1370
        mov     [esi+SMEM.name+28], 0
1370
        mov     [esi+SMEM.name+28], 0
1371
 
1371
 
1372
        lea     eax, [esi+SMEM.name]
1372
        lea     eax, [esi+SMEM.name]
1373
        stdcall strncpy, eax, [name], 31
1373
        stdcall strncpy, eax, [name], 31
1374
 
1374
 
1375
        mov     eax, [shmem_list.fd]
1375
        mov     eax, [shmem_list.fd]
1376
        mov     [esi+SMEM.bk], shmem_list
1376
        mov     [esi+SMEM.bk], shmem_list
1377
        mov     [esi+SMEM.fd], eax
1377
        mov     [esi+SMEM.fd], eax
1378
 
1378
 
1379
        mov     [eax+SMEM.bk], esi
1379
        mov     [eax+SMEM.bk], esi
1380
        mov     [shmem_list.fd], esi
1380
        mov     [shmem_list.fd], esi
1381
 
1381
 
1382
        mov     [action], SHM_OPEN
1382
        mov     [action], SHM_OPEN
1383
        mov     [owner_access], SHM_WRITE
1383
        mov     [owner_access], SHM_WRITE
1384
 
1384
 
1385
.found:
1385
.found:
1386
        mov     eax, [action]
1386
        mov     eax, [action]
1387
 
1387
 
1388
        cmp     eax, SHM_CREATE
1388
        cmp     eax, SHM_CREATE
1389
        mov     edx, E_ACCESS
1389
        mov     edx, E_ACCESS
1390
        je      .exit
1390
        je      .exit
1391
 
1391
 
1392
        cmp     eax, SHM_OPEN
1392
        cmp     eax, SHM_OPEN
1393
        mov     edx, E_PARAM
1393
        mov     edx, E_PARAM
1394
        je      .create_map
1394
        je      .create_map
1395
 
1395
 
1396
        cmp     eax, SHM_OPEN_ALWAYS
1396
        cmp     eax, SHM_OPEN_ALWAYS
1397
        jne     .fail
1397
        jne     .fail
1398
 
1398
 
1399
.create_map:
1399
.create_map:
1400
 
1400
 
1401
        mov     eax, [access]
1401
        mov     eax, [access]
1402
        and     eax, SHM_ACCESS_MASK
1402
        and     eax, SHM_ACCESS_MASK
1403
        cmp     eax, [esi+SMEM.access]
1403
        cmp     eax, [esi+SMEM.access]
1404
        mov     [access], eax
1404
        mov     [access], eax
1405
        mov     edx, E_ACCESS
1405
        mov     edx, E_ACCESS
1406
        ja      .fail
1406
        ja      .fail
1407
 
1407
 
1408
        mov     ebx, [CURRENT_TASK]
1408
        mov     ebx, [CURRENT_TASK]
1409
        shl     ebx, 5
1409
        shl     ebx, 5
1410
        mov     ebx, [CURRENT_TASK+ebx+4]
1410
        mov     ebx, [CURRENT_TASK+ebx+4]
1411
        mov     eax, sizeof.SMAP
1411
        mov     eax, sizeof.SMAP
1412
 
1412
 
1413
        call    create_kernel_object
1413
        call    create_kernel_object
1414
        test    eax, eax
1414
        test    eax, eax
1415
        mov     edi, eax
1415
        mov     edi, eax
1416
        mov     edx, E_NOMEM
1416
        mov     edx, E_NOMEM
1417
        jz      .fail
1417
        jz      .fail
1418
 
1418
 
1419
        inc     [esi+SMEM.refcount]
1419
        inc     [esi+SMEM.refcount]
1420
 
1420
 
1421
        mov     [edi+SMAP.magic], 'SMAP'
1421
        mov     [edi+SMAP.magic], 'SMAP'
1422
        mov     [edi+SMAP.destroy], destroy_smap
1422
        mov     [edi+SMAP.destroy], destroy_smap
1423
        mov     [edi+SMAP.parent], esi
1423
        mov     [edi+SMAP.parent], esi
1424
        mov     [edi+SMAP.base], 0
1424
        mov     [edi+SMAP.base], 0
1425
 
1425
 
1426
        stdcall user_alloc, [esi+SMEM.size]
1426
        stdcall user_alloc, [esi+SMEM.size]
1427
        test    eax, eax
1427
        test    eax, eax
1428
        mov     [mapped], eax
1428
        mov     [mapped], eax
1429
        mov     edx, E_NOMEM
1429
        mov     edx, E_NOMEM
1430
        jz      .cleanup2
1430
        jz      .cleanup2
1431
 
1431
 
1432
        mov     [edi+SMAP.base], eax
1432
        mov     [edi+SMAP.base], eax
1433
 
1433
 
1434
        mov     ecx, [esi+SMEM.size]
1434
        mov     ecx, [esi+SMEM.size]
1435
        mov     [size], ecx
1435
        mov     [size], ecx
1436
 
1436
 
1437
        shr     ecx, 12
1437
        shr     ecx, 12
1438
        shr     eax, 10
1438
        shr     eax, 10
1439
 
1439
 
1440
        mov     esi, [esi+SMEM.base]
1440
        mov     esi, [esi+SMEM.base]
1441
        shr     esi, 10
1441
        shr     esi, 10
1442
        lea     edi, [page_tabs+eax]
1442
        lea     edi, [page_tabs+eax]
1443
        add     esi, page_tabs
1443
        add     esi, page_tabs
1444
 
1444
 
1445
        mov     edx, [access]
1445
        mov     edx, [access]
1446
        or      edx, [owner_access]
1446
        or      edx, [owner_access]
1447
        shl     edx, 1
1447
        shl     edx, 1
1448
        or      edx, PG_SHARED+PG_UR
1448
        or      edx, PG_SHARED+PG_UR
1449
@@:
1449
@@:
1450
        lodsd
1450
        lodsd
1451
        and     eax, 0xFFFFF000
1451
        and     eax, 0xFFFFF000
1452
        or      eax, edx
1452
        or      eax, edx
1453
        stosd
1453
        stosd
1454
        loop    @B
1454
        loop    @B
1455
 
1455
 
1456
        xor     edx, edx
1456
        xor     edx, edx
1457
 
1457
 
1458
        cmp     [owner_access], 0
1458
        cmp     [owner_access], 0
1459
        jne     .fail
1459
        jne     .fail
1460
.exit:
1460
.exit:
1461
        mov     edx, [size]
1461
        mov     edx, [size]
1462
.fail:
1462
.fail:
1463
        mov     eax, [mapped]
1463
        mov     eax, [mapped]
1464
 
1464
 
1465
        popfd
1465
        popfd
1466
        pop     edi
1466
        pop     edi
1467
        pop     esi
1467
        pop     esi
1468
        pop     ebx
1468
        pop     ebx
1469
        ret
1469
        ret
1470
.cleanup:
1470
.cleanup:
1471
        mov     [size], edx
1471
        mov     [size], edx
1472
        mov     eax, esi
1472
        mov     eax, esi
1473
        call    free
1473
        call    free
1474
        jmp     .exit
1474
        jmp     .exit
1475
 
1475
 
1476
.cleanup2:
1476
.cleanup2:
1477
        mov     [size], edx
1477
        mov     [size], edx
1478
        mov     eax, edi
1478
        mov     eax, edi
1479
        call    destroy_smap
1479
        call    destroy_smap
1480
        jmp     .exit
1480
        jmp     .exit
1481
endp
1481
endp
1482
 
1482
 
1483
align 4
1483
align 4
1484
proc shmem_close stdcall, name:dword
1484
proc shmem_close stdcall, name:dword
1485
 
1485
 
1486
        mov     eax, [name]
1486
        mov     eax, [name]
1487
        test    eax, eax
1487
        test    eax, eax
1488
        jz      .fail
1488
        jz      .fail
1489
 
1489
 
1490
        push    esi
1490
        push    esi
1491
        push    edi
1491
        push    edi
1492
        pushfd
1492
        pushfd
1493
        cli
1493
        cli
1494
 
1494
 
1495
        mov     esi, [current_slot]
1495
        mov     esi, [current_slot]
1496
        add     esi, APP_OBJ_OFFSET
1496
        add     esi, APP_OBJ_OFFSET
1497
.next:
1497
.next:
1498
        mov     eax, [esi+APPOBJ.fd]
1498
        mov     eax, [esi+APPOBJ.fd]
1499
        test    eax, eax
1499
        test    eax, eax
1500
        jz      @F
1500
        jz      @F
1501
 
1501
 
1502
        cmp     eax, esi
1502
        cmp     eax, esi
1503
        mov     esi, eax
1503
        mov     esi, eax
1504
        je      @F
1504
        je      @F
1505
 
1505
 
1506
        cmp     [eax+SMAP.magic], 'SMAP'
1506
        cmp     [eax+SMAP.magic], 'SMAP'
1507
        jne     .next
1507
        jne     .next
1508
 
1508
 
1509
        mov     edi, [eax+SMAP.parent]
1509
        mov     edi, [eax+SMAP.parent]
1510
        test    edi, edi
1510
        test    edi, edi
1511
        jz      .next
1511
        jz      .next
1512
 
1512
 
1513
        lea     edi, [edi+SMEM.name]
1513
        lea     edi, [edi+SMEM.name]
1514
        stdcall strncmp, [name], edi, 32
1514
        stdcall strncmp, [name], edi, 32
1515
        test    eax, eax
1515
        test    eax, eax
1516
        jne     .next
1516
        jne     .next
1517
 
1517
 
1518
        stdcall user_free, [esi+SMAP.base]
1518
        stdcall user_free, [esi+SMAP.base]
1519
 
1519
 
1520
        mov     eax, esi
1520
        mov     eax, esi
1521
        call    [esi+APPOBJ.destroy]
1521
        call    [esi+APPOBJ.destroy]
1522
@@:
1522
@@:
1523
        popfd
1523
        popfd
1524
        pop     edi
1524
        pop     edi
1525
        pop     esi
1525
        pop     esi
1526
.fail:
1526
.fail:
1527
        ret
1527
        ret
1528
endp
1528
endp