/*___INFO__MARK_BEGIN__*/ /************************************************************************* * * The Contents of this file are made available subject to the terms of * the Sun Industry Standards Source License Version 1.2 * * Sun Microsystems Inc., March, 2001 * * * Sun Industry Standards Source License Version 1.2 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.2 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2003 by Sun Microsystems, Inc. * * All Rights Reserved. * ************************************************************************/ /*___INFO__MARK_END__*/ #include #include #include #include /* do not compile in monitoring code */ #ifndef NO_SGE_COMPILE_DEBUG #define NO_SGE_COMPILE_DEBUG #endif #include "sgermon.h" #include "sge_log.h" #include "msg_lcklib.h" #include "sge_time.h" /* enable or disable lock printing*/ /* #define PRINT_LOCK */ /****** sge_mtutil/sge_mutex_lock() ******************************************** * NAME * sge_mutex_lock() -- Mutex locking wrapper with rmon monitoring * * SYNOPSIS * void sge_mutex_lock(const char *mutex_name, const char *func, * int line, pthread_mutex_t *mutex) * * FUNCTION * Locks the passed mutex. Before and after locking rmon DLOCKPRINTF() * is used to facilitate tracking of deadlocks that are caused by * mutexes. * * INPUTS * const char *mutex_name - The name of the mutex. * const char *func - The function where sge_mutex_lock() * was called from * int line - The line number where sge_mutex_lock() * was called from * pthread_mutex_t *mutex - The mutex. * * NOTES * MT-NOTE: sge_mutex_lock() is MT-safe * MT-NOTE: * MT-NOTE: This function is considered being MT-safe, even though is does * MT-NOTE: use 'strerror()'. The error message returned from 'strerror()' * MT-NOTE: is not stored and used imediately. * * SEE ALSO * sge_mtutil/sge_mutex_unlock() *******************************************************************************/ #ifdef SGE_LOCK_DEBUG void sge_mutex_lock(const char *mutex_name, const char *func, int line, pthread_mutex_t *mutex) { int res = -1; DENTER(BASIS_LAYER, "sge_mutex_lock"); DLOCKPRINTF(("%s() line %d: about to lock mutex \"%s\" : %u\n", func, line, mutex_name, sge_get_gmt())); #ifdef PRINT_LOCK { struct timeval now; gettimeofday(&now, NULL); printf("%ld lock %lu:%lus %s\n", (long int) pthread_self(),now.tv_sec, (long unsigned)now.tv_usec, mutex_name); } #endif if (( res = pthread_mutex_lock(mutex)) != 0) { CRITICAL((SGE_EVENT, MSG_LCK_MUTEXLOCKFAILED_SSS, func, mutex_name, strerror(res))); abort(); } DLOCKPRINTF(("%s() line %d: locked mutex \"%s\" : %u\n", func, line, mutex_name, sge_get_gmt())); #ifdef PRINT_LOCK { struct timeval now; gettimeofday(&now, NULL); printf("%ld got lock %lu:%lu %s\n", (long int) pthread_self(),now.tv_sec, now.tv_usec, mutex_name); } #endif DRETURN_VOID; } /* sge_mutex_lock() */ #else void sge_mutex_lock(const char *mutex_name, const char *func, int line, pthread_mutex_t *mutex) { int res = -1; DENTER(BASIS_LAYER, "sge_mutex_lock"); if (( res = pthread_mutex_lock(mutex)) != 0) { CRITICAL((SGE_EVENT, MSG_LCK_MUTEXLOCKFAILED_SSS, func, mutex_name, strerror(res))); abort(); } DRETURN_VOID; } /* sge_mutex_lock() */ #endif /****** sge_mtutil/sge_mutex_unlock() ******************************************** * NAME * sge_mutex_unlock() -- Mutex unlocking wrapper with rmon monitoring * * SYNOPSIS * void sge_mutex_unlock(const char *mutex_name, const char *func, * int line, pthread_mutex_t *mutex) * * FUNCTION * Unlocks the passed mutex. Before and after unlocking rmon DLOCKPRINTF() * is used to facilitate tracking of deadlocks that are caused by * mutexes. * * INPUTS * const char *mutex_name - The name of the mutex. * const char *func - The function where sge_unmutex_unlock() * was called from * int line - The line number where sge_unmutex_lock() * was called from * pthread_mutex_t *mutex - The mutex. * * NOTES * MT-NOTE: sge_mutex_unlock() is MT-safe * MT-NOTE: * MT-NOTE: This function is considered being MT-safe, even though is does * MT-NOTE: use 'strerror()'. The error message returned from 'strerror()' * MT-NOTE: is not stored and used imediately. * * SEE ALSO * sge_mtutil/sge_mutex_lock() *******************************************************************************/ #ifdef SGE_LOCK_DEBUG void sge_mutex_unlock(const char *mutex_name, const char *func, int line, pthread_mutex_t *mutex) { int res = -1; DENTER(BASIS_LAYER, "sge_mutex_unlock"); if (( res = pthread_mutex_unlock(mutex)) != 0) { CRITICAL((SGE_EVENT, MSG_LCK_MUTEXUNLOCKFAILED_SSS, func, mutex_name, strerror(res))); abort(); } #ifdef PRINT_LOCK { struct timeval now; gettimeofday(&now, NULL); printf("%ld unlock %lu:%lu %s\n", (long int) pthread_self(),now.tv_sec, now.tv_usec, mutex_name); } #endif DLOCKPRINTF(("%s() line %d: unlocked mutex \"%s\"\n", func, line, mutex_name)); DRETURN_VOID; } /* sge_mutex_unlock() */ #else void sge_mutex_unlock(const char *mutex_name, const char *func, int line, pthread_mutex_t *mutex) { int res = -1; DENTER(BASIS_LAYER, "sge_mutex_unlock"); if (( res = pthread_mutex_unlock(mutex)) != 0) { CRITICAL((SGE_EVENT, MSG_LCK_MUTEXUNLOCKFAILED_SSS, func, mutex_name, strerror(res))); abort(); } DRETURN_VOID; } /* sge_mutex_unlock() */ #endif /****** sge_mtutil/sge_relative_timespec() ************************************** * NAME * sge_relative_timespec() -- set timespec to now plus timeout * * SYNOPSIS * static void sge_relative_timespec(signed long timeout, struct * timespec *ts) * * FUNCTION * Based on the relative timeout passed an absolute timespec is * returned. The timespec can e.g. be used for pthread_cond_timedwait(). * Also a timout of 0 can be used. However if the timespec returned is then * used with pthread_cond_timedwait() this requires the predicate is checked * once at least. * * INPUTS * signed long timeout - A relative timeout interval or 0 * * OUTPUTS * struct timespec *ts - An abstime timespec value * * NOTES * MT-NOTE: sge_relative_timespec() is MT safe *******************************************************************************/ void sge_relative_timespec(signed long timeout, struct timespec *ts) { struct timeval now; /* in examples also clock_gettime(CLOCK_REALTIME, &ts) was used */ gettimeofday(&now, NULL); ts->tv_sec = now.tv_sec; ts->tv_nsec = now.tv_usec * 1000; if (timeout != 0) ts->tv_sec += timeout; /* in case of DRMAA_TIMEOUT_NO_WAIT the current system time can be used assumed the predicate is checked once at least */ return; }