Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section


   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)