View | Details | Raw Unified | Return to bug 215826
Collapse All | Expand All

(-)b/libexec/rtld-elf/rtld_lock.c (-29 / +38 lines)
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]);

Return to bug 215826