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 */ |
11 | 11 |
12 #if defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) | 12 #if defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) |
13 | 13 |
14 #include "prlog.h" | 14 #include "prlog.h" |
15 #include "primpl.h" | 15 #include "primpl.h" |
16 #include "prpdce.h" | 16 #include "prpdce.h" |
17 | 17 |
18 #include <pthread.h> | 18 #include <pthread.h> |
19 #include <unistd.h> | 19 #include <unistd.h> |
20 #include <string.h> | 20 #include <string.h> |
21 #include <signal.h> | 21 #include <signal.h> |
| 22 #include <dlfcn.h> |
22 | 23 |
23 #ifdef SYMBIAN | 24 #ifdef SYMBIAN |
24 /* In Open C sched_get_priority_min/max do not work properly, so we undefine | 25 /* In Open C sched_get_priority_min/max do not work properly, so we undefine |
25 * _POSIX_THREAD_PRIORITY_SCHEDULING here. | 26 * _POSIX_THREAD_PRIORITY_SCHEDULING here. |
26 */ | 27 */ |
27 #undef _POSIX_THREAD_PRIORITY_SCHEDULING | 28 #undef _POSIX_THREAD_PRIORITY_SCHEDULING |
28 #endif | 29 #endif |
29 | 30 |
30 /* | 31 /* |
31 * Record whether or not we have the privilege to set the scheduling | 32 * Record whether or not we have the privilege to set the scheduling |
32 * policy and priority of threads. 0 means that privilege is available. | 33 * policy and priority of threads. 0 means that privilege is available. |
33 * EPERM means that privilege is not available. | 34 * EPERM means that privilege is not available. |
34 */ | 35 */ |
35 | 36 |
36 static PRIntn pt_schedpriv = 0; | 37 static PRIntn pt_schedpriv = 0; |
37 extern PRLock *_pr_sleeplock; | 38 extern PRLock *_pr_sleeplock; |
38 | 39 |
39 static struct _PT_Bookeeping | 40 static struct _PT_Bookeeping |
40 { | 41 { |
41 PRLock *ml; /* a lock to protect ourselves */ | 42 PRLock *ml; /* a lock to protect ourselves */ |
42 PRCondVar *cv; /* used to signal global things */ | 43 PRCondVar *cv; /* used to signal global things */ |
43 PRInt32 system, user; /* a count of the two different types */ | 44 PRInt32 system, user; /* a count of the two different types */ |
44 PRUintn this_many; /* number of threads allowed for exit */ | 45 PRUintn this_many; /* number of threads allowed for exit */ |
45 pthread_key_t key; /* private private data key */ | 46 pthread_key_t key; /* thread private data key */ |
46 PRThread *first, *last; /* list of threads we know about */ | 47 PRThread *first, *last; /* list of threads we know about */ |
47 #if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING) | 48 #if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING) |
48 PRInt32 minPrio, maxPrio; /* range of scheduling priorities */ | 49 PRInt32 minPrio, maxPrio; /* range of scheduling priorities */ |
49 #endif | 50 #endif |
50 } pt_book = {0}; | 51 } pt_book = {0}; |
51 | 52 |
52 static void _pt_thread_death(void *arg); | 53 static void _pt_thread_death(void *arg); |
53 static void _pt_thread_death_internal(void *arg, PRBool callDestructors); | 54 static void _pt_thread_death_internal(void *arg, PRBool callDestructors); |
54 static void init_pthread_gc_support(void); | 55 static void init_pthread_gc_support(void); |
55 | 56 |
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 pt_book.last = thred->prev; | 788 pt_book.last = thred->prev; |
788 else | 789 else |
789 thred->next->prev = thred->prev; | 790 thred->next->prev = thred->prev; |
790 PR_Unlock(pt_book.ml); | 791 PR_Unlock(pt_book.ml); |
791 } | 792 } |
792 if (callDestructors) | 793 if (callDestructors) |
793 _PR_DestroyThreadPrivate(thred); | 794 _PR_DestroyThreadPrivate(thred); |
794 PR_Free(thred->privateData); | 795 PR_Free(thred->privateData); |
795 if (NULL != thred->errorString) | 796 if (NULL != thred->errorString) |
796 PR_Free(thred->errorString); | 797 PR_Free(thred->errorString); |
| 798 if (NULL != thred->name) |
| 799 PR_Free(thred->name); |
797 PR_Free(thred->stack); | 800 PR_Free(thred->stack); |
798 if (NULL != thred->syspoll_list) | 801 if (NULL != thred->syspoll_list) |
799 PR_Free(thred->syspoll_list); | 802 PR_Free(thred->syspoll_list); |
800 #if defined(_PR_POLL_WITH_SELECT) | 803 #if defined(_PR_POLL_WITH_SELECT) |
801 if (NULL != thred->selectfd_list) | 804 if (NULL != thred->selectfd_list) |
802 PR_Free(thred->selectfd_list); | 805 PR_Free(thred->selectfd_list); |
803 #endif | 806 #endif |
804 #if defined(DEBUG) | 807 #if defined(DEBUG) |
805 memset(thred, 0xaf, sizeof(PRThread)); | 808 memset(thred, 0xaf, sizeof(PRThread)); |
806 #endif /* defined(DEBUG) */ | 809 #endif /* defined(DEBUG) */ |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
965 if (NULL != thred) | 968 if (NULL != thred) |
966 { | 969 { |
967 /* | 970 /* |
968 * PR_FALSE, because it is unsafe to call back to the | 971 * PR_FALSE, because it is unsafe to call back to the |
969 * thread private data destructors at final cleanup. | 972 * thread private data destructors at final cleanup. |
970 */ | 973 */ |
971 _pt_thread_death_internal(thred, PR_FALSE); | 974 _pt_thread_death_internal(thred, PR_FALSE); |
972 rv = pthread_setspecific(pt_book.key, NULL); | 975 rv = pthread_setspecific(pt_book.key, NULL); |
973 PR_ASSERT(0 == rv); | 976 PR_ASSERT(0 == rv); |
974 } | 977 } |
| 978 rv = pthread_key_delete(pt_book.key); |
| 979 PR_ASSERT(0 == rv); |
975 /* TODO: free other resources used by NSPR */ | 980 /* TODO: free other resources used by NSPR */ |
976 /* _pr_initialized = PR_FALSE; */ | 981 /* _pr_initialized = PR_FALSE; */ |
977 } /* _PR_Fini */ | 982 } /* _PR_Fini */ |
978 | 983 |
979 PR_IMPLEMENT(PRStatus) PR_Cleanup(void) | 984 PR_IMPLEMENT(PRStatus) PR_Cleanup(void) |
980 { | 985 { |
981 PRThread *me = PR_GetCurrentThread(); | 986 PRThread *me = PR_GetCurrentThread(); |
982 int rv; | 987 int rv; |
983 PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); | 988 PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); |
984 PR_ASSERT(me->state & PT_THREAD_PRIMORD); | 989 PR_ASSERT(me->state & PT_THREAD_PRIMORD); |
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 */ | 1610 */ |
1606 PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_GetSP\n")); | 1611 PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_GetSP\n")); |
1607 thread_tcb = (char*)tid.field1; | 1612 thread_tcb = (char*)tid.field1; |
1608 top_sp = *(char**)(thread_tcb + 128); | 1613 top_sp = *(char**)(thread_tcb + 128); |
1609 PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_GetSP %p \n", top_sp)); | 1614 PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_GetSP %p \n", top_sp)); |
1610 return top_sp; | 1615 return top_sp; |
1611 } /* PR_GetSP */ | 1616 } /* PR_GetSP */ |
1612 | 1617 |
1613 #endif /* !defined(_PR_DCETHREADS) */ | 1618 #endif /* !defined(_PR_DCETHREADS) */ |
1614 | 1619 |
| 1620 PR_IMPLEMENT(PRStatus) PR_SetCurrentThreadName(const char *name) |
| 1621 { |
| 1622 PRThread *thread; |
| 1623 size_t nameLen; |
| 1624 int result; |
| 1625 |
| 1626 if (!name) { |
| 1627 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
| 1628 return PR_FAILURE; |
| 1629 } |
| 1630 |
| 1631 thread = PR_GetCurrentThread(); |
| 1632 if (!thread) |
| 1633 return PR_FAILURE; |
| 1634 |
| 1635 PR_Free(thread->name); |
| 1636 nameLen = strlen(name); |
| 1637 thread->name = (char *)PR_Malloc(nameLen + 1); |
| 1638 if (!thread->name) |
| 1639 return PR_FAILURE; |
| 1640 memcpy(thread->name, name, nameLen + 1); |
| 1641 |
| 1642 #if defined(OPENBSD) || defined(FREEBSD) |
| 1643 result = pthread_set_name_np(thread->id, name); |
| 1644 #else /* not BSD */ |
| 1645 /* |
| 1646 * On OSX, pthread_setname_np is only available in 10.6 or later, so test |
| 1647 * for it at runtime. It also may not be available on all linux distros. |
| 1648 */ |
| 1649 #if defined(DARWIN) |
| 1650 int (*dynamic_pthread_setname_np)(const char*); |
| 1651 #else |
| 1652 int (*dynamic_pthread_setname_np)(pthread_t, const char*); |
| 1653 #endif |
| 1654 |
| 1655 *(void**)(&dynamic_pthread_setname_np) = |
| 1656 dlsym(RTLD_DEFAULT, "pthread_setname_np"); |
| 1657 if (!dynamic_pthread_setname_np) |
| 1658 return PR_SUCCESS; |
| 1659 |
| 1660 /* |
| 1661 * The 15-character name length limit is an experimentally determined |
| 1662 * length of a null-terminated string that most linux distros and OS X |
| 1663 * accept as an argument to pthread_setname_np. Otherwise the E2BIG |
| 1664 * error is returned by the function. |
| 1665 */ |
| 1666 #define SETNAME_LENGTH_CONSTRAINT 15 |
| 1667 #define SETNAME_FRAGMENT1_LENGTH (SETNAME_LENGTH_CONSTRAINT >> 1) |
| 1668 #define SETNAME_FRAGMENT2_LENGTH \ |
| 1669 (SETNAME_LENGTH_CONSTRAINT - SETNAME_FRAGMENT1_LENGTH - 1) |
| 1670 char name_dup[SETNAME_LENGTH_CONSTRAINT + 1]; |
| 1671 if (nameLen > SETNAME_LENGTH_CONSTRAINT) { |
| 1672 memcpy(name_dup, name, SETNAME_FRAGMENT1_LENGTH); |
| 1673 name_dup[SETNAME_FRAGMENT1_LENGTH] = '~'; |
| 1674 /* Note that this also copies the null terminator. */ |
| 1675 memcpy(name_dup + SETNAME_FRAGMENT1_LENGTH + 1, |
| 1676 name + nameLen - SETNAME_FRAGMENT2_LENGTH, |
| 1677 SETNAME_FRAGMENT2_LENGTH + 1); |
| 1678 name = name_dup; |
| 1679 } |
| 1680 |
| 1681 #if defined(DARWIN) |
| 1682 result = dynamic_pthread_setname_np(name); |
| 1683 #else |
| 1684 result = dynamic_pthread_setname_np(thread->id, name); |
| 1685 #endif |
| 1686 #endif /* not BSD */ |
| 1687 |
| 1688 if (result) { |
| 1689 PR_SetError(PR_UNKNOWN_ERROR, result); |
| 1690 return PR_FAILURE; |
| 1691 } |
| 1692 return PR_SUCCESS; |
| 1693 } |
| 1694 |
| 1695 PR_IMPLEMENT(const char *) PR_GetThreadName(const PRThread *thread) |
| 1696 { |
| 1697 if (!thread) |
| 1698 return NULL; |
| 1699 return thread->name; |
| 1700 } |
| 1701 |
1615 #endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */ | 1702 #endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */ |
1616 | 1703 |
1617 /* ptthread.c */ | 1704 /* ptthread.c */ |
OLD | NEW |