//kernel/trunk/generic/include/proc/task.h |
---|
56,9 → 56,9 |
task_arch_t arch; /**< Architecture specific task data. */ |
/** |
* Serializes access to the B+tree of task's futexes. This mutex is |
* independent on the task spinlock. |
*/ |
* Serializes access to the B+tree of task's futexes. This mutex is |
* independent on the task spinlock. |
*/ |
mutex_t futexes_lock; |
btree_t futexes; /**< B+tree of futexes referenced by this task. */ |
}; |
//kernel/trunk/generic/include/mm/page.h |
---|
85,6 → 85,7 |
extern void page_mapping_remove(as_t *as, __address page); |
extern pte_t *page_mapping_find(as_t *as, __address page); |
extern pte_t *page_table_create(int flags); |
extern void page_table_destroy(pte_t *page_table); |
extern void map_structure(__address s, size_t size); |
extern __address hw_map(__address physaddr, size_t size); |
//kernel/trunk/generic/include/mm/as.h |
---|
75,6 → 75,9 |
mutex_t lock; |
/** Number of references (i.e tasks that reference this as). */ |
count_t refcount; |
/** Number of processors on wich is this address space active. */ |
count_t cpu_refcount; |
90,6 → 93,7 |
struct as_operations { |
pte_t *(* page_table_create)(int flags); |
void (* page_table_destroy)(pte_t *page_table); |
void (* page_table_lock)(as_t *as, bool lock); |
void (* page_table_unlock)(as_t *as, bool unlock); |
}; |
158,18 → 162,21 |
extern link_t inactive_as_with_asid_head; |
extern void as_init(void); |
extern as_t *as_create(int flags); |
extern void as_destroy(as_t *as); |
extern void as_switch(as_t *old, as_t *new); |
extern int as_page_fault(__address page, pf_access_t access, istate_t *istate); |
extern as_area_t *as_area_create(as_t *as, int flags, size_t size, __address base, int attrs, |
mem_backend_t *backend, mem_backend_data_t *backend_data); |
extern int as_area_destroy(as_t *as, __address address); |
extern int as_area_resize(as_t *as, __address address, size_t size, int flags); |
extern int as_area_destroy(as_t *as, __address address); |
int as_area_share(as_t *src_as, __address src_base, size_t acc_size, |
as_t *dst_as, __address dst_base, int dst_flags_mask); |
extern int as_area_get_flags(as_area_t *area); |
extern bool as_area_check_access(as_area_t *area, pf_access_t access); |
extern int as_page_fault(__address page, pf_access_t access, istate_t *istate); |
extern void as_switch(as_t *old, as_t *new); |
extern void as_free(as_t *as); |
int as_area_share(as_t *src_as, __address src_base, size_t acc_size, |
as_t *dst_as, __address dst_base, int dst_flags_mask); |
extern size_t as_get_size(__address base); |
extern int used_space_insert(as_area_t *a, __address page, count_t count); |
extern int used_space_remove(as_area_t *a, __address page, count_t count); |
//kernel/trunk/generic/src/proc/task.c |
---|
107,6 → 107,15 |
btree_create(&ta->futexes); |
ipl = interrupts_disable(); |
/* |
* Increment address space reference count. |
* TODO: Reconsider the locking scheme. |
*/ |
mutex_lock(&as->lock); |
as->refcount++; |
mutex_unlock(&as->lock); |
spinlock_lock(&tasks_lock); |
ta->taskid = ++task_counter; |
139,7 → 148,7 |
rc = elf_load((elf_header_t *) program_addr, as); |
if (rc != EE_OK) { |
as_free(as); |
as_destroy(as); |
return NULL; |
} |
//kernel/trunk/generic/src/mm/as.c |
---|
121,6 → 121,7 |
else |
as->asid = ASID_INVALID; |
as->refcount = 0; |
as->cpu_refcount = 0; |
as->page_table = page_table_create(flags); |
127,13 → 128,49 |
return as; |
} |
/** Free Adress space */ |
void as_free(as_t *as) |
/** Destroy adress space. |
* |
* When there are no tasks referencing this address space (i.e. its refcount is zero), |
* the address space can be destroyed. |
*/ |
void as_destroy(as_t *as) |
{ |
ASSERT(as->cpu_refcount == 0); |
ipl_t ipl; |
bool cond; |
/* TODO: free as_areas and other resources held by as */ |
/* TODO: free page table */ |
ASSERT(as->refcount == 0); |
/* |
* Since there is no reference to this area, |
* it is safe not to lock its mutex. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&inactive_as_with_asid_lock); |
if (as->asid != ASID_INVALID && as->asid != ASID_KERNEL) { |
list_remove(&as->inactive_as_with_asid_link); |
asid_put(as->asid); |
} |
spinlock_unlock(&inactive_as_with_asid_lock); |
/* |
* Destroy address space areas of the address space. |
*/ |
for (cond = true; cond; ) { |
btree_node_t *node; |
ASSERT(!list_empty(&as->as_area_btree.leaf_head)); |
node = list_get_instance(&as->as_area_btree.leaf_head.next, btree_node_t, leaf_link); |
if ((cond = node->keys)) { |
as_area_destroy(as, node->key[0]); |
btree_remove(&as->as_area_btree, node->key[0], node); |
} |
} |
page_table_destroy(as->page_table); |
interrupts_restore(ipl); |
free(as); |
} |
840,6 → 877,20 |
return as_operations->page_table_create(flags); |
} |
/** Destroy page table. |
* |
* Destroy page table in architecture specific way. |
* |
* @param page_table Physical address of PTL0. |
*/ |
void page_table_destroy(pte_t *page_table) |
{ |
ASSERT(as_operations); |
ASSERT(as_operations->page_table_destroy); |
as_operations->page_table_destroy(page_table); |
} |
/** Lock page table. |
* |
* This function should be called before any page_mapping_insert(), |