usermode/library/common/ut_barrier.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 _UT_BARRIER_H
00034 #define _UT_BARRIER_H
00035 
00036 #include <errno.h>
00037 #include <pthread.h>
00038 
00039 /* Portable barrier implementation based on POSIX threads */
00040 
00041 #define UT_BARRIER_T       ut_barrier_t
00042 #define UT_BARRIER_INIT    ut_barrier_init
00043 #define UT_BARRIER_WAIT    ut_barrier_wait
00044 #define UT_BARRIER_DESTROY ut_barrier_destroy
00045 
00046 typedef struct ut_barrier_s ut_barrier_t;
00047 
00048 struct ut_barrier_s { 
00049         int        maxcnt;            /* maximum number of runners    */  
00050         struct _sb {  
00051                 pthread_cond_t  wait_cv;  /* cv for waiters at barrier    */  
00052                 pthread_mutex_t wait_lk;  /* mutex for waiters at barrier */  
00053                 int             runners;  /* number of running threads    */  
00054         } sb[2];  
00055     struct _sb *sbp;              /* current sub-barrier          */  
00056 };
00057 
00058 
00059 static int  
00060 ut_barrier_init(ut_barrier_t *bp, int count)
00061 {  
00062         int n;  
00063         int i;  
00064   
00065         if (count < 1) { 
00066                 return(EINVAL);  
00067         }       
00068   
00069         bp->maxcnt = count;  
00070         bp->sbp = &bp->sb[0];  
00071   
00072         for (i = 0; i < 2; ++i) {  
00073                 struct _sb *sbp = &( bp->sb[i] );  
00074                 sbp->runners = count;  
00075   
00076                 if (n = pthread_mutex_init(&sbp->wait_lk, NULL)) {  
00077                         return(n);  
00078                 }       
00079   
00080                 if (n = pthread_cond_init(&sbp->wait_cv, NULL)) {  
00081                         return(n);  
00082                 }       
00083    }  
00084    return(0);  
00085 }  
00086   
00087 
00088 static int  
00089 ut_barrier_wait(register ut_barrier_t *bp) 
00090 {  
00091         register struct _sb *sbp = bp->sbp;  
00092 
00093         pthread_mutex_lock(&sbp->wait_lk);  
00094   
00095         if (sbp->runners == 1) {    /* last thread to reach barrier */  
00096                 if (bp->maxcnt != 1) {  
00097                         /* reset runner count and switch sub-barriers */  
00098                         sbp->runners = bp->maxcnt;  
00099                         bp->sbp = (bp->sbp == &bp->sb[0]) ? &bp->sb[1] : &bp->sb[0];  
00100   
00101                         /* wake up the waiters */  
00102                         pthread_cond_broadcast(&sbp->wait_cv);  
00103         }  
00104     } else {  
00105                 sbp->runners--;    /* one less runner */  
00106   
00107                 while (sbp->runners != bp->maxcnt) { 
00108                         pthread_cond_wait( &sbp->wait_cv, &sbp->wait_lk);  
00109                 }       
00110         }  
00111   
00112         pthread_mutex_unlock(&sbp->wait_lk);  
00113   
00114     return(0);  
00115 }  
00116   
00117   
00118 static int  
00119 ut_barrier_destroy(ut_barrier_t *bp) {  
00120         int n;  
00121         int i;  
00122   
00123         for (i=0; i < 2; ++ i) {  
00124                 if (n = pthread_cond_destroy(&bp->sb[i].wait_cv)) {  
00125                         return( n );  
00126                 }       
00127   
00128                 if (n = pthread_mutex_destroy( &bp->sb[i].wait_lk)) { 
00129                         return(n);  
00130                 }  
00131         }
00132         return (0);
00133 }       
00134 
00135 #endif

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