int get_clearance(int callnumber) { sema_t *table_sema = NULL; char *tab; if (sema_trywait(&common_sema) == 0) { (void) thr_setspecific(lookup_state_key, NULL); return (0); } switch (callnumber) { case GETLDAPCONFIG: tab = "ldap"; table_sema = &ldap_sema; break; default: logit("Internal Error: get_clearance\n"); break; } if (sema_trywait(table_sema) == 0) { (void) thr_setspecific(lookup_state_key, (void*)1); return (0); } if (current_admin.debug_level >= DBG_CANT_FIND) { logit("get_clearance: throttling load for %s table\n", tab); } return (-1); }
/* * get clearance */ int _nscd_get_clearance(sema_t *sema) { if (sema_trywait(&common_sema) == 0) { (void) thr_setspecific(lookup_state_key, NULL); return (0); } if (sema_trywait(sema) == 0) { (void) thr_setspecific(lookup_state_key, (void*)1); return (0); } return (1); }
res_state __res_state(void) { res_state statp; if (thr_main() != 0) return (&_res); if (thr_once(&res_init_once, res_keycreate) != 0 || !res_thr_keycreated) return (&_res); statp = thr_getspecific(res_key); if (statp != NULL) return (statp); statp = calloc(1, sizeof(*statp)); if (statp == NULL) return (&_res); #ifdef __BIND_RES_TEXT statp->options = RES_TIMEOUT; /* Motorola, et al. */ #endif if (thr_setspecific(res_key, statp) == 0) return (statp); free(statp); return (&_res); }
static int * __nc_error(void) { static int nc_error = 0; int *nc_addr; /* * Use the static `nc_error' if we are the main thread * (including non-threaded programs), or if an allocation * fails. */ if (thr_main()) return (&nc_error); if (thr_once(&nc_once, nc_key_init) != 0 || nc_key_error != 0) return (&nc_error); if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) { nc_addr = (int *)malloc(sizeof (int)); if (thr_setspecific(nc_key, (void *) nc_addr) != 0) { free(nc_addr); return (&nc_error); } *nc_addr = 0; } return (nc_addr); }
static int * __nc_error() { static pthread_mutex_t nc_lock = PTHREAD_MUTEX_INITIALIZER; extern thread_key_t nc_key; static int nc_error = 0; int error, *nc_addr; /* * Use the static `nc_error' if we are the main thread * (including non-threaded programs), or if an allocation * fails. */ if (nc_key == -1) { error = 0; mutex_lock(&nc_lock); if (nc_key == -1) error = thr_keycreate(&nc_key, free); mutex_unlock(&nc_lock); if (error) return (&nc_error); } if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) { nc_addr = (int *)malloc(sizeof (int)); if (thr_setspecific(nc_key, (void *) nc_addr) != 0) { if (nc_addr) free(nc_addr); return (&nc_error); } *nc_addr = 0; } return (nc_addr); }
static int * __nc_error(void) { #ifdef _REENTRANT int *nc_addr = NULL; #endif static int nc_error = 0; #ifdef _REENTRANT if (__isthreaded == 0) return &nc_error; thr_once(&nc_once, __nc_error_setup); nc_addr = thr_getspecific(nc_key) ; if (nc_addr == NULL) { nc_addr = malloc(sizeof (int)); if (nc_addr == NULL) return &nc_error; if (thr_setspecific(nc_key, (void *) nc_addr) != 0) { if (nc_addr) free(nc_addr); return &nc_error; } *nc_addr = 0; } return nc_addr; #else return &nc_error; #endif }
char * fdevname(int fd) { char *buf; int error; if (thr_main() != 0) buf = fdevname_buf; else { if (thr_once(&fdevname_init_once, fdevname_keycreate) != 0 || !fdevname_keycreated) return (NULL); if ((buf = thr_getspecific(fdevname_key)) == NULL) { if ((buf = malloc(sizeof fdevname_buf)) == NULL) return (NULL); if (thr_setspecific(fdevname_key, buf) != 0) { free(buf); return (NULL); } } } if (((error = fdevname_r(fd, buf, sizeof fdevname_buf))) != 0) { errno = error; return (NULL); } return (buf); }
static char * sig_tlsalloc(void) { char *ebuf = NULL; if (thr_main() != 0) ebuf = sig_ebuf; else { if (thr_once(&sig_init_once, sig_keycreate) != 0 || !sig_keycreated) goto thr_err; if ((ebuf = thr_getspecific(sig_key)) == NULL) { if ((ebuf = malloc(sizeof(sig_ebuf))) == NULL) goto thr_err; if (thr_setspecific(sig_key, ebuf) != 0) { free(ebuf); ebuf = NULL; goto thr_err; } } } thr_err: if (ebuf == NULL) ebuf = sig_ebuf_err; return (ebuf); }
char * ttyname(int fd) { char *buf; if (thr_main() != 0) buf = ttyname_buf; else { if (thr_once(&ttyname_init_once, ttyname_keycreate) != 0 || !ttyname_keycreated) return (NULL); if ((buf = thr_getspecific(ttyname_key)) == NULL) { if ((buf = malloc(sizeof ttyname_buf)) == NULL) return (NULL); if (thr_setspecific(ttyname_key, buf) != 0) { free(buf); return (NULL); } } } if (ttyname_r(fd, buf, sizeof ttyname_buf) != 0) return (NULL); return (buf); }
/* * Broadcasts on UDP transport. Obsoleted by rpc_broadcast(). */ enum clnt_stat clnt_broadcast( u_long prog, /* program number */ u_long vers, /* version number */ u_long proc, /* procedure number */ xdrproc_t xargs, /* xdr routine for args */ caddr_t argsp, /* pointer to args */ xdrproc_t xresults, /* xdr routine for results */ caddr_t resultsp, /* pointer to results */ resultproc_t eachresult) /* call with each result obtained */ { #ifdef _REENTRANT if (__isthreaded == 0) clnt_broadcast_result_main = eachresult; else { thr_once(&clnt_broadcast_once, clnt_broadcast_setup); thr_setspecific(clnt_broadcast_key, (void *) eachresult); } #else clnt_broadcast_result_main = eachresult; #endif return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers, (rpcproc_t)proc, xargs, argsp, xresults, resultsp, (resultproc_t) rpc_wrap_bcast, "udp"); }
/* * Broadcasts on UDP transport. Obsoleted by rpc_broadcast(). */ enum clnt_stat clnt_broadcast(u_long prog, u_long vers, u_long proc, xdrproc_t xargs, void *argsp, xdrproc_t xresults, void *resultsp, resultproc_t eachresult) /* * u_long prog; // program number * u_long vers; // version number * u_long proc; // procedure number * xdrproc_t xargs; // xdr routine for args * void *argsp; // pointer to args * xdrproc_t xresults; // xdr routine for results * void *resultsp; // pointer to results * resultproc_t eachresult; // call with each result obtained */ { if (thr_main()) clnt_broadcast_result_main = eachresult; else { thr_once(&clnt_broadcast_once, clnt_broadcast_key_init); thr_setspecific(clnt_broadcast_key, (void *) eachresult); } return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers, (rpcproc_t)proc, xargs, argsp, xresults, resultsp, (resultproc_t) rpc_wrap_bcast, "udp"); }
/* Sets the thread's local storage pointer. */ int __objc_thread_set_data(void *value) { if (thr_setspecific(__objc_thread_data_key, value) == 0) return 0; else return -1; }
void exacct_seterr(int errval) { if (thr_main()) { exacct_errval = errval; return; } (void) thr_keycreate_once(&errkey, 0); (void) thr_setspecific(errkey, (void *)(intptr_t)errval); }
void _glthread_SetTSD(_glthread_TSD *tsd, void *ptr) { if (tsd->initMagic != INIT_MAGIC) { _glthread_InitTSD(tsd); } if ((errno = thr_setspecific(tsd->key, ptr)) != 0) { perror(SET_TSD_ERROR); exit(-1); } }
/*ARGSUSED*/ static void * server_tsd_bind(void *arg) { static void *value = 0; /* disable cancellation to avoid hangs if server threads disappear */ (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); (void) thr_setspecific(server_key, value); (void) door_return(NULL, 0, NULL, 0); /* make lint happy */ return (NULL); }
/*ARGSUSED*/ static void * server_tsd_bind(void *arg) { static void *value = 0; /* * disable cancellation to prevent hangs when server * threads disappear */ (void) thr_setspecific(server_key, value); (void) door_return(NULL, 0, NULL, 0); return (value); }
/* * get the per-thread-data-item for the calling thread */ static struct thr_data * _get_thr_data(void) { struct thr_data *thr_data = NULL; (void) thr_getspecific(thr_key, (void *)&thr_data); if (thr_data == NULL) { thr_data = malloc(sizeof (struct thr_data)); if (thr_data != NULL) { thr_data->fp = NULL; thr_data->Dcflags = DC_STD; thr_setspecific(thr_key, thr_data); } } return (thr_data); }
static char * _get_stop(thread_key_t *keyp) { char *str; if (thr_keycreate_once(keyp, free) != 0) return (NULL); str = pthread_getspecific(*keyp); if (str == NULL) { str = calloc(CHARS, sizeof (char)); if (thr_setspecific(*keyp, str) != 0) { if (str) (void) free(str); str = NULL; } } return (str); }
static vars_storage * _get_vars_storage(thread_key_t *keyp) { vars_storage *vars; if (thr_keycreate_once(keyp, free) != 0) return (NULL); vars = pthread_getspecific(*keyp); if (vars == NULL) { vars = calloc(1, sizeof (vars_storage)); if (thr_setspecific(*keyp, vars) != 0) { if (vars) (void) free(vars); vars = NULL; } } return (vars); }
struct servdata * __servdata_init(void) { struct servdata *sd; if (thr_main() != 0) return (&servdata); if (thr_once(&servdata_init_once, servdata_keycreate) != 0 || !servdata_thr_keycreated) return (NULL); if ((sd = thr_getspecific(servdata_key)) != NULL) return (sd); if ((sd = calloc(1, sizeof(*sd))) == NULL) return (NULL); if (thr_setspecific(servdata_key, sd) == 0) return (sd); free(sd); return (NULL); }
const char * gai_strerror(int ecode) { #if defined(NLS) nl_catd catd; char *buf; if (thr_main() != 0) buf = gai_buf; else { if (thr_once(&gai_init_once, gai_keycreate) != 0 || !gai_keycreated) goto thr_err; if ((buf = thr_getspecific(gai_key)) == NULL) { if ((buf = malloc(sizeof(gai_buf))) == NULL) goto thr_err; if (thr_setspecific(gai_key, buf) != 0) { free(buf); goto thr_err; } } } catd = catopen("libc", NL_CAT_LOCALE); if (ecode > 0 && ecode < EAI_MAX) strlcpy(buf, catgets(catd, 3, ecode, ai_errlist[ecode]), sizeof(gai_buf)); else if (ecode == 0) strlcpy(buf, catgets(catd, 3, NL_MSGMAX - 1, "Success"), sizeof(gai_buf)); else strlcpy(buf, catgets(catd, 3, NL_MSGMAX, "Unknown error"), sizeof(gai_buf)); catclose(catd); return buf; thr_err: #endif if (ecode >= 0 && ecode < EAI_MAX) return ai_errlist[ecode]; return "Unknown error"; }
void ThreadLocalStorage::set_thread_in_slot(Thread *thread) { guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; if (tlsMode == pd_tlsAccessIndirect) { #ifdef AMD64 intptr_t tbase = fs_thread(); #else intptr_t tbase = gs_thread(); #endif // AMD64 *((Thread**) (tbase + tlsOffset)) = thread ; } else if (tlsMode == pd_tlsAccessDirect) { thr_setspecific (tlsKey, (void *) thread) ; // set with thr_setspecific and then readback with gs_load to validate. #ifdef AMD64 guarantee (thread == fs_load(tlsOffset), "tls readback failure") ; #else guarantee (thread == gs_load(tlsOffset), "tls readback failure") ; #endif // AMD64 } }
struct rpc_createerr *__rpc_createerr(void) { struct rpc_createerr *rce_addr; mutex_lock(&tsd_lock); if (rce_key == -1) thr_keycreate(&rce_key, thr_keyfree); mutex_unlock(&tsd_lock); rce_addr = (struct rpc_createerr *)thr_getspecific(rce_key); if (!rce_addr) { rce_addr = (struct rpc_createerr *) mem_alloc(sizeof(struct rpc_createerr)); if (thr_setspecific(rce_key, (void *)rce_addr) != 0) { mem_free(rce_addr, sizeof(*rce_addr)); return (&rpc_createerr); } memset(rce_addr, 0, sizeof(*rce_addr)); } return (rce_addr); }
struct rpc_createerr * __rpc_createerr(void) { struct rpc_createerr *rce_addr = 0; if (thr_main()) return (&rpc_createerr); if (thr_once(&rce_once, rce_key_init) != 0 || rce_key_error != 0) return (&rpc_createerr); rce_addr = (struct rpc_createerr *)thr_getspecific(rce_key); if (!rce_addr) { rce_addr = (struct rpc_createerr *) malloc(sizeof (struct rpc_createerr)); if (thr_setspecific(rce_key, (void *) rce_addr) != 0) { free(rce_addr); return (&rpc_createerr); } memset(rce_addr, 0, sizeof (struct rpc_createerr)); return (rce_addr); } return (rce_addr); }
struct rpc_createerr* __rpc_createerr(void) { #ifdef _REENTRANT struct rpc_createerr *rce_addr = 0; if (__isthreaded == 0) return (&rpc_createerr); thr_once(&rce_once, __rpc_createerr_setup); rce_addr = thr_getspecific(rce_key); if (rce_addr == NULL) { rce_addr = malloc(sizeof(*rce_addr)); if (rce_addr == NULL) return &rpc_createerr; thr_setspecific(rce_key, (void *) rce_addr); memset(rce_addr, 0, sizeof (struct rpc_createerr)); } return (rce_addr); #else return &rpc_createerr; #endif }
/* set thread local error message */ static void set_jvm_error(const char* msg) { thr_setspecific(jvm_error_key, (void*)msg); }
void dbgsysTlsPut(int index, void *value) { thr_setspecific((thread_key_t)index, value) ; }
/* * This is the simplified interface to the client rpc layer. * The client handle is not destroyed here and is reused for * the future calls to same prog, vers, host and nettype combination. * * The total time available is 25 seconds. */ enum clnt_stat rpc_call(const char *host, /* host name */ rpcprog_t prognum, /* program number */ rpcvers_t versnum, /* version number */ rpcproc_t procnum, /* procedure number */ xdrproc_t inproc, const char *in, xdrproc_t outproc, /* in/out XDR procedures */ char *out, /* recv/send data */ const char *nettype) /* nettype */ { struct rpc_call_private *rcp = NULL; enum clnt_stat clnt_stat; struct timeval timeout, tottimeout; static thread_key_t rpc_call_key; int main_thread = 1; if ((main_thread = thr_main())) { rcp = rpc_call_private_main; } else { if (rpc_call_key == 0) { mutex_lock(&tsd_lock); if (rpc_call_key == 0) thr_keycreate(&rpc_call_key, rpc_call_destroy); mutex_unlock(&tsd_lock); } rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key); } if (rcp == NULL) { rcp = malloc(sizeof (*rcp)); if (rcp == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; return (rpc_createerr.cf_stat); } if (main_thread) rpc_call_private_main = rcp; else thr_setspecific(rpc_call_key, (void *) rcp); rcp->valid = 0; rcp->client = NULL; } if ((nettype == NULL) || (nettype[0] == 0)) nettype = "netpath"; if (!(rcp->valid && rcp->pid == getpid() && (rcp->prognum == prognum) && (rcp->versnum == versnum) && (!strcmp(rcp->host, host)) && (!strcmp(rcp->nettype, nettype)))) { int fd; rcp->valid = 0; if (rcp->client) CLNT_DESTROY(rcp->client); /* * Using the first successful transport for that type */ rcp->client = clnt_create(host, prognum, versnum, nettype); rcp->pid = getpid(); if (rcp->client == NULL) { return (rpc_createerr.cf_stat); } /* * Set time outs for connectionless case. Do it * unconditionally. Faster than doing a t_getinfo() * and then doing the right thing. */ timeout.tv_usec = 0; timeout.tv_sec = 5; CLNT_CONTROL(rcp->client, CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout); if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd)) _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */ rcp->prognum = prognum; rcp->versnum = versnum; if ((strlen(host) < (size_t)MAXHOSTNAMELEN) && (strlen(nettype) < (size_t)NETIDLEN)) { strcpy(rcp->host, host); strcpy(rcp->nettype, nettype); rcp->valid = 1; } else { rcp->valid = 0; } } /* else reuse old client */ tottimeout.tv_sec = 25; tottimeout.tv_usec = 0; /*LINTED const castaway*/ clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in, outproc, out, tottimeout); /* * if call failed, empty cache */ if (clnt_stat != RPC_SUCCESS) rcp->valid = 0; return (clnt_stat); }
/* clear thread local error message */ static void clear_jvm_error() { thr_setspecific(jvm_error_key, NULL); }
int condvarWait(condvar_t *condvar, mutex_t *mutex, thread_state_t wtype) { sigjmp_buf jmpbuf; int err; sys_thread_t *self = sysThreadSelf(); /* * There is no threads interface to get a thread's state. So, instead, * we use this hack so that the debugger agent can get at this thread's * state. Of course, this is not very reliable, but when a thread goes * to sleep, it *will* be reported as sleeping. During the transition * from running to sleep, it may be incorrectly reported, since the * setting of the state here is not atomic with the voluntary sleep. * The better fix is to extend the Solaris threads interface and have * the debugger agent call this interface OR to use libthread_db for * intra-process state reporting. * * Now, condition variables are used either for waiting to enter a * monitor (MONITOR_WAIT) or to execute a "wait()" method when already * holding a monitor (CONDVAR_WAIT). So, when condvarWait() is called * it could be to wait for a monitor or for a condition within a * monitor. This is indicated by the "wtype" argument to condvarWait(). * This type is set in the thread state before going to sleep. */ self->state = wtype; #ifdef __linux__ /* * Register our intrHandler as a cleanup handler. If we get * interrupted (i.e. canceled), we longjmp out of this handler. */ pthread_cleanup_push(intrHandler, NULL); if (setjmp(jmpbuf) == 0) { /* * Set the jmp buf and enable cancellation. */ thr_setspecific(intrJmpbufkey, &jmpbuf); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); /* * Note: pthread_cond_wait is _not_ interruptible on Linux */ #else thr_setspecific(sigusr1Jmpbufkey, &jmpbuf); if (sigsetjmp(jmpbuf, 1) == 0) { sigset_t osigset; thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset); again: #endif err = cond_wait((cond_t *) condvar, (mutex_t *) mutex); switch(err) { case 0: err = SYS_OK; break; #ifndef __linux__ case EINTR: /* Signals other than USR1 were received. */ goto again; #endif default: err = SYS_ERR; } #ifdef __linux__ /* * Disable cancellation and clear the jump buf. */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); thr_setspecific(intrJmpbufkey, NULL); #else thr_sigsetmask(SIG_SETMASK, &osigset, NULL); #endif } else { /* * we've received a SIGUSR1 to interrupt our wait. We just return * and something above use notices the change. * clear the jump buf just to be paranoid. */ #ifndef __linux__ thr_setspecific(sigusr1Jmpbufkey, NULL); #endif err = SYS_INTRPT; } #ifdef __linux__ pthread_cleanup_pop(0); #endif /* * After having woken up, change the thread state to RUNNABLE, since * it is now runnable. */ self->state = RUNNABLE; return err; } /* * Returns 0 if condition variable became true before timeout expired. * Returns 1 if timeout expired first. * Returns <0 if wait fails for any other reason. */ int condvarTimedWait(condvar_t *condvar, mutex_t *mutex, jlong millis, thread_state_t wtype) { #ifdef __linux__ jmp_buf jmpbuf; #else sigjmp_buf jmpbuf; #endif int err; struct timespec timeout; sys_thread_t *self; jlong end_time; if (millis < 0) return SYS_ERR; if (millis > (jlong)INT_MAX) { return condvarWait(condvar, mutex, wtype); } end_time = sysTimeMillis() + millis; self = sysThreadSelf(); self->state = wtype; #ifdef __linux__ /* * Register our intrHandler as a cleanup handler. If we get * interrupted (i.e. canceled), we longjmp out of this handler. */ pthread_cleanup_push(intrHandler, NULL); if (setjmp(jmpbuf) == 0) { /* * Set the jmp buf and enable cancellation. */ thr_setspecific(intrJmpbufkey, &jmpbuf); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); /* * Calculate an absolute timeout value. */ timeout.tv_sec = end_time / 1000; timeout.tv_nsec = (end_time % 1000) * 1000000; again: #else thr_setspecific(sigusr1Jmpbufkey, &jmpbuf); if (sigsetjmp(jmpbuf, 1) == 0) { sigset_t osigset; thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset); again: timeout.tv_sec = end_time / 1000; timeout.tv_nsec = (end_time % 1000) * 1000000; #endif err = cond_timedwait((cond_t *)condvar, (mutex_t *)mutex, &timeout); switch(err) { case 0: err = SYS_OK; break; case EINTR: /* Signals other than USR1 were received. */ if (sysTimeMillis() < end_time) { goto again; } /*FALLTHRU*/ #ifdef USE_PTHREADS case ETIMEDOUT: #else case ETIME: #endif err = SYS_TIMEOUT; break; default: err = SYS_ERR; } #ifdef __linux__ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); thr_setspecific(intrJmpbufkey, NULL); #else thr_sigsetmask(SIG_SETMASK, &osigset, NULL); #endif } else { /* * we've received a SIGUSR1 to interrupt our wait. We just return * and something above use notices the change. * clear the jump buf just to be paranoid. */ #ifndef __linux__ thr_setspecific(sigusr1Jmpbufkey, NULL); #endif err = SYS_INTRPT; } #ifdef __linux__ /* Remove intrHandler without calling it. */ pthread_cleanup_pop(0); sysAssert(pthread_mutex_trylock(mutex) == EBUSY); /* * After having woken up, change the thread state to RUNNABLE, since * it is now runnable. */ #endif self->state = RUNNABLE; return err; } int condvarSignal(condvar_t *condvar) { int err; err = cond_signal((cond_t *) condvar); condvar->counter++; return (err == 0 ? SYS_OK : SYS_ERR); }