usermode/library/common/plist.h

00001 /*
00002     Copyright (C) 2011 Computer Sciences Department, 
00003     University of Wisconsin -- Madison
00004 
00005     ----------------------------------------------------------------------
00006 
00007     This file is part of Mnemosyne: Lightweight Persistent Memory, 
00008     originally developed at the University of Wisconsin -- Madison.
00009 
00010     Mnemosyne was originally developed primarily by Haris Volos
00011     with contributions from Andres Jaan Tack.
00012 
00013     ----------------------------------------------------------------------
00014 
00015     Mnemosyne is free software; you can redistribute it and/or
00016     modify it under the terms of the GNU General Public License
00017     as published by the Free Software Foundation, version 2
00018     of the License.
00019  
00020     Mnemosyne is distributed in the hope that it will be useful,
00021     but WITHOUT ANY WARRANTY; without even the implied warranty of
00022     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023     GNU General Public License for more details.
00024 
00025     You should have received a copy of the GNU General Public License
00026     along with this program; if not, write to the Free Software
00027     Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00028     Boston, MA  02110-1301, USA.
00029 
00030 ### END HEADER ###
00031 */
00032 
00033 #ifndef _PLIST_H
00034 #define _PLIST_H
00035 
00036 #include <stddef.h>
00037 
00038 #define PCM_STORE(addr, val)                               \
00039         *(addr) = val; 
00040 
00041 #define PCM_BARRIER
00042 
00043 
00044 struct plist_head {
00045         struct plist_head *next;
00046         struct plist_head *prev;
00047         struct plist_head *next_shadow;
00048 };
00049 
00050 
00058 static inline void plist_init(struct plist_head *head, struct plist_head *tail)
00059 {
00060         PCM_STORE(&(head->next), tail);
00061         PCM_STORE(&(head->prev), tail);
00062         PCM_STORE(&(tail->next), head);
00063         PCM_STORE(&(tail->prev), head);
00064         PCM_BARRIER
00065 }
00066 
00067 
00068 static inline void plist_move(struct plist_head *listA, struct plist_head *listB)
00069 {
00070         struct plist_head *listA_next_old = listA->next;
00071         struct plist_head *listA_prev_old = listA->prev;
00072 
00073         PCM_STORE(&(listA->prev->next), listA->next);
00074         PCM_BARRIER;
00075         PCM_STORE(&(listA->next), listB);
00076         PCM_BARRIER;
00077         PCM_STORE(&(listB->prev->next), listA);
00078         PCM_BARRIER;
00079         PCM_STORE(&(listA_next_old->prev), listA_prev_old);
00080         PCM_BARRIER;
00081         PCM_STORE(&(listA->prev), listB->prev);
00082         PCM_BARRIER;
00083         PCM_STORE(&(listA->next->prev), listA);
00084         PCM_BARRIER;
00085 }
00086 
00094 static inline void plist_recover(struct plist_head *list)
00095 {
00096         struct plist_head *node;
00097         struct plist_head *nodeX;
00098         int               count = 0;
00099 
00100         for (node = list; prefetch(node->next), node != list || count == 0;
00101              node = node->next, count++)
00102         {               
00103                 if (node->next == node && node->prev == node) {
00104                         /* Empty list -- nothing to recover*/
00105                         return;
00106                 }
00107 recover:
00108                 if (node->next->prev->prev == node /* CYCLE_I: 1F-2B cycle */) {
00109                         nodeX = node->next->prev;
00110                     if (nodeX->next->prev != NULL &&
00111                             nodeX->next->prev->next == nodeX /* CYCLE_II: 1F-1B-1F cycle */) {
00112                                 PCM_STORE(&(nodeX->prev->next->prev), nodeX->prev);
00113                                 PCM_BARRIER
00114                                 goto recover;
00115                         } else {
00116                                 PCM_STORE(&(nodeX->next), node->next);
00117                                 PCM_BARRIER;
00118                                 PCM_STORE(&(node->next), nodeX);
00119                                 PCM_BARRIER;
00120                                 goto recover;
00121                         }       
00122                 } else if (node->next->next->prev == node /* CYCLE_II: 2F-1B cycle */) {
00123                         nodeX = node->next;
00124                     if (nodeX->prev != NULL &&
00125                             nodeX->prev->next->prev == nodeX /* CYCLE_I: 1B-1F-1B cycle */) {
00126                                 PCM_STORE(&(node->next), node->next->next);
00127                                 PCM_BARRIER;
00128                                 goto recover;
00129                         } else {
00130                                 PCM_STORE(&(nodeX->prev), node);
00131                                 PCM_BARRIER;
00132                                 PCM_STORE(&(nodeX->next->prev), nodeX);
00133                                 PCM_BARRIER;
00134                                 goto recover;
00135                         }       
00136                 }
00137         }
00138 }
00139 
00140 static inline void plist_init_S(struct plist_head *head, struct plist_head *tail)
00141 {
00142         PCM_STORE(&(head->next), tail);
00143         PCM_BARRIER
00144 }
00145 
00152 static inline void plist_add_S(struct plist_head *node, struct plist_head *head)
00153 {
00154 
00155         PCM_STORE(&(node->next), head->next);
00156         PCM_STORE(&(head->next), node);
00157         PCM_BARRIER
00158 
00159 }
00160 
00164 static inline void plist_move_DtoS(struct plist_head *listA, struct plist_head *listB)
00165 {
00166         struct plist_head *listA_next_old = listA->next;
00167         struct plist_head *listA_prev_old = listA->prev;
00168 
00169         PCM_STORE(&(listA->prev->next), listA->next);
00170         PCM_BARRIER;
00171         PCM_STORE(&(listA->next), listB);
00172         PCM_BARRIER;
00173         PCM_STORE(&(listB->prev->next), listA);
00174         PCM_BARRIER;
00175         PCM_STORE(&(listA_next_old->prev), listA_prev_old);
00176         PCM_BARRIER;
00177         PCM_STORE(&(listA->prev), NULL);
00178         PCM_BARRIER;
00179 }
00180 
00181 
00185 static inline void plist_move_StoD(struct plist_head *listA, struct plist_head *listB)
00186 {
00187         struct plist_head *listA_next_old = listA->next;
00188         struct plist_head *listA_prev_old = listA->prev;
00189 
00190         PCM_STORE(&(listA->prev->next), listA->next);
00191         PCM_BARRIER;
00192         PCM_STORE(&(listA->next), listB);
00193         PCM_BARRIER;
00194         PCM_STORE(&(listB->prev->next), listA);
00195         PCM_BARRIER;
00196         PCM_STORE(&(listA_next_old->prev), listA_prev_old);
00197         PCM_BARRIER;
00198         PCM_STORE(&(listA->prev), listB->prev);
00199         PCM_BARRIER;
00200         PCM_STORE(&(listA->next->prev), listA);
00201         PCM_BARRIER;
00202 }
00203 
00204 
00205 
00206 #endif /* _PLIST_H */

Generated on Sat Apr 23 11:43:35 2011 for Mnemosyne by  doxygen 1.4.7