|
12 | 12 | #include <init_hook.h> |
13 | 13 | #include <kip.h> |
14 | 14 | #include <platform/cortex_m.h> |
| 15 | +#include <platform/irq.h> |
15 | 16 |
|
16 | 17 | /** |
17 | 18 | * @file memory.c |
@@ -378,31 +379,79 @@ as_t *as_create(uint32_t as_spaceid) |
378 | 379 |
|
379 | 380 | as->as_spaceid = as_spaceid; |
380 | 381 | as->first = NULL; |
381 | | - as->shared = 0; |
| 382 | + as->mpu_first = NULL; |
| 383 | + as->mpu_stack_first = NULL; |
| 384 | + as->shared = 1; /* Creator holds initial reference */ |
382 | 385 |
|
383 | 386 | return as; |
384 | 387 | } |
385 | 388 |
|
386 | | -void as_destroy(as_t *as) |
| 389 | +/* |
| 390 | + * Increment address space reference count. |
| 391 | + * Called when a thread shares an existing address space. |
| 392 | + */ |
| 393 | +void as_get(as_t *as) |
387 | 394 | { |
388 | | - fpage_t *fp, *fpnext; |
389 | | - fp = as->first; |
| 395 | + uint32_t flags; |
390 | 396 |
|
391 | | - if (as->shared > 0) { |
392 | | - --as->shared; |
| 397 | + if (!as) |
393 | 398 | return; |
| 399 | + |
| 400 | + flags = irq_save_flags(); |
| 401 | + as->shared++; |
| 402 | + irq_restore_flags(flags); |
| 403 | +} |
| 404 | + |
| 405 | +/* |
| 406 | + * Decrement address space reference count. |
| 407 | + * Frees the address space when refcount reaches 0. |
| 408 | + * IRQs remain disabled through as_destroy() to prevent reentrancy. |
| 409 | + */ |
| 410 | +void as_put(as_t *as) |
| 411 | +{ |
| 412 | + uint32_t flags; |
| 413 | + |
| 414 | + if (!as) |
| 415 | + return; |
| 416 | + |
| 417 | + flags = irq_save_flags(); |
| 418 | + |
| 419 | + /* Guard against refcount underflow (double-put bug) */ |
| 420 | + if (as->shared == 0) { |
| 421 | + irq_restore_flags(flags); |
| 422 | + dbg_printf(DL_KDB, "AS: refcount underflow for %p\n", |
| 423 | + as->as_spaceid); |
| 424 | + return; |
| 425 | + } |
| 426 | + |
| 427 | + if (--as->shared == 0) { |
| 428 | + /* Keep IRQs disabled through destroy */ |
| 429 | + as_destroy(as); |
394 | 430 | } |
| 431 | + irq_restore_flags(flags); |
| 432 | +} |
| 433 | + |
| 434 | +/* |
| 435 | + * Free all fpages and the address space structure. |
| 436 | + * Called by as_put() when refcount reaches 0. |
| 437 | + * Caller must hold IRQs disabled. |
| 438 | + */ |
| 439 | +void as_destroy(as_t *as) |
| 440 | +{ |
| 441 | + fpage_t *fp, *fpnext; |
| 442 | + fp = as->first; |
395 | 443 |
|
396 | 444 | /* |
397 | 445 | * FIXME: What if a CLONED fpage which is MAPPED is to be deleted |
398 | 446 | */ |
399 | 447 | while (fp) { |
| 448 | + fpnext = fp->as_next; |
| 449 | + |
400 | 450 | if (fp->fpage.flags & FPAGE_CLONE) |
401 | 451 | unmap_fpage(as, fp); |
402 | 452 | else |
403 | 453 | destroy_fpage(fp); |
404 | 454 |
|
405 | | - fpnext = fp->as_next; |
406 | 455 | fp = fpnext; |
407 | 456 | } |
408 | 457 |
|
|
0 commit comments