(charmap_read): Prepend the condition filename == NULL.

This commit is contained in:
Ulrich Drepper 2000-07-04 00:22:32 +00:00
parent 68eefde7b6
commit 4ad1d0cfbf
9 changed files with 150 additions and 53 deletions

View File

@ -63,7 +63,7 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
/* Check whether the mutex is locked and owned by this thread. */
if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
&& mutex->__m_kind != PTHREAD_MUTEX_FAST_NP
&& mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
&& mutex->__m_owner != self)
return EINVAL;
@ -124,7 +124,7 @@ pthread_cond_timedwait_relative(pthread_cond_t *cond,
/* Check whether the mutex is locked and owned by this thread. */
if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
&& mutex->__m_kind != PTHREAD_MUTEX_FAST_NP
&& mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
&& mutex->__m_owner != self)
return EINVAL;

View File

@ -287,6 +287,9 @@ extern volatile td_thr_events_t __pthread_threads_events;
/* Pointer to descriptor of thread with last event. */
extern volatile pthread_descr __pthread_last_event;
/* Flag which tells whether we are executing on SMP kernel. */
extern int __pthread_smp_kernel;
/* Return the handle corresponding to a thread id */
static inline pthread_handle thread_handle(pthread_t id)

View File

@ -38,7 +38,7 @@ strong_alias (__pthread_mutex_init, pthread_mutex_init)
int __pthread_mutex_destroy(pthread_mutex_t * mutex)
{
if (mutex->__m_lock.__status != 0) return EBUSY;
if ((mutex->__m_lock.__status & 1) != 0) return EBUSY;
return 0;
}
strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy)
@ -49,7 +49,7 @@ int __pthread_mutex_trylock(pthread_mutex_t * mutex)
int retcode;
switch(mutex->__m_kind) {
case PTHREAD_MUTEX_FAST_NP:
case PTHREAD_MUTEX_ADAPTIVE_NP:
retcode = __pthread_trylock(&mutex->__m_lock);
return retcode;
case PTHREAD_MUTEX_RECURSIVE_NP:
@ -84,7 +84,7 @@ int __pthread_mutex_lock(pthread_mutex_t * mutex)
pthread_descr self;
switch(mutex->__m_kind) {
case PTHREAD_MUTEX_FAST_NP:
case PTHREAD_MUTEX_ADAPTIVE_NP:
__pthread_lock(&mutex->__m_lock, NULL);
return 0;
case PTHREAD_MUTEX_RECURSIVE_NP:
@ -122,7 +122,7 @@ int __pthread_mutex_timedlock (pthread_mutex_t *mutex,
return EINVAL;
switch(mutex->__m_kind) {
case PTHREAD_MUTEX_FAST_NP:
case PTHREAD_MUTEX_ADAPTIVE_NP:
__pthread_lock(&mutex->__m_lock, NULL);
return 0;
case PTHREAD_MUTEX_RECURSIVE_NP:
@ -158,7 +158,7 @@ strong_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock)
int __pthread_mutex_unlock(pthread_mutex_t * mutex)
{
switch (mutex->__m_kind) {
case PTHREAD_MUTEX_FAST_NP:
case PTHREAD_MUTEX_ADAPTIVE_NP:
__pthread_unlock(&mutex->__m_lock);
return 0;
case PTHREAD_MUTEX_RECURSIVE_NP:
@ -170,7 +170,7 @@ int __pthread_mutex_unlock(pthread_mutex_t * mutex)
__pthread_unlock(&mutex->__m_lock);
return 0;
case PTHREAD_MUTEX_ERRORCHECK_NP:
if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0)
if (mutex->__m_owner != thread_self() || (mutex->__m_lock.__status & 1) == 0)
return EPERM;
mutex->__m_owner = NULL;
__pthread_alt_unlock(&mutex->__m_lock);
@ -199,7 +199,7 @@ strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
{
if (kind != PTHREAD_MUTEX_FAST_NP
if (kind != PTHREAD_MUTEX_ADAPTIVE_NP
&& kind != PTHREAD_MUTEX_RECURSIVE_NP
&& kind != PTHREAD_MUTEX_ERRORCHECK_NP
&& kind != PTHREAD_MUTEX_TIMED_NP)

View File

@ -150,7 +150,7 @@ pthread_descr __pthread_main_thread = &__pthread_initial_thread;
/* Limit between the stack of the initial thread (above) and the
stacks of other threads (below). Aligned on a STACK_SIZE boundary. */
char *__pthread_initial_thread_bos = NULL;
char *__pthread_initial_thread_bos;
/* File descriptor for sending requests to the thread manager. */
/* Initially -1, meaning that the thread manager is not running. */
@ -163,13 +163,17 @@ int __pthread_manager_reader;
/* Limits of the thread manager stack */
char *__pthread_manager_thread_bos = NULL;
char *__pthread_manager_thread_tos = NULL;
char *__pthread_manager_thread_bos;
char *__pthread_manager_thread_tos;
/* For process-wide exit() */
int __pthread_exit_requested = 0;
int __pthread_exit_code = 0;
int __pthread_exit_requested;
int __pthread_exit_code;
/* Nozero if the machine has more than one processor. */
int __pthread_smp_kernel;
#if !__ASSUME_REALTIME_SIGNALS
/* Pointers that select new or old suspend/resume functions
@ -212,7 +216,7 @@ static int current_rtmin = -1;
static int current_rtmax = -1;
int __pthread_sig_restart = SIGUSR1;
int __pthread_sig_cancel = SIGUSR2;
int __pthread_sig_debug = 0;
int __pthread_sig_debug;
#else
static int current_rtmin;
static int current_rtmax;
@ -224,7 +228,7 @@ int __pthread_sig_debug = __SIGRTMIN + 2;
#else
int __pthread_sig_restart = SIGUSR1;
int __pthread_sig_cancel = SIGUSR2;
int __pthread_sig_debug = 0;
int __pthread_sig_debug;
#endif
static int rtsigs_initialized;
@ -399,6 +403,8 @@ static void pthread_initialize(void)
__cxa_atexit((void (*) (void *)) pthread_exit_process, NULL, __dso_handle);
else
__on_exit (pthread_exit_process, NULL);
/* How many processors. */
__pthread_smp_kernel = sysconf (_SC_NPROCESSORS_ONLN) > 1;
}
void __pthread_initialize(void)

View File

@ -24,12 +24,20 @@
#include "spinlock.h"
#include "restart.h"
/* The status field of a spinlock has the following meaning:
0: spinlock is free
1: spinlock is taken, no thread is waiting on it
ADDR: psinlock is taken, ADDR is address of thread descriptor for
first waiting thread, other waiting threads are linked via
their p_nextlock field.
/* The status field of a spinlock is a pointer whose least significant
bit is a locked flag.
Thus the field values have the following meanings:
status == 0: spinlock is free
status == 1: spinlock is taken; no thread is waiting on it
(status & 1) == 1: spinlock is taken and (status & ~1L) is a
pointer to the first waiting thread; other
waiting threads are linked via the p_nextlock
field.
(status & 1) == 0: same as above, but spinlock is not taken.
The waiting list is not sorted by priority order.
Actually, we always insert at top of list (sole insertion mode
that can be performed without locking).
@ -38,29 +46,70 @@
This is safe because there are no concurrent __pthread_unlock
operations -- only the thread that locked the mutex can unlock it. */
void internal_function __pthread_lock(struct _pthread_fastlock * lock,
pthread_descr self)
{
#if defined HAS_COMPARE_AND_SWAP
long oldstatus, newstatus;
int spurious_wakeup_count = 0;
int successful_seizure, spurious_wakeup_count = 0;
int spin_count = 0;
#endif
#if defined TEST_FOR_COMPARE_AND_SWAP
if (!__pthread_has_cas)
#endif
#if !defined HAS_COMPARE_AND_SWAP
{
__pthread_acquire(&lock->__spinlock);
return 0;
}
#endif
#if defined HAS_COMPARE_AND_SWAP
again:
/* On SMP, try spinning to get the lock. */
if (__pthread_smp_kernel) {
int max_count = lock->__spinlock * 2 + 10;
for (spin_count = 0; spin_count < max_count; spin_count++) {
if (((oldstatus = lock->__status) & 1) == 0) {
if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1))
{
if (spin_count)
lock->__spinlock += (spin_count - lock->__spinlock) / 8;
return;
}
}
}
lock->__spinlock += (spin_count - lock->__spinlock) / 8;
}
/* No luck, try once more or suspend. */
do {
oldstatus = lock->__status;
if (oldstatus == 0) {
newstatus = 1;
successful_seizure = 0;
if ((oldstatus & 1) == 0) {
newstatus = oldstatus | 1;
successful_seizure = 1;
} else {
if (self == NULL)
self = thread_self();
newstatus = (long) self;
newstatus = (long) self | 1;
}
if (self != NULL) {
THREAD_SETMEM(self, p_nextlock, (pthread_descr) oldstatus);
THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus & ~1L));
/* Make sure the store in p_nextlock completes before performing
the compare-and-swap */
MEMORY_BARRIER();
}
} while(! compare_and_swap(&lock->__status, oldstatus, newstatus,
&lock->__spinlock));
} while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
/* Suspend with guard against spurious wakeup.
This can happen in pthread_cond_timedwait_relative, when the thread
@ -68,7 +117,7 @@ void internal_function __pthread_lock(struct _pthread_fastlock * lock,
locks the queue to remove itself. At that point it may still be on the
queue, and may be resumed by a condition signal. */
if (oldstatus != 0) {
if (!successful_seizure) {
for (;;) {
suspend(self);
if (self->p_nextlock != NULL) {
@ -78,37 +127,50 @@ void internal_function __pthread_lock(struct _pthread_fastlock * lock,
}
break;
}
goto again;
}
/* Put back any resumes we caught that don't belong to us. */
while (spurious_wakeup_count--)
restart(self);
#endif
}
int __pthread_unlock(struct _pthread_fastlock * lock)
{
#if defined HAS_COMPARE_AND_SWAP
long oldstatus;
pthread_descr thr, * ptr, * maxptr;
int maxprio;
#endif
again:
oldstatus = lock->__status;
if (oldstatus == 0 || oldstatus == 1) {
/* No threads are waiting for this lock. Please note that we also
enter this case if the lock is not taken at all. If this wouldn't
be done here we would crash further down. */
if (! compare_and_swap_with_release_semantics (&lock->__status,
oldstatus, 0,
&lock->__spinlock))
goto again;
#if defined TEST_FOR_COMPARE_AND_SWAP
if (!__pthread_has_cas)
#endif
#if !defined HAS_COMPARE_AND_SWAP
{
lock->__spinlock = 0;
WRITE_MEMORY_BARRIER();
return 0;
}
#endif
#if defined HAS_COMPARE_AND_SWAP
again:
oldstatus = lock->__status;
while ((oldstatus = lock->__status) == 1) {
if (__compare_and_swap_with_release_semantics(&lock->__status,
oldstatus, 0))
return 0;
}
/* Find thread in waiting queue with maximal priority */
ptr = (pthread_descr *) &lock->__status;
thr = (pthread_descr) oldstatus;
thr = (pthread_descr) (oldstatus & ~1L);
maxprio = 0;
maxptr = ptr;
while (thr != (pthread_descr) 1) {
while (thr != 0) {
if (thr->p_priority >= maxprio) {
maxptr = ptr;
maxprio = thr->p_priority;
@ -128,16 +190,25 @@ again:
/* Remove max prio thread from waiting list. */
if (maxptr == (pthread_descr *) &lock->__status) {
/* If max prio thread is at head, remove it with compare-and-swap
to guard against concurrent lock operation */
thr = (pthread_descr) oldstatus;
if (! compare_and_swap_with_release_semantics
(&lock->__status, oldstatus, (long)(thr->p_nextlock),
&lock->__spinlock))
to guard against concurrent lock operation. This removal
also has the side effect of marking the lock as released
because the new status comes from thr->p_nextlock whose
least significant bit is clear. */
thr = (pthread_descr) (oldstatus & ~1L);
if (! __compare_and_swap_with_release_semantics
(&lock->__status, oldstatus, (long)(thr->p_nextlock)))
goto again;
} else {
/* No risk of concurrent access, remove max prio thread normally */
/* No risk of concurrent access, remove max prio thread normally.
But in this case we must also flip the least significant bit
of the status to mark the lock as released. */
thr = *maxptr;
*maxptr = thr->p_nextlock;
do {
oldstatus = lock->__status;
} while (!__compare_and_swap_with_release_semantics(&lock->__status,
oldstatus, oldstatus & ~1L));
}
/* Prevent reordering of store to *maxptr above and store to thr->p_nextlock
below */
@ -147,6 +218,7 @@ again:
restart(thr);
return 0;
#endif
}
/*

View File

@ -81,6 +81,7 @@ static inline int compare_and_swap(long * ptr, long oldval, long newval,
#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
#define compare_and_swap_with_release_semantics compare_and_swap
#define __compare_and_swap_with_release_semantics __compare_and_swap
#endif
/* Internal locks */
@ -97,13 +98,26 @@ static inline void __pthread_init_lock(struct _pthread_fastlock * lock)
static inline int __pthread_trylock (struct _pthread_fastlock * lock)
{
#if defined HAS_COMPARE_AND_SWAP
long oldstatus;
#endif
#if defined TEST_FOR_COMPARE_AND_SWAP
if (!__pthread_has_cas)
#endif
#if !defined HAS_COMPARE_AND_SWAP
{
return (testandset(&lock->__spinlock) : EBUSY : 0)
}
#endif
#if defined HAS_COMPARE_AND_SWAP
do {
oldstatus = lock->__status;
if (oldstatus != 0) return EBUSY;
} while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock));
return 0;
#endif
}
/* Variation of internal lock used for pthread_mutex_t, supporting

View File

@ -25,8 +25,9 @@
/* Fast locks (not abstract because mutexes and conditions aren't abstract). */
struct _pthread_fastlock
{
long int __status; /* "Free" or "taken" or head of waiting list */
int __spinlock; /* For compare-and-swap emulation */
long int __status; /* "Free" or "taken" or head of waiting list */
int __spinlock; /* Used by compare_and_swap emulation. Also,
adaptive SMP lock stores spin count here. */
};
#ifndef _PTHREAD_DESCR_DEFINED

View File

@ -77,10 +77,10 @@ enum
enum
{
PTHREAD_MUTEX_FAST_NP,
PTHREAD_MUTEX_TIMED_NP,
PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_TIMED_NP
PTHREAD_MUTEX_ADAPTIVE_NP
#ifdef __USE_UNIX98
,
PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,

View File

@ -159,7 +159,8 @@ charmap_read (const char *filename)
== 1)
|| fscanf (fp, "%% alias %as", &name) == 1)
{
if (strcasecmp (name, filename) == 0)
if (filename != NULL
&& strcasecmp (name, filename) == 0)
break;
free (name);