Return-Path: Delivered-To: apmail-new-httpd-archive@apache.org Received: (qmail 17443 invoked by uid 500); 20 Jul 2001 17:31:40 -0000 Mailing-List: contact new-httpd-help@apache.org; run by ezmlm Precedence: bulk Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list new-httpd@apache.org Received: (qmail 17396 invoked from network); 20 Jul 2001 17:31:40 -0000 Date: Fri, 20 Jul 2001 10:30:53 -0700 From: Aaron Bannert To: new-httpd , dev@apr.apache.org Subject: [PATCH] APR thread updates and associated httpd-2.0 changes Message-ID: <20010720103053.C12411@ebuilt.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i X-AntiVirus: scanned for viruses by AMaViS 0.2.1-pre3 (http://amavis.org/) X-Spam-Rating: h31.sny.collab.net 1.6.2 0/1000/N I submitted most of this patch last weekend. Since then I've fixed a small bug in the apr_thread_exit() patch I made (I could really use APR commit access for the little things like this :). I haven't heard any objections (Ryan ;), so I assume these changes were acceptable. I've also brought my httpd-2.0 tree up to date with the APR patch. (Pretty minor changes. Please verify.) As a reminder, here are the things this fixes/changes: - fixes apr_thread_exit(), it wasn't actually passing the return status back. - changes apr_thread_start_t (worker's function prototype) to take the parameter apr_thread_param_t, which contains the thread pointer and the opaque data pointer. - adds a new test in test/testthread.c to make sure apr_thread_exit() is working. (and the new parts for httpd-2.0) - updates httpd-2.0 to work with the above changes. changes the worker functions in the threaded mpm and perchild mpm. enjoy, -aaron Index: server/mpm/perchild/perchild.c =================================================================== RCS file: /home/cvspublic/httpd-2.0/server/mpm/perchild/perchild.c,v retrieving revision 1.71 diff -u -r1.71 perchild.c --- server/mpm/perchild/perchild.c 2001/07/18 20:45:35 1.71 +++ server/mpm/perchild/perchild.c 2001/07/20 17:11:30 @@ -512,7 +512,7 @@ } } -static void *worker_thread(void *); +static void *worker_thread(apr_thread_param_t *); /* Starts a thread as long as we're below max_threads */ static int start_thread(void) @@ -579,8 +579,9 @@ /* idle_thread_count should be incremented before starting a worker_thread */ -static void *worker_thread(void *arg) +static void *worker_thread(apr_thread_param_t *param) { + apr_thread_t *thread = param->t; apr_socket_t *csd = NULL; apr_pool_t *tpool; /* Pool for this thread */ apr_pool_t *ptrans; /* Pool for per-transaction stuff */ @@ -588,7 +589,7 @@ int srv; int curr_pollfd, last_pollfd = 0; int thread_just_started = 1; - int thread_num = *((int *) arg); + int thread_num = *((int *) param->data); long conn_id = child_num * HARD_THREAD_LIMIT + thread_num; apr_pollfd_t *pollset; int n; @@ -789,6 +790,7 @@ } apr_lock_release(worker_thread_count_mutex); + apr_thread_exit(thread, NULL); return NULL; } Index: server/mpm/threaded/threaded.c =================================================================== RCS file: /home/cvspublic/httpd-2.0/server/mpm/threaded/threaded.c,v retrieving revision 1.46 diff -u -r1.46 threaded.c --- server/mpm/threaded/threaded.c 2001/07/18 20:45:36 1.46 +++ server/mpm/threaded/threaded.c 2001/07/20 17:11:32 @@ -520,9 +520,10 @@ apr_lock_release(pipe_of_death_mutex); } -static void * worker_thread(void * dummy) +static void * worker_thread(apr_thread_param_t *param) { - proc_info * ti = dummy; + apr_thread_t *thread = param->t; + proc_info * ti = param->data; int process_slot = ti->pid; int thread_slot = ti->tid; apr_pool_t *tpool = ti->tpool; @@ -658,6 +659,7 @@ } apr_lock_release(worker_thread_count_mutex); + apr_thread_exit(thread, NULL); return NULL; } @@ -671,9 +673,10 @@ return 0; } -static void *start_threads(void * dummy) +static void *start_threads(apr_thread_param_t *param) { - thread_starter *ts = dummy; + apr_thread_t *thread = param->t; + thread_starter *ts = param->data; apr_thread_t **threads = ts->threads; apr_threadattr_t *thread_attr = ts->threadattr; int child_num_arg = ts->child_num_arg; @@ -733,6 +736,7 @@ * "life_status" is almost right, but it's in the worker's structure, and * the name could be clearer. gla */ + apr_thread_exit(thread, NULL); return NULL; } Index: srclib/apr/include/apr_thread_proc.h =================================================================== RCS file: /home/cvspublic/apr/include/apr_thread_proc.h,v retrieving revision 1.65 diff -u -r1.65 apr_thread_proc.h --- srclib/apr/include/apr_thread_proc.h 2001/06/06 18:11:06 1.65 +++ srclib/apr/include/apr_thread_proc.h 2001/07/20 17:11:32 @@ -125,7 +125,13 @@ typedef struct apr_other_child_rec_t apr_other_child_rec_t; #endif /* APR_HAS_OTHER_CHILD */ -typedef void *(APR_THREAD_FUNC *apr_thread_start_t)(void *); +struct apr_thread_param_t { + apr_thread_t *t; + void *data; +}; +typedef struct apr_thread_param_t apr_thread_param_t; + +typedef void *(APR_THREAD_FUNC *apr_thread_start_t)(apr_thread_param_t *); enum kill_conditions { kill_never, /* process is never sent any signals */ Index: srclib/apr/test/testthread.c =================================================================== RCS file: /home/cvspublic/apr/test/testthread.c,v retrieving revision 1.17 diff -u -r1.17 testthread.c --- srclib/apr/test/testthread.c 2001/03/14 15:56:44 1.17 +++ srclib/apr/test/testthread.c 2001/07/20 17:11:33 @@ -72,57 +72,66 @@ } #else /* !APR_HAS_THREADS */ -void * APR_THREAD_FUNC thread_func1(void *data); -void * APR_THREAD_FUNC thread_func2(void *data); -void * APR_THREAD_FUNC thread_func3(void *data); -void * APR_THREAD_FUNC thread_func4(void *data); +void * APR_THREAD_FUNC thread_func1(apr_thread_param_t *thrparm); +void * APR_THREAD_FUNC thread_func2(apr_thread_param_t *thrparm); +void * APR_THREAD_FUNC thread_func3(apr_thread_param_t *thrparm); +void * APR_THREAD_FUNC thread_func4(apr_thread_param_t *thrparm); apr_lock_t *thread_lock; apr_pool_t *context; int x = 0; +apr_status_t exit_ret_val = 123; /* just some made up number to check on later */ -void * APR_THREAD_FUNC thread_func1(void *data) +void * APR_THREAD_FUNC thread_func1(apr_thread_param_t *thrparm) { int i; + apr_thread_t *thread = thrparm->t; for (i = 0; i < 10000; i++) { apr_lock_acquire(thread_lock); x++; apr_lock_release(thread_lock); } + apr_thread_exit(thread, &exit_ret_val); return NULL; } -void * APR_THREAD_FUNC thread_func2(void *data) +void * APR_THREAD_FUNC thread_func2(apr_thread_param_t *thrparm) { int i; + apr_thread_t *thread = thrparm->t; for (i = 0; i < 10000; i++) { apr_lock_acquire(thread_lock); x++; apr_lock_release(thread_lock); } + apr_thread_exit(thread, &exit_ret_val); return NULL; } -void * APR_THREAD_FUNC thread_func3(void *data) +void * APR_THREAD_FUNC thread_func3(apr_thread_param_t *thrparm) { int i; + apr_thread_t *thread = thrparm->t; for (i = 0; i < 10000; i++) { apr_lock_acquire(thread_lock); x++; apr_lock_release(thread_lock); } + apr_thread_exit(thread, &exit_ret_val); return NULL; } -void * APR_THREAD_FUNC thread_func4(void *data) +void * APR_THREAD_FUNC thread_func4(apr_thread_param_t *thrparm) { int i; + apr_thread_t *thread = thrparm->t; for (i = 0; i < 10000; i++) { apr_lock_acquire(thread_lock); x++; apr_lock_release(thread_lock); } + apr_thread_exit(thread, &exit_ret_val); return NULL; } @@ -172,7 +181,15 @@ apr_thread_join(&s2, t2); apr_thread_join(&s3, t3); apr_thread_join(&s4, t4); - fprintf (stdout, "OK\n"); + fprintf (stdout, "OK\n"); + + fprintf(stdout, "Checking thread's returned value......."); + if (s1 != exit_ret_val || s2 != exit_ret_val || + s3 != exit_ret_val || s4 != exit_ret_val) { + fprintf(stderr, "Invalid return value (not expected value)\n"); + exit(-1); + } + fprintf(stdout, "OK\n"); fprintf(stdout, "Checking if locks worked......."); if (x != 40000) { Index: srclib/apr/threadproc/beos/thread.c =================================================================== RCS file: /home/cvspublic/apr/threadproc/beos/thread.c,v retrieving revision 1.22 diff -u -r1.22 thread.c --- srclib/apr/threadproc/beos/thread.c 2001/06/14 18:52:05 1.22 +++ srclib/apr/threadproc/beos/thread.c 2001/07/20 17:11:33 @@ -94,13 +94,17 @@ { int32 temp; apr_status_t stat; + struct thread_info_t *thr_info; + apr_thread_t *thread; + apr_thread_param_t *thrparm; - (*new) = (apr_thread_t *)apr_palloc(cont, sizeof(apr_thread_t)); - if ((*new) == NULL) { + thread = (apr_thread_t *)apr_palloc(cont, sizeof(apr_thread_t)); + (*new) = thread; + if (thread == NULL) { return APR_ENOMEM; } - (*new)->cntxt = cont; + thread->cntxt = cont; /* First we create the new thread...*/ if (attr) @@ -108,14 +112,23 @@ else temp = B_NORMAL_PRIORITY; - stat = apr_pool_create(&(*new)->cntxt, cont); + stat = apr_pool_create(&thread->cntxt, cont); if (stat != APR_SUCCESS) { return stat; } - (*new)->td = spawn_thread((thread_func)func, "apr thread", temp, data); + thread->cntxt = cont; + + thrparm = (apr_thread_param_t *)apr_palloc(cont, sizeof(apr_thread_param_t)); + if (thrparm == NULL) { + return APR_ENOMEM; + } + thrparm->t = thread; + thrparm->data = data; + + thread->td = spawn_thread((thread_func)func, "apr thread", temp, thrparm); /* Now we try to run it...*/ - if (resume_thread((*new)->td) == B_NO_ERROR) { + if (resume_thread(thread->td) == B_NO_ERROR) { return APR_SUCCESS; } else { @@ -142,7 +155,11 @@ apr_status_t apr_thread_join(apr_status_t *retval, apr_thread_t *thd) { - if (wait_for_thread(thd->td,(void *)&retval) == B_NO_ERROR) { + apr_status_t *thrstat = NULL; + + if (wait_for_thread(thd->td,(void *)&thrstat) == B_NO_ERROR) { + if (retval != NULL && thrstat != NULL) + *retval = *thrstat; return APR_SUCCESS; } else { Index: srclib/apr/threadproc/os2/thread.c =================================================================== RCS file: /home/cvspublic/apr/threadproc/os2/thread.c,v retrieving revision 1.22 diff -u -r1.22 thread.c --- srclib/apr/threadproc/os2/thread.c 2001/06/16 01:27:15 1.22 +++ srclib/apr/threadproc/os2/thread.c 2001/07/20 17:11:33 @@ -94,8 +94,18 @@ static void apr_thread_begin(void *arg) { - apr_thread_t *thread = (apr_thread_t *)arg; - thread->rv = thread->func(thread->data); + apr_thread_param_t *thrparm; + apr_thread_t *thread = (apr_thread_t *)arg; + + thrparm = (apr_thread_param_t *)apr_palloc(cont, sizeof(apr_thread_param_t)); + if (thrparm == NULL) { + return APR_ENOMEM; + } + + thrparm->t = thread; + thrparm->data = data; + + thread->rv = thread->func(thrparm); } @@ -132,12 +142,23 @@ } } - if (thread->attr->attr & APR_THREADATTR_DETACHED) + if (thread->attr->attr & APR_THREADATTR_DETACHED) { + apr_thread_param_t *thrparm; + + thrparm = (apr_thread_param_t *)apr_palloc(cont, sizeof(apr_thread_param_t)); + if (thrparm == NULL) { + return APR_ENOMEM; + } + + thrparm->t = thread; + thrparm->data = data; + thread->tid = _beginthread((os2_thread_start_t)func, NULL, - APR_THREAD_STACKSIZE, data); - else + APR_THREAD_STACKSIZE, thrparm); + } else { thread->tid = _beginthread(apr_thread_begin, NULL, APR_THREAD_STACKSIZE, thread); + } if (thread->tid < 0) { return errno; @@ -180,7 +201,8 @@ if (rc == ERROR_INVALID_THREADID) rc = 0; /* Thread had already terminated */ - *retval = (apr_status_t)thd->rv; + if (retval != NULL) + *retval = (apr_status_t)thd->rv; return APR_OS2_STATUS(rc); } Index: srclib/apr/threadproc/unix/thread.c =================================================================== RCS file: /home/cvspublic/apr/threadproc/unix/thread.c,v retrieving revision 1.39 diff -u -r1.39 thread.c --- srclib/apr/threadproc/unix/thread.c 2001/06/14 18:52:09 1.39 +++ srclib/apr/threadproc/unix/thread.c 2001/07/20 17:11:33 @@ -122,32 +122,43 @@ { apr_status_t stat; pthread_attr_t *temp; + apr_thread_t *thread; + apr_thread_param_t *thrparm; - (*new) = (apr_thread_t *)apr_pcalloc(cont, sizeof(apr_thread_t)); + thread = (apr_thread_t *)apr_pcalloc(cont, sizeof(apr_thread_t)); + (*new) = thread; - if ((*new) == NULL) { + if (thread == NULL) { return APR_ENOMEM; } - (*new)->td = (pthread_t *)apr_pcalloc(cont, sizeof(pthread_t)); + thread->td = (pthread_t *)apr_pcalloc(cont, sizeof(pthread_t)); - if ((*new)->td == NULL) { + if (thread->td == NULL) { return APR_ENOMEM; } - (*new)->cntxt = cont; - if (attr) temp = attr->attr; else temp = NULL; - - stat = apr_pool_create(&(*new)->cntxt, cont); + + thread->cntxt = cont; + + stat = apr_pool_create(&thread->cntxt, cont); if (stat != APR_SUCCESS) { return stat; } + + thrparm = (apr_thread_param_t *)apr_pcalloc(cont, sizeof(apr_thread_param_t)); + if (thrparm == NULL) { + return APR_ENOMEM; + } - if ((stat = pthread_create((*new)->td, temp, func, data)) == 0) { + thrparm->t = thread; + thrparm->data = data; + + if ((stat = pthread_create(thread->td, temp, (void*)func, thrparm)) == 0) { return APR_SUCCESS; } else { @@ -155,7 +166,7 @@ stat = errno; #endif return stat; - } + } } apr_os_thread_t apr_os_thread_current(void) @@ -178,8 +189,11 @@ apr_status_t apr_thread_join(apr_status_t *retval, apr_thread_t *thd) { apr_status_t stat; + apr_status_t *thrstat = NULL; - if ((stat = pthread_join(*thd->td,(void *)&retval)) == 0) { + if ((stat = pthread_join(*thd->td,(void **)&thrstat)) == 0) { + if (retval != NULL && thrstat != NULL) + *retval = *thrstat; return APR_SUCCESS; } else { Index: srclib/apr/threadproc/win32/thread.c =================================================================== RCS file: /home/cvspublic/apr/threadproc/win32/thread.c,v retrieving revision 1.32 diff -u -r1.32 thread.c --- srclib/apr/threadproc/win32/thread.c 2001/07/06 14:20:03 1.32 +++ srclib/apr/threadproc/win32/thread.c 2001/07/20 17:11:33 @@ -97,25 +97,36 @@ apr_status_t stat; unsigned temp; int lasterror; + apr_thread_t *thread; + apr_thread_param_t *thrparm; - (*new) = (apr_thread_t *)apr_palloc(cont, sizeof(apr_thread_t)); + thread = (apr_thread_t *)apr_palloc(cont, sizeof(apr_thread_t)); + (*new) = thread; - if ((*new) == NULL) { + if (thread == NULL) { return APR_ENOMEM; } - (*new)->cntxt = cont; + thread->cntxt = cont; - stat = apr_pool_create(&(*new)->cntxt, cont); + stat = apr_pool_create(&thread->cntxt, cont); if (stat != APR_SUCCESS) { return stat; } + thrparm = (apr_thread_param_t *)apr_palloc(cont, sizeof(apr_thread_param_t)); + if (thrparm == NULL) { + return APR_ENOMEM; + } + + thrparm->t = thread; + thrparm->data = data; + /* Use 0 for Thread Stack Size, because that will default the stack to the * same size as the calling thread. */ - if (((*new)->td = (HANDLE *)_beginthreadex(NULL, 0, (unsigned int (APR_THREAD_FUNC *)(void *))func, - data, 0, &temp)) == 0) { + if ((thread->td = (HANDLE *)_beginthreadex(NULL, 0, (unsigned int (APR_THREAD_FUNC *)(void *))func, + thrparm, 0, &temp)) == 0) { lasterror = apr_get_os_error(); return APR_EEXIST; /* MSVC++ doc doesn't mention any additional error info @@ -124,7 +135,7 @@ } if (attr && attr->detach) { - CloseHandle((*new)->td); + CloseHandle(thread->td); } return APR_SUCCESS;