1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
/* GNU Objective C Runtime Thread Interface
Copyright (C) 1996 Free Software Foundation, Inc.
Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
This file is part of GNU CC.
GNU CC 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, or (at your option) any later version.
GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of 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
GNU CC; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, if you link this library with files compiled with
GCC to produce an executable, this does not cause the resulting executable
to be covered by the GNU General Public License. This exception does not
however invalidate any other reasons why the executable file might be
covered by the GNU General Public License. */
#include <stdlib.h>
#include "runtime.h"
/*************************************************************************
* Universal static variables:
*/
int __objc_thread_exit_status = 0; /* Global exit status. */
/* Flag which lets us know if we ever became multi threaded */
int __objc_is_multi_threaded = 0;
/* The hook function called when the runtime becomes multi threaded */
objc_thread_callback _objc_became_multi_threaded = NULL;
/*****************************************************************************
* Universal Functionality
*/
/*
Use this to set the hook function that will be called when the
runtime initially becomes multi threaded.
The hook function is only called once, meaning only when the
2nd thread is spawned, not for each and every thread.
It returns the previous hook function or NULL if there is none.
A program outside of the runtime could set this to some function so
it can be informed; for example, the GNUstep Base Library sets it
so it can implement the NSBecomingMultiThreaded notification.
*/
objc_thread_callback objc_set_thread_callback(objc_thread_callback func)
{
objc_thread_callback temp = _objc_became_multi_threaded;
_objc_became_multi_threaded = func;
return temp;
}
/********
* First function called in a thread, starts everything else.
*/
struct __objc_thread_start_state
{
SEL selector;
id object;
id argument;
};
static volatile void
__objc_thread_detach_function(struct __objc_thread_start_state *istate)
{
if (istate) { /* Is state valid? */
id (*imp)(id,SEL,id);
SEL selector = istate->selector;
id object = istate->object;
id argument = istate->argument;
objc_free(istate);
/* Clear out the thread local storage */
objc_thread_set_data(NULL);
/* Check to see if we just became multi threaded */
if (!__objc_is_multi_threaded) {
__objc_is_multi_threaded = 1;
/* Call the hook function */
if (_objc_became_multi_threaded != NULL)
(*_objc_became_multi_threaded)();
}
if ((imp = (id(*)(id, SEL, id))objc_msg_lookup(object, selector))) {
(*imp)(object, selector, argument);
}
else
fprintf(stderr, "__objc_thread_start called with bad selector.\n");
}
else {
fprintf(stderr, "__objc_thread_start called with NULL state.\n");
}
objc_thread_exit();
}
/********
* Detach a new thread of execution and return its id. Returns NULL if fails.
* Thread is started by sending message with selector to object. Message
* takes a single argument.
*/
_objc_thread_t
objc_thread_detach(SEL selector, id object, id argument)
{
struct __objc_thread_start_state *istate; /* Initialial thread state. */
_objc_thread_t thread_id = NULL; /* Detached thread id. */
if (!(istate = (struct __objc_thread_start_state *)
objc_malloc(sizeof(*istate)))) /* Can we allocate state? */
return NULL; /* No, abort. */
istate->selector = selector; /* Initialize the thread's */
istate->object = object; /* state structure. */
istate->argument = argument;
if ((thread_id = objc_thread_create((void *)__objc_thread_detach_function,
istate)) == NULL) {
objc_free(istate); /* Release state if failed. */
return thread_id;
}
return thread_id;
}
#undef objc_mutex_lock()
#undef objc_mutex_unlock()
int
objc_mutex_unlock_x(_objc_mutex_t mutex, const char *f, int l)
{
printf("%16.16s#%4d < unlock", f, l);
return objc_mutex_unlock(mutex);
}
int
objc_mutex_lock_x(_objc_mutex_t mutex, const char *f, int l)
{
printf("%16.16s#%4d < lock", f, l);
return objc_mutex_lock(mutex);
}
/* End of File */
|