my_thr_init.c 7.13 KB
Newer Older
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
1 2 3 4 5 6 7 8
/* Copyright (C) 2000 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
10 11 12 13 14 15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
16 17

/*
18 19
  Functions to handle initializating and allocationg of all mysys & debug
  thread variables.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
20 21 22 23 24 25 26 27 28 29
*/

#include "mysys_priv.h"
#include <m_string.h>

#ifdef THREAD
#ifdef USE_TLS
pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
#else
pthread_key(struct st_my_thread_var, THR_KEY_mysys);
30
#endif /* USE_TLS */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
31 32 33
pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,THR_LOCK_keycache,
	        THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
	        THR_LOCK_net, THR_LOCK_charset; 
34
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
35 36
pthread_mutex_t LOCK_localtime_r;
#endif
37 38 39
#ifndef HAVE_GETHOSTBYNAME_R
pthread_mutex_t LOCK_gethostbyname_r;
#endif
40 41 42 43 44 45
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
pthread_mutexattr_t my_fast_mutexattr;
#endif
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
pthread_mutexattr_t my_errchk_mutexattr;
#endif
bk@work.mysql.com's avatar
bk@work.mysql.com committed
46 47 48 49 50 51 52 53

my_bool my_thread_global_init(void)
{
  if (pthread_key_create(&THR_KEY_mysys,free))
  {
    fprintf(stderr,"Can't initialize threads: error %d\n",errno);
    exit(1);
  }
54 55 56 57
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
  pthread_mutexattr_init(&my_fast_mutexattr);
  pthread_mutexattr_setkind_np(&my_fast_mutexattr,PTHREAD_MUTEX_ADAPTIVE_NP);
#endif
58
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
59 60 61 62 63 64 65 66 67 68 69 70 71 72
  pthread_mutexattr_init(&my_errchk_mutexattr);
  pthread_mutexattr_setkind_np(&my_errchk_mutexattr,
			       PTHREAD_MUTEX_ERRORCHECK_NP);
#endif

  pthread_mutex_init(&THR_LOCK_malloc,MY_MUTEX_INIT_FAST);
  pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
  pthread_mutex_init(&THR_LOCK_keycache,MY_MUTEX_INIT_FAST);
  pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
  pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW);
  pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW);
  pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST);
  pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST);
  pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
73
#if defined( __WIN__) || defined(OS2)
74
  win_pthread_init();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
75
#endif
76
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
77
  pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW);
78 79 80
#endif
#ifndef HAVE_GETHOSTBYNAME_R
  pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
81 82 83 84
#endif
  return my_thread_init();
}

85

bk@work.mysql.com's avatar
bk@work.mysql.com committed
86 87 88 89 90
void my_thread_global_end(void)
{
#if defined(USE_TLS)
  (void) TlsFree(THR_KEY_mysys);
#endif
91 92 93 94 95
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
  pthread_mutexattr_destroy(&my_fast_mutexattr);
#endif
#ifdef PPTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
  pthread_mutexattr_destroy(&my_errchk_mutexattr);
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
96 97 98 99 100 101 102 103 104 105
#endif
  pthread_mutex_destroy(&THR_LOCK_malloc);
  pthread_mutex_destroy(&THR_LOCK_open);
  pthread_mutex_destroy(&THR_LOCK_keycache);
  pthread_mutex_destroy(&THR_LOCK_lock);
  pthread_mutex_destroy(&THR_LOCK_isam);
  pthread_mutex_destroy(&THR_LOCK_myisam);
  pthread_mutex_destroy(&THR_LOCK_heap);
  pthread_mutex_destroy(&THR_LOCK_net);
  pthread_mutex_destroy(&THR_LOCK_charset);
106
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
107
  pthread_mutex_destroy(&LOCK_localtime_r);
108
#endif
109 110 111
#ifndef HAVE_GETHOSTBYNAME_R
  pthread_mutex_destroy(&LOCK_gethostbyname_r);
#endif
bk@work.mysql.com's avatar
bk@work.mysql.com committed
112 113 114 115
}

static long thread_id=0;

116
/*
117
  We can't use mutex_locks here if we are using windows as
118 119 120 121 122
  we may have compiled the program with SAFE_MUTEX, in which
  case the checking of mutex_locks will not work until
  the pthread_self thread specific variable is initialized.
*/

bk@work.mysql.com's avatar
bk@work.mysql.com committed
123 124 125
my_bool my_thread_init(void)
{
  struct st_my_thread_var *tmp;
126 127
  my_bool error=0;

128
#ifdef EXTRA_DEBUG_THREADS
129 130
  fprintf(stderr,"my_thread_init(): thread_id=%ld\n",pthread_self());
#endif  
131
#if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
132
  pthread_mutex_lock(&THR_LOCK_lock);
133
#endif
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
134

bk@work.mysql.com's avatar
bk@work.mysql.com committed
135 136 137
#if !defined(__WIN__) || defined(USE_TLS)
  if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys))
  {
138
#ifdef EXTRA_DEBUG_THREADS
139
    fprintf(stderr,"my_thread_init() called more than once in thread %ld\n",
140
	        pthread_self());
141
#endif    
142
    goto end;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
143
  }
144
  if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
145
  {
146 147
    error= 1;
    goto end;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
148 149 150 151
  }
  pthread_setspecific(THR_KEY_mysys,tmp);

#else
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
152 153 154 155 156
  /*
    Skip initialization if the thread specific variable is already initialized
  */
  if (THR_KEY_mysys.id)
    goto end;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
157 158 159
  tmp= &THR_KEY_mysys;
#endif
  tmp->id= ++thread_id;
160
  pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
161
  pthread_cond_init(&tmp->suspend, NULL);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
162 163

end:
164
#if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
165
  pthread_mutex_unlock(&THR_LOCK_lock);
166
#endif
167
  return error;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
168 169
}

170

bk@work.mysql.com's avatar
bk@work.mysql.com committed
171 172 173
void my_thread_end(void)
{
  struct st_my_thread_var *tmp=my_thread_var;
174
#ifdef EXTRA_DEBUG_THREADS
175 176 177
  fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ld\n",
	  tmp,pthread_self());
#endif  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
178 179 180
  if (tmp)
  {
#if !defined(DBUG_OFF)
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
181
    /* tmp->dbug is allocated inside DBUG library */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
182 183 184 185 186 187 188 189 190 191
    if (tmp->dbug)
    {
      free(tmp->dbug);
      tmp->dbug=0;
    }
#endif
#if !defined(__bsdi__) || defined(HAVE_mit_thread) /* bsdi dumps core here */
    pthread_cond_destroy(&tmp->suspend);
#endif
    pthread_mutex_destroy(&tmp->mutex);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
192
#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS)
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
193
    free(tmp);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
194 195
#endif
  }
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
196 197 198 199
  /* The following free has to be done, even if my_thread_var() is 0 */
#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS)
  pthread_setspecific(THR_KEY_mysys,0);
#endif
bk@work.mysql.com's avatar
bk@work.mysql.com committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
}

struct st_my_thread_var *_my_thread_var(void)
{
  struct st_my_thread_var *tmp=
    my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
#if defined(USE_TLS)
  /* This can only happen in a .DLL */
  if (!tmp)
  {
    my_thread_init();
    tmp=my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
  }
#endif
  return tmp;
}

217

bk@work.mysql.com's avatar
bk@work.mysql.com committed
218
/****************************************************************************
219
  Get name of current thread.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
****************************************************************************/

#define UNKNOWN_THREAD -1

long my_thread_id()
{
#if defined(HAVE_PTHREAD_GETSEQUENCE_NP)
  return pthread_getsequence_np(pthread_self());
#elif (defined(__sun) || defined(__sgi) || defined(__linux__)) && !defined(HAVE_mit_thread)
  return pthread_self();
#else
  return my_thread_var->id;
#endif
}

#ifdef DBUG_OFF
236
const char *my_thread_name(void)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
237 238 239 240 241 242
{
  return "no_name";
}

#else

243
const char *my_thread_name(void)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
244 245 246 247 248 249 250 251 252 253 254 255 256 257
{
  char name_buff[100];
  struct st_my_thread_var *tmp=my_thread_var;
  if (!tmp->name[0])
  {
    long id=my_thread_id();
    sprintf(name_buff,"T@%ld", id);
    strmake(tmp->name,name_buff,THREAD_NAME_SIZE);
  }
  return tmp->name;
}
#endif /* DBUG_OFF */

#endif /* THREAD */