1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * gthread.c: MT safety related functions
5 * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe
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.
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.
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.
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/.
44 #include "gthreadprivate.h"
48 g_thread_error_quark (void)
50 return g_quark_from_static_string ("g_thread_error");
53 /* Keep this in sync with GRealThread in gmain.c! */
54 typedef struct _GRealThread GRealThread
;
58 gpointer private_data
;
61 GSystemThread system_thread
;
64 typedef struct _GStaticPrivateNode GStaticPrivateNode
;
65 struct _GStaticPrivateNode
68 GDestroyNotify destroy
;
71 static void g_thread_cleanup (gpointer data
);
72 static void g_thread_fail (void);
74 /* Global variables */
76 static GSystemThread zero_thread
; /* This is initialized to all zero */
77 gboolean g_thread_use_default_impl
= TRUE
;
78 gboolean g_threads_got_initialized
= FALSE
;
80 GThreadFunctions g_thread_functions_for_glib_use
= {
81 (GMutex
*(*)())g_thread_fail
, /* mutex_new */
82 NULL
, /* mutex_lock */
83 NULL
, /* mutex_trylock */
84 NULL
, /* mutex_unlock */
85 NULL
, /* mutex_free */
86 (GCond
*(*)())g_thread_fail
, /* cond_new */
87 NULL
, /* cond_signal */
88 NULL
, /* cond_broadcast */
90 NULL
, /* cond_timed_wait */
92 (GPrivate
*(*)(GDestroyNotify
))g_thread_fail
, /* private_new */
93 NULL
, /* private_get */
94 NULL
, /* private_set */
95 (void(*)(GThreadFunc
, gpointer
, gulong
,
96 gboolean
, gboolean
, GThreadPriority
,
97 gpointer
, GError
**))g_thread_fail
, /* thread_create */
98 NULL
, /* thread_yield */
99 NULL
, /* thread_join */
100 NULL
, /* thread_exit */
101 NULL
, /* thread_set_priority */
102 NULL
/* thread_self */
107 static GMutex
*g_once_mutex
= NULL
;
108 static GCond
*g_once_cond
= NULL
;
109 static GPrivate
*g_thread_specific_private
= NULL
;
110 static GRealThread
*g_thread_all_threads
= NULL
;
111 static GSList
*g_thread_free_indeces
= NULL
;
113 G_LOCK_DEFINE_STATIC (g_thread
);
115 #ifdef G_THREADS_ENABLED
116 /* This must be called only once, before any threads are created.
117 * It will only be called from g_thread_init() in -lgthread.
120 g_thread_init_glib (void)
122 /* We let the main thread (the one that calls g_thread_init) inherit
123 * the static_private data set before calling g_thread_init
125 GRealThread
* main_thread
= (GRealThread
*) g_thread_self ();
127 /* mutex and cond creation works without g_threads_got_initialized */
128 g_once_mutex
= g_mutex_new ();
129 g_once_cond
= g_cond_new ();
131 /* we may only create mutex and cond in here */
132 _g_mem_thread_init_noprivate_nomessage ();
134 /* setup the basic threading system */
135 g_threads_got_initialized
= TRUE
;
136 g_thread_specific_private
= g_private_new (g_thread_cleanup
);
137 g_private_set (g_thread_specific_private
, main_thread
);
138 G_THREAD_UF (thread_self
, (&main_thread
->system_thread
));
140 /* complete memory system initialization, g_private_*() works now */
141 _g_slice_thread_init_nomessage ();
143 /* accomplish log system initialization to enable messaging */
144 _g_messages_thread_init_nomessage ();
146 /* we may run full-fledged initializers from here */
147 _g_atomic_thread_init ();
148 _g_convert_thread_init ();
149 _g_rand_thread_init ();
150 _g_main_thread_init ();
151 _g_utils_thread_init ();
153 _g_win32_thread_init ();
156 #endif /* G_THREADS_ENABLED */
159 g_once_impl (GOnce
*once
,
163 g_mutex_lock (g_once_mutex
);
165 while (once
->status
== G_ONCE_STATUS_PROGRESS
)
166 g_cond_wait (g_once_cond
, g_once_mutex
);
168 if (once
->status
!= G_ONCE_STATUS_READY
)
170 once
->status
= G_ONCE_STATUS_PROGRESS
;
171 g_mutex_unlock (g_once_mutex
);
173 once
->retval
= func (arg
);
175 g_mutex_lock (g_once_mutex
);
176 once
->status
= G_ONCE_STATUS_READY
;
177 g_cond_broadcast (g_once_cond
);
180 g_mutex_unlock (g_once_mutex
);
186 g_static_mutex_init (GStaticMutex
*mutex
)
188 static const GStaticMutex init_mutex
= G_STATIC_MUTEX_INIT
;
190 g_return_if_fail (mutex
);
196 g_static_mutex_get_mutex_impl (GMutex
** mutex
)
198 if (!g_thread_supported ())
201 g_assert (g_once_mutex
);
203 g_mutex_lock (g_once_mutex
);
206 g_atomic_pointer_set (mutex
, g_mutex_new());
208 g_mutex_unlock (g_once_mutex
);
214 g_static_mutex_free (GStaticMutex
* mutex
)
216 GMutex
**runtime_mutex
;
218 g_return_if_fail (mutex
);
220 /* The runtime_mutex is the first (or only) member of GStaticMutex,
221 * see both versions (of glibconfig.h) in configure.in */
222 runtime_mutex
= ((GMutex
**)mutex
);
225 g_mutex_free (*runtime_mutex
);
227 *runtime_mutex
= NULL
;
231 g_static_rec_mutex_init (GStaticRecMutex
*mutex
)
233 static const GStaticRecMutex init_mutex
= G_STATIC_REC_MUTEX_INIT
;
235 g_return_if_fail (mutex
);
241 g_static_rec_mutex_lock (GStaticRecMutex
* mutex
)
245 g_return_if_fail (mutex
);
247 if (!g_thread_supported ())
250 G_THREAD_UF (thread_self
, (&self
));
252 if (g_system_thread_equal (self
, mutex
->owner
))
257 g_static_mutex_lock (&mutex
->mutex
);
258 g_system_thread_assign (mutex
->owner
, self
);
263 g_static_rec_mutex_trylock (GStaticRecMutex
* mutex
)
267 g_return_val_if_fail (mutex
, FALSE
);
269 if (!g_thread_supported ())
272 G_THREAD_UF (thread_self
, (&self
));
274 if (g_system_thread_equal (self
, mutex
->owner
))
280 if (!g_static_mutex_trylock (&mutex
->mutex
))
283 g_system_thread_assign (mutex
->owner
, self
);
289 g_static_rec_mutex_unlock (GStaticRecMutex
* mutex
)
291 g_return_if_fail (mutex
);
293 if (!g_thread_supported ())
296 if (mutex
->depth
> 1)
301 g_system_thread_assign (mutex
->owner
, zero_thread
);
302 g_static_mutex_unlock (&mutex
->mutex
);
306 g_static_rec_mutex_lock_full (GStaticRecMutex
*mutex
,
310 g_return_if_fail (mutex
);
312 if (!g_thread_supported ())
318 G_THREAD_UF (thread_self
, (&self
));
320 if (g_system_thread_equal (self
, mutex
->owner
))
322 mutex
->depth
+= depth
;
325 g_static_mutex_lock (&mutex
->mutex
);
326 g_system_thread_assign (mutex
->owner
, self
);
327 mutex
->depth
= depth
;
331 g_static_rec_mutex_unlock_full (GStaticRecMutex
*mutex
)
335 g_return_val_if_fail (mutex
, 0);
337 if (!g_thread_supported ())
340 depth
= mutex
->depth
;
342 g_system_thread_assign (mutex
->owner
, zero_thread
);
344 g_static_mutex_unlock (&mutex
->mutex
);
350 g_static_rec_mutex_free (GStaticRecMutex
*mutex
)
352 g_return_if_fail (mutex
);
354 g_static_mutex_free (&mutex
->mutex
);
358 g_static_private_init (GStaticPrivate
*private_key
)
360 private_key
->index
= 0;
364 g_static_private_get (GStaticPrivate
*private_key
)
366 GRealThread
*self
= (GRealThread
*) g_thread_self ();
369 array
= self
->private_data
;
373 if (!private_key
->index
)
375 else if (private_key
->index
<= array
->len
)
376 return g_array_index (array
, GStaticPrivateNode
,
377 private_key
->index
- 1).data
;
383 g_static_private_set (GStaticPrivate
*private_key
,
385 GDestroyNotify notify
)
387 GRealThread
*self
= (GRealThread
*) g_thread_self ();
389 static guint next_index
= 0;
390 GStaticPrivateNode
*node
;
392 array
= self
->private_data
;
395 array
= g_array_new (FALSE
, TRUE
, sizeof (GStaticPrivateNode
));
396 self
->private_data
= array
;
399 if (!private_key
->index
)
403 if (!private_key
->index
)
405 if (g_thread_free_indeces
)
408 GPOINTER_TO_UINT (g_thread_free_indeces
->data
);
409 g_thread_free_indeces
=
410 g_slist_delete_link (g_thread_free_indeces
,
411 g_thread_free_indeces
);
414 private_key
->index
= ++next_index
;
420 if (private_key
->index
> array
->len
)
421 g_array_set_size (array
, private_key
->index
);
423 node
= &g_array_index (array
, GStaticPrivateNode
, private_key
->index
- 1);
426 gpointer ddata
= node
->data
;
427 GDestroyNotify ddestroy
= node
->destroy
;
430 node
->destroy
= notify
;
437 node
->destroy
= notify
;
442 g_static_private_free (GStaticPrivate
*private_key
)
444 guint index
= private_key
->index
;
450 private_key
->index
= 0;
454 thread
= g_thread_all_threads
;
457 GArray
*array
= thread
->private_data
;
458 thread
= thread
->next
;
460 if (array
&& index
<= array
->len
)
462 GStaticPrivateNode
*node
= &g_array_index (array
,
465 gpointer ddata
= node
->data
;
466 GDestroyNotify ddestroy
= node
->destroy
;
469 node
->destroy
= NULL
;
479 g_thread_free_indeces
= g_slist_prepend (g_thread_free_indeces
,
480 GUINT_TO_POINTER (index
));
485 g_thread_cleanup (gpointer data
)
489 GRealThread
* thread
= data
;
490 if (thread
->private_data
)
492 GArray
* array
= thread
->private_data
;
495 for (i
= 0; i
< array
->len
; i
++ )
497 GStaticPrivateNode
*node
=
498 &g_array_index (array
, GStaticPrivateNode
, i
);
500 node
->destroy (node
->data
);
502 g_array_free (array
, TRUE
);
505 /* We only free the thread structure, if it isn't joinable. If
506 it is, the structure is freed in g_thread_join */
507 if (!thread
->thread
.joinable
)
512 for (t
= g_thread_all_threads
, p
= NULL
; t
; p
= t
, t
= t
->next
)
519 g_thread_all_threads
= t
->next
;
525 /* Just to make sure, this isn't used any more */
526 g_system_thread_assign (thread
->system_thread
, zero_thread
);
535 g_error ("The thread system is not yet initialized.");
539 g_thread_create_proxy (gpointer data
)
541 GRealThread
* thread
= data
;
545 /* This has to happen before G_LOCK, as that might call g_thread_self */
546 g_private_set (g_thread_specific_private
, data
);
548 /* the lock makes sure, that thread->system_thread is written,
549 before thread->thread.func is called. See g_thread_create. */
553 thread
->retval
= thread
->thread
.func (thread
->thread
.data
);
559 g_thread_create_full (GThreadFunc func
,
564 GThreadPriority priority
,
568 GError
*local_error
= NULL
;
569 g_return_val_if_fail (func
, NULL
);
570 g_return_val_if_fail (priority
>= G_THREAD_PRIORITY_LOW
, NULL
);
571 g_return_val_if_fail (priority
<= G_THREAD_PRIORITY_URGENT
, NULL
);
573 result
= g_new0 (GRealThread
, 1);
575 result
->thread
.joinable
= joinable
;
576 result
->thread
.priority
= priority
;
577 result
->thread
.func
= func
;
578 result
->thread
.data
= data
;
579 result
->private_data
= NULL
;
581 G_THREAD_UF (thread_create
, (g_thread_create_proxy
, result
,
582 stack_size
, joinable
, bound
, priority
,
583 &result
->system_thread
, &local_error
));
584 result
->next
= g_thread_all_threads
;
585 g_thread_all_threads
= result
;
590 g_propagate_error (error
, local_error
);
595 return (GThread
*) result
;
599 g_thread_exit (gpointer retval
)
601 GRealThread
* real
= (GRealThread
*) g_thread_self ();
602 real
->retval
= retval
;
603 G_THREAD_CF (thread_exit
, (void)0, ());
607 g_thread_join (GThread
* thread
)
609 GRealThread
* real
= (GRealThread
*) thread
;
613 g_return_val_if_fail (thread
, NULL
);
614 g_return_val_if_fail (thread
->joinable
, NULL
);
615 g_return_val_if_fail (!g_system_thread_equal (real
->system_thread
,
618 G_THREAD_UF (thread_join
, (&real
->system_thread
));
620 retval
= real
->retval
;
623 for (t
= g_thread_all_threads
, p
= NULL
; t
; p
= t
, t
= t
->next
)
625 if (t
== (GRealThread
*) thread
)
630 g_thread_all_threads
= t
->next
;
636 /* Just to make sure, this isn't used any more */
637 thread
->joinable
= 0;
638 g_system_thread_assign (real
->system_thread
, zero_thread
);
640 /* the thread structure for non-joinable threads is freed upon
641 thread end. We free the memory here. This will leave a loose end,
642 if a joinable thread is not joined. */
650 g_thread_set_priority (GThread
* thread
,
651 GThreadPriority priority
)
653 GRealThread
* real
= (GRealThread
*) thread
;
655 g_return_if_fail (thread
);
656 g_return_if_fail (!g_system_thread_equal (real
->system_thread
, zero_thread
));
657 g_return_if_fail (priority
>= G_THREAD_PRIORITY_LOW
);
658 g_return_if_fail (priority
<= G_THREAD_PRIORITY_URGENT
);
660 thread
->priority
= priority
;
662 G_THREAD_CF (thread_set_priority
, (void)0,
663 (&real
->system_thread
, priority
));
669 GRealThread
* thread
= g_private_get (g_thread_specific_private
);
673 /* If no thread data is available, provide and set one. This
674 can happen for the main thread and for threads, that are not
676 thread
= g_new0 (GRealThread
, 1);
677 thread
->thread
.joinable
= FALSE
; /* This is a save guess */
678 thread
->thread
.priority
= G_THREAD_PRIORITY_NORMAL
; /* This is
680 thread
->thread
.func
= NULL
;
681 thread
->thread
.data
= NULL
;
682 thread
->private_data
= NULL
;
684 if (g_thread_supported ())
685 G_THREAD_UF (thread_self
, (&thread
->system_thread
));
687 g_private_set (g_thread_specific_private
, thread
);
690 thread
->next
= g_thread_all_threads
;
691 g_thread_all_threads
= thread
;
695 return (GThread
*)thread
;
699 g_static_rw_lock_init (GStaticRWLock
* lock
)
701 static const GStaticRWLock init_lock
= G_STATIC_RW_LOCK_INIT
;
703 g_return_if_fail (lock
);
709 g_static_rw_lock_wait (GCond
** cond
, GStaticMutex
* mutex
)
712 *cond
= g_cond_new ();
713 g_cond_wait (*cond
, g_static_mutex_get_mutex (mutex
));
717 g_static_rw_lock_signal (GStaticRWLock
* lock
)
719 if (lock
->want_to_write
&& lock
->write_cond
)
720 g_cond_signal (lock
->write_cond
);
721 else if (lock
->want_to_read
&& lock
->read_cond
)
722 g_cond_broadcast (lock
->read_cond
);
726 g_static_rw_lock_reader_lock (GStaticRWLock
* lock
)
728 g_return_if_fail (lock
);
730 if (!g_threads_got_initialized
)
733 g_static_mutex_lock (&lock
->mutex
);
734 lock
->want_to_read
++;
735 while (lock
->have_writer
|| lock
->want_to_write
)
736 g_static_rw_lock_wait (&lock
->read_cond
, &lock
->mutex
);
737 lock
->want_to_read
--;
738 lock
->read_counter
++;
739 g_static_mutex_unlock (&lock
->mutex
);
743 g_static_rw_lock_reader_trylock (GStaticRWLock
* lock
)
745 gboolean ret_val
= FALSE
;
747 g_return_val_if_fail (lock
, FALSE
);
749 if (!g_threads_got_initialized
)
752 g_static_mutex_lock (&lock
->mutex
);
753 if (!lock
->have_writer
&& !lock
->want_to_write
)
755 lock
->read_counter
++;
758 g_static_mutex_unlock (&lock
->mutex
);
763 g_static_rw_lock_reader_unlock (GStaticRWLock
* lock
)
765 g_return_if_fail (lock
);
767 if (!g_threads_got_initialized
)
770 g_static_mutex_lock (&lock
->mutex
);
771 lock
->read_counter
--;
772 if (lock
->read_counter
== 0)
773 g_static_rw_lock_signal (lock
);
774 g_static_mutex_unlock (&lock
->mutex
);
778 g_static_rw_lock_writer_lock (GStaticRWLock
* lock
)
780 g_return_if_fail (lock
);
782 if (!g_threads_got_initialized
)
785 g_static_mutex_lock (&lock
->mutex
);
786 lock
->want_to_write
++;
787 while (lock
->have_writer
|| lock
->read_counter
)
788 g_static_rw_lock_wait (&lock
->write_cond
, &lock
->mutex
);
789 lock
->want_to_write
--;
790 lock
->have_writer
= TRUE
;
791 g_static_mutex_unlock (&lock
->mutex
);
795 g_static_rw_lock_writer_trylock (GStaticRWLock
* lock
)
797 gboolean ret_val
= FALSE
;
799 g_return_val_if_fail (lock
, FALSE
);
801 if (!g_threads_got_initialized
)
804 g_static_mutex_lock (&lock
->mutex
);
805 if (!lock
->have_writer
&& !lock
->read_counter
)
807 lock
->have_writer
= TRUE
;
810 g_static_mutex_unlock (&lock
->mutex
);
815 g_static_rw_lock_writer_unlock (GStaticRWLock
* lock
)
817 g_return_if_fail (lock
);
819 if (!g_threads_got_initialized
)
822 g_static_mutex_lock (&lock
->mutex
);
823 lock
->have_writer
= FALSE
;
824 g_static_rw_lock_signal (lock
);
825 g_static_mutex_unlock (&lock
->mutex
);
829 g_static_rw_lock_free (GStaticRWLock
* lock
)
831 g_return_if_fail (lock
);
835 g_cond_free (lock
->read_cond
);
836 lock
->read_cond
= NULL
;
838 if (lock
->write_cond
)
840 g_cond_free (lock
->write_cond
);
841 lock
->write_cond
= NULL
;
843 g_static_mutex_free (&lock
->mutex
);
848 * @thread_func: function to call for all GThread structures
849 * @user_data: second argument to @thread_func
851 * Call @thread_func on all existing #GThread structures. Note that
852 * threads may decide to exit while @thread_func is running, so
853 * without intimate knowledge about the lifetime of foreign threads,
854 * @thread_func shouldn't access the GThread* pointer passed in as
855 * first argument. However, @thread_func will not be called for threads
856 * which are known to have exited already.
858 * Due to thread lifetime checks, this function has an execution complexity
859 * which is quadratic in the number of existing threads.
864 g_thread_foreach (GFunc thread_func
,
867 GSList
*slist
= NULL
;
869 g_return_if_fail (thread_func
!= NULL
);
870 /* snapshot the list of threads for iteration */
872 for (thread
= g_thread_all_threads
; thread
; thread
= thread
->next
)
873 slist
= g_slist_prepend (slist
, thread
);
875 /* walk the list, skipping non-existant threads */
878 GSList
*node
= slist
;
880 /* check whether the current thread still exists */
882 for (thread
= g_thread_all_threads
; thread
; thread
= thread
->next
)
883 if (thread
== node
->data
)
887 thread_func (thread
, user_data
);
888 g_slist_free_1 (node
);
892 #define __G_THREAD_C__
893 #include "galiasdef.c"