summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>2003-09-11 00:29:37 +0000
committerwtc%netscape.com <devnull@localhost>2003-09-11 00:29:37 +0000
commit7833838dc872c52014deb72b018bf8d297b1c88d (patch)
treec13642e33461338454893870500925f557ee6bad
parenta1bc1b5e718250c3ca18736f80c0e6d4ff3f092e (diff)
downloadnspr-hg-7833838dc872c52014deb72b018bf8d297b1c88d.tar.gz
Bugzilla bug 214411: implement automatic attaching and detaching of SolarisNSPR_4_4_BASE
native threads. The patch contains contribution by Gerard Roos <gerard.roos@adnovum.ch>. Modified Files: _solaris.h primpl.h solaris.c pruthr.c foreign.c provider.c
-rw-r--r--pr/include/md/_solaris.h2
-rw-r--r--pr/include/private/primpl.h3
-rw-r--r--pr/src/md/unix/solaris.c35
-rw-r--r--pr/src/threads/combined/pruthr.c7
-rw-r--r--pr/tests/foreign.c39
-rw-r--r--pr/tests/provider.c57
6 files changed, 134 insertions, 9 deletions
diff --git a/pr/include/md/_solaris.h b/pr/include/md/_solaris.h
index 01b5fed4..811681bf 100644
--- a/pr/include/md/_solaris.h
+++ b/pr/include/md/_solaris.h
@@ -221,6 +221,7 @@ extern struct PRLock *_pr_schedLock;
#define THREAD_KEY_T thread_key_t
+extern struct PRThread *_pr_attached_thread_tls();
extern struct PRThread *_pr_current_thread_tls();
extern struct _PRCPU *_pr_current_cpu_tls();
extern struct PRThread *_pr_last_thread_tls();
@@ -229,6 +230,7 @@ extern THREAD_KEY_T threadid_key;
extern THREAD_KEY_T cpuid_key;
extern THREAD_KEY_T last_thread_key;
+#define _MD_GET_ATTACHED_THREAD() _pr_attached_thread_tls()
#define _MD_CURRENT_THREAD() _pr_current_thread_tls()
#define _MD_CURRENT_CPU() _pr_current_cpu_tls()
#define _MD_LAST_THREAD() _pr_last_thread_tls()
diff --git a/pr/include/private/primpl.h b/pr/include/private/primpl.h
index b0cd1b5b..351781bf 100644
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -304,7 +304,8 @@ typedef struct _PRInterruptTable {
#define _PR_CPU_PTR(_qp) \
((_PRCPU*) ((char*) (_qp) - offsetof(_PRCPU,links)))
-#if !defined(IRIX) && !defined(WIN32) && !defined(XP_OS2)
+#if !defined(IRIX) && !defined(WIN32) && !defined(XP_OS2) \
+ && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY))
#define _MD_GET_ATTACHED_THREAD() (_PR_MD_CURRENT_THREAD())
#endif
diff --git a/pr/src/md/unix/solaris.c b/pr/src/md/unix/solaris.c
index 4dd1c06e..3313ac83 100644
--- a/pr/src/md/unix/solaris.c
+++ b/pr/src/md/unix/solaris.c
@@ -183,9 +183,25 @@ THREAD_KEY_T cpuid_key;
THREAD_KEY_T last_thread_key;
static sigset_t set, oldset;
+static void
+threadid_key_destructor(void *value)
+{
+ PRThread *me = (PRThread *)value;
+ PR_ASSERT((me != NULL) && (me->flags & _PR_ATTACHED));
+ /*
+ * The Solaris thread library sets the thread specific
+ * data (the current thread) to NULL before invoking
+ * the destructor. We need to restore it to prevent the
+ * _PR_MD_CURRENT_THREAD() call in _PRI_DetachThread()
+ * from attaching the thread again.
+ */
+ _PR_MD_SET_CURRENT_THREAD(me);
+ _PRI_DetachThread();
+}
+
void _MD_EarlyInit(void)
{
- THR_KEYCREATE(&threadid_key, NULL);
+ THR_KEYCREATE(&threadid_key, threadid_key_destructor);
THR_KEYCREATE(&cpuid_key, NULL);
THR_KEYCREATE(&last_thread_key, NULL);
sigemptyset(&set);
@@ -337,7 +353,7 @@ void _MD_lock(struct _MDLock *md_lock)
mutex_lock(&md_lock->lock);
}
-PRThread *_pr_current_thread_tls()
+PRThread *_pr_attached_thread_tls()
{
PRThread *ret;
@@ -345,6 +361,21 @@ PRThread *_pr_current_thread_tls()
return ret;
}
+PRThread *_pr_current_thread_tls()
+{
+ PRThread *thread;
+
+ thread = _MD_GET_ATTACHED_THREAD();
+
+ if (NULL == thread) {
+ thread = _PRI_AttachThread(
+ PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+ PR_ASSERT(thread != NULL);
+
+ return thread;
+}
+
PRStatus
_MD_wait(PRThread *thread, PRIntervalTime ticks)
{
diff --git a/pr/src/threads/combined/pruthr.c b/pr/src/threads/combined/pruthr.c
index cbdfd2c0..a86fe5d0 100644
--- a/pr/src/threads/combined/pruthr.c
+++ b/pr/src/threads/combined/pruthr.c
@@ -1510,13 +1510,14 @@ PR_IMPLEMENT(PRThread*) PR_AttachThread(PRThreadType type,
PR_IMPLEMENT(void) PR_DetachThread(void)
{
/*
- * On IRIX and Windows, foreign threads are detached when
+ * On IRIX, Solaris, and Windows, foreign threads are detached when
* they terminate.
*/
-#if !defined(IRIX) && !defined(WIN32)
+#if !defined(IRIX) && !defined(WIN32) \
+ && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY))
PRThread *me;
if (_pr_initialized) {
- me = _MD_GET_ATTACHED_THREAD();
+ me = _PR_MD_GET_ATTACHED_THREAD();
if ((me != NULL) && (me->flags & _PR_ATTACHED))
_PRI_DetachThread();
}
diff --git a/pr/tests/foreign.c b/pr/tests/foreign.c
index 2fe48b1b..5457cc8c 100644
--- a/pr/tests/foreign.c
+++ b/pr/tests/foreign.c
@@ -63,7 +63,7 @@
#include <stdlib.h>
static enum {
- thread_nspr, thread_pthread, thread_sproc, thread_win32
+ thread_nspr, thread_pthread, thread_uithread, thread_sproc, thread_win32
} thread_provider;
typedef void (*StartFn)(void*);
@@ -94,6 +94,18 @@ static void *pthread_start(void *arg)
} /* pthread_start */
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+#include <thread.h>
+static void *uithread_start(void *arg)
+{
+ StartFn start = ((StartObject*)arg)->start;
+ void *data = ((StartObject*)arg)->arg;
+ PR_Free(arg);
+ start(data);
+ return NULL;
+} /* uithread_start */
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
+
#if defined(IRIX) && !defined(_PR_PTHREADS)
#include <sys/types.h>
#include <sys/prctl.h>
@@ -169,6 +181,29 @@ static PRStatus CreateThread(StartFn start, void *arg)
break;
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+ case thread_uithread:
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ {
+ int rv;
+ thread_t id;
+ long flags;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ flags = THR_DETACHED;
+
+ rv = thr_create(NULL, NULL, uithread_start, start_object, flags, &id);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ break;
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
+
case thread_sproc:
#if defined(IRIX) && !defined(_PR_PTHREADS)
{
@@ -335,6 +370,8 @@ PRIntn main(PRIntn argc, char **argv)
thread_provider = thread_win32;
#elif defined(_PR_PTHREADS)
thread_provider = thread_pthread;
+#elif defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ thread_provider = thread_uithread;
#elif defined(IRIX)
thread_provider = thread_sproc;
#else
diff --git a/pr/tests/provider.c b/pr/tests/provider.c
index 5fd91bea..9fc68d13 100644
--- a/pr/tests/provider.c
+++ b/pr/tests/provider.c
@@ -127,7 +127,7 @@ typedef enum Verbosity
} Verbosity;
static enum {
- thread_nspr, thread_pthread, thread_sproc, thread_win32
+ thread_nspr, thread_pthread, thread_uithread, thread_sproc, thread_win32
} thread_provider;
static PRInt32 domain = AF_INET;
@@ -658,6 +658,20 @@ static void *pthread_start(void *arg)
} /* pthread_start */
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+#include <thread.h>
+
+static void *uithread_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return NULL;
+} /* uithread_start */
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
+
#if defined(IRIX) && !defined(_PR_PTHREADS)
#include <sys/types.h>
#include <sys/prctl.h>
@@ -698,6 +712,11 @@ static PRStatus JoinThread(PRThread *thread)
rv = PR_SUCCESS;
break;
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+ case thread_uithread:
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ rv = PR_SUCCESS;
+ break;
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
case thread_win32:
#if defined(WIN32)
rv = PR_SUCCESS;
@@ -759,6 +778,29 @@ static PRStatus NewThread(
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
break;
+ case thread_uithread:
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ {
+ int rv;
+ thread_t id;
+ long flags;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ flags = THR_DETACHED;
+
+ rv = thr_create(NULL, NULL, uithread_start, start_object, flags, &id);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
+ break;
+
case thread_sproc:
#if defined(IRIX) && !defined(_PR_PTHREADS)
{
@@ -947,9 +989,15 @@ static void PR_CALLBACK Server(void *arg)
PRNetAddr serverAddress;
CSServer_t *server = (CSServer_t*)arg;
PRThread *me = server->thread = PR_CurrentThread();
+ PRSocketOptionData sockOpt;
server->listener = PR_Socket(domain, SOCK_STREAM, protocol);
+ sockOpt.option = PR_SockOpt_Reuseaddr;
+ sockOpt.value.reuse_addr = PR_TRUE;
+ rv = PR_SetSocketOption(server->listener, &sockOpt);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
memset(&serverAddress, 0, sizeof(serverAddress));
rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress);
@@ -1063,7 +1111,7 @@ static void Help(void)
PR_fprintf(debug_out, "\t-e <seconds> duration of the test in seconds (10)\n");
PR_fprintf(debug_out, "\t-s <string> dsn name of server (localhost)\n");
PR_fprintf(debug_out, "\t-G use GLOBAL threads (LOCAL)\n");
- PR_fprintf(debug_out, "\t-T <string> thread provider ('n' | 'p' | 'w')(n)\n");
+ PR_fprintf(debug_out, "\t-T <string> thread provider ('n' | 'p' | 'u' | 'w')(n)\n");
PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n");
PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n");
PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n");
@@ -1115,6 +1163,8 @@ PRIntn main(PRIntn argc, char** argv)
thread_provider = thread_win32;
#elif defined(_PR_PTHREADS)
thread_provider = thread_pthread;
+#elif defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ thread_provider = thread_uithread;
#elif defined(IRIX)
thread_provider = thread_sproc;
#else
@@ -1146,6 +1196,7 @@ PRIntn main(PRIntn argc, char** argv)
case 'T': /* the thread provider */
if ('n' == *opt->value) thread_provider = thread_nspr;
else if ('p' == *opt->value) thread_provider = thread_pthread;
+ else if ('u' == *opt->value) thread_provider = thread_uithread;
else if ('w' == *opt->value) thread_provider = thread_win32;
else {Help(); return 2; }
break;
@@ -1374,6 +1425,8 @@ PRIntn main(PRIntn argc, char** argv)
thread_type = "\nWin32 Thread Statistics\n";
else if (thread_provider == thread_pthread)
thread_type = "\npthread Statistics\n";
+ else if (thread_provider == thread_uithread)
+ thread_type = "\nUnix International (UI) Thread Statistics\n";
else if (thread_provider == thread_sproc)
thread_type = "\nsproc Statistics\n";
else {