8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
25 * Copyright (c) 2017 by The MathWorks, Inc. All rights reserved.
26 */
27 /*
28 * Copyright 2016 Joyent, Inc.
29 */
30
31 #include "lint.h"
32 #include "thr_uberdata.h"
33 #include <pthread.h>
34 #include <procfs.h>
35 #include <sys/uio.h>
36 #include <ctype.h>
37 #include "libc.h"
38
39 /*
40 * These symbols should not be exported from libc, but
41 * /lib/libm.so.2 references _thr_main. libm needs to be fixed.
42 * Also, some older versions of the Studio compiler/debugger
43 * components reference them. These need to be fixed, too.
44 */
45 #pragma weak _thr_main = thr_main
46 #pragma weak _thr_create = thr_create
47 #pragma weak _thr_join = thr_join
48 #pragma weak _thr_self = thr_self
543 ulwp_t *ulwp = NULL;
544 ulwp_t **ulwpp;
545
546 if (self->ul_lwpid == tid) {
547 ulwp = self;
548 ulwp_lock(ulwp, udp);
549 } else if ((ulwpp = find_lwpp(tid)) != NULL) {
550 ulwp = *ulwpp;
551 }
552
553 if (ulwp && ulwp->ul_dead) {
554 ulwp_unlock(ulwp, udp);
555 ulwp = NULL;
556 }
557
558 return (ulwp);
559 }
560
561 int
562 _thrp_create(void *stk, size_t stksize, void *(*func)(void *), void *arg,
563 long flags, thread_t *new_thread, size_t guardsize)
564 {
565 ulwp_t *self = curthread;
566 uberdata_t *udp = self->ul_uberdata;
567 ucontext_t uc;
568 uint_t lwp_flags;
569 thread_t tid;
570 int error;
571 ulwp_t *ulwp;
572
573 /*
574 * Enforce the restriction of not creating any threads
575 * until the primary link map has been initialized.
576 * Also, disallow thread creation to a child of vfork().
577 */
578 if (!self->ul_primarymap || self->ul_vfork)
579 return (ENOTSUP);
580
581 if (udp->hash_size == 1)
582 finish_init();
583
698 ulwp->ul_back = udp->all_lwps->ul_back;
699 ulwp->ul_back->ul_forw = ulwp;
700 ulwp->ul_forw->ul_back = ulwp;
701 hash_in(ulwp, udp);
702 udp->nthreads++;
703 if (flags & THR_DAEMON)
704 udp->ndaemons++;
705 if (flags & THR_NEW_LWP)
706 thr_concurrency++;
707 __libc_threaded = 1; /* inform stdio */
708 lmutex_unlock(&udp->link_lock);
709
710 if (__td_event_report(self, TD_CREATE, udp)) {
711 self->ul_td_evbuf.eventnum = TD_CREATE;
712 self->ul_td_evbuf.eventdata = (void *)(uintptr_t)tid;
713 tdb_event(TD_CREATE, udp);
714 }
715
716 exit_critical(self);
717
718 if (!(flags & THR_SUSPENDED))
719 (void) _thrp_continue(tid, TSTP_REGULAR);
720
721 return (0);
722 }
723
724 int
725 thr_create(void *stk, size_t stksize, void *(*func)(void *), void *arg,
726 long flags, thread_t *new_thread)
727 {
728 return (_thrp_create(stk, stksize, func, arg, flags, new_thread, 0));
729 }
730
731 /*
732 * A special cancellation cleanup hook for DCE.
733 * cleanuphndlr, when it is not NULL, will contain a callback
734 * function to be called before a thread is terminated in
735 * thr_exit() as a result of being cancelled.
736 */
737 static void (*cleanuphndlr)(void) = NULL;
738
739 /*
740 * _pthread_setcleanupinit: sets the cleanup hook.
741 */
742 int
743 _pthread_setcleanupinit(void (*func)(void))
744 {
745 cleanuphndlr = func;
746 return (0);
747 }
748
2381 if (new_level < 0)
2382 return (EINVAL);
2383 if (new_level > 65536) /* 65536 is totally arbitrary */
2384 return (EAGAIN);
2385 pthread_concurrency = new_level;
2386 return (0);
2387 }
2388
2389 size_t
2390 thr_min_stack(void)
2391 {
2392 return (MINSTACK);
2393 }
2394
2395 int
2396 __nthreads(void)
2397 {
2398 return (curthread->ul_uberdata->nthreads);
2399 }
2400
2401 /*
2402 * XXX
2403 * The remainder of this file implements the private interfaces to java for
2404 * garbage collection. It is no longer used, at least by java 1.2.
2405 * It can all go away once all old JVMs have disappeared.
2406 */
2407
2408 int suspendingallmutators; /* when non-zero, suspending all mutators. */
2409 int suspendedallmutators; /* when non-zero, all mutators suspended. */
2410 int mutatorsbarrier; /* when non-zero, mutators barrier imposed. */
2411 mutex_t mutatorslock = DEFAULTMUTEX; /* used to enforce mutators barrier. */
2412 cond_t mutatorscv = DEFAULTCV; /* where non-mutators sleep. */
2413
2414 /*
2415 * Get the available register state for the target thread.
2416 * Return non-volatile registers: TRS_NONVOLATILE
2417 */
2418 #pragma weak _thr_getstate = thr_getstate
2419 int
2420 thr_getstate(thread_t tid, int *flag, lwpid_t *lwp, stack_t *ss, gregset_t rs)
|
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
25 * Copyright (c) 2017 by The MathWorks, Inc. All rights reserved.
26 */
27 /*
28 * Copyright 2018 Joyent, Inc.
29 */
30
31 #include "lint.h"
32 #include "thr_uberdata.h"
33 #include <pthread.h>
34 #include <procfs.h>
35 #include <sys/uio.h>
36 #include <ctype.h>
37 #include "libc.h"
38
39 /*
40 * These symbols should not be exported from libc, but
41 * /lib/libm.so.2 references _thr_main. libm needs to be fixed.
42 * Also, some older versions of the Studio compiler/debugger
43 * components reference them. These need to be fixed, too.
44 */
45 #pragma weak _thr_main = thr_main
46 #pragma weak _thr_create = thr_create
47 #pragma weak _thr_join = thr_join
48 #pragma weak _thr_self = thr_self
543 ulwp_t *ulwp = NULL;
544 ulwp_t **ulwpp;
545
546 if (self->ul_lwpid == tid) {
547 ulwp = self;
548 ulwp_lock(ulwp, udp);
549 } else if ((ulwpp = find_lwpp(tid)) != NULL) {
550 ulwp = *ulwpp;
551 }
552
553 if (ulwp && ulwp->ul_dead) {
554 ulwp_unlock(ulwp, udp);
555 ulwp = NULL;
556 }
557
558 return (ulwp);
559 }
560
561 int
562 _thrp_create(void *stk, size_t stksize, void *(*func)(void *), void *arg,
563 long flags, thread_t *new_thread, size_t guardsize, const char *name)
564 {
565 ulwp_t *self = curthread;
566 uberdata_t *udp = self->ul_uberdata;
567 ucontext_t uc;
568 uint_t lwp_flags;
569 thread_t tid;
570 int error;
571 ulwp_t *ulwp;
572
573 /*
574 * Enforce the restriction of not creating any threads
575 * until the primary link map has been initialized.
576 * Also, disallow thread creation to a child of vfork().
577 */
578 if (!self->ul_primarymap || self->ul_vfork)
579 return (ENOTSUP);
580
581 if (udp->hash_size == 1)
582 finish_init();
583
698 ulwp->ul_back = udp->all_lwps->ul_back;
699 ulwp->ul_back->ul_forw = ulwp;
700 ulwp->ul_forw->ul_back = ulwp;
701 hash_in(ulwp, udp);
702 udp->nthreads++;
703 if (flags & THR_DAEMON)
704 udp->ndaemons++;
705 if (flags & THR_NEW_LWP)
706 thr_concurrency++;
707 __libc_threaded = 1; /* inform stdio */
708 lmutex_unlock(&udp->link_lock);
709
710 if (__td_event_report(self, TD_CREATE, udp)) {
711 self->ul_td_evbuf.eventnum = TD_CREATE;
712 self->ul_td_evbuf.eventdata = (void *)(uintptr_t)tid;
713 tdb_event(TD_CREATE, udp);
714 }
715
716 exit_critical(self);
717
718 if (name != NULL)
719 (void) pthread_setname_np(tid, name);
720
721 if (!(flags & THR_SUSPENDED))
722 (void) _thrp_continue(tid, TSTP_REGULAR);
723
724 return (0);
725 }
726
727 int
728 thr_create(void *stk, size_t stksize, void *(*func)(void *), void *arg,
729 long flags, thread_t *new_thread)
730 {
731 return (_thrp_create(stk, stksize, func, arg, flags, new_thread, 0,
732 NULL));
733 }
734
735 /*
736 * A special cancellation cleanup hook for DCE.
737 * cleanuphndlr, when it is not NULL, will contain a callback
738 * function to be called before a thread is terminated in
739 * thr_exit() as a result of being cancelled.
740 */
741 static void (*cleanuphndlr)(void) = NULL;
742
743 /*
744 * _pthread_setcleanupinit: sets the cleanup hook.
745 */
746 int
747 _pthread_setcleanupinit(void (*func)(void))
748 {
749 cleanuphndlr = func;
750 return (0);
751 }
752
2385 if (new_level < 0)
2386 return (EINVAL);
2387 if (new_level > 65536) /* 65536 is totally arbitrary */
2388 return (EAGAIN);
2389 pthread_concurrency = new_level;
2390 return (0);
2391 }
2392
2393 size_t
2394 thr_min_stack(void)
2395 {
2396 return (MINSTACK);
2397 }
2398
2399 int
2400 __nthreads(void)
2401 {
2402 return (curthread->ul_uberdata->nthreads);
2403 }
2404
2405 /* "/proc/self/lwp/%u/lwpname" w/o stdio */
2406 static void
2407 lwpname_path(pthread_t tid, char *buf, size_t bufsize)
2408 {
2409 (void) strlcpy(buf, "/proc/self/lwp/", bufsize);
2410 ultos((uint64_t)tid, 10, buf + strlen(buf));
2411 (void) strlcat(buf, "/lwpname", bufsize);
2412 }
2413
2414 #pragma weak pthread_setname_np = thr_setname
2415 int
2416 thr_setname(pthread_t tid, const char *name)
2417 {
2418 extern ssize_t __write(int, const void *, size_t);
2419 char path[PATH_MAX];
2420 int saved_errno;
2421 size_t len;
2422 ssize_t n;
2423 int fd;
2424
2425 if (name == NULL)
2426 name = "";
2427
2428 len = strlen(name) + 1;
2429 if (len > THREAD_NAME_MAX)
2430 return (ERANGE);
2431
2432 lwpname_path(tid, path, sizeof (path));
2433
2434 if ((fd = __open(path, O_WRONLY, 0)) < 0) {
2435 if (errno == ENOENT)
2436 errno = ESRCH;
2437 return (errno);
2438 }
2439
2440 n = __write(fd, name, len);
2441 saved_errno = errno;
2442 (void) __close(fd);
2443
2444 if (n < 0)
2445 return (saved_errno);
2446 if (n != len)
2447 return (EFAULT);
2448 return (0);
2449 }
2450
2451 #pragma weak pthread_getname_np = thr_getname
2452 int
2453 thr_getname(pthread_t tid, char *buf, size_t bufsize)
2454 {
2455 extern ssize_t __read(int, void *, size_t);
2456 char name[THREAD_NAME_MAX];
2457 char path[PATH_MAX];
2458 int saved_errno;
2459 ssize_t n;
2460 int fd;
2461
2462 if (buf == NULL)
2463 return (EINVAL);
2464
2465 lwpname_path(tid, path, sizeof (path));
2466
2467 if ((fd = __open(path, O_RDONLY, 0)) < 0) {
2468 if (errno == ENOENT)
2469 errno = ESRCH;
2470 return (errno);
2471 }
2472
2473 n = __read(fd, name, sizeof (name));
2474 saved_errno = errno;
2475 (void) __close(fd);
2476
2477 if (n < 0)
2478 return (saved_errno);
2479 if (n != sizeof (name))
2480 return (EFAULT);
2481 if (strlcpy(buf, name, bufsize) >= bufsize)
2482 return (ERANGE);
2483 return (0);
2484 }
2485
2486 /*
2487 * XXX
2488 * The remainder of this file implements the private interfaces to java for
2489 * garbage collection. It is no longer used, at least by java 1.2.
2490 * It can all go away once all old JVMs have disappeared.
2491 */
2492
2493 int suspendingallmutators; /* when non-zero, suspending all mutators. */
2494 int suspendedallmutators; /* when non-zero, all mutators suspended. */
2495 int mutatorsbarrier; /* when non-zero, mutators barrier imposed. */
2496 mutex_t mutatorslock = DEFAULTMUTEX; /* used to enforce mutators barrier. */
2497 cond_t mutatorscv = DEFAULTCV; /* where non-mutators sleep. */
2498
2499 /*
2500 * Get the available register state for the target thread.
2501 * Return non-volatile registers: TRS_NONVOLATILE
2502 */
2503 #pragma weak _thr_getstate = thr_getstate
2504 int
2505 thr_getstate(thread_t tid, int *flag, lwpid_t *lwp, stack_t *ss, gregset_t rs)
|