~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/internal/my_thr_init.cc

  • Committer: LinuxJedi
  • Date: 2010-09-09 06:14:45 UTC
  • mto: (1750.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1751.
  • Revision ID: linuxjedi@linuxjedi-laptop-20100909061445-1jz91d5eed932616
Fix another wrong header, grr...

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/*
17
17
  Functions to handle initializating and allocationg of all mysys & debug
21
21
#include "config.h"
22
22
 
23
23
#include "drizzled/internal/my_sys.h"
 
24
#include "drizzled/internal/my_pthread.h"
24
25
#include "drizzled/internal/thread_var.h"
25
26
#include "drizzled/internal/m_string.h"
26
27
 
38
39
# endif
39
40
#endif
40
41
 
41
 
#include <boost/thread/thread.hpp>
42
 
#include <boost/thread/mutex.hpp>
43
 
#include <boost/thread/tss.hpp>
44
 
 
45
42
namespace drizzled
46
43
{
47
44
namespace internal
48
45
{
49
46
 
50
 
boost::thread_specific_ptr<st_my_thread_var> THR_KEY_mysys;
51
 
boost::mutex THR_LOCK_threads;
 
47
pthread_key_t THR_KEY_mysys;
 
48
pthread_mutex_t THR_LOCK_lock;
 
49
pthread_mutex_t THR_LOCK_threads;
 
50
pthread_cond_t  THR_COND_threads;
 
51
uint32_t            THR_thread_count= 0;
 
52
static uint32_t my_thread_end_wait_time= 5;
 
53
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
54
pthread_mutexattr_t my_fast_mutexattr;
 
55
#endif
52
56
 
53
57
/*
54
58
  initialize thread environment
63
67
 
64
68
bool my_thread_global_init(void)
65
69
{
 
70
  int pth_ret;
 
71
 
 
72
  if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
 
73
  {
 
74
    fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret);
 
75
    return 1;
 
76
  }
 
77
 
 
78
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
79
  /*
 
80
    Set mutex type to "fast" a.k.a "adaptive"
 
81
 
 
82
    In this case the thread may steal the mutex from some other thread
 
83
    that is waiting for the same mutex.  This will save us some
 
84
    context switches but may cause a thread to 'starve forever' while
 
85
    waiting for the mutex (not likely if the code within the mutex is
 
86
    short).
 
87
  */
 
88
  pthread_mutexattr_init(&my_fast_mutexattr);
 
89
  pthread_mutexattr_settype(&my_fast_mutexattr,
 
90
                            PTHREAD_MUTEX_ADAPTIVE_NP);
 
91
#endif
 
92
 
 
93
  pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
 
94
  pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
 
95
  pthread_cond_init(&THR_COND_threads, NULL);
66
96
  if (my_thread_init())
67
97
  {
68
98
    my_thread_global_end();                     /* Clean up */
74
104
 
75
105
void my_thread_global_end(void)
76
106
{
 
107
  struct timespec abstime;
 
108
  bool all_threads_killed= 1;
 
109
 
 
110
  set_timespec(abstime, my_thread_end_wait_time);
 
111
  pthread_mutex_lock(&THR_LOCK_threads);
 
112
  while (THR_thread_count > 0)
 
113
  {
 
114
    int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
 
115
                                      &abstime);
 
116
    if (error == ETIMEDOUT || error == ETIME)
 
117
    {
 
118
      /*
 
119
        We shouldn't give an error here, because if we don't have
 
120
        pthread_kill(), programs like mysqld can't ensure that all threads
 
121
        are killed when we enter here.
 
122
      */
 
123
      if (THR_thread_count)
 
124
        fprintf(stderr,
 
125
                "Error in my_thread_global_end(): %d threads didn't exit\n",
 
126
                THR_thread_count);
 
127
      all_threads_killed= 0;
 
128
      break;
 
129
    }
 
130
  }
 
131
  pthread_mutex_unlock(&THR_LOCK_threads);
 
132
 
 
133
  pthread_key_delete(THR_KEY_mysys);
 
134
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
135
  pthread_mutexattr_destroy(&my_fast_mutexattr);
 
136
#endif
 
137
  pthread_mutex_destroy(&THR_LOCK_lock);
 
138
  if (all_threads_killed)
 
139
  {
 
140
    pthread_mutex_destroy(&THR_LOCK_threads);
 
141
    pthread_cond_destroy(&THR_COND_threads);
 
142
  }
77
143
}
78
144
 
79
145
static uint64_t thread_id= 0;
91
157
 
92
158
bool my_thread_init(void)
93
159
{
94
 
  // We should mever see my_thread_init()  called twice
95
 
  if (THR_KEY_mysys.get())
96
 
    return 0;
97
 
 
98
 
  st_my_thread_var *tmp= new st_my_thread_var;
 
160
  bool error=0;
 
161
  st_my_thread_var *tmp= NULL;
 
162
 
 
163
#ifdef EXTRA_DEBUG_THREADS
 
164
  fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
 
165
          (uint32_t) pthread_self());
 
166
#endif
 
167
 
 
168
  if (pthread_getspecific(THR_KEY_mysys))
 
169
  {
 
170
#ifdef EXTRA_DEBUG_THREADS
 
171
    fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
 
172
            (long) pthread_self());
 
173
#endif
 
174
    goto end;
 
175
  }
 
176
  tmp= static_cast<st_my_thread_var *>(calloc(1, sizeof(*tmp)));
99
177
  if (tmp == NULL)
100
178
  {
101
 
    return true;
 
179
    error= 1;
 
180
    goto end;
102
181
  }
103
 
  THR_KEY_mysys.reset(tmp);
 
182
  pthread_setspecific(THR_KEY_mysys,tmp);
 
183
  tmp->pthread_self= pthread_self();
 
184
  pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
 
185
  pthread_cond_init(&tmp->suspend, NULL);
 
186
  tmp->init= 1;
104
187
 
105
 
  boost::mutex::scoped_lock scopedLock(THR_LOCK_threads);
 
188
  pthread_mutex_lock(&THR_LOCK_threads);
106
189
  tmp->id= ++thread_id;
 
190
  ++THR_thread_count;
 
191
  pthread_mutex_unlock(&THR_LOCK_threads);
107
192
 
108
 
  return false;
 
193
end:
 
194
  return error;
109
195
}
110
196
 
111
197
 
123
209
 
124
210
void my_thread_end(void)
125
211
{
 
212
  st_my_thread_var *tmp=
 
213
    static_cast<st_my_thread_var *>(pthread_getspecific(THR_KEY_mysys));
 
214
 
 
215
#ifdef EXTRA_DEBUG_THREADS
 
216
  fprintf(stderr,"my_thread_end(): tmp: 0x%lx  pthread_self: 0x%lx  thread_id: %ld\n",
 
217
          (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
 
218
#endif
 
219
  if (tmp && tmp->init)
 
220
  {
 
221
#if !defined(__bsdi__) && !defined(__OpenBSD__)
 
222
 /* bsdi and openbsd 3.5 dumps core here */
 
223
    pthread_cond_destroy(&tmp->suspend);
 
224
#endif
 
225
    pthread_mutex_destroy(&tmp->mutex);
 
226
    free(tmp);
 
227
 
 
228
    /*
 
229
      Decrement counter for number of running threads. We are using this
 
230
      in my_thread_global_end() to wait until all threads have called
 
231
      my_thread_end and thus freed all memory they have allocated in
 
232
      my_thread_init()
 
233
    */
 
234
    pthread_mutex_lock(&THR_LOCK_threads);
 
235
    assert(THR_thread_count != 0);
 
236
    if (--THR_thread_count == 0)
 
237
      pthread_cond_signal(&THR_COND_threads);
 
238
    pthread_mutex_unlock(&THR_LOCK_threads);
 
239
  }
126
240
}
127
241
 
128
242
struct st_my_thread_var *_my_thread_var(void)
129
243
{
130
 
  return THR_KEY_mysys.get();
 
244
  struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
 
245
  return tmp;
131
246
}
132
247
 
133
248
} /* namespace internal */