1*10a4fa49Srie /* 2*10a4fa49Srie * CDDL HEADER START 3*10a4fa49Srie * 4*10a4fa49Srie * The contents of this file are subject to the terms of the 5*10a4fa49Srie * Common Development and Distribution License (the "License"). 6*10a4fa49Srie * You may not use this file except in compliance with the License. 7*10a4fa49Srie * 8*10a4fa49Srie * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*10a4fa49Srie * or http://www.opensolaris.org/os/licensing. 10*10a4fa49Srie * See the License for the specific language governing permissions 11*10a4fa49Srie * and limitations under the License. 12*10a4fa49Srie * 13*10a4fa49Srie * When distributing Covered Code, include this CDDL HEADER in each 14*10a4fa49Srie * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*10a4fa49Srie * If applicable, add the following below this CDDL HEADER, with the 16*10a4fa49Srie * fields enclosed by brackets "[]" replaced with your own identifying 17*10a4fa49Srie * information: Portions Copyright [yyyy] [name of copyright owner] 18*10a4fa49Srie * 19*10a4fa49Srie * CDDL HEADER END 20*10a4fa49Srie */ 21*10a4fa49Srie 22*10a4fa49Srie /* 23*10a4fa49Srie * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*10a4fa49Srie * Use is subject to license terms. 25*10a4fa49Srie */ 26*10a4fa49Srie #pragma ident "%Z%%M% %I% %E% SMI" 27*10a4fa49Srie 28*10a4fa49Srie /* 29*10a4fa49Srie * Implementation of all external interfaces between ld.so.1 and libc. 30*10a4fa49Srie * 31*10a4fa49Srie * This file started as a set of routines that provided synchronization and 32*10a4fa49Srie * locking operations using calls to libthread. libthread has merged with libc, 33*10a4fa49Srie * and things have gotten a little simpler. This file continues to establish 34*10a4fa49Srie * and redirect various events within ld.so.1 to interfaces within libc. 35*10a4fa49Srie * 36*10a4fa49Srie * Until libc is loaded and relocated, any external interfaces are captured 37*10a4fa49Srie * locally. Each link-map list maintains its own set of external vectors, as 38*10a4fa49Srie * each link-map list typically provides its own libc. Although this per-link- 39*10a4fa49Srie * map list vectoring provides a degree of flexibility, there is a protocol 40*10a4fa49Srie * expected when calling various libc interfaces. 41*10a4fa49Srie * 42*10a4fa49Srie * i. Any new alternative link-map list should call CI_THRINIT, and then call 43*10a4fa49Srie * CI_TLS_MODADD to register any TLS for each object of that link-map list 44*10a4fa49Srie * (this item is labeled i. as auditors can be the first objects loaded, 45*10a4fa49Srie * and they exist on their own lik-map list). 46*10a4fa49Srie * 47*10a4fa49Srie * ii. For the primary link-map list, CI_TLS_STATMOD must be called first to 48*10a4fa49Srie * register any static TLS. This routine is called regardless of there 49*10a4fa49Srie * being any TLS, as this routine also establishes the link-map list as the 50*10a4fa49Srie * primary list and fixes the association of uberdata). CI_THRINIT should 51*10a4fa49Srie * then be called. 52*10a4fa49Srie * 53*10a4fa49Srie * iii. Any objects added to an existing link-map list (primary or alternative) 54*10a4fa49Srie * should call CI_TLS_MODADD to register any additional TLS. 55*10a4fa49Srie * 56*10a4fa49Srie * These events are established by: 57*10a4fa49Srie * 58*10a4fa49Srie * i. Typically, libc is loaded as part of the primary dependencies of any 59*10a4fa49Srie * link-map list (since the Unified Process Model (UPM), libc can't be 60*10a4fa49Srie * lazily loaded). To minimize the possibility of loading and registering 61*10a4fa49Srie * objects, and then tearing them down (because of a relocation error), 62*10a4fa49Srie * external vectors are established as part of load_completion(). This 63*10a4fa49Srie * routine is called on completion of any operation that can cause objects 64*10a4fa49Srie * to be loaded. This point of control insures the objects have been fully 65*10a4fa49Srie * analyzed and relocated, and moved to their controlling link-map list. 66*10a4fa49Srie * The external vectors are established prior to any .inits being fired. 67*10a4fa49Srie * 68*10a4fa49Srie * ii. Calls to CI_THRINIT, and CI_TLS_MODADD also occur as part of 69*10a4fa49Srie * load_completion(). CI_THRINIT is only called once for each link-map 70*10a4fa49Srie * control list. 71*10a4fa49Srie * 72*10a4fa49Srie * iii. Calls to CI_TLS_STATMOD, and CI_THRINIT occur for the primary link-map 73*10a4fa49Srie * list in the final stages of setup(). 74*10a4fa49Srie * 75*10a4fa49Srie * The interfaces provide by libc can be divided into two families. The first 76*10a4fa49Srie * family consists of those interfaces that should be called from the link-map 77*10a4fa49Srie * list. It's possible that these interfaces convey state concerning the 78*10a4fa49Srie * link-map list they are part of: 79*10a4fa49Srie * 80*10a4fa49Srie * CI_ATEXIT 81*10a4fa49Srie * CI TLS_MODADD 82*10a4fa49Srie * CI_TLS_MODREM 83*10a4fa49Srie * CI_TLS_STATMOD 84*10a4fa49Srie * CI_THRINIT 85*10a4fa49Srie * 86*10a4fa49Srie * The second family are global in nature, that is, the link-map list from 87*10a4fa49Srie * which they are called provides no state information. In fact, for 88*10a4fa49Srie * CI_BIND_GUARD, the calling link-map isn't even known. The link-map can only 89*10a4fa49Srie * be deduced after ld.so.1's global lock has been obtained. Therefore, the 90*10a4fa49Srie * following interfaces are also maintained as global: 91*10a4fa49Srie * 92*10a4fa49Srie * CI_LCMESSAGES 93*10a4fa49Srie * CI_BIND_GUARD 94*10a4fa49Srie * CI_BIND_CLEAR 95*10a4fa49Srie * CI_THR_SELF 96*10a4fa49Srie * 97*10a4fa49Srie * Note, it is possible that these global interfaces are obtained from an 98*10a4fa49Srie * alternative link-map list that gets torn down because of a processing 99*10a4fa49Srie * failure (unlikely, because the link-map list components must be analyzed 100*10a4fa49Srie * and relocated prior to load_completion(), but perhaps the tear down is still 101*10a4fa49Srie * a possibility). Thus the global interfaces may have to be replaced. Once 102*10a4fa49Srie * the interfaces have been obtained from the primary link-map, they can 103*10a4fa49Srie * remain fixed, as the primary link-map isn't going to go anywhere. 104*10a4fa49Srie * 105*10a4fa49Srie * The last wrinkle in the puzzle is what happens if an alternative link-map 106*10a4fa49Srie * is loaded with no libc dependency? In this case, the alternative objects 107*10a4fa49Srie * can not call CI_THRINIT, can not be allowed to use TLS, and will not receive 108*10a4fa49Srie * any atexit processing. 109*10a4fa49Srie * 110*10a4fa49Srie * The history of these external interfaces is defined by their version: 111*10a4fa49Srie * 112*10a4fa49Srie * TI_VERSION == 1 113*10a4fa49Srie * Under this model libthread provided rw_rwlock/rw_unlock, through which 114*10a4fa49Srie * all rt_mutex_lock/rt_mutex_unlock calls were vectored. 115*10a4fa49Srie * Under libc/libthread these interfaces provided _sigon/_sigoff (unlike 116*10a4fa49Srie * lwp/libthread that provided signal blocking via bind_guard/bind_clear). 117*10a4fa49Srie * 118*10a4fa49Srie * TI_VERSION == 2 119*10a4fa49Srie * Under this model only libthreads bind_guard/bind_clear and thr_self 120*10a4fa49Srie * interfaces were used. Both libthreads blocked signals under the 121*10a4fa49Srie * bind_guard/bind_clear interfaces. Lower level locking is derived 122*10a4fa49Srie * from internally bound _lwp_ interfaces. This removes recursive 123*10a4fa49Srie * problems encountered when obtaining locking interfaces from libthread. 124*10a4fa49Srie * The use of mutexes over reader/writer locks also enables the use of 125*10a4fa49Srie * condition variables for controlling thread concurrency (allows access 126*10a4fa49Srie * to objects only after their .init has completed). 127*10a4fa49Srie * 128*10a4fa49Srie * NOTE, the TI_VERSION indicated the ti_interface version number, where the 129*10a4fa49Srie * ti_interface was a large vector of functions passed to both libc (to override 130*10a4fa49Srie * the thread stub interfaces) and ld.so.1. ld.so.1 used only a small subset of 131*10a4fa49Srie * these interfaces. 132*10a4fa49Srie * 133*10a4fa49Srie * CI_VERSION == 1 134*10a4fa49Srie * Introduced with CI_VERSION & CI_ATEXIT 135*10a4fa49Srie * 136*10a4fa49Srie * CI_VERSION == 2 (Solaris 8 update 2). 137*10a4fa49Srie * Added support for CI_LCMESSAGES 138*10a4fa49Srie * 139*10a4fa49Srie * CI_VERSION == 3 (Solaris 9). 140*10a4fa49Srie * Added the following versions to the CI table: 141*10a4fa49Srie * 142*10a4fa49Srie * CI_BIND_GUARD, CI_BIND_CLEAR, CI_THR_SELF 143*10a4fa49Srie * CI_TLS_MODADD, CI_TLS_MOD_REMOVE, CI_TLS_STATMOD 144*10a4fa49Srie * 145*10a4fa49Srie * This version introduced the DT_SUNW_RTLDINFO structure as a mechanism 146*10a4fa49Srie * to handshake with ld.so.1. 147*10a4fa49Srie * 148*10a4fa49Srie * CI_VERSION == 4 (Solaris 10). 149*10a4fa49Srie * Added the CI_THRINIT handshake as part of the libc/libthread unified 150*10a4fa49Srie * process model. libc now initializes the current thread pointer from 151*10a4fa49Srie * this interface (and no longer relies on the INITFIRST flag - which 152*10a4fa49Srie * others have started to camp out on). 153*10a4fa49Srie * 154*10a4fa49Srie * Release summary: 155*10a4fa49Srie * 156*10a4fa49Srie * Solaris 8 CI_ATEXIT via _ld_libc() 157*10a4fa49Srie * TI_* via _ld_concurrency() 158*10a4fa49Srie * 159*10a4fa49Srie * Solaris 9 CI_ATEXIT and CI_LCMESSAGES via _ld_libc() 160*10a4fa49Srie * CI_* via RTLDINFO and _ld_libc() - new libthread 161*10a4fa49Srie * TI_* via _ld_concurrency() - old libthread 162*10a4fa49Srie * 163*10a4fa49Srie * Solaris 10 CI_ATEXIT and CI_LCMESSAGES via _ld_libc() 164*10a4fa49Srie * CI_* via RTLDINFO and _ld_libc() - new libthread 165*10a4fa49Srie */ 166*10a4fa49Srie #include "_synonyms.h" 167*10a4fa49Srie 168*10a4fa49Srie #include <sys/debug.h> 169*10a4fa49Srie #include <synch.h> 170*10a4fa49Srie #include <signal.h> 171*10a4fa49Srie #include <thread.h> 172*10a4fa49Srie #include <synch.h> 173*10a4fa49Srie #include <strings.h> 174*10a4fa49Srie #include <stdio.h> 175*10a4fa49Srie #include <debug.h> 176*10a4fa49Srie #include <libc_int.h> 177*10a4fa49Srie #include "_elf.h" 178*10a4fa49Srie #include "_rtld.h" 179*10a4fa49Srie 180*10a4fa49Srie /* 181*10a4fa49Srie * This interface provides the unified process model communication between 182*10a4fa49Srie * ld.so.1 and libc. This interface is supplied through RTLDINFO. 183*10a4fa49Srie */ 184*10a4fa49Srie void 185*10a4fa49Srie get_lcinterface(Rt_map *lmp, Lc_interface *funcs) 186*10a4fa49Srie { 187*10a4fa49Srie int tag, threaded = 0; 188*10a4fa49Srie Lm_list *lml; 189*10a4fa49Srie Lc_desc *lcp; 190*10a4fa49Srie 191*10a4fa49Srie if ((lmp == 0) || (funcs == 0)) 192*10a4fa49Srie return; 193*10a4fa49Srie 194*10a4fa49Srie lml = LIST(lmp); 195*10a4fa49Srie lcp = &lml->lm_lcs[0]; 196*10a4fa49Srie 197*10a4fa49Srie DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD)); 198*10a4fa49Srie 199*10a4fa49Srie for (tag = funcs->ci_tag; tag; tag = (++funcs)->ci_tag) { 200*10a4fa49Srie char *gptr; 201*10a4fa49Srie char *lptr = funcs->ci_un.ci_ptr; 202*10a4fa49Srie 203*10a4fa49Srie DBG_CALL(Dbg_util_lcinterface(lmp, tag, lptr)); 204*10a4fa49Srie 205*10a4fa49Srie if (tag >= CI_MAX) 206*10a4fa49Srie continue; 207*10a4fa49Srie 208*10a4fa49Srie /* 209*10a4fa49Srie * Maintain all interfaces on a per-link-map basis. Note, for 210*10a4fa49Srie * most interfaces, only the first interface is used for any 211*10a4fa49Srie * link-map list. This prevents accidents with developers who 212*10a4fa49Srie * manage to load two different versions of libc. 213*10a4fa49Srie */ 214*10a4fa49Srie if ((lcp[tag].lc_lmp) && 215*10a4fa49Srie (tag != CI_LCMESSAGES) && (tag != CI_VERSION)) { 216*10a4fa49Srie DBG_CALL(Dbg_unused_lcinterface(lmp, 217*10a4fa49Srie lcp[tag].lc_lmp, tag)); 218*10a4fa49Srie continue; 219*10a4fa49Srie } 220*10a4fa49Srie 221*10a4fa49Srie lcp[tag].lc_un.lc_ptr = lptr; 222*10a4fa49Srie lcp[tag].lc_lmp = lmp; 223*10a4fa49Srie 224*10a4fa49Srie gptr = glcs[tag].lc_un.lc_ptr; 225*10a4fa49Srie 226*10a4fa49Srie /* 227*10a4fa49Srie * Process any interfaces that must be maintained on a global 228*10a4fa49Srie * basis. 229*10a4fa49Srie */ 230*10a4fa49Srie switch (tag) { 231*10a4fa49Srie case CI_ATEXIT: 232*10a4fa49Srie break; 233*10a4fa49Srie 234*10a4fa49Srie case CI_LCMESSAGES: 235*10a4fa49Srie /* 236*10a4fa49Srie * At startup, ld.so.1 can establish a locale from one 237*10a4fa49Srie * of the locale family of environment variables (see 238*10a4fa49Srie * ld_str_env() and readenv_user()). During process 239*10a4fa49Srie * execution the locale can also be changed by the user. 240*10a4fa49Srie * This interface is called from libc should the locale 241*10a4fa49Srie * be modified. Presently, only one global locale is 242*10a4fa49Srie * maintained for all link-map lists, and only objects 243*10a4fa49Srie * on the primrary link-map may change this locale. 244*10a4fa49Srie */ 245*10a4fa49Srie if ((lml->lm_flags & LML_FLG_BASELM) && 246*10a4fa49Srie ((gptr == 0) || (strcmp(gptr, lptr) != 0))) { 247*10a4fa49Srie /* 248*10a4fa49Srie * If we've obtained a message locale (typically 249*10a4fa49Srie * supplied via libc's setlocale()), then 250*10a4fa49Srie * register the locale for use in dgettext() so 251*10a4fa49Srie * as to reestablish the locale for ld.so.1's 252*10a4fa49Srie * messages. 253*10a4fa49Srie */ 254*10a4fa49Srie if (gptr) { 255*10a4fa49Srie free((void *)gptr); 256*10a4fa49Srie rtld_flags |= RT_FL_NEWLOCALE; 257*10a4fa49Srie } 258*10a4fa49Srie glcs[tag].lc_un.lc_ptr = strdup(lptr); 259*10a4fa49Srie 260*10a4fa49Srie /* 261*10a4fa49Srie * Clear any cached messages. 262*10a4fa49Srie */ 263*10a4fa49Srie err_strs[ERR_NONE] = 0; 264*10a4fa49Srie err_strs[ERR_WARNING] = 0; 265*10a4fa49Srie err_strs[ERR_FATAL] = 0; 266*10a4fa49Srie err_strs[ERR_ELF] = 0; 267*10a4fa49Srie 268*10a4fa49Srie nosym_str = 0; 269*10a4fa49Srie } 270*10a4fa49Srie break; 271*10a4fa49Srie 272*10a4fa49Srie case CI_BIND_GUARD: 273*10a4fa49Srie case CI_BIND_CLEAR: 274*10a4fa49Srie case CI_THR_SELF: 275*10a4fa49Srie /* 276*10a4fa49Srie * If the global vector is unset, or this is the primary 277*10a4fa49Srie * link-map, set the global vector. 278*10a4fa49Srie */ 279*10a4fa49Srie if ((gptr == 0) || (lml->lm_flags & LML_FLG_BASELM)) 280*10a4fa49Srie glcs[tag].lc_un.lc_ptr = lptr; 281*10a4fa49Srie 282*10a4fa49Srie /* FALLTHROUGH */ 283*10a4fa49Srie 284*10a4fa49Srie case CI_TLS_MODADD: 285*10a4fa49Srie case CI_TLS_MODREM: 286*10a4fa49Srie case CI_TLS_STATMOD: 287*10a4fa49Srie case CI_THRINIT: 288*10a4fa49Srie threaded++; 289*10a4fa49Srie break; 290*10a4fa49Srie 291*10a4fa49Srie case CI_VERSION: 292*10a4fa49Srie if ((rtld_flags2 & RT_FL2_RTLDSEEN) == 0) { 293*10a4fa49Srie rtld_flags2 |= RT_FL2_RTLDSEEN; 294*10a4fa49Srie 295*10a4fa49Srie if (funcs->ci_un.ci_val >= CI_V_FOUR) { 296*10a4fa49Srie Listnode *lnp; 297*10a4fa49Srie Lm_list *lml2; 298*10a4fa49Srie 299*10a4fa49Srie rtld_flags2 |= RT_FL2_UNIFPROC; 300*10a4fa49Srie 301*10a4fa49Srie /* 302*10a4fa49Srie * We might have seen auditor which is 303*10a4fa49Srie * not dependent on libc. Such an 304*10a4fa49Srie * auditor's link map list has 305*10a4fa49Srie * LML_FLG_HOLDLOCK set. This lock 306*10a4fa49Srie * needs to be dropped. Refer to 307*10a4fa49Srie * audit_setup() in audit.c. 308*10a4fa49Srie */ 309*10a4fa49Srie if ((rtld_flags2 & RT_FL2_HASAUDIT) == 310*10a4fa49Srie 0) 311*10a4fa49Srie break; 312*10a4fa49Srie 313*10a4fa49Srie /* 314*10a4fa49Srie * Yes, we did. Take care of them. 315*10a4fa49Srie */ 316*10a4fa49Srie for (LIST_TRAVERSE(&dynlm_list, lnp, 317*10a4fa49Srie lml2)) { 318*10a4fa49Srie Rt_map *map = 319*10a4fa49Srie (Rt_map *)lml2->lm_head; 320*10a4fa49Srie 321*10a4fa49Srie if (FLAGS(map) & FLG_RT_AUDIT) { 322*10a4fa49Srie lml2->lm_flags &= 323*10a4fa49Srie ~LML_FLG_HOLDLOCK; 324*10a4fa49Srie } 325*10a4fa49Srie } 326*10a4fa49Srie } 327*10a4fa49Srie } 328*10a4fa49Srie break; 329*10a4fa49Srie 330*10a4fa49Srie default: 331*10a4fa49Srie break; 332*10a4fa49Srie } 333*10a4fa49Srie } 334*10a4fa49Srie 335*10a4fa49Srie if (threaded == 0) 336*10a4fa49Srie return; 337*10a4fa49Srie 338*10a4fa49Srie /* 339*10a4fa49Srie * If a version of libc gives us only a subset of the TLS interfaces - 340*10a4fa49Srie * it's confused and we discard the whole lot. 341*10a4fa49Srie */ 342*10a4fa49Srie if ((lcp[CI_TLS_MODADD].lc_un.lc_func && 343*10a4fa49Srie lcp[CI_TLS_MODREM].lc_un.lc_func && 344*10a4fa49Srie lcp[CI_TLS_STATMOD].lc_un.lc_func) == 0) { 345*10a4fa49Srie lcp[CI_TLS_MODADD].lc_un.lc_func = 0; 346*10a4fa49Srie lcp[CI_TLS_MODREM].lc_un.lc_func = 0; 347*10a4fa49Srie lcp[CI_TLS_STATMOD].lc_un.lc_func = 0; 348*10a4fa49Srie } 349*10a4fa49Srie 350*10a4fa49Srie /* 351*10a4fa49Srie * Indicate that we're now thread capable, and enable concurrency if 352*10a4fa49Srie * requested. 353*10a4fa49Srie */ 354*10a4fa49Srie if ((rtld_flags & RT_FL_NOCONCUR) == 0) 355*10a4fa49Srie rtld_flags |= RT_FL_CONCUR; 356*10a4fa49Srie if ((lml->lm_flags & LML_FLG_RTLDLM) == 0) 357*10a4fa49Srie rtld_flags |= RT_FL_THREADS; 358*10a4fa49Srie } 359*10a4fa49Srie 360*10a4fa49Srie /* 361*10a4fa49Srie * At this point we know we have a set of objects that have been fully analyzed 362*10a4fa49Srie * and relocated. Prior to the next major step of running .init sections (ie. 363*10a4fa49Srie * running user code), retrieve any RTLDINFO interfaces. 364*10a4fa49Srie */ 365*10a4fa49Srie int 366*10a4fa49Srie rt_get_extern(Lm_list *lml, Rt_map *lmp) 367*10a4fa49Srie { 368*10a4fa49Srie if (lml->lm_rti) { 369*10a4fa49Srie Aliste off; 370*10a4fa49Srie Rti_desc *rti; 371*10a4fa49Srie 372*10a4fa49Srie for (ALIST_TRAVERSE(lml->lm_rti, off, rti)) 373*10a4fa49Srie get_lcinterface(rti->rti_lmp, rti->rti_info); 374*10a4fa49Srie 375*10a4fa49Srie free(lml->lm_rti); 376*10a4fa49Srie lml->lm_rti = 0; 377*10a4fa49Srie } 378*10a4fa49Srie 379*10a4fa49Srie /* 380*10a4fa49Srie * Perform some sanity checks. If we have TLS requirements we better 381*10a4fa49Srie * have the associated external interfaces. 382*10a4fa49Srie */ 383*10a4fa49Srie if (lml->lm_tls && (lml->lm_lcs[CI_TLS_STATMOD].lc_un.lc_func == 0)) { 384*10a4fa49Srie eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ERR_TLS_NOTLS), 385*10a4fa49Srie NAME(lmp)); 386*10a4fa49Srie return (0); 387*10a4fa49Srie } 388*10a4fa49Srie return (1); 389*10a4fa49Srie } 390*10a4fa49Srie 391*10a4fa49Srie static int bindmask = 0; 392*10a4fa49Srie 393*10a4fa49Srie int 394*10a4fa49Srie rt_bind_guard(int bindflag) 395*10a4fa49Srie { 396*10a4fa49Srie int (*fptr)(int); 397*10a4fa49Srie 398*10a4fa49Srie if ((fptr = glcs[CI_BIND_GUARD].lc_un.lc_func) != NULL) { 399*10a4fa49Srie return ((*fptr)(bindflag)); 400*10a4fa49Srie } else { 401*10a4fa49Srie if ((bindflag & bindmask) == 0) { 402*10a4fa49Srie bindmask |= bindflag; 403*10a4fa49Srie return (1); 404*10a4fa49Srie } 405*10a4fa49Srie return (0); 406*10a4fa49Srie } 407*10a4fa49Srie } 408*10a4fa49Srie 409*10a4fa49Srie int 410*10a4fa49Srie rt_bind_clear(int bindflag) 411*10a4fa49Srie { 412*10a4fa49Srie int (*fptr)(int); 413*10a4fa49Srie 414*10a4fa49Srie if ((fptr = glcs[CI_BIND_CLEAR].lc_un.lc_func) != NULL) { 415*10a4fa49Srie return ((*fptr)(bindflag)); 416*10a4fa49Srie } else { 417*10a4fa49Srie if (bindflag == 0) 418*10a4fa49Srie return (bindmask); 419*10a4fa49Srie else { 420*10a4fa49Srie bindmask &= ~bindflag; 421*10a4fa49Srie return (0); 422*10a4fa49Srie } 423*10a4fa49Srie } 424*10a4fa49Srie } 425*10a4fa49Srie 426*10a4fa49Srie /* 427*10a4fa49Srie * Make sure threads have been initialized. This interface is called once for 428*10a4fa49Srie * each link-map list. 429*10a4fa49Srie */ 430*10a4fa49Srie void 431*10a4fa49Srie rt_thr_init(Lm_list *lml) 432*10a4fa49Srie { 433*10a4fa49Srie void (*fptr)(void); 434*10a4fa49Srie 435*10a4fa49Srie if ((fptr = (void (*)())lml->lm_lcs[CI_THRINIT].lc_un.lc_func) != 0) { 436*10a4fa49Srie lml->lm_lcs[CI_THRINIT].lc_un.lc_func = 0; 437*10a4fa49Srie leave((Lm_list *)0); 438*10a4fa49Srie (*fptr)(); 439*10a4fa49Srie (void) enter(); 440*10a4fa49Srie } 441*10a4fa49Srie } 442*10a4fa49Srie 443*10a4fa49Srie thread_t 444*10a4fa49Srie rt_thr_self() 445*10a4fa49Srie { 446*10a4fa49Srie thread_t (*fptr)(void); 447*10a4fa49Srie 448*10a4fa49Srie if ((fptr = (thread_t (*)())glcs[CI_THR_SELF].lc_un.lc_func) != NULL) 449*10a4fa49Srie return ((*fptr)()); 450*10a4fa49Srie 451*10a4fa49Srie return (1); 452*10a4fa49Srie } 453*10a4fa49Srie 454*10a4fa49Srie int 455*10a4fa49Srie rt_mutex_lock(Rt_lock * mp) 456*10a4fa49Srie { 457*10a4fa49Srie return (_lwp_mutex_lock((lwp_mutex_t *)mp)); 458*10a4fa49Srie } 459*10a4fa49Srie 460*10a4fa49Srie int 461*10a4fa49Srie rt_mutex_unlock(Rt_lock * mp) 462*10a4fa49Srie { 463*10a4fa49Srie return (_lwp_mutex_unlock((lwp_mutex_t *)mp)); 464*10a4fa49Srie } 465*10a4fa49Srie 466*10a4fa49Srie Rt_cond * 467*10a4fa49Srie rt_cond_create() 468*10a4fa49Srie { 469*10a4fa49Srie return (calloc(1, sizeof (Rt_cond))); 470*10a4fa49Srie } 471*10a4fa49Srie 472*10a4fa49Srie int 473*10a4fa49Srie rt_cond_wait(Rt_cond * cvp, Rt_lock * mp) 474*10a4fa49Srie { 475*10a4fa49Srie return (_lwp_cond_wait(cvp, (lwp_mutex_t *)mp)); 476*10a4fa49Srie } 477*10a4fa49Srie 478*10a4fa49Srie int 479*10a4fa49Srie rt_cond_broadcast(Rt_cond * cvp) 480*10a4fa49Srie { 481*10a4fa49Srie return (_lwp_cond_broadcast(cvp)); 482*10a4fa49Srie } 483*10a4fa49Srie 484*10a4fa49Srie #ifdef EXPAND_RELATIVE 485*10a4fa49Srie 486*10a4fa49Srie /* 487*10a4fa49Srie * Mutex interfaces to resolve references from any objects extracted from 488*10a4fa49Srie * libc_pic.a. Note, as ld.so.1 is essentially single threaded these can be 489*10a4fa49Srie * noops. 490*10a4fa49Srie */ 491*10a4fa49Srie #pragma weak lmutex_lock = __mutex_lock 492*10a4fa49Srie #pragma weak _private_mutex_lock = __mutex_lock 493*10a4fa49Srie #pragma weak mutex_lock = __mutex_lock 494*10a4fa49Srie #pragma weak _mutex_lock = __mutex_lock 495*10a4fa49Srie /* ARGSUSED */ 496*10a4fa49Srie int 497*10a4fa49Srie __mutex_lock(mutex_t *mp) 498*10a4fa49Srie { 499*10a4fa49Srie return (0); 500*10a4fa49Srie } 501*10a4fa49Srie 502*10a4fa49Srie #pragma weak lmutex_unlock = __mutex_unlock 503*10a4fa49Srie #pragma weak _private_mutex_unlock = __mutex_unlock 504*10a4fa49Srie #pragma weak mutex_unlock = __mutex_unlock 505*10a4fa49Srie #pragma weak _mutex_unlock = __mutex_unlock 506*10a4fa49Srie /* ARGSUSED */ 507*10a4fa49Srie int 508*10a4fa49Srie __mutex_unlock(mutex_t *mp) 509*10a4fa49Srie { 510*10a4fa49Srie return (0); 511*10a4fa49Srie } 512*10a4fa49Srie 513*10a4fa49Srie /* 514*10a4fa49Srie * This is needed to satisfy sysconf() (case _SC_THREAD_STACK_MIN) 515*10a4fa49Srie */ 516*10a4fa49Srie #pragma weak thr_min_stack = _thr_min_stack 517*10a4fa49Srie size_t 518*10a4fa49Srie _thr_min_stack() 519*10a4fa49Srie { 520*10a4fa49Srie #ifdef _LP64 521*10a4fa49Srie return (8 * 1024); 522*10a4fa49Srie #else 523*10a4fa49Srie return (4 * 1024); 524*10a4fa49Srie #endif 525*10a4fa49Srie } 526*10a4fa49Srie 527*10a4fa49Srie #endif /* EXPAND_RELATIVE */ 528