示例#1
0
/*
 * __OVFL_DELETE -- Delete an overflow chain.
 *
 * Parameters:
 *	t:	tree
 *	p:	pointer to { pgno_t, u_int32_t }
 *
 * Returns:
 *	RET_ERROR, RET_SUCCESS
 */
int
__ovfl_delete(BTREE *t, void *p)
{
	PAGE *h;
	pgno_t pg;
	size_t plen;
	u_int32_t sz;

	memmove(&pg, p, sizeof(pgno_t));
	memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));

#ifdef DEBUG
	if (pg == P_INVALID || sz == 0)
		LIBC_ABORT("%s", pg == P_INVALID ? "pg == P_INVALID" : "sz == 0");
#endif
	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
		return (RET_ERROR);

	/* Don't delete chains used by internal pages. */
	if (h->flags & P_PRESERVE) {
		mpool_put(t->bt_mp, h, 0);
		return (RET_SUCCESS);
	}

	/* Step through the chain, calling the free routine for each page. */
	for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) {
		pg = h->nextpg;
		__bt_free(t, h);
		if (sz <= plen)
			break;
		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
			return (RET_ERROR);
	}
	return (RET_SUCCESS);
}
示例#2
0
/*
 * __OVFL_GET -- Get an overflow key/data item.
 *
 * Parameters:
 *	t:	tree
 *	p:	pointer to { pgno_t, u_int32_t }
 *	buf:	storage address
 *	bufsz:	storage size
 *
 * Returns:
 *	RET_ERROR, RET_SUCCESS
 */
int
__ovfl_get(BTREE *t, void *p, size_t *ssz, void **buf, size_t *bufsz)
{
	PAGE *h;
	pgno_t pg;
	size_t nb, plen;
	u_int32_t sz;

	memmove(&pg, p, sizeof(pgno_t));
	memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
	*ssz = sz;

#ifdef DEBUG
	if (pg == P_INVALID || sz == 0)
		LIBC_ABORT("%s", pg == P_INVALID ? "pg == P_INVALID" : "sz == 0");
#endif
	/* Make the buffer bigger as necessary. */
	if (*bufsz < sz) {
		*buf = reallocf(*buf, sz);
		if (*buf == NULL)
			return (RET_ERROR);
		*bufsz = sz;
	}

	/*
	 * Step through the linked list of pages, copying the data on each one
	 * into the buffer.  Never copy more than the data's length.
	 */
	plen = t->bt_psize - BTDATAOFF;
	for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
			return (RET_ERROR);

		nb = MIN(sz, plen);
		memmove(p, (char *)h + BTDATAOFF, nb);
		mpool_put(t->bt_mp, h, 0);

		if ((sz -= nb) == 0)
			break;
	}
	return (RET_SUCCESS);
}
/*
 * Wait for a thread to terminate and obtain its exit value.
 */
int
pthread_join(pthread_t thread,
	     void **value_ptr)
{
	int res = 0;
	pthread_t self = pthread_self();
	mach_port_t kthport;
	int conforming = 0;
#if !__DARWIN_UNIX03
	kern_return_t kern_res;
#endif

#if __DARWIN_UNIX03
	if (__unix_conforming == 0)
		__unix_conforming = 1;

#ifdef VARIANT_CANCELABLE
	_pthread_testcancel(self, 1);
#endif /* VARIANT_CANCELABLE */
#endif /* __DARWIN_UNIX03 */

	if ((res = _pthread_lookup_thread(thread, &kthport, 1)) != 0)
		return(res);

	if (thread->sig == _PTHREAD_SIG)
	{
	if (thread->newstyle == 0) {
		semaphore_t death = new_sem_from_pool(); /* in case we need it */

		LOCK(thread->lock);
		if ((thread->detached & PTHREAD_CREATE_JOINABLE) &&
			thread->death == SEMAPHORE_NULL)
		{

			assert(thread->joiner == NULL);
			if (thread != self && (self == NULL || self->joiner != thread))
			{
				int already_exited = (thread->detached & _PTHREAD_EXITED);

				thread->death = death;
				thread->joiner = self;
				UNLOCK(thread->lock);

				if (!already_exited)
				{
#if __DARWIN_UNIX03
					/* Wait for it to signal... */
					pthread_cleanup_push(__posix_join_cleanup, (void *)thread);
					do {
						res = __semwait_signal(death, 0, 0, 0, (int64_t)0, (int32_t)0);
					} while ((res < 0) && (errno == EINTR));
					pthread_cleanup_pop(0);

#else /* __DARWIN_UNIX03 */
					/* Wait for it to signal... */
					do {
						PTHREAD_MACH_CALL(semaphore_wait(death), kern_res);
					} while (kern_res != KERN_SUCCESS);
#endif /* __DARWIN_UNIX03 */
				}

				LOCK(_pthread_list_lock);
				TAILQ_REMOVE(&__pthread_head, thread, plist);
#if WQ_TRACE
				__kdebug_trace(0x9000010, thread, 0, 0, 16, 0);
#endif
				UNLOCK(_pthread_list_lock);
				/* ... and wait for it to really be dead */
				while ((res = _pthread_reap_thread(thread,
							thread->kernel_thread,
							value_ptr, __unix_conforming)) == EAGAIN)
				{
					sched_yield();
				}

			} else {
				UNLOCK(thread->lock);
				res = EDEADLK;
			}
		} else {
			UNLOCK(thread->lock);
			res = EINVAL;
		}
		restore_sem_to_pool(death);
		return res;
	} else {
		/* new style */

		semaphore_t death = SEMAPHORE_NULL; /* in case we need it */
		semaphore_t joinsem = SEMAPHORE_NULL;

		if (thread->joiner_notify == MACH_PORT_NULL)
			 death = new_sem_from_pool();

		LOCK(thread->lock);
		if ((thread->detached & PTHREAD_CREATE_JOINABLE) &&
			(thread->joiner == NULL))
		{
			assert(thread->kernel_thread == kthport);
			if (thread != self && (self == NULL || self->joiner != thread))
			{
				if (thread->joiner_notify == MACH_PORT_NULL) {
					if (death == SEMAPHORE_NULL)
						LIBC_ABORT("thread %p: death == SEMAPHORE_NULL", thread);
					thread->joiner_notify = death;
					death = SEMAPHORE_NULL;
				}
				joinsem = thread->joiner_notify;
				thread->joiner = self;
				UNLOCK(thread->lock);

				if (death != SEMAPHORE_NULL) {
					restore_sem_to_pool(death);
					death = SEMAPHORE_NULL;
				}
#if __DARWIN_UNIX03
				/* Wait for it to signal... */
				pthread_cleanup_push(__posix_join_cleanup, (void *)thread);
				do {
					res = __semwait_signal(joinsem, 0, 0, 0, (int64_t)0, (int32_t)0);
				} while ((res < 0) && (errno == EINTR));
				pthread_cleanup_pop(0);
#else /* __DARWIN_UNIX03 */
				/* Wait for it to signal... */
				do {
					PTHREAD_MACH_CALL(semaphore_wait(joinsem), kern_res);
				} while (kern_res != KERN_SUCCESS);
#endif /* __DARWIN_UNIX03 */

				restore_sem_to_pool(joinsem);
				res = _pthread_join_cleanup(thread, value_ptr, conforming);
			} else {
				UNLOCK(thread->lock);
				res = EDEADLK;
			}
		} else {
			UNLOCK(thread->lock);
			res = EINVAL;
		}
		if (death != SEMAPHORE_NULL)
			restore_sem_to_pool(death);
		return res;
	}/* end of new style */
	}
	return ESRCH;
}
示例#4
0
/*
 * This is the long double version of __hdtoa().
 */
char *
__hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
    char **rve)
{
	static const int sigfigs = (LDBL_MANT_DIG + 3) / 4;
	union IEEEl2bits u;
	char *s, *s0;
	int bufsize, f;

	u.e = e;
	*sign = u.bits.sign;

	switch (f = fpclassify(e)) {
	case FP_NORMAL:
	case FP_SUPERNORMAL:
		*decpt = u.bits.exp - LDBL_ADJ;
		break;
	case FP_ZERO:
		*decpt = 1;
		return (nrv_alloc("0", rve, 1));
	case FP_SUBNORMAL:
		u.e *= 0x1p514L;
		*decpt = u.bits.exp - (514 + LDBL_ADJ);
		break;
	case FP_INFINITE:
		*decpt = INT_MAX;
		return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
	case FP_NAN:
		*decpt = INT_MAX;
		return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
	default:
		LIBC_ABORT("fpclassify returned %d", f);
	}

	/* FP_NORMAL or FP_SUBNORMAL */

	if (ndigits == 0)		/* dtoa() compatibility */
		ndigits = 1;

	/*
	 * For simplicity, we generate all the digits even if the
	 * caller has requested fewer.
	 */
	bufsize = (sigfigs > ndigits) ? sigfigs : ndigits;
	s0 = rv_alloc(bufsize);

	/*
	 * We work from right to left, first adding any requested zero
	 * padding, then the least significant portion of the
	 * mantissa, followed by the most significant.  The buffer is
	 * filled with the byte values 0x0 through 0xf, which are
	 * converted to xdigs[0x0] through xdigs[0xf] after the
	 * rounding phase.
	 */
	for (s = s0 + bufsize - 1; s > s0 + sigfigs - 1; s--)
		*s = 0;
	for (; s > s0 + sigfigs - (LDBL_MANL_SIZE / 4) - 1 && s > s0; s--) {
		*s = u.bits.manl & 0xf;
		u.bits.manl >>= 4;
	}
	for (; s > s0; s--) {
		*s = u.bits.manh & 0xf;
		u.bits.manh >>= 4;
	}

	/*
	 * At this point, we have snarfed all the bits in the
	 * mantissa, with the possible exception of the highest-order
	 * (partial) nibble, which is dealt with by the next
	 * statement.  We also tack on the implicit normalization bit.
	 */
	*s = u.bits.manh | (1U << ((LDBL_MANT_DIG - 1) % 4));

	/* If ndigits < 0, we are expected to auto-size the precision. */
	if (ndigits < 0) {
		for (ndigits = sigfigs; s0[ndigits - 1] == 0; ndigits--)
			;
	}

	if (sigfigs > ndigits && s0[ndigits] != 0)
		dorounding(s0, ndigits, u.bits.sign, decpt);

	s = s0 + ndigits;
	if (rve != NULL)
		*rve = s;
	*s-- = '\0';
	for (; s >= s0; s--)
		*s = xdigs[(unsigned int)*s];

	return (s0);
}
示例#5
0
/*
 * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(),
 * except that the floating point argument is passed by reference.
 * When dtoa() is passed a NaN or infinity, it sets expt to 9999.
 * However, a long double could have a valid exponent of 9999, so we
 * use INT_MAX in ldtoa() instead.
 */
char *
__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
    char **rve)
{
#if defined(__arm__) 
	/* On arm, double == long double, so short circuit this */
	char * ret = __dtoa((double)*ld, mode, ndigits, decpt, sign, rve);
	if (*decpt == 9999)
		*decpt = INT_MAX;
	return ret;
#else
	FPI fpi = {
		LDBL_MANT_DIG,			/* nbits */
		LDBL_MIN_EXP - LDBL_MANT_DIG,	/* emin */
		LDBL_MAX_EXP - LDBL_MANT_DIG,	/* emax */
		FLT_ROUNDS,	       		/* rounding */
#ifdef Sudden_Underflow	/* unused, but correct anyway */
		1
#else
		0
#endif
	};
	int be, kind;
	char *ret;
	union IEEEl2bits u;
	uint32_t bits[(LDBL_MANT_DIG + 31) / 32];
	void *vbits = bits;
	int type;

	u.e = *ld;
	type = fpclassify(u.e);

	/*
	 * gdtoa doesn't know anything about the sign of the number, so
	 * if the number is negative, we need to swap rounding modes of
	 * 2 (upwards) and 3 (downwards).
	 */
	*sign = u.bits.sign;
	fpi.rounding ^= (fpi.rounding >> 1) & u.bits.sign;

	be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1);
	LDBL_TO_ARRAY32(u, bits);

	switch (type) {
	case FP_NORMAL:
	case FP_SUPERNORMAL:
		kind = STRTOG_Normal;
#ifdef	LDBL_IMPLICIT_NBIT
		bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32);
#endif /* LDBL_IMPLICIT_NBIT */
		break;
	case FP_ZERO:
		kind = STRTOG_Zero;
		break;
	case FP_SUBNORMAL:
		kind = STRTOG_Denormal;
		be++;
		break;
	case FP_INFINITE:
		kind = STRTOG_Infinite;
		break;
	case FP_NAN:
		kind = STRTOG_NaN;
		break;
	default:
		LIBC_ABORT("fpclassify returned %d", type);
	}

	ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve);
	if (*decpt == -32768)
		*decpt = INT_MAX;
	return ret;
#endif
}