/* * __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); }
/* * __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; }
/* * 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); }
/* * 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 }