Drizzled Public API Documentation

os0thread.cc
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
00004 
00005 This program is free software; you can redistribute it and/or modify it under
00006 the terms of the GNU General Public License as published by the Free Software
00007 Foundation; version 2 of the License.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT
00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License along with
00014 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00015 St, Fifth Floor, Boston, MA 02110-1301 USA
00016 
00017 *****************************************************************************/
00018 
00019 /**************************************************/
00026 #include "os0thread.h"
00027 #ifdef UNIV_NONINL
00028 #include "os0thread.ic"
00029 #endif
00030 
00031 #ifdef __WIN__
00032 #include <windows.h>
00033 #else
00034 #include <sys/select.h>
00035 #endif
00036 
00037 #ifndef UNIV_HOTBACKUP
00038 #include "srv0srv.h"
00039 #include "os0sync.h"
00040 
00041 /***************************************************************/
00044 UNIV_INTERN
00045 ibool
00046 os_thread_eq(
00047 /*=========*/
00048   os_thread_id_t  a,  
00049   os_thread_id_t  b)  
00050 {
00051 #ifdef __WIN__
00052   if (a == b) {
00053     return(TRUE);
00054   }
00055 
00056   return(FALSE);
00057 #else
00058   if (pthread_equal(a, b)) {
00059     return(TRUE);
00060   }
00061 
00062   return(FALSE);
00063 #endif
00064 }
00065 
00066 /****************************************************************/
00070 UNIV_INTERN
00071 ulint
00072 os_thread_pf(
00073 /*=========*/
00074   os_thread_id_t  a)  
00075 {
00076 #ifdef UNIV_HPUX10
00077   /* In HP-UX-10.20 a pthread_t is a struct of 3 fields: field1, field2,
00078   field3. We do not know if field1 determines the thread uniquely. */
00079 
00080   return((ulint)(a.field1));
00081 #else
00082   return((ulint)a);
00083 #endif
00084 }
00085 
00086 /*****************************************************************/
00091 UNIV_INTERN
00092 os_thread_id_t
00093 os_thread_get_curr_id(void)
00094 /*=======================*/
00095 {
00096 #ifdef __WIN__
00097   return(GetCurrentThreadId());
00098 #else
00099   return(pthread_self());
00100 #endif
00101 }
00102 
00103 /****************************************************************/
00108 UNIV_INTERN
00109 os_thread_t
00110 os_thread_create(
00111 /*=============*/
00112 #ifndef __WIN__
00113   os_posix_f_t    start_f,
00114 #else
00115   ulint (*start_f)(void*),    
00117 #endif
00118   void*     arg,    
00120   os_thread_id_t*   thread_id)  
00122 {
00123 #ifdef __WIN__
00124   os_thread_t thread;
00125   DWORD   win_thread_id;
00126 
00127   os_mutex_enter(os_sync_mutex);
00128   os_thread_count++;
00129   os_mutex_exit(os_sync_mutex);
00130 
00131   thread = CreateThread(NULL, /* no security attributes */
00132             0,  /* default size stack */
00133             (LPTHREAD_START_ROUTINE)start_f,
00134             arg,
00135             0,  /* thread runs immediately */
00136             &win_thread_id);
00137 
00138   if (thread_id) {
00139     *thread_id = win_thread_id;
00140   }
00141 
00142   return(thread);
00143 #else
00144   int   ret;
00145   os_thread_t pthread;
00146   pthread_attr_t  attr;
00147 
00148 #ifndef UNIV_HPUX10
00149   pthread_attr_init(&attr);
00150 #endif
00151 
00152 #ifdef UNIV_AIX
00153   /* We must make sure a thread stack is at least 32 kB, otherwise
00154   InnoDB might crash; we do not know if the default stack size on
00155   AIX is always big enough. An empirical test on AIX-4.3 suggested
00156   the size was 96 kB, though. */
00157 
00158   ret = pthread_attr_setstacksize(&attr,
00159           (size_t)(PTHREAD_STACK_MIN
00160              + 32 * 1024));
00161   if (ret) {
00162     fprintf(stderr,
00163       "InnoDB: Error: pthread_attr_setstacksize"
00164       " returned %d\n", ret);
00165     exit(1);
00166   }
00167 #endif
00168   os_mutex_enter(os_sync_mutex);
00169   os_thread_count++;
00170   os_mutex_exit(os_sync_mutex);
00171 
00172 #ifdef UNIV_HPUX10
00173   ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
00174 #else
00175   ret = pthread_create(&pthread, &attr, start_f, arg);
00176 #endif
00177   if (ret) {
00178     fprintf(stderr,
00179       "InnoDB: Error: pthread_create returned %d\n", ret);
00180     exit(1);
00181   }
00182 
00183 #ifndef UNIV_HPUX10
00184   pthread_attr_destroy(&attr);
00185 #endif
00186 
00187   if (thread_id) {
00188     *thread_id = pthread;
00189   }
00190 
00191   return(pthread);
00192 #endif
00193 }
00194 
00195 /*****************************************************************/
00197 UNIV_INTERN
00198 void
00199 os_thread_exit(
00200 /*===========*/
00201   void* exit_value) 
00203 {
00204 #ifdef UNIV_DEBUG_THREAD_CREATION
00205   fprintf(stderr, "Thread exits, id %lu\n",
00206     os_thread_pf(os_thread_get_curr_id()));
00207 #endif
00208 
00209 #ifdef UNIV_PFS_THREAD
00210   pfs_delete_thread();
00211 #endif
00212 
00213   os_mutex_enter(os_sync_mutex);
00214   os_thread_count--;
00215   os_mutex_exit(os_sync_mutex);
00216 
00217 #ifdef __WIN__
00218   ExitThread((DWORD)exit_value);
00219 #else
00220   pthread_detach(pthread_self());
00221   pthread_exit(exit_value);
00222 #endif
00223 }
00224 
00225 /*****************************************************************/
00228 UNIV_INTERN
00229 os_thread_t
00230 os_thread_get_curr(void)
00231 /*====================*/
00232 {
00233 #ifdef __WIN__
00234   return(GetCurrentThread());
00235 #else
00236   return(pthread_self());
00237 #endif
00238 }
00239 
00240 /*****************************************************************/
00242 UNIV_INTERN
00243 void
00244 os_thread_yield(void)
00245 /*=================*/
00246 {
00247 #if defined(__WIN__)
00248   SwitchToThread();
00249 #elif (defined(HAVE_SCHED_YIELD) && defined(HAVE_SCHED_H))
00250   sched_yield();
00251 #elif defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
00252   pthread_yield();
00253 #elif defined(HAVE_PTHREAD_YIELD_ONE_ARG)
00254   pthread_yield(0);
00255 #else
00256   os_thread_sleep(0);
00257 #endif
00258 }
00259 #endif /* !UNIV_HOTBACKUP */
00260 
00261 /*****************************************************************/
00263 UNIV_INTERN
00264 void
00265 os_thread_sleep(
00266 /*============*/
00267   ulint tm) 
00268 {
00269 #ifdef __WIN__
00270   Sleep((DWORD) tm / 1000);
00271 #else
00272   struct timeval  t;
00273 
00274   t.tv_sec = tm / 1000000;
00275   t.tv_usec = tm % 1000000;
00276 
00277   select(0, NULL, NULL, NULL, &t);
00278 #endif
00279 }
00280 
00281 #ifndef UNIV_HOTBACKUP
00282 /******************************************************************/
00284 UNIV_INTERN
00285 void
00286 os_thread_set_priority(
00287 /*===================*/
00288   os_thread_t handle, 
00289   ulint   pri)  
00290 {
00291 #ifdef __WIN__
00292   int os_pri;
00293 
00294   if (pri == OS_THREAD_PRIORITY_BACKGROUND) {
00295     os_pri = THREAD_PRIORITY_BELOW_NORMAL;
00296   } else if (pri == OS_THREAD_PRIORITY_NORMAL) {
00297     os_pri = THREAD_PRIORITY_NORMAL;
00298   } else if (pri == OS_THREAD_PRIORITY_ABOVE_NORMAL) {
00299     os_pri = THREAD_PRIORITY_HIGHEST;
00300   } else {
00301     ut_error;
00302   }
00303 
00304   ut_a(SetThreadPriority(handle, os_pri));
00305 #else
00306   UT_NOT_USED(handle);
00307   UT_NOT_USED(pri);
00308 #endif
00309 }
00310 
00311 /******************************************************************/
00314 UNIV_INTERN
00315 ulint
00316 os_thread_get_priority(
00317 /*===================*/
00318   os_thread_t /*handle __attribute__((unused))*/)
00320 {
00321 #ifdef __WIN__
00322   int os_pri;
00323   ulint pri;
00324 
00325   os_pri = GetThreadPriority(handle);
00326 
00327   if (os_pri == THREAD_PRIORITY_BELOW_NORMAL) {
00328     pri = OS_THREAD_PRIORITY_BACKGROUND;
00329   } else if (os_pri == THREAD_PRIORITY_NORMAL) {
00330     pri = OS_THREAD_PRIORITY_NORMAL;
00331   } else if (os_pri == THREAD_PRIORITY_HIGHEST) {
00332     pri = OS_THREAD_PRIORITY_ABOVE_NORMAL;
00333   } else {
00334     ut_error;
00335   }
00336 
00337   return(pri);
00338 #else
00339   return(0);
00340 #endif
00341 }
00342 
00343 /******************************************************************/
00346 UNIV_INTERN
00347 ulint
00348 os_thread_get_last_error(void)
00349 /*==========================*/
00350 {
00351 #ifdef __WIN__
00352   return(GetLastError());
00353 #else
00354   return(0);
00355 #endif
00356 }
00357 #endif /* !UNIV_HOTBACKUP */