Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 16 Jan 2005 01:05:02 GMT
From:      David Xu <davidxu@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 69097 for review
Message-ID:  <200501160105.j0G1525o014890@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=69097

Change 69097 by davidxu@davidxu_tiger on 2005/01/16 01:04:45

	simplify code for creating new thread.

Affected files ...

.. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_create.c#6 edit
.. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_list.c#3 edit

Differences ...

==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_create.c#6 (text+ko) ====

@@ -58,167 +58,118 @@
 	       void *(*start_routine) (void *), void *arg)
 {
 	ucontext_t uc;
-	sigset_t sigmask;
+	sigset_t sigmask, oldsigmask;
 	struct pthread *curthread, *new_thread;
 	int ret = 0;
 
 	_thr_check_init();
 
 	/*
-	 * Turn on threaded mode, if failed, it is unnecessary to
-	 * do further work.
+	 * Tell libc and others now they need lock to protect their data.
 	 */
-	if (_thr_isthreaded() == 0 && _thr_setthreaded(1)) {
+	if (_thr_isthreaded() == 0 && _thr_setthreaded(1))
 		return (EAGAIN);
-	}
+
 	curthread = _get_curthread();
+	if ((new_thread = _thr_alloc(curthread)) == NULL)
+		return (EAGAIN);
 
-	/*
-	 * Allocate memory for the thread structure.
-	 * Some functions use malloc, so don't put it
-	 * in a critical region.
-	 */
-	if ((new_thread = _thr_alloc(curthread)) == NULL) {
-		/* Insufficient memory to create a thread: */
-		ret = EAGAIN;
-	} else {
-		/* Check if default thread attributes are required: */
-		if (attr == NULL || *attr == NULL)
-			/* Use the default thread attributes: */
-			new_thread->attr = _pthread_attr_default;
-		else {
-			new_thread->attr = *(*attr);
-			if ((*attr)->sched_inherit == PTHREAD_INHERIT_SCHED) {
-				/* inherit scheduling contention scop */
-				if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
-					new_thread->attr.flags |= PTHREAD_SCOPE_SYSTEM;
-				else
-					new_thread->attr.flags &= ~PTHREAD_SCOPE_SYSTEM;
-				/*
-				 * scheduling policy and scheduling parameters will be
-				 * inherited in following code.
-				 */
-			}
-		}
-
-		if (_thread_scope_system > 0)
+	if (attr == NULL || *attr == NULL)
+		/* Use the default thread attributes: */
+		new_thread->attr = _pthread_attr_default;
+	else
+		new_thread->attr = *(*attr);
+	if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) {
+		/* inherit scheduling contention scope */
+		if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
 			new_thread->attr.flags |= PTHREAD_SCOPE_SYSTEM;
-		else if (_thread_scope_system < 0)
+		else
 			new_thread->attr.flags &= ~PTHREAD_SCOPE_SYSTEM;
+		/*
+		 * scheduling policy and scheduling parameters will be
+		 * inherited in following code.
+		 */
+	}
 
-		if (create_stack(&new_thread->attr) != 0) {
-			/* Insufficient memory to create a stack: */
-			ret = EAGAIN;
-			new_thread->isdead = 1;
-			_thr_free(curthread, new_thread);
-		} else {
-			new_thread->tid = 0;
-			new_thread->cycle = 0;
-			new_thread->isdead = 0;
-			new_thread->rtld_bits = 0;
-			/*
-			 * Write a magic value to the thread structure
-			 * to help identify valid ones:
-			 */
-			new_thread->magic = THR_MAGIC;
+	if (_thread_scope_system > 0)
+		new_thread->attr.flags |= PTHREAD_SCOPE_SYSTEM;
+	else if (_thread_scope_system < 0)
+		new_thread->attr.flags &= ~PTHREAD_SCOPE_SYSTEM;
 
-			new_thread->start_routine = start_routine;
-			new_thread->arg = arg;
-			new_thread->cancelflags = PTHREAD_CANCEL_ENABLE |
-				    PTHREAD_CANCEL_DEFERRED;
+	if (create_stack(&new_thread->attr) != 0) {
+		/* Insufficient memory to create a stack: */
+		new_thread->terminated = 1;
+		_thr_free(curthread, new_thread);
+		return (EAGAIN);
+	}
+	/*
+	 * Write a magic value to the thread structure
+	 * to help identify valid ones:
+	 */
+	new_thread->magic = THR_MAGIC;
+	new_thread->start_routine = start_routine;
+	new_thread->arg = arg;
+	new_thread->cancelflags = PTHREAD_CANCEL_ENABLE |
+	    PTHREAD_CANCEL_DEFERRED;
+	getcontext(&uc);
+	SIGFILLSET(uc.uc_sigmask);
+	uc.uc_stack.ss_sp = new_thread->attr.stackaddr_attr;
+	uc.uc_stack.ss_size = new_thread->attr.stacksize_attr;
+	makecontext(&uc, (void (*)(void))thread_start, 1, new_thread);
 
-			/* No thread is wanting to join to this one: */
-			new_thread->joiner = NULL;
-			new_thread->join_status.thread = NULL;
-			new_thread->critical_count = 0;
-			new_thread->sflags = 0;
-			getcontext(&uc);
-			SIGFILLSET(uc.uc_sigmask);
-			uc.uc_stack.ss_sp = new_thread->attr.stackaddr_attr;
-			uc.uc_stack.ss_size = new_thread->attr.stacksize_attr;
-			makecontext(&uc, (void (*)(void))thread_start, 1,
-			            new_thread);
+	/*
+	 * Check if this thread is to inherit the scheduling
+	 * attributes from its parent:
+	 */
+	if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) {
+		/*
+		 * Copy the scheduling attributes. Lock the scheduling
+		 * lock to get consistent scheduling parameters.
+		 */
+		THR_LOCK(curthread);
+		new_thread->base_priority = curthread->base_priority;
+		new_thread->attr.prio = curthread->base_priority;
+		new_thread->attr.sched_policy = curthread->attr.sched_policy;
+		THR_UNLOCK(curthread);
+	} else {
+		/*
+		 * Use just the thread priority, leaving the
+		 * other scheduling attributes as their
+		 * default values:
+		 */
+		new_thread->base_priority = new_thread->attr.prio;
+	}
+	new_thread->active_priority = new_thread->base_priority;
 
-			/*
-			 * Check if this thread is to inherit the scheduling
-			 * attributes from its parent:
-			 */
-			if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) {
-				/*
-				 * Copy the scheduling attributes.
-				 * Lock the scheduling lock to get consistent
-				 * scheduling parameters.
-				 */
-				THR_LOCK(curthread);
-				new_thread->base_priority =
-				    curthread->base_priority &
-				    ~THR_SIGNAL_PRIORITY;
-				new_thread->attr.prio =
-				    curthread->base_priority &
-				    ~THR_SIGNAL_PRIORITY;
-				new_thread->attr.sched_policy =
-				    curthread->attr.sched_policy;
-				THR_UNLOCK(curthread);
-			} else {
-				/*
-				 * Use just the thread priority, leaving the
-				 * other scheduling attributes as their
-				 * default values:
-				 */
-				new_thread->base_priority =
-			    		new_thread->attr.prio;
-			}
-			new_thread->active_priority = new_thread->base_priority;
-			new_thread->inherited_priority = 0;
+	/* Initialize the mutex queue: */
+	TAILQ_INIT(&new_thread->mutexq);
+	TAILQ_INIT(&new_thread->pri_mutexq);
 
-			/* Initialize the mutex queue: */
-			TAILQ_INIT(&new_thread->mutexq);
-			TAILQ_INIT(&new_thread->pri_mutexq);
-
-			/* Initialise hooks in the thread structure: */
-			new_thread->specific = NULL;
-			new_thread->specific_data_count = 0;
-			new_thread->cleanup = NULL;
-			new_thread->flags = 0;
-			new_thread->tlflags = 0;
-			new_thread->sigbackout = NULL;
-			new_thread->error = 0;
-			SIGEMPTYSET(new_thread->sigpend);
-			new_thread->check_pending = 0;
-			new_thread->refcount = 0;
-			new_thread->locklevel = 0;
-			new_thread->rdlock_count = 0;
-			new_thread->data.mutex = 0;
-			new_thread->priority_mutex_count = 0;
-			new_thread->rtld_bits = 0;
-			if (new_thread->attr.suspend == THR_CREATE_SUSPENDED)
-				new_thread->flags = THR_FLAGS_SUSPENDED;
-			new_thread->state = PS_RUNNING;
-			/*
-			 * Schedule the new thread.
-			 */
-			SIGFILLSET(sigmask);
-			/*
-			 * Thread created by thr_create() inherits currrent thread
-			 * sigmask, however, before new thread setup itself correctly,
-			 * it can not handle signal, so we should masks all signals here.
-			 */
-			__sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask);
-			new_thread->sigmask = curthread->sigmask;
-			/* Add the new thread. */
-			_thr_link(curthread, new_thread);
-			/* Return a pointer to the thread structure: */
-			(*thread) = new_thread;
-			ret = thr_create(&uc, &new_thread->tid, 0);
-			__sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
-			if (ret != 0) {
-				_thr_unlink(curthread, new_thread);
-				free_thread(curthread, new_thread);
-				(*thread) = 0;
-			}
-		}
+	/* Initialise hooks in the thread structure: */
+	if (new_thread->attr.suspend == THR_CREATE_SUSPENDED)
+		new_thread->flags = THR_FLAGS_SUSPENDED;
+	new_thread->state = PS_RUNNING;
+	/*
+	 * Thread created by thr_create() inherits currrent thread
+	 * sigmask, however, before new thread setup itself correctly,
+	 * it can not handle signal, so we should masks all signals here.
+	 */
+	SIGFILLSET(sigmask);
+	__sys_sigprocmask(SIG_SETMASK, &sigmask, &oldsigmask);
+	new_thread->sigmask = oldsigmask;
+	/* Add the new thread. */
+	_thr_link(curthread, new_thread);
+	/* Return thread pointer eariler so that new thread can use it. */
+	(*thread) = new_thread;
+	/* Schedule the new thread. */
+	ret = thr_create(&uc, &new_thread->tid, 0);
+	__sys_sigprocmask(SIG_SETMASK, &oldsigmask, NULL);
+	if (ret != 0) {
+		_thr_unlink(curthread, new_thread);
+		free_thread(curthread, new_thread);
+		(*thread) = 0;
+		ret = EAGAIN;
 	}
-	/* Return the status: */
 	return (ret);
 }
 
@@ -226,7 +177,7 @@
 free_thread(struct pthread *curthread, struct pthread *thread)
 {
 	free_stack(curthread, &thread->attr);
-	curthread->isdead = 1;
+	curthread->terminated = 1;
 	_thr_free(curthread, thread);
 }
 

==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_list.c#3 (text+ko) ====

@@ -28,8 +28,6 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
 #include <sys/types.h>
 #include <sys/queue.h>
 
@@ -61,6 +59,7 @@
  */
 static TAILQ_HEAD(, pthread)	free_threadq;
 static struct umtx		free_thread_lock;
+static struct umtx		tcb_lock;
 static int			free_thread_count = 0;
 static int			inited = 0;
 static u_int64_t		next_uniqueid = 1;
@@ -70,9 +69,6 @@
 static struct thread_hash_head	thr_hashtable[HASH_QUEUES];
 #define	THREAD_HASH(thrd)	(((unsigned long)thrd >> 12) % HASH_QUEUES)
 
-/* Lock for thread tcb constructor/destructor */
-static struct	umtx		tcb_lock;
-
 static void	thr_destroy(struct pthread *curthread, struct pthread *thread);
 
 void
@@ -81,7 +77,7 @@
 	int i;
 
 	_gc_count = 0;
-	umtx_init(&_thread_list_lock);
+	umtx_init(&_thr_list_lock);
 	TAILQ_INIT(&_thread_list);
 	TAILQ_INIT(&free_threadq);
 	umtx_init(&free_thread_lock);
@@ -96,6 +92,7 @@
 void
 _thr_gc(struct pthread *curthread)
 {
+	return;
 	struct pthread *td, *td_next;
 	TAILQ_HEAD(, pthread) worklist;
 
@@ -105,26 +102,14 @@
 	/* Check the threads waiting for GC. */
 	for (td = TAILQ_FIRST(&_thread_gc_list); td != NULL; td = td_next) {
 		td_next = TAILQ_NEXT(td, gcle);
-		if ((td->tlflags & TLFLAGS_GC_SAFE) == 0)
-			continue;
-		else if (td->isdead == 0) {
+		if (td->terminated == 0) {
 			/* make sure we are not still in userland */
 			continue;
 		}
-		/*
-		 * Remove the thread from the GC list.  If the thread
-		 * isn't yet detached, it will get added back to the
-		 * GC list at a later time.
-		 */
-		THR_GCLIST_REMOVE(td);
-		DBG_MSG("Freeing thread %p stack\n", td);
-		/*
-		 * We can free the thread stack since it's no longer
-		 * in use.
-		 */
 		_thr_stack_free(&td->attr);
 		if (((td->tlflags & TLFLAGS_DETACHED) != 0) &&
 		    (td->refcount == 0)) {
+			THR_GCLIST_REMOVE(td);
 			/*
 			 * The thread has detached and is no longer
 			 * referenced.  It is safe to remove all
@@ -156,6 +141,7 @@
 _thr_alloc(struct pthread *curthread)
 {
 	struct pthread	*thread = NULL;
+	struct tcb	*tcb = NULL;
 
 	if (curthread != NULL) {
 		if (GC_NEEDED())
@@ -164,6 +150,7 @@
 			THR_LOCK_ACQUIRE(curthread, &free_thread_lock);
 			if ((thread = TAILQ_FIRST(&free_threadq)) != NULL) {
 				TAILQ_REMOVE(&free_threadq, thread, tle);
+				tcb = thread->tcb;
 				free_thread_count--;
 			}
 			THR_LOCK_RELEASE(curthread, &free_thread_lock);
@@ -171,25 +158,21 @@
 	}
 	if ((thread == NULL) &&
 	    ((thread = malloc(sizeof(struct pthread))) != NULL)) {
-		bzero(thread, sizeof(struct pthread));
 		if (curthread) {
 			THR_LOCK_ACQUIRE(curthread, &tcb_lock);
-			thread->tcb = _tcb_ctor(thread, 0 /* not initial tls */);
+			tcb = _tcb_ctor(thread, 0 /* not initial tls */);
 			THR_LOCK_RELEASE(curthread, &tcb_lock);
 		} else {
-			thread->tcb = _tcb_ctor(thread, 1 /* initial tls */);
+			tcb = _tcb_ctor(thread, 1 /* initial tls */);
 		}
-		if (thread->tcb == NULL) {
+		if (tcb == NULL) {
 			free(thread);
 			thread = NULL;
-		} else {
-			/*
-			 * Initialize thread locking.
-			 */
-			umtx_init(&thread->lock);
 		}
-	} else if (thread != NULL) {
-		umtx_init(&thread->lock);
+	}
+	if (thread) {
+		memset(thread, 0, sizeof(*thread));
+		thread->tcb = tcb;
 	}
 	return (thread);
 }
@@ -310,8 +293,6 @@
 	THREAD_LIST_LOCK(curthread);
 	if ((ret = _thr_find_thread(curthread, thread, include_dead)) == 0) {
 		thread->refcount++;
-		if (curthread != NULL)
-			curthread->critical_count++;
 	}
 	THREAD_LIST_UNLOCK(curthread);
 
@@ -325,8 +306,6 @@
 	if (thread != NULL) {
 		THREAD_LIST_LOCK(curthread);
 		thread->refcount--;
-		if (curthread != NULL)
-			curthread->critical_count--;
 		if ((thread->refcount == 0) &&
 		    (thread->tlflags & TLFLAGS_GC_SAFE) != 0)
 			THR_GCLIST_ADD(thread);
@@ -346,8 +325,9 @@
 
 	pthread = _thr_hash_find(thread);
 	if (pthread) {
-		if (include_dead == 0 && pthread->state == PS_DEAD)
+		if (include_dead == 0 && pthread->state == PS_DEAD) {
 			pthread = NULL;
+		}	
 	}
 
 	/* Return zero if the thread exists: */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200501160105.j0G1525o014890>