OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libobjc/] [accessors.m] - Blame information for rev 739

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 739 jeremybenn
/* GNU Objective C Runtime accessors functions
2
   Copyright (C) 2010 Free Software Foundation, Inc.
3
   Contributed by Nicola Pero
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under the
8
terms of the GNU General Public License as published by the Free Software
9
Foundation; either version 3, or (at your option) any later version.
10
 
11
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14
details.
15
 
16
Under Section 7 of GPL version 3, you are granted additional
17
permissions described in the GCC Runtime Library Exception, version
18
3.1, as published by the Free Software Foundation.
19
 
20
You should have received a copy of the GNU General Public License and
21
a copy of the GCC Runtime Library Exception along with this program;
22
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23
<http://www.gnu.org/licenses/>.  */
24
 
25
#include "objc-private/common.h"
26
#include "objc/objc.h"
27
#include "objc/thr.h"
28
#include <string.h>                    /* For memcpy */
29
 
30
/* This file contains functions that the compiler uses when
31
   synthesizing accessors (getters/setters) for properties.  The
32
   functions are part of the ABI, but are meant to be used by the
33
   compiler and not by users; for this reason, they are not declared
34
   in public header files.  The compiler automatically generates
35
   declarations for these functions.  */
36
 
37
/* Properties can be "atomic", which requires protecting them from
38
   concurrency issues using a lock.  Unfortunately, we can't have a
39
   lock for each property, so we'll go with a small pool of locks.
40
   Any time a property is accessed in an "atomic" way, we pick a
41
   random lock from the pool (random, but always the same one for the
42
   same property of the same object) and use it to protect access to
43
   the property.
44
 
45
   The size of the pool is currently 16.  A bigger pool can help
46
   reduce contention, ie, reduce the chances that two threads,
47
   operating on unrelated properties, will have to wait for each other
48
   because the properties use the same lock.  16 seems big enough at
49
   the moment.  */
50
#define ACCESSORS_NUMBER_OF_LOCKS 16
51
 
52
#define ACCESSORS_HASH(POINTER) ((((size_t)POINTER >> 8) ^ (size_t)POINTER) & (ACCESSORS_NUMBER_OF_LOCKS - 1))
53
 
54
static objc_mutex_t accessors_locks[ACCESSORS_NUMBER_OF_LOCKS];
55
 
56
/* This is called at startup to setup the locks.  */
57
void
58
__objc_accessors_init (void)
59
{
60
  int i;
61
 
62
  for (i = 0; i < ACCESSORS_NUMBER_OF_LOCKS; i++)
63
    accessors_locks[i] = objc_mutex_allocate ();
64
}
65
 
66
/* The property accessors automatically call various methods from the
67
   Foundation library (eg, GNUstep-base).  These methods are not
68
   implemented here, but we need to declare them so we can compile the
69
   runtime.  The Foundation library will need to provide
70
   implementations of these methods (most likely in the root class,
71
   eg, NSObject) as the accessors only work with objects of classes
72
   that implement these methods.  */
73
@interface _libobjcNSObject
74
- (id) copyWithZone: (void *)zone;
75
- (id) mutableCopyWithZone: (void *)zone;
76
@end
77
#define COPY(X)         [((_libobjcNSObject *)(X)) copyWithZone: NULL]
78
#define MUTABLE_COPY(X) [((_libobjcNSObject *)(X)) mutableCopyWithZone: NULL]
79
 
80
 
81
#if OBJC_WITH_GC
82
 
83
#  define AUTORELEASE(X)  (X)
84
#  define RELEASE(X)
85
#  define RETAIN(X)       (X)
86
 
87
#else
88
 
89
@interface _libobjcNSObject (RetainReleaseMethods)
90
- (id) autorelease;
91
- (oneway void) release;
92
- (id) retain;
93
@end
94
#  define AUTORELEASE(X)  [((_libobjcNSObject *)(X)) autorelease]
95
#  define RELEASE(X)      [((_libobjcNSObject *)(X)) release]
96
#  define RETAIN(X)       [((_libobjcNSObject *)(X)) retain]
97
 
98
#endif
99
 
100
/* The compiler uses this function when implementing some synthesized
101
   getters for properties of type 'id'.  */
102
id
103
objc_getProperty (id self, SEL __attribute__((unused)) _cmd, ptrdiff_t offset, BOOL is_atomic)
104
{
105
  if (self != nil)
106
    {
107
      id *pointer_to_ivar = (id *)((char *)self + offset);
108
 
109
 
110
      if (is_atomic == NO)
111
        {
112
          /* Note that in this case, we do not RETAIN/AUTORELEASE the
113
             returned value.  The programmer should do it if it is
114
             needed.  Since access is non-atomic, other threads can be
115
             ignored and the caller has full control of what happens
116
             to the object and whether it needs to be RETAINed or not,
117
             so it makes sense to leave the decision to him/her.  This
118
             is also what the Apple/NeXT runtime does.  */
119
          return *pointer_to_ivar;
120
        }
121
      else
122
        {
123
          objc_mutex_t lock = accessors_locks[ACCESSORS_HASH (pointer_to_ivar)];
124
          id result;
125
 
126
          objc_mutex_lock (lock);
127
          result = RETAIN (*(pointer_to_ivar));
128
          objc_mutex_unlock (lock);
129
 
130
          return AUTORELEASE (result);
131
        }
132
    }
133
 
134
  return nil;
135
}
136
 
137
/* The compiler uses this function when implementing some synthesized
138
   setters for properties of type 'id'.
139
 
140
   PS: Note how 'should_copy' is declared 'BOOL' but then actually
141
   takes values from 0 to 2.  This hack was introduced by Apple; we
142
   do the same for compatibility reasons.  */
143
void
144
objc_setProperty (id self, SEL __attribute__((unused)) _cmd, ptrdiff_t offset, id new_value, BOOL is_atomic, BOOL should_copy)
145
{
146
  if (self != nil)
147
    {
148
      id *pointer_to_ivar = (id *)((char *)self + offset);
149
      id retained_value;
150
#if !OBJC_WITH_GC
151
      id old_value;
152
#endif
153
 
154
      switch (should_copy)
155
        {
156
        case 0: /* retain */
157
          {
158
            if (*pointer_to_ivar == new_value)
159
              return;
160
            retained_value = RETAIN (new_value);
161
            break;
162
          }
163
        case 2: /* mutable copy */
164
          {
165
            retained_value = MUTABLE_COPY (new_value);
166
            break;
167
          }
168
        case 1: /* copy */
169
        default:
170
          {
171
            retained_value = COPY (new_value);
172
            break;
173
          }
174
        }
175
 
176
      if (is_atomic == NO)
177
        {
178
#if !OBJC_WITH_GC
179
          old_value = *pointer_to_ivar;
180
#endif
181
          *pointer_to_ivar = retained_value;
182
        }
183
      else
184
        {
185
          objc_mutex_t lock = accessors_locks[ACCESSORS_HASH (pointer_to_ivar)];
186
 
187
          objc_mutex_lock (lock);
188
#if !OBJC_WITH_GC
189
          old_value = *pointer_to_ivar;
190
#endif
191
          *pointer_to_ivar = retained_value;
192
          objc_mutex_unlock (lock);
193
        }
194
#if !OBJC_WITH_GC
195
      RELEASE (old_value);
196
#endif
197
    }
198
}
199
 
200
/* The compiler uses this function when implementing some synthesized
201
   getters for properties of arbitrary C types.  The data is just
202
   copied.  Compatibility Note: this function does not exist in the
203
   Apple/NeXT runtime.  */
204
void
205
objc_getPropertyStruct (void *destination, const void *source, ptrdiff_t size, BOOL is_atomic, BOOL __attribute__((unused)) has_strong)
206
{
207
  if (is_atomic == NO)
208
    memcpy (destination, source, size);
209
  else
210
    {
211
      objc_mutex_t lock = accessors_locks[ACCESSORS_HASH (source)];
212
 
213
      objc_mutex_lock (lock);
214
      memcpy (destination, source, size);
215
      objc_mutex_unlock (lock);
216
    }
217
}
218
 
219
/* The compiler uses this function when implementing some synthesized
220
   setters for properties of arbitrary C types.  The data is just
221
   copied.  Compatibility Note: this function does not exist in the
222
   Apple/NeXT runtime.  */
223
void
224
objc_setPropertyStruct (void *destination, const void *source, ptrdiff_t size, BOOL is_atomic, BOOL __attribute__((unused)) has_strong)
225
{
226
  if (is_atomic == NO)
227
    memcpy (destination, source, size);
228
  else
229
    {
230
      objc_mutex_t lock = accessors_locks[ACCESSORS_HASH (destination)];
231
 
232
      objc_mutex_lock (lock);
233
      memcpy (destination, source, size);
234
      objc_mutex_unlock (lock);
235
    }
236
}
237
 
238
/* This is the function that the Apple/NeXT runtime has instead of
239
   objc_getPropertyStruct and objc_setPropertyStruct.  We include it
240
   for API compatibility (just for people who may have used
241
   objc_copyStruct on the NeXT runtime thinking it was a public API);
242
   the compiler never generates calls to it with the GNU runtime.
243
   This function is clumsy because it requires two locks instead of
244
   one.  */
245
void
246
objc_copyStruct (void *destination, const void *source, ptrdiff_t size, BOOL is_atomic, BOOL __attribute__((unused)) has_strong)
247
{
248
  if (is_atomic == NO)
249
    memcpy (destination, source, size);
250
  else
251
    {
252
      /* We don't know which one is the property, so we have to lock
253
         both.  One of them is most likely a temporary buffer in the
254
         local stack and we really wouldn't want to lock it (our
255
         objc_getPropertyStruct and objc_setPropertyStruct functions
256
         don't lock it).  Note that if we're locking more than one
257
         accessor lock at once, we need to always lock them in the
258
         same order to avoid deadlocks.  */
259
      objc_mutex_t first_lock;
260
      objc_mutex_t second_lock;
261
 
262
      if (ACCESSORS_HASH (source) == ACCESSORS_HASH (destination))
263
        {
264
          /* A lucky collision.  */
265
          first_lock = accessors_locks[ACCESSORS_HASH (source)];
266
          objc_mutex_lock (first_lock);
267
          memcpy (destination, source, size);
268
          objc_mutex_unlock (first_lock);
269
          return;
270
        }
271
 
272
      if (ACCESSORS_HASH (source) > ACCESSORS_HASH (destination))
273
        {
274
          first_lock = accessors_locks[ACCESSORS_HASH (source)];
275
          second_lock = accessors_locks[ACCESSORS_HASH (destination)];
276
        }
277
      else
278
        {
279
          first_lock = accessors_locks[ACCESSORS_HASH (destination)];
280
          second_lock = accessors_locks[ACCESSORS_HASH (source)];
281
        }
282
 
283
      objc_mutex_lock (first_lock);
284
      objc_mutex_lock (second_lock);
285
      memcpy (destination, source, size);
286
      objc_mutex_unlock (second_lock);
287
      objc_mutex_unlock (first_lock);
288
    }
289
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.