Rev 886 | Rev 889 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
859 | serge | 1 | |
2 | #include |
||
3 | #include |
||
4 | #include |
||
5 | #include |
||
6 | #include |
||
7 | |||
8 | |||
888 | serge | 9 | |
10 | |||
859 | serge | 11 | { |
12 | link_t link; |
||
13 | link_t adj; |
||
14 | addr_t base; |
||
15 | size_t size; |
||
16 | void *parent; |
||
888 | serge | 17 | u32_t state; |
886 | serge | 18 | }md_t; |
859 | serge | 19 | |
20 | |||
886 | serge | 21 | #define MD_USED 2 |
22 | |||
23 | |||
859 | serge | 24 | u32_t av_mapped; |
888 | serge | 25 | u32_t av_unmapped; |
26 | |||
859 | serge | 27 | |
888 | serge | 28 | link_t unmapped[32]; |
29 | |||
886 | serge | 30 | |
31 | |||
888 | serge | 32 | |
33 | }heap_t; |
||
859 | serge | 34 | |
35 | |||
886 | serge | 36 | |
859 | serge | 37 | slab_cache_t *phm_slab; |
38 | |||
39 | |||
40 | |||
886 | serge | 41 | heap_t sheap; |
42 | |||
43 | |||
44 | |||
888 | serge | 45 | { asm volatile ("bts %0, _lheap+4"::"r"(idx):"cc"); } |
46 | |||
886 | serge | 47 | |
888 | serge | 48 | { asm volatile ("btr %0, _lheap+4"::"r"(idx):"cc"); } |
49 | |||
859 | serge | 50 | |
888 | serge | 51 | { asm volatile ("bts %0, _sheap"::"r"(idx):"cc"); } |
886 | serge | 52 | |
859 | serge | 53 | |
888 | serge | 54 | { asm volatile ("btr %0, _sheap"::"r"(idx):"cc"); } |
886 | serge | 55 | |
859 | serge | 56 | |
888 | serge | 57 | { asm volatile ("bts %0, _sheap+4"::"r"(idx):"cc"); } |
58 | |||
859 | serge | 59 | |
888 | serge | 60 | { asm volatile ("btr %0, _sheap+4"::"r"(idx):"cc"); } |
61 | |||
62 | |||
63 | |||
859 | serge | 64 | { |
65 | md_t *md; |
||
66 | u32_t i; |
||
67 | |||
68 | |||
69 | ASSERT(size != 0) |
||
70 | ASSERT((base & 0x3FFFFF) == 0); |
||
862 | serge | 71 | ASSERT((size & 0x3FFFFF) == 0); |
72 | |||
859 | serge | 73 | |
74 | { |
||
75 | list_initialize(&lheap.mapped[i]); |
||
888 | serge | 76 | list_initialize(&lheap.unmapped[i]); |
77 | |||
78 | |||
79 | list_initialize(&sheap.unmapped[i]); |
||
80 | }; |
||
859 | serge | 81 | |
82 | |||
886 | serge | 83 | list_initialize(&sheap.used); |
84 | |||
85 | |||
86 | |||
859 | serge | 87 | |
88 | |||
89 | |||
90 | |||
91 | md->base = base; |
||
92 | md->size = size; |
||
93 | md->parent = NULL; |
||
94 | md->state = MD_FREE; |
||
886 | serge | 95 | |
859 | serge | 96 | |
888 | serge | 97 | lheap.av_mapped = 0x00000000; |
98 | lheap.av_unmapped = 0x80000000; |
||
99 | sheap.av_mapped = 0x00000000; |
||
100 | sheap.av_unmapped = 0x00000000; |
||
101 | |||
859 | serge | 102 | |
103 | }; |
||
104 | |||
105 | |||
106 | { |
||
107 | md_t *md = NULL; |
||
108 | |||
109 | |||
110 | u32_t mask; |
||
111 | |||
112 | |||
862 | serge | 113 | |
859 | serge | 114 | |
115 | mask = lheap.av_unmapped & ( -1< |
||
888 | serge | 116 | |
859 | serge | 117 | |
118 | { |
||
119 | if(idx0 == 31) |
||
862 | serge | 120 | { |
121 | md_t *tmp = (md_t*)lheap.unmapped[31].next; |
||
888 | serge | 122 | while((link_t*)tmp != &lheap.unmapped[31]) |
123 | { |
||
862 | serge | 124 | if(tmp->size >= size) |
125 | { |
||
126 | DBG("remove large tmp %x\n", tmp); |
||
127 | |||
859 | serge | 128 | |
862 | serge | 129 | break; |
130 | }; |
||
131 | }; |
||
132 | tmp = (md_t*)tmp->link.next; |
||
133 | } |
||
134 | else |
||
135 | { |
||
136 | idx0 = _bsf(mask); |
||
137 | |||
859 | serge | 138 | |
888 | serge | 139 | |
862 | serge | 140 | |
888 | serge | 141 | }; |
862 | serge | 142 | } |
859 | serge | 143 | else |
144 | return NULL; |
||
145 | |||
146 | |||
886 | serge | 147 | |
148 | |||
859 | serge | 149 | if(list_empty(&lheap.unmapped[idx0])) |
888 | serge | 150 | _reset_lavu(idx0); |
151 | |||
859 | serge | 152 | |
153 | { |
||
154 | count_t idx1; |
||
155 | md_t *new_md = (md_t*)slab_alloc(md_slab,0); /* FIXME check */ |
||
886 | serge | 156 | |
859 | serge | 157 | |
158 | list_insert(&new_md->adj, &md->adj); |
||
861 | serge | 159 | |
859 | serge | 160 | |
161 | new_md->size = size; |
||
162 | new_md->parent = NULL; |
||
888 | serge | 163 | new_md->state = MD_USED; |
886 | serge | 164 | |
859 | serge | 165 | |
166 | md->size-= size; |
||
167 | |||
168 | |||
169 | |||
170 | |||
888 | serge | 171 | _set_lavu(idx1); |
172 | |||
859 | serge | 173 | |
174 | }; |
||
886 | serge | 175 | md->state = MD_USED; |
176 | |||
177 | |||
859 | serge | 178 | } |
179 | |||
180 | |||
888 | serge | 181 | { |
859 | serge | 182 | eflags_t efl; |
886 | serge | 183 | |
859 | serge | 184 | |
886 | serge | 185 | |
859 | serge | 186 | |
886 | serge | 187 | u32_t mask; |
188 | |||
859 | serge | 189 | |
886 | serge | 190 | |
859 | serge | 191 | |
886 | serge | 192 | |
859 | serge | 193 | |
886 | serge | 194 | mask = sheap.av_unmapped & ( -1< |
888 | serge | 195 | |
859 | serge | 196 | |
888 | serge | 197 | |
861 | serge | 198 | |
886 | serge | 199 | { |
200 | if(idx0 == 31) |
||
201 | { |
||
862 | serge | 202 | ASSERT( !list_empty(&sheap.unmapped[31])); |
888 | serge | 203 | |
886 | serge | 204 | |
888 | serge | 205 | while((link_t*)tmp != &sheap.unmapped[31]) |
206 | { |
||
886 | serge | 207 | if(tmp->size >= size) |
208 | { |
||
209 | md = tmp; |
||
210 | break; |
||
211 | }; |
||
212 | tmp = (md_t*)tmp->link.next; |
||
213 | }; |
||
214 | } |
||
215 | else |
||
216 | { |
||
217 | idx0 = _bsf(mask); |
||
218 | |||
219 | |||
888 | serge | 220 | |
886 | serge | 221 | |
888 | serge | 222 | } |
886 | serge | 223 | }; |
224 | |||
225 | |||
226 | { |
||
227 | DBG("remove md %x\n", md); |
||
228 | |||
229 | |||
230 | ASSERT(md->parent != NULL); |
||
888 | serge | 231 | |
886 | serge | 232 | |
233 | if(list_empty(&sheap.unmapped[idx0])) |
||
888 | serge | 234 | _reset_savu(idx0); |
235 | } |
||
886 | serge | 236 | else |
237 | { |
||
238 | md_t *lmd; |
||
239 | lmd = find_large_md((size+0x3FFFFF)&~0x3FFFFF); |
||
240 | |||
241 | |||
242 | |||
243 | |||
244 | { |
||
245 | safe_sti(efl); |
||
246 | return NULL; |
||
247 | }; |
||
862 | serge | 248 | |
861 | serge | 249 | |
888 | serge | 250 | ASSERT(lmd->base != 0); |
251 | ASSERT((lmd->base & 0x3FFFFF) == 0); |
||
252 | ASSERT(lmd->parent == NULL); |
||
253 | |||
254 | |||
886 | serge | 255 | |
862 | serge | 256 | |
886 | serge | 257 | list_initialize(&md->adj); |
258 | md->base = lmd->base; |
||
259 | md->size = lmd->size; |
||
260 | md->parent = lmd; |
||
261 | md->state = MD_USED; |
||
262 | }; |
||
263 | |||
862 | serge | 264 | |
886 | serge | 265 | { |
266 | count_t idx1; |
||
267 | md_t *new_md = (md_t*)slab_alloc(md_slab,0); /* FIXME check */ |
||
268 | |||
862 | serge | 269 | |
886 | serge | 270 | list_insert(&new_md->adj, &md->adj); |
271 | |||
859 | serge | 272 | |
886 | serge | 273 | new_md->size = size; |
274 | new_md->parent = md->parent; |
||
275 | new_md->state = MD_USED; |
||
276 | |||
859 | serge | 277 | |
886 | serge | 278 | md->size-= size; |
279 | md->state = MD_FREE; |
||
280 | |||
859 | serge | 281 | |
886 | serge | 282 | |
859 | serge | 283 | |
886 | serge | 284 | |
859 | serge | 285 | |
886 | serge | 286 | list_prepend(&md->link, &sheap.unmapped[idx1]); |
888 | serge | 287 | else |
886 | serge | 288 | { |
289 | if( list_empty(&sheap.unmapped[31])) |
||
888 | serge | 290 | list_prepend(&md->link, &sheap.unmapped[31]); |
291 | else |
||
886 | serge | 292 | { |
293 | md_t *tmp = (md_t*)sheap.unmapped[31].next; |
||
888 | serge | 294 | |
859 | serge | 295 | |
888 | serge | 296 | { |
886 | serge | 297 | if(md->base < tmp->base) |
298 | break; |
||
299 | tmp = (md_t*)tmp->link.next; |
||
300 | } |
||
301 | list_insert(&md->link, &tmp->link); |
||
302 | }; |
||
303 | }; |
||
304 | |||
859 | serge | 305 | |
888 | serge | 306 | |
861 | serge | 307 | |
886 | serge | 308 | |
861 | serge | 309 | |
886 | serge | 310 | }; |
311 | |||
861 | serge | 312 | |
886 | serge | 313 | |
859 | serge | 314 | |
886 | serge | 315 | |
859 | serge | 316 | |
886 | serge | 317 | } |
859 | serge | 318 | |
319 | |||
888 | serge | 320 | { |
886 | serge | 321 | eflags_t efl; |
888 | serge | 322 | |
323 | |||
324 | |||
325 | |||
326 | u32_t mask; |
||
327 | |||
328 | |||
329 | |||
330 | |||
331 | |||
332 | |||
333 | mask = sheap.av_mapped & ( -1< |
||
334 | |||
335 | |||
336 | idx0, mask); |
||
337 | |||
338 | |||
339 | { |
||
340 | if(idx0 == 31) |
||
341 | { |
||
342 | ASSERT( !list_empty(&sheap.mapped[31])); |
||
343 | |||
344 | |||
345 | while((link_t*)tmp != &sheap.mapped[31]) |
||
346 | { |
||
347 | if(tmp->size >= size) |
||
348 | { |
||
349 | md = tmp; |
||
350 | break; |
||
351 | }; |
||
352 | tmp = (md_t*)tmp->link.next; |
||
353 | }; |
||
354 | } |
||
355 | else |
||
356 | { |
||
357 | idx0 = _bsf(mask); |
||
358 | |||
359 | |||
360 | |||
361 | |||
362 | } |
||
363 | }; |
||
364 | |||
365 | |||
366 | { |
||
367 | DBG("remove md %x\n", md); |
||
368 | |||
369 | |||
370 | |||
371 | |||
372 | if(list_empty(&sheap.mapped[idx0])) |
||
373 | _reset_savm(idx0); |
||
374 | } |
||
375 | else |
||
376 | { |
||
377 | md_t *lmd; |
||
378 | addr_t frame; |
||
379 | addr_t *pte; |
||
380 | int i; |
||
381 | |||
382 | |||
383 | |||
384 | |||
385 | |||
386 | |||
387 | { |
||
388 | safe_sti(efl); |
||
389 | return NULL; |
||
390 | }; |
||
391 | |||
392 | |||
393 | ASSERT(lmd->base != 0); |
||
394 | ASSERT((lmd->base & 0x3FFFFF) == 0); |
||
395 | ASSERT(lmd->parent == NULL); |
||
396 | |||
397 | |||
398 | |||
399 | |||
400 | |||
401 | |||
402 | |||
403 | |||
404 | { |
||
405 | *pte++ = frame; |
||
406 | frame+= 4096; |
||
407 | } |
||
408 | |||
409 | |||
410 | |||
411 | |||
412 | list_initialize(&md->adj); |
||
413 | md->base = lmd->base; |
||
414 | md->size = lmd->size; |
||
415 | md->parent = lmd; |
||
416 | md->state = MD_USED; |
||
417 | }; |
||
418 | |||
419 | |||
420 | { |
||
421 | count_t idx1; |
||
422 | md_t *new_md = (md_t*)slab_alloc(md_slab,0); /* FIXME check */ |
||
423 | |||
424 | |||
425 | list_insert(&new_md->adj, &md->adj); |
||
426 | |||
427 | |||
428 | new_md->size = size; |
||
429 | new_md->parent = md->parent; |
||
430 | |||
431 | |||
432 | md->size-= size; |
||
433 | md->state = MD_FREE; |
||
434 | |||
435 | |||
436 | |||
437 | |||
438 | |||
439 | |||
440 | list_prepend(&md->link, &sheap.mapped[idx1]); |
||
441 | else |
||
442 | { |
||
443 | if( list_empty(&sheap.mapped[31])) |
||
444 | list_prepend(&md->link, &sheap.mapped[31]); |
||
445 | else |
||
446 | { |
||
447 | md_t *tmp = (md_t*)sheap.mapped[31].next; |
||
448 | |||
449 | |||
450 | { |
||
451 | if(md->base < tmp->base) |
||
452 | break; |
||
453 | tmp = (md_t*)tmp->link.next; |
||
454 | } |
||
455 | list_insert(&md->link, &tmp->link); |
||
456 | }; |
||
457 | }; |
||
458 | |||
459 | |||
460 | |||
461 | |||
462 | }; |
||
463 | |||
464 | |||
465 | |||
466 | |||
467 | |||
468 | |||
469 | } |
||
470 | |||
471 | |||
472 | { |
||
473 | eflags_t efl ; |
||
886 | serge | 474 | md_t *fd; |
475 | md_t *bk; |
||
476 | count_t idx; |
||
477 | |||
478 | |||
888 | serge | 479 | |
480 | |||
886 | serge | 481 | spinlock_lock(&sheap.lock); |
482 | |||
483 | |||
484 | { |
||
485 | bk = (md_t*)md->adj.prev; |
||
486 | fd = (md_t*)md->adj.next; |
||
487 | |||
488 | |||
489 | { |
||
490 | idx = (fd->size>>12) - 1 < 32 ? (fd->size>>12) - 1 : 31; |
||
491 | |||
492 | |||
493 | if(list_empty(&sheap.unmapped[idx])) |
||
888 | serge | 494 | _reset_savu(idx); |
495 | |||
886 | serge | 496 | |
497 | md->adj.next = fd->adj.next; |
||
498 | md->adj.next->prev = (link_t*)md; |
||
499 | slab_free(md_slab, fd); |
||
500 | }; |
||
501 | if(bk->state == MD_FREE) |
||
502 | { |
||
503 | idx = (bk->size>>12) - 1 < 32 ? (bk->size>>12) - 1 : 31; |
||
504 | |||
505 | |||
506 | if(list_empty(&sheap.unmapped[idx])) |
||
888 | serge | 507 | _reset_savu(idx); |
508 | |||
886 | serge | 509 | |
510 | bk->adj.next = md->adj.next; |
||
511 | bk->adj.next->prev = (link_t*)bk; |
||
512 | slab_free(md_slab, md); |
||
513 | md = fd; |
||
514 | }; |
||
515 | }; |
||
516 | |||
517 | |||
518 | |||
519 | |||
520 | |||
521 | |||
888 | serge | 522 | |
886 | serge | 523 | |
524 | list_prepend(&md->link, &sheap.unmapped[idx]); |
||
888 | serge | 525 | else |
886 | serge | 526 | { |
527 | if( list_empty(&sheap.unmapped[31])) |
||
888 | serge | 528 | list_prepend(&md->link, &sheap.unmapped[31]); |
529 | else |
||
886 | serge | 530 | { |
531 | md_t *tmp = (md_t*)sheap.unmapped[31].next; |
||
888 | serge | 532 | |
886 | serge | 533 | |
888 | serge | 534 | { |
886 | serge | 535 | if(md->base < tmp->base) |
536 | break; |
||
537 | tmp = (md_t*)tmp->link.next; |
||
538 | } |
||
539 | list_insert(&md->link, &tmp->link); |
||
540 | }; |
||
541 | }; |
||
542 | spinlock_unlock(&sheap.lock); |
||
543 | safe_sti(efl); |
||
544 | |||
545 | |||
546 | |||
547 | |||
888 | serge | 548 | { |
549 | eflags_t efl ; |
||
550 | md_t *fd; |
||
551 | md_t *bk; |
||
552 | count_t idx; |
||
553 | |||
886 | serge | 554 | |
888 | serge | 555 | ASSERT( ((md_t*)(md->parent))->parent != NULL); |
556 | |||
886 | serge | 557 | |
888 | serge | 558 | spinlock_lock(&sheap.lock); |
559 | |||
859 | serge | 560 | |
888 | serge | 561 | { |
562 | bk = (md_t*)md->adj.prev; |
||
563 | fd = (md_t*)md->adj.next; |
||
564 | |||
565 | |||
566 | { |
||
859 | serge | 567 | idx = (fd->size>>12) - 1 < 32 ? (fd->size>>12) - 1 : 31; |
888 | serge | 568 | |
859 | serge | 569 | |
888 | serge | 570 | if(list_empty(&sheap.mapped[idx])) |
571 | _reset_savm(idx); |
||
572 | |||
859 | serge | 573 | |
888 | serge | 574 | md->adj.next = fd->adj.next; |
575 | md->adj.next->prev = (link_t*)md; |
||
576 | slab_free(md_slab, fd); |
||
577 | }; |
||
578 | if(bk->state == MD_FREE) |
||
579 | { |
||
580 | idx = (bk->size>>12) - 1 < 32 ? (bk->size>>12) - 1 : 31; |
||
581 | |||
859 | serge | 582 | |
888 | serge | 583 | if(list_empty(&sheap.mapped[idx])) |
584 | _reset_savm(idx); |
||
585 | |||
586 | |||
587 | bk->adj.next = md->adj.next; |
||
588 | bk->adj.next->prev = (link_t*)bk; |
||
589 | slab_free(md_slab, md); |
||
590 | md = fd; |
||
591 | }; |
||
592 | }; |
||
859 | serge | 593 | |
594 | |||
888 | serge | 595 | |
859 | serge | 596 | |
888 | serge | 597 | |
859 | serge | 598 | |
888 | serge | 599 | |
859 | serge | 600 | |
888 | serge | 601 | list_prepend(&md->link, &sheap.mapped[idx]); |
602 | else |
||
603 | { |
||
604 | if( list_empty(&sheap.mapped[31])) |
||
605 | list_prepend(&md->link, &sheap.mapped[31]); |
||
606 | else |
||
607 | { |
||
859 | serge | 608 | md_t *tmp = (md_t*)sheap.mapped[31].next; |
888 | serge | 609 | |
859 | serge | 610 | |
888 | serge | 611 | { |
859 | serge | 612 | if(md->base < tmp->base) |
888 | serge | 613 | break; |
614 | tmp = (md_t*)tmp->link.next; |
||
615 | } |
||
859 | serge | 616 | list_insert(&md->link, &tmp->link); |
888 | serge | 617 | }; |
618 | }; |
||
619 | spinlock_unlock(&sheap.lock); |
||
620 | safe_sti(efl); |
||
621 | }; |
||
859 | serge | 622 | |
623 | |||
888 | serge | 624 | |
886 | serge | 625 | { |
859 | serge | 626 | eflags_t efl; |
886 | serge | 627 | |
859 | serge | 628 | |
886 | serge | 629 | |
859 | serge | 630 | |
886 | serge | 631 | |
632 | |||
633 | |||
634 | |||
635 | |||
636 | |||
888 | serge | 637 | { |
886 | serge | 638 | md = find_mapped_md(size); |
888 | serge | 639 | |
886 | serge | 640 | |
888 | serge | 641 | return NULL; |
642 | |||
886 | serge | 643 | |
888 | serge | 644 | |
886 | serge | 645 | |
888 | serge | 646 | ASSERT( lmd->parent != NULL); |
647 | |||
886 | serge | 648 | |
888 | serge | 649 | (flags & 0xFFF); |
650 | DBG("frame %x\n", frame); |
||
651 | ASSERT(frame != 0); |
||
652 | |||
886 | serge | 653 | |
888 | serge | 654 | addr_t *pte = &((addr_t*)page_tabs)[md->base>>12]; |
655 | |||
656 | |||
657 | { |
||
886 | serge | 658 | *pte++ = frame; |
659 | frame+= 4096; |
||
660 | }; |
||
661 | } |
||
888 | serge | 662 | else |
663 | md = find_unmapped_md(size); |
||
664 | |||
886 | serge | 665 | |
888 | serge | 666 | return NULL; |
667 | |||
668 | |||
669 | ASSERT(md->state == MD_USED); |
||
670 | |||
671 | |||
672 | |||
886 | serge | 673 | spinlock_lock(&sheap.lock); |
674 | |||
675 | |||
676 | list_prepend(&md->link, &sheap.used); |
||
677 | else |
||
678 | { |
||
679 | md_t *tmp = (md_t*)sheap.used.next; |
||
680 | |||
681 | |||
682 | { |
||
683 | if(md->base < tmp->base) |
||
684 | break; |
||
685 | tmp = (md_t*)tmp->link.next; |
||
686 | } |
||
687 | list_insert(&md->link, &tmp->link); |
||
688 | }; |
||
689 | |||
690 | |||
691 | safe_sti(efl); |
||
692 | |||
693 | |||
694 | return (void*)md->base; |
||
695 | }; |
||
859 | serge | 696 | |
697 | |||
886 | serge | 698 | { |
859 | serge | 699 | eflags_t efl; |
886 | serge | 700 | |
859 | serge | 701 | |
886 | serge | 702 | md_t *md = NULL; |
703 | |||
859 | serge | 704 | |
886 | serge | 705 | |
861 | serge | 706 | |
886 | serge | 707 | ASSERT( ((addr_t)mem & 0xFFF) == 0 ); |
708 | ASSERT( ! list_empty(&sheap.used)); |
||
709 | |||
862 | serge | 710 | |
886 | serge | 711 | |
864 | serge | 712 | |
886 | serge | 713 | |
864 | serge | 714 | |
886 | serge | 715 | { |
716 | if( tmp->base == (addr_t)mem ) |
||
717 | { |
||
718 | md = tmp; |
||
719 | break; |
||
720 | }; |
||
721 | tmp = (md_t*)tmp->link.next; |
||
722 | } |
||
723 | |||
864 | serge | 724 | |
886 | serge | 725 | { |
726 | md_t *lmd; |
||
888 | serge | 727 | |
728 | |||
886 | serge | 729 | |
859 | serge | 730 | |
886 | serge | 731 | |
864 | serge | 732 | |
888 | serge | 733 | |
734 | |||
735 | |||
736 | |||
737 | |||
738 | |||
739 | { |
||
740 | count_t tmp = md->size >> 12; |
||
886 | serge | 741 | addr_t *pte = &((addr_t*)page_tabs)[md->base>>12]; |
742 | |||
743 | |||
744 | { |
||
745 | *pte++ = 0; |
||
746 | asm volatile ( |
||
747 | "invlpg (%0)" |
||
748 | ::"r" (mem) ); |
||
888 | serge | 749 | mem+= 4096; |
886 | serge | 750 | }; |
751 | |||
888 | serge | 752 | |
753 | } |
||
754 | else |
||
755 | free_unmapped_md( md ); |
||
756 | } |
||
886 | serge | 757 | else |
758 | DBG("\tERROR: invalid base address: %x\n", mem); |
||
759 | |||
760 | |||
761 | };>>>>>>>>>>>>>>1024;> |
||
762 |