Loading...
pthreads.subproj/pthread.c Libc-186 Libc-166
--- Libc/Libc-186/pthreads.subproj/pthread.c
+++ Libc/Libc-166/pthreads.subproj/pthread.c
@@ -55,10 +55,8 @@
  */
 
 size_t _pthread_stack_size = 0;
-int _spin_tries = 0;
-#if !defined(__ppc__)
+int _spin_tries = 1;
 int _cpu_has_altivec = 0;
-#endif
 
 /* This global should be used (carefully) by anyone needing to know if a pthread has been
 ** created.
@@ -106,6 +104,14 @@
 #define STACK_SELF(sp)		STACK_START(sp)
 
 #endif
+
+/* This is the struct used to recycle (or terminate) a thread */
+/* We stash the thread port into the reply port of the message */
+
+typedef struct {
+	mach_msg_header_t header;
+	mach_msg_trailer_t trailer;
+} recycle_msg_t;
 
 /* Set the base address to use as the stack pointer, before adjusting due to the ABI */
 
@@ -508,6 +514,12 @@
     }
 }
 
+pthread_t _cachedThread = (pthread_t)0;
+
+void _clear_thread_cache(void) {
+    _cachedThread = (pthread_t)0;
+}
+
 /*
  * Create and start execution of a new thread.
  */
@@ -515,6 +527,7 @@
 static void
 _pthread_body(pthread_t self)
 {
+    _clear_thread_cache();
     _pthread_set_self(self);
     pthread_exit((self->fun)(self->arg));
 }
@@ -708,9 +721,9 @@
 			thread->death = MACH_PORT_NULL;
 			UNLOCK(thread->lock);
 			if (num_joiners > 0)
-			{
-				/* Wake up a joiner */
-				PTHREAD_MACH_CALL(semaphore_signal(thread->joiners), kern_res);
+			{ /* Have to tell these guys this thread can't be joined with */
+				swtch_pri(0);
+				PTHREAD_MACH_CALL(semaphore_signal_all(thread->joiners), kern_res);
 			}
 			/* Destroy 'control' semaphores */
 			PTHREAD_MACH_CALL(semaphore_destroy(mach_task_self(),
@@ -718,10 +731,6 @@
 			PTHREAD_MACH_CALL(semaphore_destroy(mach_task_self(),
 						    death), kern_res);
 			return (ESUCCESS);
-		} else if (thread->detached == _PTHREAD_EXITED) {
-			UNLOCK(thread->lock);
-			pthread_join(thread, NULL);
-			return ESUCCESS;
 		} else
 		{
 			UNLOCK(thread->lock);
@@ -739,20 +748,16 @@
 /* terminated, it will be yanked out from under the mach_msg() call. */
 
 static void _pthread_become_available(pthread_t thread) {
-	mach_msg_empty_rcv_t msg = { { 0 } };
+	recycle_msg_t msg = { { 0 } };
 	kern_return_t ret;
 
-	if (thread->reply_port == MACH_PORT_NULL) {
-		thread->reply_port = mach_reply_port();
-	}
 	msg.header.msgh_size = sizeof msg - sizeof msg.trailer;
 	msg.header.msgh_remote_port = thread_recycle_port;
 	msg.header.msgh_local_port = MACH_PORT_NULL; 
 	msg.header.msgh_id = (int)thread;
 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
-	ret = mach_msg(&msg.header, MACH_SEND_MSG | MACH_RCV_MSG,
-			msg.header.msgh_size, sizeof msg,
-			thread->reply_port, MACH_MSG_TIMEOUT_NONE,
+	ret = mach_msg(&msg.header, MACH_SEND_MSG, msg.header.msgh_size, 0,
+			MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
 			MACH_PORT_NULL);
 	while (1) {
 		ret = thread_suspend(thread->kernel_thread);
@@ -762,17 +767,17 @@
 
 /* Check to see if any threads are available. Return immediately */
 
-static kern_return_t _pthread_check_for_available_threads(mach_msg_empty_rcv_t *msg) {
+static kern_return_t _pthread_check_for_available_threads(recycle_msg_t *msg) {
 	return mach_msg(&msg->header, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0,
-			sizeof(mach_msg_empty_rcv_t), thread_recycle_port, 0,
+			sizeof(recycle_msg_t), thread_recycle_port, 0,
 			MACH_PORT_NULL);
 }
 
 /* Terminate all available threads and deallocate their stacks */
 static void _pthread_reap_threads(void) {
 	kern_return_t ret;
-	mach_msg_empty_rcv_t msg = { { 0 } };
-	while((ret = _pthread_check_for_available_threads(&msg)) == KERN_SUCCESS) {
+	recycle_msg_t msg = { { 0 } };
+	while(_pthread_check_for_available_threads(&msg) == KERN_SUCCESS) {
 		pthread_t th = (pthread_t)msg.header.msgh_id;
 		mach_port_t kernel_thread = th->kernel_thread;
 		mach_port_t reply_port = th->reply_port; 
@@ -802,14 +807,31 @@
 		}
 		free(th);
 	}
-	assert(ret == MACH_RCV_TIMED_OUT);
-}
-
-/* For compatibility... */
+}
+
+
+static void *
+stackAddress(void)
+{
+    unsigned dummy;
+    return (void *)((unsigned)&dummy & ~ (PTHREAD_STACK_MIN - 1));
+}
+
+extern pthread_t _pthread_self(void);
 
 pthread_t
-_pthread_self() {
-	return pthread_self();
+pthread_self(void)
+{
+    void * myStack = (void *)0;
+    pthread_t cachedThread = _cachedThread;
+    if (cachedThread) {
+        myStack = stackAddress();
+        if ((void *)((unsigned)(cachedThread->stackaddr - 1) & ~ (PTHREAD_STACK_MIN - 1)) == myStack) {
+            return cachedThread;
+        }
+    }
+    _cachedThread = _pthread_self();
+    return _cachedThread;
 }
 
 /*
@@ -822,6 +844,7 @@
         struct _pthread_handler_rec *handler;
 	kern_return_t kern_res;
 	int num_joiners;
+    _clear_thread_cache();
 	while ((handler = self->cleanup_stack) != 0)
 	{
 		(handler->routine)(handler->arg);
@@ -837,14 +860,10 @@
 		UNLOCK(self->lock);
 		if (num_joiners > 0)
 		{
-			/* POSIX says that multiple pthread_join() calls on */
-			/* the same thread are undefined so we just wake up */
-			/* the first one to join */
-			PTHREAD_MACH_CALL(semaphore_signal(self->joiners), kern_res);
-		}
-		do {
-			PTHREAD_MACH_CALL(semaphore_wait(self->death), kern_res);
-		} while (kern_res == KERN_ABORTED);
+			swtch_pri(0);
+			PTHREAD_MACH_CALL(semaphore_signal_all(self->joiners), kern_res);
+		}
+		PTHREAD_MACH_CALL(semaphore_wait(self->death), kern_res);
 	} else
 		UNLOCK(self->lock);
 	/* Destroy thread & reclaim resources */
@@ -877,9 +896,7 @@
 		{
 			thread->num_joiners++;
 			UNLOCK(thread->lock);
-			do {
-				PTHREAD_MACH_CALL(semaphore_wait(thread->joiners), kern_res);
-			 } while (kern_res == KERN_ABORTED);
+			PTHREAD_MACH_CALL(semaphore_wait(thread->joiners), kern_res);
 			LOCK(thread->lock);
 			thread->num_joiners--;
 		}
@@ -892,6 +909,7 @@
 					*value_ptr = thread->exit_value;
 				}
 				UNLOCK(thread->lock);
+				swtch_pri(0);
 				PTHREAD_MACH_CALL(semaphore_signal(thread->death), kern_res);
 				return (ESUCCESS);
 			} else
@@ -1165,10 +1183,14 @@
 	}
 	attrs = &_attr;
 	pthread_attr_init(attrs);
-	_pthread_set_self(&_thread);
+    _clear_thread_cache();
+    _pthread_set_self(&_thread);
 
         _pthread_create(&_thread, attrs, USRSTACK, mach_thread_self());
-        thread = &_thread;
+        thread = (pthread_t)malloc(sizeof(struct _pthread));
+	memcpy(thread, &_thread, sizeof(struct _pthread));
+    _clear_thread_cache();
+        _pthread_set_self(thread);
         thread->detached = _PTHREAD_CREATE_PARENT;
 
         /* See if we're on a multiprocessor and set _spin_tries if so.  */
@@ -1177,7 +1199,7 @@
 	len = sizeof(numcpus);
 	if (sysctl(mib, 2, &numcpus, &len, NULL, 0) == 0) {
 		if (numcpus > 1) {
-			_spin_tries = MP_SPIN_TRIES;
+			_spin_tries = SPIN_TRIES;
 		}
 	} else {
 		count = HOST_BASIC_INFO_COUNT;
@@ -1188,7 +1210,7 @@
 			printf("host_info failed (%d)\n", kr);
 		else {
 			if (basic_info.avail_cpus > 1)
-				_spin_tries = MP_SPIN_TRIES;
+				_spin_tries = SPIN_TRIES;
 			/* This is a crude test */
 			if (basic_info.cpu_subtype >= CPU_SUBTYPE_POWERPC_7400) 
 				_cpu_has_altivec = 1;