Example #1
0
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);
}
Example #2
0
/*
 * 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);
}
Example #3
0
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);
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
0
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
}
Example #7
0
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);
}
Example #8
0
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);
}
Example #9
0
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);
}
Example #10
0
/*
 * 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");
}
Example #11
0
/*
 * 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");
}
Example #12
0
/* 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;
}
Example #13
0
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);
}
Example #14
0
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);
   }
}
Example #15
0
/*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);
}
Example #16
0
/*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);
}
Example #17
0
/*
 * 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);
}
Example #18
0
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);
}
Example #19
0
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);
}
Example #20
0
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);
}
Example #21
0
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
  }
}
Example #23
0
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);
}
Example #24
0
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);
}
Example #25
0
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
}
Example #26
0
/* 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) ;
}
Example #28
0
/*
 * 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);
}
Example #29
0
/* 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);
}