~ubuntu-branches/ubuntu/utopic/glib2.0/utopic

« back to all changes in this revision

Viewing changes to glib/gthread.c

Tags: upstream-2.12.12
ImportĀ upstreamĀ versionĀ 2.12.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GLIB - Library of useful routines for C programming
 
2
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
 
3
 *
 
4
 * gthread.c: MT safety related functions
 
5
 * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe
 
6
 *                Owen Taylor
 
7
 *
 
8
 * This library is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU Lesser General Public
 
10
 * License as published by the Free Software Foundation; either
 
11
 * version 2 of the License, or (at your option) any later version.
 
12
 *
 
13
 * This library is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 * Lesser General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU Lesser General Public
 
19
 * License along with this library; if not, write to the
 
20
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
21
 * Boston, MA 02111-1307, USA.
 
22
 */
 
23
 
 
24
/*
 
25
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
 
26
 * file for a list of people on the GLib Team.  See the ChangeLog
 
27
 * files for a list of changes.  These files are distributed with
 
28
 * GLib at ftp://ftp.gtk.org/pub/gtk/.
 
29
 */
 
30
 
 
31
/*
 
32
 * MT safe
 
33
 */
 
34
 
 
35
#include "config.h"
 
36
 
 
37
#include "glib.h"
 
38
#include "gthreadprivate.h"
 
39
 
 
40
#ifdef HAVE_UNISTD_H
 
41
#include <unistd.h>
 
42
#endif
 
43
 
 
44
#ifndef G_OS_WIN32
 
45
#include <sys/time.h>
 
46
#include <time.h>
 
47
#else
 
48
#include <windows.h>
 
49
#endif /* G_OS_WIN32 */
 
50
 
 
51
#include <string.h>
 
52
 
 
53
#include "galias.h"
 
54
 
 
55
GQuark
 
56
g_thread_error_quark (void)
 
57
{
 
58
  return g_quark_from_static_string ("g_thread_error");
 
59
}
 
60
 
 
61
/* Keep this in sync with GRealThread in gmain.c! */
 
62
typedef struct _GRealThread GRealThread;
 
63
struct  _GRealThread
 
64
{
 
65
  GThread thread;
 
66
  gpointer private_data;
 
67
  GRealThread *next;
 
68
  gpointer retval;
 
69
  GSystemThread system_thread;
 
70
};
 
71
 
 
72
typedef struct _GStaticPrivateNode GStaticPrivateNode;
 
73
struct _GStaticPrivateNode
 
74
{
 
75
  gpointer       data;
 
76
  GDestroyNotify destroy;
 
77
};
 
78
 
 
79
static void    g_thread_cleanup (gpointer data);
 
80
static void    g_thread_fail (void);
 
81
static guint64 gettime (void);
 
82
 
 
83
guint64        (*g_thread_gettime) (void) = gettime;
 
84
 
 
85
/* Global variables */
 
86
 
 
87
static GSystemThread zero_thread; /* This is initialized to all zero */
 
88
gboolean g_thread_use_default_impl = TRUE;
 
89
gboolean g_threads_got_initialized = FALSE;
 
90
 
 
91
GThreadFunctions g_thread_functions_for_glib_use = {
 
92
  (GMutex*(*)())g_thread_fail,                 /* mutex_new */
 
93
  NULL,                                        /* mutex_lock */
 
94
  NULL,                                        /* mutex_trylock */
 
95
  NULL,                                        /* mutex_unlock */
 
96
  NULL,                                        /* mutex_free */
 
97
  (GCond*(*)())g_thread_fail,                  /* cond_new */
 
98
  NULL,                                        /* cond_signal */
 
99
  NULL,                                        /* cond_broadcast */
 
100
  NULL,                                        /* cond_wait */
 
101
  NULL,                                        /* cond_timed_wait  */
 
102
  NULL,                                        /* cond_free */
 
103
  (GPrivate*(*)(GDestroyNotify))g_thread_fail, /* private_new */
 
104
  NULL,                                        /* private_get */
 
105
  NULL,                                        /* private_set */
 
106
  (void(*)(GThreadFunc, gpointer, gulong,
 
107
           gboolean, gboolean, GThreadPriority,
 
108
           gpointer, GError**))g_thread_fail,  /* thread_create */
 
109
  NULL,                                        /* thread_yield */
 
110
  NULL,                                        /* thread_join */
 
111
  NULL,                                        /* thread_exit */
 
112
  NULL,                                        /* thread_set_priority */
 
113
  NULL,                                        /* thread_self */
 
114
  NULL                                         /* thread_equal */
 
115
};
 
116
 
 
117
/* Local data */
 
118
 
 
119
static GMutex   *g_once_mutex = NULL;
 
120
static GCond    *g_once_cond = NULL;
 
121
static GPrivate *g_thread_specific_private = NULL;
 
122
static GRealThread *g_thread_all_threads = NULL;
 
123
static GSList   *g_thread_free_indeces = NULL;
 
124
 
 
125
G_LOCK_DEFINE_STATIC (g_thread);
 
126
 
 
127
#ifdef G_THREADS_ENABLED
 
128
/* This must be called only once, before any threads are created.
 
129
 * It will only be called from g_thread_init() in -lgthread.
 
130
 */
 
131
void
 
132
g_thread_init_glib (void)
 
133
{
 
134
  /* We let the main thread (the one that calls g_thread_init) inherit
 
135
   * the static_private data set before calling g_thread_init
 
136
   */
 
137
  GRealThread* main_thread = (GRealThread*) g_thread_self ();
 
138
 
 
139
  /* mutex and cond creation works without g_threads_got_initialized */
 
140
  g_once_mutex = g_mutex_new ();
 
141
  g_once_cond = g_cond_new ();
 
142
 
 
143
  /* we may only create mutex and cond in here */
 
144
  _g_mem_thread_init_noprivate_nomessage ();
 
145
 
 
146
  /* setup the basic threading system */
 
147
  g_threads_got_initialized = TRUE;
 
148
  g_thread_specific_private = g_private_new (g_thread_cleanup);
 
149
  g_private_set (g_thread_specific_private, main_thread);
 
150
  G_THREAD_UF (thread_self, (&main_thread->system_thread));
 
151
 
 
152
  /* complete memory system initialization, g_private_*() works now */
 
153
  _g_slice_thread_init_nomessage ();
 
154
 
 
155
  /* accomplish log system initialization to enable messaging */
 
156
  _g_messages_thread_init_nomessage ();
 
157
 
 
158
  /* we may run full-fledged initializers from here */
 
159
  _g_atomic_thread_init ();
 
160
  _g_convert_thread_init ();
 
161
  _g_rand_thread_init ();
 
162
  _g_main_thread_init ();
 
163
  _g_utils_thread_init ();
 
164
#ifdef G_OS_WIN32
 
165
  _g_win32_thread_init ();
 
166
#endif
 
167
}
 
168
#endif /* G_THREADS_ENABLED */
 
169
 
 
170
gpointer
 
171
g_once_impl (GOnce       *once,
 
172
             GThreadFunc  func,
 
173
             gpointer     arg)
 
174
{
 
175
  g_mutex_lock (g_once_mutex);
 
176
 
 
177
  while (once->status == G_ONCE_STATUS_PROGRESS)
 
178
    g_cond_wait (g_once_cond, g_once_mutex);
 
179
 
 
180
  if (once->status != G_ONCE_STATUS_READY)
 
181
    {
 
182
      once->status = G_ONCE_STATUS_PROGRESS;
 
183
      g_mutex_unlock (g_once_mutex);
 
184
 
 
185
      once->retval = func (arg);
 
186
 
 
187
      g_mutex_lock (g_once_mutex);
 
188
      once->status = G_ONCE_STATUS_READY;
 
189
      g_cond_broadcast (g_once_cond);
 
190
    }
 
191
 
 
192
  g_mutex_unlock (g_once_mutex);
 
193
 
 
194
  return once->retval;
 
195
}
 
196
 
 
197
void
 
198
g_static_mutex_init (GStaticMutex *mutex)
 
199
{
 
200
  static const GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
 
201
 
 
202
  g_return_if_fail (mutex);
 
203
 
 
204
  *mutex = init_mutex;
 
205
}
 
206
 
 
207
GMutex *
 
208
g_static_mutex_get_mutex_impl (GMutex** mutex)
 
209
{
 
210
  if (!g_thread_supported ())
 
211
    return NULL;
 
212
 
 
213
  g_assert (g_once_mutex);
 
214
 
 
215
  g_mutex_lock (g_once_mutex);
 
216
 
 
217
  if (!(*mutex))
 
218
    g_atomic_pointer_set (mutex, g_mutex_new());
 
219
 
 
220
  g_mutex_unlock (g_once_mutex);
 
221
 
 
222
  return *mutex;
 
223
}
 
224
 
 
225
void
 
226
g_static_mutex_free (GStaticMutex* mutex)
 
227
{
 
228
  GMutex **runtime_mutex;
 
229
 
 
230
  g_return_if_fail (mutex);
 
231
 
 
232
  /* The runtime_mutex is the first (or only) member of GStaticMutex,
 
233
   * see both versions (of glibconfig.h) in configure.in */
 
234
  runtime_mutex = ((GMutex**)mutex);
 
235
 
 
236
  if (*runtime_mutex)
 
237
    g_mutex_free (*runtime_mutex);
 
238
 
 
239
  *runtime_mutex = NULL;
 
240
}
 
241
 
 
242
void
 
243
g_static_rec_mutex_init (GStaticRecMutex *mutex)
 
244
{
 
245
  static const GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
 
246
 
 
247
  g_return_if_fail (mutex);
 
248
 
 
249
  *mutex = init_mutex;
 
250
}
 
251
 
 
252
void
 
253
g_static_rec_mutex_lock (GStaticRecMutex* mutex)
 
254
{
 
255
  GSystemThread self;
 
256
 
 
257
  g_return_if_fail (mutex);
 
258
 
 
259
  if (!g_thread_supported ())
 
260
    return;
 
261
 
 
262
  G_THREAD_UF (thread_self, (&self));
 
263
 
 
264
  if (g_system_thread_equal (self, mutex->owner))
 
265
    {
 
266
      mutex->depth++;
 
267
      return;
 
268
    }
 
269
  g_static_mutex_lock (&mutex->mutex);
 
270
  g_system_thread_assign (mutex->owner, self);
 
271
  mutex->depth = 1;
 
272
}
 
273
 
 
274
gboolean
 
275
g_static_rec_mutex_trylock (GStaticRecMutex* mutex)
 
276
{
 
277
  GSystemThread self;
 
278
 
 
279
  g_return_val_if_fail (mutex, FALSE);
 
280
 
 
281
  if (!g_thread_supported ())
 
282
    return TRUE;
 
283
 
 
284
  G_THREAD_UF (thread_self, (&self));
 
285
 
 
286
  if (g_system_thread_equal (self, mutex->owner))
 
287
    {
 
288
      mutex->depth++;
 
289
      return TRUE;
 
290
    }
 
291
 
 
292
  if (!g_static_mutex_trylock (&mutex->mutex))
 
293
    return FALSE;
 
294
 
 
295
  g_system_thread_assign (mutex->owner, self);
 
296
  mutex->depth = 1;
 
297
  return TRUE;
 
298
}
 
299
 
 
300
void
 
301
g_static_rec_mutex_unlock (GStaticRecMutex* mutex)
 
302
{
 
303
  g_return_if_fail (mutex);
 
304
 
 
305
  if (!g_thread_supported ())
 
306
    return;
 
307
 
 
308
  if (mutex->depth > 1)
 
309
    {
 
310
      mutex->depth--;
 
311
      return;
 
312
    }
 
313
  g_system_thread_assign (mutex->owner, zero_thread);
 
314
  g_static_mutex_unlock (&mutex->mutex);
 
315
}
 
316
 
 
317
void
 
318
g_static_rec_mutex_lock_full   (GStaticRecMutex *mutex,
 
319
                                guint            depth)
 
320
{
 
321
  GSystemThread self;
 
322
  g_return_if_fail (mutex);
 
323
 
 
324
  if (!g_thread_supported ())
 
325
    return;
 
326
 
 
327
  if (depth == 0)
 
328
    return;
 
329
 
 
330
  G_THREAD_UF (thread_self, (&self));
 
331
 
 
332
  if (g_system_thread_equal (self, mutex->owner))
 
333
    {
 
334
      mutex->depth += depth;
 
335
      return;
 
336
    }
 
337
  g_static_mutex_lock (&mutex->mutex);
 
338
  g_system_thread_assign (mutex->owner, self);
 
339
  mutex->depth = depth;
 
340
}
 
341
 
 
342
guint
 
343
g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex)
 
344
{
 
345
  guint depth;
 
346
 
 
347
  g_return_val_if_fail (mutex, 0);
 
348
 
 
349
  if (!g_thread_supported ())
 
350
    return 1;
 
351
 
 
352
  depth = mutex->depth;
 
353
 
 
354
  g_system_thread_assign (mutex->owner, zero_thread);
 
355
  mutex->depth = 0;
 
356
  g_static_mutex_unlock (&mutex->mutex);
 
357
 
 
358
  return depth;
 
359
}
 
360
 
 
361
void
 
362
g_static_rec_mutex_free (GStaticRecMutex *mutex)
 
363
{
 
364
  g_return_if_fail (mutex);
 
365
 
 
366
  g_static_mutex_free (&mutex->mutex);
 
367
}
 
368
 
 
369
void
 
370
g_static_private_init (GStaticPrivate *private_key)
 
371
{
 
372
  private_key->index = 0;
 
373
}
 
374
 
 
375
gpointer
 
376
g_static_private_get (GStaticPrivate *private_key)
 
377
{
 
378
  GRealThread *self = (GRealThread*) g_thread_self ();
 
379
  GArray *array;
 
380
 
 
381
  array = self->private_data;
 
382
  if (!array)
 
383
    return NULL;
 
384
 
 
385
  if (!private_key->index)
 
386
    return NULL;
 
387
  else if (private_key->index <= array->len)
 
388
    return g_array_index (array, GStaticPrivateNode,
 
389
                          private_key->index - 1).data;
 
390
  else
 
391
    return NULL;
 
392
}
 
393
 
 
394
void
 
395
g_static_private_set (GStaticPrivate *private_key,
 
396
                      gpointer        data,
 
397
                      GDestroyNotify  notify)
 
398
{
 
399
  GRealThread *self = (GRealThread*) g_thread_self ();
 
400
  GArray *array;
 
401
  static guint next_index = 0;
 
402
  GStaticPrivateNode *node;
 
403
 
 
404
  array = self->private_data;
 
405
  if (!array)
 
406
    {
 
407
      array = g_array_new (FALSE, TRUE, sizeof (GStaticPrivateNode));
 
408
      self->private_data = array;
 
409
    }
 
410
 
 
411
  if (!private_key->index)
 
412
    {
 
413
      G_LOCK (g_thread);
 
414
 
 
415
      if (!private_key->index)
 
416
        {
 
417
          if (g_thread_free_indeces)
 
418
            {
 
419
              private_key->index =
 
420
                GPOINTER_TO_UINT (g_thread_free_indeces->data);
 
421
              g_thread_free_indeces =
 
422
                g_slist_delete_link (g_thread_free_indeces,
 
423
                                     g_thread_free_indeces);
 
424
            }
 
425
          else
 
426
            private_key->index = ++next_index;
 
427
        }
 
428
 
 
429
      G_UNLOCK (g_thread);
 
430
    }
 
431
 
 
432
  if (private_key->index > array->len)
 
433
    g_array_set_size (array, private_key->index);
 
434
 
 
435
  node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
 
436
  if (node->destroy)
 
437
    {
 
438
      gpointer ddata = node->data;
 
439
      GDestroyNotify ddestroy = node->destroy;
 
440
 
 
441
      node->data = data;
 
442
      node->destroy = notify;
 
443
 
 
444
      ddestroy (ddata);
 
445
    }
 
446
  else
 
447
    {
 
448
      node->data = data;
 
449
      node->destroy = notify;
 
450
    }
 
451
}
 
452
 
 
453
void
 
454
g_static_private_free (GStaticPrivate *private_key)
 
455
{
 
456
  guint index = private_key->index;
 
457
  GRealThread *thread;
 
458
 
 
459
  if (!index)
 
460
    return;
 
461
 
 
462
  private_key->index = 0;
 
463
 
 
464
  G_LOCK (g_thread);
 
465
 
 
466
  thread = g_thread_all_threads;
 
467
  while (thread)
 
468
    {
 
469
      GArray *array = thread->private_data;
 
470
      thread = thread->next;
 
471
 
 
472
      if (array && index <= array->len)
 
473
        {
 
474
          GStaticPrivateNode *node = &g_array_index (array,
 
475
                                                     GStaticPrivateNode,
 
476
                                                     index - 1);
 
477
          gpointer ddata = node->data;
 
478
          GDestroyNotify ddestroy = node->destroy;
 
479
 
 
480
          node->data = NULL;
 
481
          node->destroy = NULL;
 
482
 
 
483
          if (ddestroy)
 
484
            {
 
485
              G_UNLOCK (g_thread);
 
486
              ddestroy (ddata);
 
487
              G_LOCK (g_thread);
 
488
              }
 
489
        }
 
490
    }
 
491
  g_thread_free_indeces = g_slist_prepend (g_thread_free_indeces,
 
492
                                           GUINT_TO_POINTER (index));
 
493
  G_UNLOCK (g_thread);
 
494
}
 
495
 
 
496
static void
 
497
g_thread_cleanup (gpointer data)
 
498
{
 
499
  if (data)
 
500
    {
 
501
      GRealThread* thread = data;
 
502
      if (thread->private_data)
 
503
        {
 
504
          GArray* array = thread->private_data;
 
505
          guint i;
 
506
 
 
507
          for (i = 0; i < array->len; i++ )
 
508
            {
 
509
              GStaticPrivateNode *node =
 
510
                &g_array_index (array, GStaticPrivateNode, i);
 
511
              if (node->destroy)
 
512
                node->destroy (node->data);
 
513
            }
 
514
          g_array_free (array, TRUE);
 
515
        }
 
516
 
 
517
      /* We only free the thread structure, if it isn't joinable. If
 
518
         it is, the structure is freed in g_thread_join */
 
519
      if (!thread->thread.joinable)
 
520
        {
 
521
          GRealThread *t, *p;
 
522
 
 
523
          G_LOCK (g_thread);
 
524
          for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
 
525
            {
 
526
              if (t == thread)
 
527
                {
 
528
                  if (p)
 
529
                    p->next = t->next;
 
530
                  else
 
531
                    g_thread_all_threads = t->next;
 
532
                  break;
 
533
                }
 
534
            }
 
535
          G_UNLOCK (g_thread);
 
536
 
 
537
          /* Just to make sure, this isn't used any more */
 
538
          g_system_thread_assign (thread->system_thread, zero_thread);
 
539
          g_free (thread);
 
540
        }
 
541
    }
 
542
}
 
543
 
 
544
static void
 
545
g_thread_fail (void)
 
546
{
 
547
  g_error ("The thread system is not yet initialized.");
 
548
}
 
549
 
 
550
#define G_NSEC_PER_SEC 1000000000
 
551
 
 
552
static guint64
 
553
gettime (void)
 
554
{
 
555
#ifdef G_OS_WIN32
 
556
  guint64 v;
 
557
 
 
558
  /* Returns 100s of nanoseconds since start of 1601 */
 
559
  GetSystemTimeAsFileTime ((FILETIME *)&v);
 
560
 
 
561
  /* Offset to Unix epoch */
 
562
  v -= G_GINT64_CONSTANT (116444736000000000);
 
563
  /* Convert to nanoseconds */
 
564
  v *= 100;
 
565
 
 
566
  return v;
 
567
#else
 
568
  struct timeval tv;
 
569
 
 
570
  gettimeofday (&tv, NULL);
 
571
 
 
572
  return (guint64) tv.tv_sec * G_NSEC_PER_SEC + tv.tv_usec * (G_NSEC_PER_SEC / G_USEC_PER_SEC); 
 
573
#endif
 
574
}
 
575
 
 
576
static gpointer
 
577
g_thread_create_proxy (gpointer data)
 
578
{
 
579
  GRealThread* thread = data;
 
580
 
 
581
  g_assert (data);
 
582
 
 
583
  /* This has to happen before G_LOCK, as that might call g_thread_self */
 
584
  g_private_set (g_thread_specific_private, data);
 
585
 
 
586
  /* the lock makes sure, that thread->system_thread is written,
 
587
     before thread->thread.func is called. See g_thread_create. */
 
588
  G_LOCK (g_thread);
 
589
  G_UNLOCK (g_thread);
 
590
 
 
591
  thread->retval = thread->thread.func (thread->thread.data);
 
592
 
 
593
  return NULL;
 
594
}
 
595
 
 
596
GThread*
 
597
g_thread_create_full (GThreadFunc                func,
 
598
                      gpointer           data,
 
599
                      gulong             stack_size,
 
600
                      gboolean           joinable,
 
601
                      gboolean           bound,
 
602
                      GThreadPriority    priority,
 
603
                      GError                **error)
 
604
{
 
605
  GRealThread* result;
 
606
  GError *local_error = NULL;
 
607
  g_return_val_if_fail (func, NULL);
 
608
  g_return_val_if_fail (priority >= G_THREAD_PRIORITY_LOW, NULL);
 
609
  g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL);
 
610
 
 
611
  result = g_new0 (GRealThread, 1);
 
612
 
 
613
  result->thread.joinable = joinable;
 
614
  result->thread.priority = priority;
 
615
  result->thread.func = func;
 
616
  result->thread.data = data;
 
617
  result->private_data = NULL;
 
618
  G_LOCK (g_thread);
 
619
  G_THREAD_UF (thread_create, (g_thread_create_proxy, result,
 
620
                               stack_size, joinable, bound, priority,
 
621
                               &result->system_thread, &local_error));
 
622
  result->next = g_thread_all_threads;
 
623
  g_thread_all_threads = result;
 
624
  G_UNLOCK (g_thread);
 
625
 
 
626
  if (local_error)
 
627
    {
 
628
      g_propagate_error (error, local_error);
 
629
      g_free (result);
 
630
      return NULL;
 
631
    }
 
632
 
 
633
  return (GThread*) result;
 
634
}
 
635
 
 
636
void
 
637
g_thread_exit (gpointer retval)
 
638
{
 
639
  GRealThread* real = (GRealThread*) g_thread_self ();
 
640
  real->retval = retval;
 
641
  G_THREAD_CF (thread_exit, (void)0, ());
 
642
}
 
643
 
 
644
gpointer
 
645
g_thread_join (GThread* thread)
 
646
{
 
647
  GRealThread* real = (GRealThread*) thread;
 
648
  GRealThread *p, *t;
 
649
  gpointer retval;
 
650
 
 
651
  g_return_val_if_fail (thread, NULL);
 
652
  g_return_val_if_fail (thread->joinable, NULL);
 
653
  g_return_val_if_fail (!g_system_thread_equal (real->system_thread,
 
654
                                                zero_thread), NULL);
 
655
 
 
656
  G_THREAD_UF (thread_join, (&real->system_thread));
 
657
 
 
658
  retval = real->retval;
 
659
 
 
660
  G_LOCK (g_thread);
 
661
  for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
 
662
    {
 
663
      if (t == (GRealThread*) thread)
 
664
        {
 
665
          if (p)
 
666
            p->next = t->next;
 
667
          else
 
668
            g_thread_all_threads = t->next;
 
669
          break;
 
670
        }
 
671
    }
 
672
  G_UNLOCK (g_thread);
 
673
 
 
674
  /* Just to make sure, this isn't used any more */
 
675
  thread->joinable = 0;
 
676
  g_system_thread_assign (real->system_thread, zero_thread);
 
677
 
 
678
  /* the thread structure for non-joinable threads is freed upon
 
679
     thread end. We free the memory here. This will leave a loose end,
 
680
     if a joinable thread is not joined. */
 
681
 
 
682
  g_free (thread);
 
683
 
 
684
  return retval;
 
685
}
 
686
 
 
687
void
 
688
g_thread_set_priority (GThread* thread,
 
689
                       GThreadPriority priority)
 
690
{
 
691
  GRealThread* real = (GRealThread*) thread;
 
692
 
 
693
  g_return_if_fail (thread);
 
694
  g_return_if_fail (!g_system_thread_equal (real->system_thread, zero_thread));
 
695
  g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW);
 
696
  g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
 
697
 
 
698
  thread->priority = priority;
 
699
 
 
700
  G_THREAD_CF (thread_set_priority, (void)0,
 
701
               (&real->system_thread, priority));
 
702
}
 
703
 
 
704
GThread*
 
705
g_thread_self (void)
 
706
{
 
707
  GRealThread* thread = g_private_get (g_thread_specific_private);
 
708
 
 
709
  if (!thread)
 
710
    {
 
711
      /* If no thread data is available, provide and set one.  This
 
712
         can happen for the main thread and for threads, that are not
 
713
         created by GLib. */
 
714
      thread = g_new0 (GRealThread, 1);
 
715
      thread->thread.joinable = FALSE; /* This is a save guess */
 
716
      thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is
 
717
                                                             just a guess */
 
718
      thread->thread.func = NULL;
 
719
      thread->thread.data = NULL;
 
720
      thread->private_data = NULL;
 
721
 
 
722
      if (g_thread_supported ())
 
723
        G_THREAD_UF (thread_self, (&thread->system_thread));
 
724
 
 
725
      g_private_set (g_thread_specific_private, thread);
 
726
 
 
727
      G_LOCK (g_thread);
 
728
      thread->next = g_thread_all_threads;
 
729
      g_thread_all_threads = thread;
 
730
      G_UNLOCK (g_thread);
 
731
    }
 
732
 
 
733
  return (GThread*)thread;
 
734
}
 
735
 
 
736
void
 
737
g_static_rw_lock_init (GStaticRWLock* lock)
 
738
{
 
739
  static const GStaticRWLock init_lock = G_STATIC_RW_LOCK_INIT;
 
740
 
 
741
  g_return_if_fail (lock);
 
742
 
 
743
  *lock = init_lock;
 
744
}
 
745
 
 
746
inline static void
 
747
g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
 
748
{
 
749
  if (!*cond)
 
750
      *cond = g_cond_new ();
 
751
  g_cond_wait (*cond, g_static_mutex_get_mutex (mutex));
 
752
}
 
753
 
 
754
inline static void
 
755
g_static_rw_lock_signal (GStaticRWLock* lock)
 
756
{
 
757
  if (lock->want_to_write && lock->write_cond)
 
758
    g_cond_signal (lock->write_cond);
 
759
  else if (lock->want_to_read && lock->read_cond)
 
760
    g_cond_broadcast (lock->read_cond);
 
761
}
 
762
 
 
763
void
 
764
g_static_rw_lock_reader_lock (GStaticRWLock* lock)
 
765
{
 
766
  g_return_if_fail (lock);
 
767
 
 
768
  if (!g_threads_got_initialized)
 
769
    return;
 
770
 
 
771
  g_static_mutex_lock (&lock->mutex);
 
772
  lock->want_to_read++;
 
773
  while (lock->have_writer || lock->want_to_write)
 
774
    g_static_rw_lock_wait (&lock->read_cond, &lock->mutex);
 
775
  lock->want_to_read--;
 
776
  lock->read_counter++;
 
777
  g_static_mutex_unlock (&lock->mutex);
 
778
}
 
779
 
 
780
gboolean
 
781
g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
 
782
{
 
783
  gboolean ret_val = FALSE;
 
784
 
 
785
  g_return_val_if_fail (lock, FALSE);
 
786
 
 
787
  if (!g_threads_got_initialized)
 
788
    return TRUE;
 
789
 
 
790
  g_static_mutex_lock (&lock->mutex);
 
791
  if (!lock->have_writer && !lock->want_to_write)
 
792
    {
 
793
      lock->read_counter++;
 
794
      ret_val = TRUE;
 
795
    }
 
796
  g_static_mutex_unlock (&lock->mutex);
 
797
  return ret_val;
 
798
}
 
799
 
 
800
void
 
801
g_static_rw_lock_reader_unlock  (GStaticRWLock* lock)
 
802
{
 
803
  g_return_if_fail (lock);
 
804
 
 
805
  if (!g_threads_got_initialized)
 
806
    return;
 
807
 
 
808
  g_static_mutex_lock (&lock->mutex);
 
809
  lock->read_counter--;
 
810
  if (lock->read_counter == 0)
 
811
    g_static_rw_lock_signal (lock);
 
812
  g_static_mutex_unlock (&lock->mutex);
 
813
}
 
814
 
 
815
void
 
816
g_static_rw_lock_writer_lock (GStaticRWLock* lock)
 
817
{
 
818
  g_return_if_fail (lock);
 
819
 
 
820
  if (!g_threads_got_initialized)
 
821
    return;
 
822
 
 
823
  g_static_mutex_lock (&lock->mutex);
 
824
  lock->want_to_write++;
 
825
  while (lock->have_writer || lock->read_counter)
 
826
    g_static_rw_lock_wait (&lock->write_cond, &lock->mutex);
 
827
  lock->want_to_write--;
 
828
  lock->have_writer = TRUE;
 
829
  g_static_mutex_unlock (&lock->mutex);
 
830
}
 
831
 
 
832
gboolean
 
833
g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
 
834
{
 
835
  gboolean ret_val = FALSE;
 
836
 
 
837
  g_return_val_if_fail (lock, FALSE);
 
838
 
 
839
  if (!g_threads_got_initialized)
 
840
    return TRUE;
 
841
 
 
842
  g_static_mutex_lock (&lock->mutex);
 
843
  if (!lock->have_writer && !lock->read_counter)
 
844
    {
 
845
      lock->have_writer = TRUE;
 
846
      ret_val = TRUE;
 
847
    }
 
848
  g_static_mutex_unlock (&lock->mutex);
 
849
  return ret_val;
 
850
}
 
851
 
 
852
void
 
853
g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
 
854
{
 
855
  g_return_if_fail (lock);
 
856
 
 
857
  if (!g_threads_got_initialized)
 
858
    return;
 
859
 
 
860
  g_static_mutex_lock (&lock->mutex);
 
861
  lock->have_writer = FALSE;
 
862
  g_static_rw_lock_signal (lock);
 
863
  g_static_mutex_unlock (&lock->mutex);
 
864
}
 
865
 
 
866
void
 
867
g_static_rw_lock_free (GStaticRWLock* lock)
 
868
{
 
869
  g_return_if_fail (lock);
 
870
 
 
871
  if (lock->read_cond)
 
872
    {
 
873
      g_cond_free (lock->read_cond);
 
874
      lock->read_cond = NULL;
 
875
    }
 
876
  if (lock->write_cond)
 
877
    {
 
878
      g_cond_free (lock->write_cond);
 
879
      lock->write_cond = NULL;
 
880
    }
 
881
  g_static_mutex_free (&lock->mutex);
 
882
}
 
883
 
 
884
/**
 
885
 * g_thread_foreach
 
886
 * @thread_func: function to call for all GThread structures
 
887
 * @user_data:   second argument to @thread_func
 
888
 *
 
889
 * Call @thread_func on all existing #GThread structures. Note that
 
890
 * threads may decide to exit while @thread_func is running, so
 
891
 * without intimate knowledge about the lifetime of foreign threads,
 
892
 * @thread_func shouldn't access the GThread* pointer passed in as
 
893
 * first argument. However, @thread_func will not be called for threads
 
894
 * which are known to have exited already.
 
895
 *
 
896
 * Due to thread lifetime checks, this function has an execution complexity
 
897
 * which is quadratic in the number of existing threads.
 
898
 *
 
899
 * Since: 2.10
 
900
 */
 
901
void
 
902
g_thread_foreach (GFunc    thread_func,
 
903
                  gpointer user_data)
 
904
{
 
905
  GSList *slist = NULL;
 
906
  GRealThread *thread;
 
907
  g_return_if_fail (thread_func != NULL);
 
908
  /* snapshot the list of threads for iteration */
 
909
  G_LOCK (g_thread);
 
910
  for (thread = g_thread_all_threads; thread; thread = thread->next)
 
911
    slist = g_slist_prepend (slist, thread);
 
912
  G_UNLOCK (g_thread);
 
913
  /* walk the list, skipping non-existant threads */
 
914
  while (slist)
 
915
    {
 
916
      GSList *node = slist;
 
917
      slist = node->next;
 
918
      /* check whether the current thread still exists */
 
919
      G_LOCK (g_thread);
 
920
      for (thread = g_thread_all_threads; thread; thread = thread->next)
 
921
        if (thread == node->data)
 
922
          break;
 
923
      G_UNLOCK (g_thread);
 
924
      if (thread)
 
925
        thread_func (thread, user_data);
 
926
      g_slist_free_1 (node);
 
927
    }
 
928
}
 
929
 
 
930
#define __G_THREAD_C__
 
931
#include "galiasdef.c"