OLD | NEW |
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 /* This Source Code Form is subject to the terms of the Mozilla Public | 2 /* This Source Code Form is subject to the terms of the Mozilla Public |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | 3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | 5 |
6 /* | 6 /* |
7 ** File: ptthread.c | 7 ** File: ptthread.c |
8 ** Descritpion: Implemenation for threds using pthreds | 8 ** Descritpion: Implemenation for threds using pthreds |
9 ** Exports: ptthread.h | 9 ** Exports: ptthread.h |
10 */ | 10 */ |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 static PRIntn pt_schedpriv = 0; | 45 static PRIntn pt_schedpriv = 0; |
46 extern PRLock *_pr_sleeplock; | 46 extern PRLock *_pr_sleeplock; |
47 | 47 |
48 static struct _PT_Bookeeping | 48 static struct _PT_Bookeeping |
49 { | 49 { |
50 PRLock *ml; /* a lock to protect ourselves */ | 50 PRLock *ml; /* a lock to protect ourselves */ |
51 PRCondVar *cv; /* used to signal global things */ | 51 PRCondVar *cv; /* used to signal global things */ |
52 PRInt32 system, user; /* a count of the two different types */ | 52 PRInt32 system, user; /* a count of the two different types */ |
53 PRUintn this_many; /* number of threads allowed for exit */ | 53 PRUintn this_many; /* number of threads allowed for exit */ |
54 pthread_key_t key; /* thread private data key */ | 54 pthread_key_t key; /* thread private data key */ |
| 55 PRBool keyCreated; /* whether 'key' should be deleted */ |
55 PRThread *first, *last; /* list of threads we know about */ | 56 PRThread *first, *last; /* list of threads we know about */ |
56 #if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING) | 57 #if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING) |
57 PRInt32 minPrio, maxPrio; /* range of scheduling priorities */ | 58 PRInt32 minPrio, maxPrio; /* range of scheduling priorities */ |
58 #endif | 59 #endif |
59 } pt_book = {0}; | 60 } pt_book = {0}; |
60 | 61 |
61 static void _pt_thread_death(void *arg); | 62 static void _pt_thread_death(void *arg); |
62 static void _pt_thread_death_internal(void *arg, PRBool callDestructors); | 63 static void _pt_thread_death_internal(void *arg, PRBool callDestructors); |
63 static void init_pthread_gc_support(void); | 64 static void init_pthread_gc_support(void); |
64 | 65 |
(...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 * | 973 * |
973 * NB: The destructor logic seems to have a bug so it isn't used. | 974 * NB: The destructor logic seems to have a bug so it isn't used. |
974 * NBB: Oh really? I'm going to give it a spin - AOF 19 June 1998. | 975 * NBB: Oh really? I'm going to give it a spin - AOF 19 June 1998. |
975 * More info - the problem is that pthreads calls the destructor | 976 * More info - the problem is that pthreads calls the destructor |
976 * eagerly as the thread returns from its root, rather than lazily | 977 * eagerly as the thread returns from its root, rather than lazily |
977 * after the thread is joined. Therefore, threads that are joining | 978 * after the thread is joined. Therefore, threads that are joining |
978 * and holding PRThread references are actually holding pointers to | 979 * and holding PRThread references are actually holding pointers to |
979 * nothing. | 980 * nothing. |
980 */ | 981 */ |
981 rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death); | 982 rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death); |
| 983 if (0 != rv) |
| 984 PR_Assert("0 == rv", __FILE__, __LINE__); |
| 985 pt_book.keyCreated = PR_TRUE; |
| 986 rv = pthread_setspecific(pt_book.key, thred); |
982 PR_ASSERT(0 == rv); | 987 PR_ASSERT(0 == rv); |
983 rv = pthread_setspecific(pt_book.key, thred); | |
984 PR_ASSERT(0 == rv); | |
985 } /* _PR_InitThreads */ | 988 } /* _PR_InitThreads */ |
986 | 989 |
987 #ifdef __GNUC__ | 990 #ifdef __GNUC__ |
988 /* | 991 /* |
989 * GCC supports the constructor and destructor attributes as of | 992 * GCC supports the constructor and destructor attributes as of |
990 * version 2.5. | 993 * version 2.5. |
991 */ | 994 */ |
992 static void _PR_Fini(void) __attribute__ ((destructor)); | 995 static void _PR_Fini(void) __attribute__ ((destructor)); |
993 #elif defined(__SUNPRO_C) | 996 #elif defined(__SUNPRO_C) |
994 /* | 997 /* |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 #endif | 1037 #endif |
1035 #elif defined(AIX) | 1038 #elif defined(AIX) |
1036 /* Need to use the -binitfini::_PR_Fini linker option. */ | 1039 /* Need to use the -binitfini::_PR_Fini linker option. */ |
1037 #endif | 1040 #endif |
1038 | 1041 |
1039 void _PR_Fini(void) | 1042 void _PR_Fini(void) |
1040 { | 1043 { |
1041 void *thred; | 1044 void *thred; |
1042 int rv; | 1045 int rv; |
1043 | 1046 |
1044 if (!_pr_initialized) return; | 1047 if (!_pr_initialized) { |
| 1048 /* Either NSPR was never successfully initialized or |
| 1049 * PR_Cleanup has been called already. */ |
| 1050 if (pt_book.keyCreated) |
| 1051 { |
| 1052 rv = pthread_key_delete(pt_book.key); |
| 1053 PR_ASSERT(0 == rv); |
| 1054 pt_book.keyCreated = PR_FALSE; |
| 1055 } |
| 1056 return; |
| 1057 } |
1045 | 1058 |
1046 _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred); | 1059 _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred); |
1047 if (NULL != thred) | 1060 if (NULL != thred) |
1048 { | 1061 { |
1049 /* | 1062 /* |
1050 * PR_FALSE, because it is unsafe to call back to the | 1063 * PR_FALSE, because it is unsafe to call back to the |
1051 * thread private data destructors at final cleanup. | 1064 * thread private data destructors at final cleanup. |
1052 */ | 1065 */ |
1053 _pt_thread_death_internal(thred, PR_FALSE); | 1066 _pt_thread_death_internal(thred, PR_FALSE); |
1054 rv = pthread_setspecific(pt_book.key, NULL); | 1067 rv = pthread_setspecific(pt_book.key, NULL); |
1055 PR_ASSERT(0 == rv); | 1068 PR_ASSERT(0 == rv); |
1056 } | 1069 } |
1057 rv = pthread_key_delete(pt_book.key); | 1070 rv = pthread_key_delete(pt_book.key); |
1058 PR_ASSERT(0 == rv); | 1071 PR_ASSERT(0 == rv); |
| 1072 pt_book.keyCreated = PR_FALSE; |
1059 /* TODO: free other resources used by NSPR */ | 1073 /* TODO: free other resources used by NSPR */ |
1060 /* _pr_initialized = PR_FALSE; */ | 1074 /* _pr_initialized = PR_FALSE; */ |
1061 } /* _PR_Fini */ | 1075 } /* _PR_Fini */ |
1062 | 1076 |
1063 PR_IMPLEMENT(PRStatus) PR_Cleanup(void) | 1077 PR_IMPLEMENT(PRStatus) PR_Cleanup(void) |
1064 { | 1078 { |
1065 PRThread *me = PR_GetCurrentThread(); | 1079 PRThread *me = PR_GetCurrentThread(); |
1066 int rv; | 1080 int rv; |
1067 PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); | 1081 PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); |
1068 PR_ASSERT(me->state & PT_THREAD_PRIMORD); | 1082 PR_ASSERT(me->state & PT_THREAD_PRIMORD); |
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1774 PR_IMPLEMENT(const char *) PR_GetThreadName(const PRThread *thread) | 1788 PR_IMPLEMENT(const char *) PR_GetThreadName(const PRThread *thread) |
1775 { | 1789 { |
1776 if (!thread) | 1790 if (!thread) |
1777 return NULL; | 1791 return NULL; |
1778 return thread->name; | 1792 return thread->name; |
1779 } | 1793 } |
1780 | 1794 |
1781 #endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */ | 1795 #endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */ |
1782 | 1796 |
1783 /* ptthread.c */ | 1797 /* ptthread.c */ |
OLD | NEW |