|
Lines 38-45
Link Here
|
| 38 |
* In this algorithm the lock is a single word. Its low-order bit is |
38 |
* In this algorithm the lock is a single word. Its low-order bit is |
| 39 |
* set when a writer holds the lock. The remaining high-order bits |
39 |
* set when a writer holds the lock. The remaining high-order bits |
| 40 |
* contain a count of readers desiring the lock. The algorithm requires |
40 |
* contain a count of readers desiring the lock. The algorithm requires |
| 41 |
* atomic "compare_and_store" and "add" operations, which we implement |
41 |
* atomic "compare_and_store" and "add" operations, which we take |
| 42 |
* using assembly language sequences in "rtld_start.S". |
42 |
* from machine/atomic.h. |
| 43 |
*/ |
43 |
*/ |
| 44 |
|
44 |
|
| 45 |
#include <sys/param.h> |
45 |
#include <sys/param.h> |
|
Lines 64-73
typedef struct Struct_Lock {
Link Here
|
| 64 |
} Lock; |
64 |
} Lock; |
| 65 |
|
65 |
|
| 66 |
static sigset_t fullsigmask, oldsigmask; |
66 |
static sigset_t fullsigmask, oldsigmask; |
| 67 |
static int thread_flag; |
67 |
static int thread_flag, wnested; |
| 68 |
|
68 |
|
| 69 |
static void * |
69 |
static void * |
| 70 |
def_lock_create() |
70 |
def_lock_create(void) |
| 71 |
{ |
71 |
{ |
| 72 |
void *base; |
72 |
void *base; |
| 73 |
char *p; |
73 |
char *p; |
|
Lines 117-145
def_rlock_acquire(void *lock)
Link Here
|
| 117 |
static void |
117 |
static void |
| 118 |
def_wlock_acquire(void *lock) |
118 |
def_wlock_acquire(void *lock) |
| 119 |
{ |
119 |
{ |
| 120 |
Lock *l = (Lock *)lock; |
120 |
Lock *l; |
| 121 |
sigset_t tmp_oldsigmask; |
121 |
sigset_t tmp_oldsigmask; |
| 122 |
|
122 |
int w; |
| 123 |
for ( ; ; ) { |
123 |
|
| 124 |
sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask); |
124 |
l = (Lock *)lock; |
| 125 |
if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG)) |
125 |
for (;;) { |
| 126 |
break; |
126 |
w = atomic_fetchadd_int(&wnested, 1); |
| 127 |
sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL); |
127 |
if (w == 0) |
| 128 |
} |
128 |
sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask); |
| 129 |
oldsigmask = tmp_oldsigmask; |
129 |
if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG)) |
|
|
130 |
break; |
| 131 |
if (atomic_fetchadd_int(&wnested, -1) == 1) |
| 132 |
sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL); |
| 133 |
} |
| 134 |
if (w == 0) |
| 135 |
oldsigmask = tmp_oldsigmask; |
| 130 |
} |
136 |
} |
| 131 |
|
137 |
|
| 132 |
static void |
138 |
static void |
| 133 |
def_lock_release(void *lock) |
139 |
def_lock_release(void *lock) |
| 134 |
{ |
140 |
{ |
| 135 |
Lock *l = (Lock *)lock; |
141 |
Lock *l; |
| 136 |
|
142 |
|
| 137 |
if ((l->lock & WAFLAG) == 0) |
143 |
l = (Lock *)lock; |
| 138 |
atomic_add_rel_int(&l->lock, -RC_INCR); |
144 |
if ((l->lock & WAFLAG) == 0) |
| 139 |
else { |
145 |
atomic_add_rel_int(&l->lock, -RC_INCR); |
| 140 |
atomic_add_rel_int(&l->lock, -WAFLAG); |
146 |
else { |
| 141 |
sigprocmask(SIG_SETMASK, &oldsigmask, NULL); |
147 |
assert(wnested > 0); |
| 142 |
} |
148 |
atomic_add_rel_int(&l->lock, -WAFLAG); |
|
|
149 |
if (atomic_fetchadd_int(&wnested, -1) == 1) |
| 150 |
sigprocmask(SIG_SETMASK, &oldsigmask, NULL); |
| 151 |
} |
| 143 |
} |
152 |
} |
| 144 |
|
153 |
|
| 145 |
static int |
154 |
static int |
|
Lines 269-275
lock_restart_for_upgrade(RtldLockState *lockstate)
Link Here
|
| 269 |
} |
278 |
} |
| 270 |
|
279 |
|
| 271 |
void |
280 |
void |
| 272 |
lockdflt_init() |
281 |
lockdflt_init(void) |
| 273 |
{ |
282 |
{ |
| 274 |
int i; |
283 |
int i; |
| 275 |
|
284 |
|
|
Lines 373-384
_rtld_atfork_pre(int *locks)
Link Here
|
| 373 |
return; |
382 |
return; |
| 374 |
|
383 |
|
| 375 |
/* |
384 |
/* |
| 376 |
* Warning: this does not work with the rtld compat locks |
385 |
* Warning: this did not worked well with the rtld compat |
| 377 |
* above, since the thread signal mask is corrupted (set to |
386 |
* locks above, when the thread signal mask was corrupted (set |
| 378 |
* all signals blocked) if two locks are taken in write mode. |
387 |
* to all signals blocked) if two locks were taken |
| 379 |
* The caller of the _rtld_atfork_pre() must provide the |
388 |
* simultaneously in the write mode. The caller of the |
| 380 |
* working implementation of the locks, and libthr locks are |
389 |
* _rtld_atfork_pre() must provide the working implementation |
| 381 |
* fine. |
390 |
* of the locks anyway, and libthr locks are fine. |
| 382 |
*/ |
391 |
*/ |
| 383 |
wlock_acquire(rtld_phdr_lock, &ls[0]); |
392 |
wlock_acquire(rtld_phdr_lock, &ls[0]); |
| 384 |
wlock_acquire(rtld_bind_lock, &ls[1]); |
393 |
wlock_acquire(rtld_bind_lock, &ls[1]); |