nfs-ganesha 1.4

fridgethr.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  * ---------------------------------------
00024  */
00025 
00033 #ifdef HAVE_CONFIG_H
00034 #include "config.h"
00035 #endif
00036 
00037 #ifdef _SOLARIS
00038 #include "solaris_port.h"
00039 #endif
00040 
00041 #include "HashData.h"
00042 #include "HashTable.h"
00043 #include "log.h"
00044 #include "nfs_core.h"
00045 #include "nfs_exports.h"
00046 #include "config_parsing.h"
00047 #include <stdlib.h>
00048 #include <string.h>
00049 #include <sys/socket.h>
00050 #include <netinet/in.h>
00051 #include <arpa/inet.h>
00052 #include <pthread.h>
00053 
00054 typedef struct fridge_entry__
00055 {
00056   pthread_t thrid ;
00057   pthread_mutex_t condmutex ;
00058   pthread_cond_t condvar ;
00059   unsigned int frozen ;
00060   void * arg ;
00061   struct fridge_entry__ * pprev ;
00062   struct fridge_entry__ * pnext ;
00063 } fridge_entry_t  ;
00064 
00065 static pthread_mutex_t fridge_mutex ;
00066 static fridge_entry_t * fridge_content = NULL ;
00067 static pthread_attr_t attr_thr ;
00068 
00069 static void fridgethr_remove( fridge_entry_t * pfe ) 
00070 {
00071    if( pfe == NULL )
00072         return ;
00073 
00074    P( fridge_mutex ) ;
00075  
00076    if( pfe->pprev != NULL ) pfe->pprev->pnext = pfe->pnext ;
00077    if( pfe->pnext != NULL ) pfe->pnext->pprev = pfe->pprev ;
00078 
00079    if( pfe->pnext == NULL && pfe->pprev == NULL ) /* Is the fridge empty ? */
00080      fridge_content = NULL ;
00081 
00082    V( fridge_mutex ) ;
00083 
00084    gsh_free(pfe) ;
00085 
00086    return ;
00087  } /* fridgethr_remove */
00088 
00089 int fridgethr_get( pthread_t * pthrid, void *(*thrfunc)(void*), void * thrarg )
00090 {
00091   fridge_entry_t * pfe = NULL ;
00092 
00093   P( fridge_mutex ) ;
00094   if( fridge_content == NULL )
00095    {
00096     V( fridge_mutex ) ;
00097     return pthread_create( pthrid, &attr_thr, thrfunc, thrarg ) ;
00098    }
00099 
00100   pfe = fridge_content ;
00101   pfe->frozen = FALSE ;
00102   if( pfe->pprev != NULL )
00103       pfe->pprev->pnext = pfe->pnext ;
00104 
00105   if( pfe->pnext != NULL )
00106       pfe->pnext->pprev = pfe->pprev ;
00107 
00108   fridge_content = fridge_content->pprev ;
00109 
00110   pfe->arg = thrarg ;
00111   if( pthread_cond_signal( &pfe->condvar ) )
00112    {
00113      V( fridge_mutex ) ;
00114      return -1 ;
00115    }
00116     
00117   *pthrid = pfe->thrid ;
00118  
00119   V( fridge_mutex ) ;
00120   return 0 ;
00121 } /* fridgethr_get */
00122 
00123 void * fridgethr_freeze( )
00124 {
00125   fridge_entry_t * pfe = NULL ;
00126   struct timespec timeout ;
00127   struct timeval    tp;
00128   int rc = 0 ;
00129   void *arg = NULL;
00130 
00131   if( ( rc = gettimeofday( &tp, NULL ) ) != 0 )
00132     return NULL ;
00133 
00134   /* Be careful : pthread_cond_timedwait take an *absolute* time as time specification, not a duration */ 
00135   timeout.tv_sec = tp.tv_sec + nfs_param.core_param.tcp_fridge_expiration_delay ;
00136   timeout.tv_nsec = 0 ; 
00137 
00138   if ((pfe = gsh_malloc(sizeof(fridge_entry_t))) == NULL)
00139     return NULL ;
00140 
00141   pfe->thrid = pthread_self();
00142   pthread_mutex_init(&(pfe->condmutex), NULL);
00143   pthread_cond_init(&(pfe->condvar), NULL);
00144   pfe->pprev = NULL;
00145   pfe->pnext = NULL;
00146   pfe->frozen = TRUE;
00147 
00148   P(fridge_mutex);
00149   if( fridge_content == NULL )
00150    {
00151      pfe->pprev = NULL ;
00152      pfe->pnext = NULL ;
00153    }
00154   else
00155    {
00156      pfe->pprev = fridge_content ;
00157      pfe->pnext = NULL ;
00158      fridge_content->pnext = pfe ;
00159    }
00160   fridge_content = pfe ;
00161   V( fridge_mutex ) ;
00162 
00163   P( pfe->condmutex ) ;
00164   while( pfe->frozen == TRUE && rc == 0 ) 
00165     if( nfs_param.core_param.tcp_fridge_expiration_delay > 0 )
00166        rc = pthread_cond_timedwait( &pfe->condvar, &pfe->condmutex, &timeout ) ;
00167     else
00168        rc = pthread_cond_wait( &pfe->condvar, &pfe->condmutex ) ;
00169 
00170   if( rc != ETIMEDOUT )
00171     arg = pfe->arg;
00172 
00173   fridgethr_remove( pfe );  
00174   return arg;
00175 } /* fridgethr_freeze */
00176 
00177 int fridgethr_init( )
00178 {
00179   /* Spawns a new thread to handle the connection */
00180   pthread_attr_init(&attr_thr) ; 
00181   pthread_attr_setscope(&attr_thr, PTHREAD_SCOPE_SYSTEM);
00182   pthread_attr_setdetachstate(&attr_thr, PTHREAD_CREATE_DETACHED);      /* If not, the conn mgr will be "defunct" threads */
00183   pthread_attr_setstacksize(&attr_thr, THREAD_STACK_SIZE);
00184 
00185   fridge_content = NULL ;
00186 
00187   if( pthread_mutex_init( &fridge_mutex, NULL ) != 0 )
00188     return -1 ;
00189 
00190   return 0 ;
00191 } /* fridgethr_init */