mirror of
https://git.FreeBSD.org/ports.git
synced 2025-01-18 08:02:48 +00:00
Add an optional experimental patch that reduce the number of context
switches on UP systems when the thread waiting on a condition has a higher priority than the thread signalling the condition. Bump port revision.
This commit is contained in:
parent
97c49bb411
commit
60032d4ed7
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=47555
@ -7,7 +7,7 @@
|
||||
|
||||
PORTNAME= linuxthreads
|
||||
PORTVERSION= 2.2.3
|
||||
PORTREVISION= 1
|
||||
PORTREVISION= 2
|
||||
CATEGORIES= devel
|
||||
MASTER_SITES= ${MASTER_SITE_GNU}
|
||||
MASTER_SITE_SUBDIR= glibc
|
||||
@ -33,6 +33,14 @@ WRKSRC= ${WRKDIR}/${PKGNAME}
|
||||
SRC_BASE= /usr/src
|
||||
LIBSRC_BASE= ${SRC_BASE}/lib
|
||||
|
||||
.if !defined(WITH_CONDWAIT_PATCH)
|
||||
pre-fetch:
|
||||
@${ECHO}
|
||||
@${ECHO} You can use an experimental patch to reduce the number of
|
||||
@${ECHO} condition variable triggered context switches by defining
|
||||
@${ECHO} WITH_CONDWAIT_PATCH
|
||||
.endif
|
||||
|
||||
post-extract:
|
||||
@mv ${WRKDIR}/linuxthreads ${WRKSRC}
|
||||
@mv ${WRKDIR}/linuxthreads_db ${WRKSRC}
|
||||
@ -46,6 +54,17 @@ post-extract:
|
||||
@test -f ${WRKSRC}/libgcc_r/Makefile || \
|
||||
${LN} -s ${FILESDIR}/Makefile.libgcc_r ${WRKSRC}/libgcc_r/Makefile
|
||||
|
||||
.if defined(WITH_CONDWAIT_PATCH)
|
||||
post-patch:
|
||||
@${ECHO_MSG} "===> Applying experimental patch condwait-patch"
|
||||
@if ${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/condwait-patch; then \
|
||||
${ECHO_MSG} "===> Patch condwait-patch applied successfully"; \
|
||||
else \
|
||||
${ECHO_MSG} ">>Patch condwait-patch failed to apply cleanly"; \
|
||||
false ; \
|
||||
fi
|
||||
.endif
|
||||
|
||||
pre-build:
|
||||
@cd ${WRKSRC}/libgcc_r ; \
|
||||
${MAKE}
|
||||
|
306
devel/linuxthreads/files/condwait-patch
Normal file
306
devel/linuxthreads/files/condwait-patch
Normal file
@ -0,0 +1,306 @@
|
||||
diff -ru ../../work.orig/linuxthreads-2.2.3_1/condvar.c ./condvar.c
|
||||
--- ../../work.orig/linuxthreads-2.2.3_1/condvar.c Thu Apr 12 21:02:02 2001
|
||||
+++ ./condvar.c Wed Jul 18 13:30:47 2001
|
||||
@@ -55,6 +55,8 @@
|
||||
return did_remove;
|
||||
}
|
||||
|
||||
+extern int __pthread_mutex_condwait_completelock(pthread_mutex_t *mutex);
|
||||
+
|
||||
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
volatile pthread_descr self = thread_self();
|
||||
@@ -74,6 +76,7 @@
|
||||
|
||||
/* Register extrication interface */
|
||||
THREAD_SETMEM(self, p_condvar_avail, 0);
|
||||
+ THREAD_SETMEM(self, p_condwait_mutex, mutex);
|
||||
__pthread_set_own_extricate_if(self, &extr);
|
||||
|
||||
/* Atomically enqueue thread for waiting, but only if it is not
|
||||
@@ -121,15 +124,35 @@
|
||||
if (THREAD_GETMEM(self, p_woken_by_cancel)
|
||||
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
|
||||
THREAD_SETMEM(self, p_woken_by_cancel, 0);
|
||||
- pthread_mutex_lock(mutex);
|
||||
+ if (THREAD_GETMEM(self, p_condwait_mutex) == NULL) {
|
||||
+ if (THREAD_GETMEM(self, p_condwait_extra_restart) != 0) {
|
||||
+ if (spurious_wakeup_count > 0)
|
||||
+ spurious_wakeup_count--;
|
||||
+ else
|
||||
+ suspend(self);
|
||||
+ }
|
||||
+ __pthread_mutex_condwait_completelock(mutex);
|
||||
+ } else
|
||||
+ pthread_mutex_lock(mutex);
|
||||
__pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
|
||||
}
|
||||
|
||||
+ if (THREAD_GETMEM(self, p_condwait_mutex) == NULL &&
|
||||
+ THREAD_GETMEM(self, p_condwait_extra_restart) != 0) {
|
||||
+ if (spurious_wakeup_count > 0)
|
||||
+ spurious_wakeup_count--;
|
||||
+ else
|
||||
+ suspend(self);
|
||||
+ }
|
||||
+
|
||||
/* Put back any resumes we caught that don't belong to us. */
|
||||
while (spurious_wakeup_count--)
|
||||
restart(self);
|
||||
|
||||
- pthread_mutex_lock(mutex);
|
||||
+ if (THREAD_GETMEM(self, p_condwait_mutex) == NULL)
|
||||
+ __pthread_mutex_condwait_completelock(mutex);
|
||||
+ else
|
||||
+ pthread_mutex_lock(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -155,6 +178,7 @@
|
||||
|
||||
/* Register extrication interface */
|
||||
THREAD_SETMEM(self, p_condvar_avail, 0);
|
||||
+ THREAD_SETMEM(self, p_condwait_mutex, mutex);
|
||||
__pthread_set_own_extricate_if(self, &extr);
|
||||
|
||||
/* Enqueue to wait on the condition and check for cancellation. */
|
||||
@@ -215,15 +239,35 @@
|
||||
if (THREAD_GETMEM(self, p_woken_by_cancel)
|
||||
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
|
||||
THREAD_SETMEM(self, p_woken_by_cancel, 0);
|
||||
- pthread_mutex_lock(mutex);
|
||||
+ if (THREAD_GETMEM(self, p_condwait_mutex) == NULL) {
|
||||
+ if (THREAD_GETMEM(self, p_condwait_extra_restart) != 0) {
|
||||
+ if (spurious_wakeup_count > 0)
|
||||
+ spurious_wakeup_count--;
|
||||
+ else
|
||||
+ suspend(self);
|
||||
+ }
|
||||
+ __pthread_mutex_condwait_completelock(mutex);
|
||||
+ } else
|
||||
+ pthread_mutex_lock(mutex);
|
||||
__pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
|
||||
}
|
||||
|
||||
+ if (THREAD_GETMEM(self, p_condwait_mutex) == NULL &&
|
||||
+ THREAD_GETMEM(self, p_condwait_extra_restart) != 0) {
|
||||
+ if (spurious_wakeup_count > 0)
|
||||
+ spurious_wakeup_count--;
|
||||
+ else
|
||||
+ suspend(self);
|
||||
+ }
|
||||
+
|
||||
/* Put back any resumes we caught that don't belong to us. */
|
||||
while (spurious_wakeup_count--)
|
||||
restart(self);
|
||||
|
||||
- pthread_mutex_lock(mutex);
|
||||
+ if (THREAD_GETMEM(self, p_condwait_mutex) == NULL)
|
||||
+ __pthread_mutex_condwait_completelock(mutex);
|
||||
+ else
|
||||
+ pthread_mutex_lock(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -242,9 +286,27 @@
|
||||
th = dequeue(&cond->__c_waiting);
|
||||
__pthread_unlock(&cond->__c_lock);
|
||||
if (th != NULL) {
|
||||
- th->p_condvar_avail = 1;
|
||||
- WRITE_MEMORY_BARRIER();
|
||||
- restart(th);
|
||||
+ pthread_mutex_t *mutex = th->p_condwait_mutex;
|
||||
+ if (th->p_condvar_avail == 0 &&
|
||||
+ mutex != NULL &&
|
||||
+ (mutex->__m_kind == PTHREAD_MUTEX_ERRORCHECK_NP ||
|
||||
+ mutex->__m_kind == PTHREAD_MUTEX_TIMED_NP) &&
|
||||
+ __pthread_alt_condwait_queuelock(&mutex->__m_lock, th) == 0) {
|
||||
+ th->p_condwait_mutex = NULL;
|
||||
+ th->p_condwait_extra_restart = 0;
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ th->p_condvar_avail = 1;
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ if (th->p_condwait_waitnode.abandoned) {
|
||||
+ th->p_condwait_extra_restart = 1;
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ restart(th);
|
||||
+ }
|
||||
+ } else {
|
||||
+ th->p_condvar_avail = 1;
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ restart(th);
|
||||
+ }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -260,9 +322,27 @@
|
||||
__pthread_unlock(&cond->__c_lock);
|
||||
/* Now signal each process in the queue */
|
||||
while ((th = dequeue(&tosignal)) != NULL) {
|
||||
- th->p_condvar_avail = 1;
|
||||
- WRITE_MEMORY_BARRIER();
|
||||
- restart(th);
|
||||
+ pthread_mutex_t *mutex = th->p_condwait_mutex;
|
||||
+ if (th->p_condvar_avail == 0 &&
|
||||
+ mutex != NULL &&
|
||||
+ (mutex->__m_kind == PTHREAD_MUTEX_ERRORCHECK_NP ||
|
||||
+ mutex->__m_kind == PTHREAD_MUTEX_TIMED_NP) &&
|
||||
+ __pthread_alt_condwait_queuelock(&mutex->__m_lock, th) == 0) {
|
||||
+ th->p_condwait_mutex = NULL;
|
||||
+ th->p_condwait_extra_restart = 0;
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ th->p_condvar_avail = 1;
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ if (th->p_condwait_waitnode.abandoned) {
|
||||
+ th->p_condwait_extra_restart = 1;
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ restart(th);
|
||||
+ }
|
||||
+ } else {
|
||||
+ th->p_condvar_avail = 1;
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ restart(th);
|
||||
+ }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
diff -ru ../../work.orig/linuxthreads-2.2.3_1/internals.h ./internals.h
|
||||
--- ../../work.orig/linuxthreads-2.2.3_1/internals.h Wed Jul 18 07:25:04 2001
|
||||
+++ ./internals.h Wed Jul 18 10:55:57 2001
|
||||
@@ -125,6 +125,13 @@
|
||||
int pr_lock_count;
|
||||
} pthread_readlock_info;
|
||||
|
||||
+
|
||||
+struct wait_node {
|
||||
+ struct wait_node *next; /* Next node in null terminated linked list */
|
||||
+ pthread_descr thr; /* The thread waiting with this node */
|
||||
+ int abandoned; /* Atomic flag */
|
||||
+};
|
||||
+
|
||||
struct _pthread_descr_struct {
|
||||
union {
|
||||
struct {
|
||||
@@ -189,6 +196,9 @@
|
||||
hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */
|
||||
#endif
|
||||
/* New elements must be added at the end. */
|
||||
+ pthread_mutex_t *p_condwait_mutex;
|
||||
+ struct wait_node p_condwait_waitnode;
|
||||
+ char p_condwait_extra_restart;
|
||||
} __attribute__ ((aligned(32))); /* We need to align the structure so that
|
||||
doubles are aligned properly. This is 8
|
||||
bytes on MIPS and 16 bytes on MIPS64.
|
||||
diff -ru ../../work.orig/linuxthreads-2.2.3_1/mutex.c ./mutex.c
|
||||
--- ../../work.orig/linuxthreads-2.2.3_1/mutex.c Sun Jan 7 04:35:20 2001
|
||||
+++ ./mutex.c Wed Jul 18 09:09:13 2001
|
||||
@@ -92,6 +92,24 @@
|
||||
}
|
||||
strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock)
|
||||
|
||||
+int __pthread_mutex_condwait_completelock(pthread_mutex_t *mutex)
|
||||
+{
|
||||
+ pthread_descr self;
|
||||
+
|
||||
+ switch(mutex->__m_kind) {
|
||||
+ case PTHREAD_MUTEX_ERRORCHECK_NP:
|
||||
+ self = thread_self();
|
||||
+ if (mutex->__m_owner == self) return EDEADLK;
|
||||
+ mutex->__m_owner = self;
|
||||
+ return 0;
|
||||
+ case PTHREAD_MUTEX_TIMED_NP:
|
||||
+ return 0;
|
||||
+ default:
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
int __pthread_mutex_lock(pthread_mutex_t * mutex)
|
||||
{
|
||||
pthread_descr self;
|
||||
diff -ru ../../work.orig/linuxthreads-2.2.3_1/spinlock.c ./spinlock.c
|
||||
--- ../../work.orig/linuxthreads-2.2.3_1/spinlock.c Wed Jul 18 07:25:04 2001
|
||||
+++ ./spinlock.c Wed Jul 18 10:56:34 2001
|
||||
@@ -232,12 +232,6 @@
|
||||
*/
|
||||
|
||||
|
||||
-struct wait_node {
|
||||
- struct wait_node *next; /* Next node in null terminated linked list */
|
||||
- pthread_descr thr; /* The thread waiting with this node */
|
||||
- int abandoned; /* Atomic flag */
|
||||
-};
|
||||
-
|
||||
static long wait_node_free_list;
|
||||
#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
|
||||
static int wait_node_free_list_spinlock;
|
||||
@@ -360,6 +354,55 @@
|
||||
}
|
||||
|
||||
#endif
|
||||
+
|
||||
+int __pthread_alt_condwait_queuelock(struct _pthread_fastlock * lock,
|
||||
+ pthread_descr th)
|
||||
+{
|
||||
+#if defined HAS_COMPARE_AND_SWAP
|
||||
+ long oldstatus, newstatus;
|
||||
+#endif
|
||||
+
|
||||
+#if defined TEST_FOR_COMPARE_AND_SWAP
|
||||
+ if (!__pthread_has_cas)
|
||||
+#endif
|
||||
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
|
||||
+ {
|
||||
+ __pthread_acquire(&lock->__spinlock);
|
||||
+
|
||||
+ if (lock->__status == 0) {
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ lock->__spinlock = __LT_SPINLOCK_INIT;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ th->p_condwait_waitnode.abandoned = 0;
|
||||
+ th->p_condwait_waitnode.next = (struct wait_node *) lock->__status;
|
||||
+ th->p_condwait_waitnode.thr = th;
|
||||
+ lock->__status = (long) &th->p_condwait_waitnode;
|
||||
+
|
||||
+ WRITE_MEMORY_BARRIER();
|
||||
+ lock->__spinlock = __LT_SPINLOCK_INIT;
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+#if defined HAS_COMPARE_AND_SWAP
|
||||
+ do {
|
||||
+ oldstatus = lock->__status;
|
||||
+ if (oldstatus == 0) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ th->p_condwait_waitnode.thr = th;
|
||||
+ newstatus = (long) &th->p_condwait_waitnode;
|
||||
+ th->p_condwait_waitnode.abandoned = 0;
|
||||
+ th->p_condwait_waitnode.next = (struct wait_node *) oldstatus;
|
||||
+ /* Make sure the store in wait_node.next completes before performing
|
||||
+ the compare-and-swap */
|
||||
+ MEMORY_BARRIER();
|
||||
+ } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
|
||||
void __pthread_alt_lock(struct _pthread_fastlock * lock,
|
||||
pthread_descr self)
|
||||
diff -ru ../../work.orig/linuxthreads-2.2.3_1/spinlock.h ./spinlock.h
|
||||
--- ../../work.orig/linuxthreads-2.2.3_1/spinlock.h Wed Jul 18 07:25:04 2001
|
||||
+++ ./spinlock.h Wed Jul 18 09:14:58 2001
|
||||
@@ -130,6 +130,9 @@
|
||||
timed-out waits. Warning: do not mix these operations with the above ones
|
||||
over the same lock object! */
|
||||
|
||||
+extern int __pthread_alt_condwait_queuelock(struct _pthread_fastlock * lock,
|
||||
+ pthread_descr th);
|
||||
+
|
||||
extern void __pthread_alt_lock(struct _pthread_fastlock * lock,
|
||||
pthread_descr self);
|
||||
|
Loading…
Reference in New Issue
Block a user