asid.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00059 #include <mm/asid.h>
00060 #include <mm/as.h>
00061 #include <mm/tlb.h>
00062 #include <arch/mm/asid.h>
00063 #include <synch/spinlock.h>
00064 #include <synch/mutex.h>
00065 #include <arch.h>
00066 #include <adt/list.h>
00067 #include <debug.h>
00068 
00072 SPINLOCK_INITIALIZE(asidlock);
00073 
00074 static count_t asids_allocated = 0;
00075 
00083 asid_t asid_get(void)
00084 {
00085         asid_t asid;
00086         link_t *tmp;
00087         as_t *as;
00088 
00089         /*
00090          * Check if there is an unallocated ASID.
00091          */
00092         
00093         spinlock_lock(&asidlock);
00094         if (asids_allocated == ASIDS_ALLOCABLE) {
00095 
00096                 /*
00097                  * All ASIDs are already allocated.
00098                  * Resort to stealing.
00099                  */
00100                 
00101                 /*
00102                  * Remove the first item on the list.
00103                  * It is guaranteed to belong to an
00104                  * inactive address space.
00105                  */
00106                 ASSERT(!list_empty(&inactive_as_with_asid_head));
00107                 tmp = inactive_as_with_asid_head.next;
00108                 list_remove(tmp);
00109                 
00110                 as = list_get_instance(tmp, as_t, inactive_as_with_asid_link);
00111                 mutex_lock_active(&as->lock);
00112 
00113                 /*
00114                  * Steal the ASID.
00115                  * Note that the stolen ASID is not active.
00116                  */
00117                 asid = as->asid;
00118                 ASSERT(asid != ASID_INVALID);
00119 
00120                 /*
00121                  * Notify the address space from wich the ASID
00122                  * was stolen by invalidating its asid member.
00123                  */
00124                 as->asid = ASID_INVALID;
00125                 mutex_unlock(&as->lock);
00126 
00127                 /*
00128                  * Get the system rid of the stolen ASID.
00129                  */
00130                 tlb_shootdown_start(TLB_INVL_ASID, asid, 0, 0);
00131                 tlb_invalidate_asid(asid);
00132                 tlb_shootdown_finalize();
00133         } else {
00134 
00135                 /*
00136                  * There is at least one unallocated ASID.
00137                  * Find it and assign it.
00138                  */
00139 
00140                 asid = asid_find_free();
00141                 asids_allocated++;
00142 
00143                 /*
00144                  * Purge the allocated rid from TLBs.
00145                  */
00146                 tlb_shootdown_start(TLB_INVL_ASID, asid, 0, 0);
00147                 tlb_invalidate_asid(asid);
00148                 tlb_shootdown_finalize();
00149         }
00150         
00151         spinlock_unlock(&asidlock);
00152         
00153         return asid;
00154 }
00155 
00163 void asid_put(asid_t asid)
00164 {
00165         ipl_t ipl;
00166 
00167         ipl = interrupts_disable();
00168         spinlock_lock(&asidlock);
00169 
00170         asids_allocated--;
00171         asid_put_arch(asid);
00172         
00173         spinlock_unlock(&asidlock);
00174         interrupts_restore(ipl);
00175 }
00176 

Generated on Sun Jun 18 17:17:04 2006 for HelenOS Kernel (ppc32) by  doxygen 1.4.6