TEST(pthread, pthread_attr_setguardsize) { pthread_attr_t attributes; ASSERT_EQ(0, pthread_attr_init(&attributes)); // Get the default guard size. size_t default_guard_size; ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &default_guard_size)); // No such thing as too small: will be rounded up to one page by pthread_create. ASSERT_EQ(0, pthread_attr_setguardsize(&attributes, 128)); size_t guard_size; ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size)); ASSERT_EQ(128U, guard_size); ASSERT_EQ(4096U, GetActualGuardSize(attributes)); // Large enough and a multiple of the page size. ASSERT_EQ(0, pthread_attr_setguardsize(&attributes, 32*1024)); ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size)); ASSERT_EQ(32*1024U, guard_size); // Large enough but not a multiple of the page size; will be rounded up by pthread_create. ASSERT_EQ(0, pthread_attr_setguardsize(&attributes, 32*1024 + 1)); ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size)); ASSERT_EQ(32*1024U + 1, guard_size); }
static int get_stack(void **addr, size_t *size) { #define CHECK_ERR(expr) \ {int err = (expr); if (err) return err;} #if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP pthread_attr_t attr; size_t guard = 0; # ifdef HAVE_PTHREAD_GETATTR_NP CHECK_ERR(pthread_getattr_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif if (pthread_attr_getguardsize(&attr, &guard) == 0) { STACK_GROW_DIR_DETECTION; STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + guard)); *size -= guard; } # else CHECK_ERR(pthread_attr_init(&attr)); CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr)); CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); *size -= guard; # ifndef HAVE_PTHREAD_GETATTR_NP pthread_attr_destroy(&attr); # endif #elif defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP pthread_t th = pthread_self(); *addr = pthread_get_stackaddr_np(th); *size = pthread_get_stacksize_np(th); #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP stack_t stk; # if defined HAVE_THR_STKSEGMENT CHECK_ERR(thr_stksegment(&stk)); # else CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk)); # endif *addr = stk.ss_sp; *size = stk.ss_size; #elif defined HAVE_PTHREAD_GETTHRDS_NP pthread_t th = pthread_self(); struct __pthrdsinfo thinfo; char reg[256]; int regsiz=sizeof(reg); CHECK_ERR(pthread_getthrds_np(&th, PTHRDSINFO_QUERY_ALL, &thinfo, sizeof(thinfo), ®, ®siz)); *addr = thinfo.__pi_stackaddr; *size = thinfo.__pi_stacksize; #endif return 0; #undef CHECK_ERR }
static int get_stack(void **addr, size_t *size) { #define CHECK_ERR(expr) \ {int err = (expr); if (err) return err;} #if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP pthread_attr_t attr; size_t guard = 0; # ifdef HAVE_PTHREAD_GETATTR_NP CHECK_ERR(pthread_getattr_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif if (pthread_attr_getguardsize(&attr, &guard) == 0) { STACK_GROW_DIR_DETECTION; STACK_DIR_UPPER((void)0, *addr = (char *)*addr + guard); *size -= guard; } # else CHECK_ERR(pthread_attr_init(&attr)); CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr)); CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); # ifndef HAVE_PTHREAD_GETATTR_NP pthread_attr_destroy(&attr); # endif size -= guard; #elif defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP pthread_t th = pthread_self(); *addr = pthread_get_stackaddr_np(th); *size = pthread_get_stacksize_np(th); #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP stack_t stk; # if defined HAVE_THR_STKSEGMENT CHECK_ERR(thr_stksegment(&stk)); # else CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk)); # endif *addr = stk.ss_sp; *size = stk.ss_size; #endif return 0; #undef CHECK_ERR }
/* Reads guard size attribute */ void read_guard_attribute(pthread_attr_t *attr) { size_t guardsize; pthread_attr_getguardsize(attr,&guardsize); printf("\n Guard Attribute"); printf("\n\tGuard Size=%u\n", guardsize); }
int main (void) { pthread_t thread; int rv; pthread_attr_t attr; size_t stacksize, guardsize; char *stackaddr; pthread_attr_init(&attr); /* 起始化執行緒屬性物件*/ /* 申請用作執行緒堆疊的空間 */ stackaddr = (void *)thread_stack_alloc(PTHREAD_STACK_MIN); /* 設定執行緒屬性物件中的堆疊位址和大小 */ rv = pthread_attr_setstack(&attr, stackaddr, PTHREAD_STACK_MIN); check_error(rv, "pthread_setstack()"); /* 檢視堆疊屬性值 */ pthread_attr_getstack(&attr, (void *)&stackaddr, &stacksize); pthread_attr_getguardsize(&attr, &guardsize); printf("stack attributes: stackaddr=%d, stacksize=%d, guardsize=%d\n", stackaddr, stacksize, guardsize); /* 建立執行緒 */ rv = pthread_create(&thread, &attr, (void *(*)())Hello, (void *)NULL); check_error(rv, "pthread_create()"); pthread_attr_destroy(&attr); /* 及時銷毀執行緒屬性物件,避免再次使用 */ check_error(rv, "pthread_attr_destroy()"); /* ... 後繼程式程式碼 ... */ pthread_exit(NULL); }
void AsyncFuncImpl::start() { struct rlimit rlim; m_node = Util::next_numa_node(); // Allocate the thread-stack pthread_attr_init(&m_attr); if (getrlimit(RLIMIT_STACK, &rlim) != 0 || rlim.rlim_cur == RLIM_INFINITY || rlim.rlim_cur < m_stackSizeMinimum) { rlim.rlim_cur = m_stackSizeMinimum; } // On Success use the allocated memory for the thread's stack if (posix_memalign(&m_threadStack, Util::s_pageSize, rlim.rlim_cur) == 0) { size_t guardsize; if (pthread_attr_getguardsize(&m_attr, &guardsize) == 0 && guardsize) { mprotect(m_threadStack, guardsize, PROT_NONE); } madvise(m_threadStack, rlim.rlim_cur, MADV_DONTNEED); Util::numa_bind_to(m_threadStack, rlim.rlim_cur, m_node); pthread_attr_setstack(&m_attr, m_threadStack, rlim.rlim_cur); } pthread_create(&m_threadId, &m_attr, ThreadFunc, (void*)this); assert(m_threadId); }
static void fct (union sigval s) { mqd_t q = *(mqd_t *) s.sival_ptr; pthread_attr_t nattr; int ret = pthread_getattr_np (pthread_self (), &nattr); if (ret) { errno = ret; printf ("pthread_getattr_np failed: %m\n"); fct_err = 1; } else { ret = pthread_attr_getguardsize (&nattr, &fct_guardsize); if (ret) { errno = ret; printf ("pthread_attr_getguardsize failed: %m\n"); fct_err = 1; } if (pthread_attr_destroy (&nattr) != 0) { puts ("pthread_attr_destroy failed"); fct_err = 1; } } ++fct_cnt; fct_err |= mqsend (q); }
void clone_attributes(pthread_attr_t *new_attr, pthread_attr_t *old_attr) { struct sched_param param; void *addr; size_t size; int value; (void) pthread_attr_init(new_attr); if (old_attr != NULL) { (void) pthread_attr_getstack(old_attr, &addr, &size); /* don't allow a non-NULL thread stack address */ (void) pthread_attr_setstack(new_attr, NULL, size); (void) pthread_attr_getscope(old_attr, &value); (void) pthread_attr_setscope(new_attr, value); (void) pthread_attr_getinheritsched(old_attr, &value); (void) pthread_attr_setinheritsched(new_attr, value); (void) pthread_attr_getschedpolicy(old_attr, &value); (void) pthread_attr_setschedpolicy(new_attr, value); (void) pthread_attr_getschedparam(old_attr, ¶m); (void) pthread_attr_setschedparam(new_attr, ¶m); (void) pthread_attr_getguardsize(old_attr, &size); (void) pthread_attr_setguardsize(new_attr, size); } /* make all pool threads be detached threads */ (void) pthread_attr_setdetachstate(new_attr, PTHREAD_CREATE_DETACHED); }
static void display_pthread_attr (pthread_attr_t *attr, char *prefix) { int s, i; size_t v; void *stkaddr; struct sched_param sp; s = pthread_attr_getdetachstate (attr, &i); if (s != 0) handle_error_en (s, "pthread_attr_getdetachstate"); printf ("%sDetach state = %s\n", prefix, (i == PTHREAD_CREATE_DETACHED) ? "PTHREAD_CREATE_DETACHED" : (i == PTHREAD_CREATE_JOINABLE) ? "PTHREAD_CREATE_JOINABLE" : "???"); s = pthread_attr_getscope (attr, &i); if (s != 0) handle_error_en (s, "pthread_attr_getscope"); printf ("%sScope = %s\n", prefix, (i == PTHREAD_SCOPE_SYSTEM) ? "PTHREAD_SCOPE_SYSTEM" : (i == PTHREAD_SCOPE_PROCESS) ? "PTHREAD_SCOPE_PROCESS" : "???"); s = pthread_attr_getinheritsched (attr, &i); if (s != 0) handle_error_en (s, "pthread_attr_getinheritsched"); printf ("%sInherit scheduler = %s\n", prefix, (i == PTHREAD_INHERIT_SCHED) ? "PTHREAD_INHERIT_SCHED" : (i == PTHREAD_EXPLICIT_SCHED) ? "PTHREAD_EXPLICIT_SCHED" : "???"); s = pthread_attr_getschedpolicy (attr, &i); if (s != 0) handle_error_en (s, "pthread_attr_getschedpolicy"); printf ("%sScheduling policy = %s\n", prefix, (i == SCHED_OTHER) ? "SCHED_OTHER" : (i == SCHED_FIFO) ? "SCHED_FIFO" : (i == SCHED_RR) ? "SCHED_RR" : "???"); s = pthread_attr_getschedparam (attr, &sp); if (s != 0) handle_error_en (s, "pthread_attr_getschedparam"); printf ("%sScheduling priority = %d\n", prefix, sp.sched_priority); s = pthread_attr_getguardsize (attr, &v); if (s != 0) handle_error_en (s, "pthread_attr_getguardsize"); printf ("%sGuard size = %ld bytes\n", prefix, v); s = pthread_attr_getstack (attr, &stkaddr, &v); if (s != 0) handle_error_en (s, "pthread_attr_getstack"); printf ("%sStack address = %p\n", prefix, stkaddr); printf ("%sStack size = 0x%zx bytes\n", prefix, v); }
size_t ThreadFactory::guardSize() const { size_t value = 0; int ret = pthread_attr_getguardsize(&attr_, &value); if (ret != 0) FTL_PTHREAD_EXCEPTION("pthread_attr_getguardsize", ret); return value; }
static int init_psd_structure(port_shared_data_t* data) { int err; pthread_attr_t pthread_attr; size_t stack_size, guard_size; memset(data, 0, sizeof(port_shared_data_t)); if ((err = pthread_key_create(&data->tls_key, NULL)) != 0) return err; if ((err = pthread_mutex_init(&data->suspend_mutex, NULL)) != 0) return err; if ((err = pthread_mutex_init(&data->suspend_init_mutex, NULL)) != 0) return err; pthread_attr_init(&pthread_attr); err = pthread_attr_getstacksize(&pthread_attr, &stack_size); pthread_attr_destroy(&pthread_attr); if (err != 0) return err; pthread_attr_init(&pthread_attr); err = pthread_attr_getguardsize(&pthread_attr, &guard_size); pthread_attr_destroy(&pthread_attr); if (err != 0) return err; if (sem_init(&data->yield_sem, 0, 0) != 0) return err; data->foreign_stack_size = stack_size; data->guard_page_size = guard_size; data->mem_protect_size = MEM_PROTECT_SIZE; data->req_type = THREADREQ_NONE; data->signal_set = FALSE; data->guard_stack_size = 64*1024; if (data->guard_stack_size < MINSIGSTKSZ) data->guard_stack_size = (MINSIGSTKSZ + guard_size - 1) & ~(guard_size - 1); return 0; }
/************************************************* * Function: Pthread_attr_getguradsize() * Description: 获取线程栈警戒缓冲区大小包裹函数 * Input: *attr---线程属性结构 * Output: *guardsize--线程栈警戒缓冲区大小 * Return: 0/errno *************************************************/ int Pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) { int rval; if(attr==AII_NULL || guardsize==AII_NULL) { return -1; } rval = pthread_attr_getguardsize(attr, guardsize); if (rval != 0) { debug_info(DEBUG_LEVEL_4,"Pthread_attr_getguardsize() failed!\n"); } return rval; }
void Thread::_poison_stack() { pthread_attr_t attr; size_t stack_size, guard_size; void *stackp; uint8_t *end, *start, *curr; uint32_t *p; if (pthread_getattr_np(_ctx, &attr) != 0 || pthread_attr_getstack(&attr, &stackp, &stack_size) != 0 || pthread_attr_getguardsize(&attr, &guard_size) != 0) { return; } /* The stack either grows upward or downard. The guard part always * protects the end */ end = (uint8_t *) stackp; start = end + stack_size; curr = (uint8_t *) alloca(sizeof(uint32_t)); /* if curr is closer to @end, the stack actually grows from low to high * virtual address: this is because this function should be executing very * early in the thread's life and close to the thread creation, assuming * the actual stack size is greater than the guard size and the stack * until now is resonably small */ if (abs(curr - start) > abs(curr - end)) { std::swap(end, start); end -= guard_size; for (p = (uint32_t *) end; p > (uint32_t *) curr; p--) { *p = STACK_POISON; } } else { end += guard_size; for (p = (uint32_t *) end; p < (uint32_t *) curr; p++) { *p = STACK_POISON; } } _stack_debug.start = (uint32_t *) start; _stack_debug.end = (uint32_t *) end; }
static void thr2 (union sigval sigval) { pthread_attr_t nattr; int err = 0; size_t guardsize = -1; int ret = pthread_getattr_np (pthread_self (), &nattr); if (ret) { errno = ret; printf ("*** pthread_getattr_np failed: %m\n"); err = 1; } else { ret = pthread_attr_getguardsize (&nattr, &guardsize); if (ret) { errno = ret; printf ("*** pthread_attr_getguardsize failed: %m\n"); err = 1; } if (pthread_attr_destroy (&nattr) != 0) { puts ("*** pthread_attr_destroy failed"); err = 1; } } pthread_mutex_lock (&lock); thr2_err = clock_gettime (TEST_CLOCK, &thr2_ts) | err; if (thr2_cnt >= 5) { struct itimerspec it = { }; thr2_err |= timer_settime (timer_thr2, 0, &it, NULL); } thr2_sigval = sigval; ++thr2_cnt; thr2_guardsize = guardsize; pthread_cond_signal (&cond); pthread_mutex_unlock (&lock); }
void *AsyncFuncImpl::ThreadFunc(void *obj) { pthread_attr_t *attr; size_t stacksize, guardsize; void *stackaddr; attr = ((AsyncFuncImpl*)obj)->getThreadAttr(); pthread_attr_getstack(attr, &stackaddr, &stacksize); // Get the guard page's size, because the stack address returned // above starts at the guard page, so the thread's stack limit is // stackaddr + guardsize. if (pthread_attr_getguardsize(attr, &guardsize) != 0) guardsize = 0; ASSERT(stackaddr != NULL); ASSERT(stacksize >= PTHREAD_STACK_MIN); Util::s_stackLimit = uintptr_t(stackaddr) + guardsize; Util::s_stackSize = stacksize; ((AsyncFuncImpl*)obj)->threadFuncImpl(); return NULL; }
static void display_stack_related_attributes(pthread_attr_t *attr, char *prefix) { int s; size_t stack_size, guard_size; void *stack_addr; s = pthread_attr_getguardsize(attr, &guard_size); if (s != 0) handle_error_en(s, "pthread_attr_getguardsize"); printf("%sGuard size = %lu bytes\n", prefix, guard_size); s = pthread_attr_getstack(attr, &stack_addr, &stack_size); if (s != 0) handle_error_en(s, "pthread_attr_getstack"); printf("%sStack address = %p", prefix, stack_addr); if (stack_size > 0) printf(" (EOS = %p)", (char *) stack_addr + stack_size); printf("\n"); printf("%sStack size = 0x%lx (%lu) bytes\n", prefix, stack_size, stack_size); }
static int print_thread_attr(pthread_attr_t *attr) { if (attr == NULL) { return THREAD_ATTR_FAILED; } int detach_state = 0; int ret = 0; char *stack_addr = NULL; size_t stack_size = 0; size_t guard_size = 0; ret = pthread_attr_getdetachstate(attr, &detach_state); if (detach_state == PTHREAD_CREATE_JOINABLE) { printf("Thread detach state: JOINABLE\n"); } else if (detach_state == PTHREAD_CREATE_DETACHED) { printf("Thread detach state: DETACHED\n"); } ret = pthread_attr_getstack(attr, (void**)&stack_addr, &stack_size); printf("stack_addr:%p, stack_size:%zd\n", stack_addr, stack_size); ret = pthread_attr_getstacksize(attr, &stack_size); printf("stack size:%#x\n", stack_size); ret = pthread_attr_getguardsize(attr, &guard_size); printf("guard size:%#x\n", guard_size); ret = pthread_getconcurrency(); printf("concurrency is %d\n", ret); return THREAD_ATTR_OK; }
/** * Determines the stack address of the current thread */ static void* getStackAddress(void) { void* result = NULL; size_t stackSize = 0; pthread_t self = pthread_self(); #if defined(DARWIN) result = pthread_get_stackaddr_np(self); stackSize = pthread_get_stacksize_np(self); // pthread_get_stackaddr_np returns the beginning (highest address) of the stack // while we want the address of the memory area allocated for the stack (lowest address). result -= stackSize; #else size_t guardSize = 0; pthread_attr_t attr; pthread_getattr_np(self, &attr); pthread_attr_getstack(&attr, &result, &stackSize); pthread_attr_getguardsize(&attr, &guardSize); // On Linux pthread_attr_getstack() returns the address of the memory area allocated for the stack // including the guard page (except for the main thread which returns the correct stack address and // pthread_attr_getguardsize() returns 0 even if there is a guard page). result += guardSize; #endif return result; }
bool AsyncFuncImpl::waitForEnd(int seconds /* = 0 */) { if (m_threadId == 0) return true; { Lock lock(m_stopMonitor.getMutex()); while (!m_stopped) { if (seconds > 0) { if (!m_stopMonitor.wait(seconds)) { // wait timed out return false; } } else { m_stopMonitor.wait(); } } } void *ret = nullptr; pthread_join(m_threadId, &ret); m_threadId = 0; if (m_threadStack != nullptr) { size_t guardsize; if (pthread_attr_getguardsize(&m_attr, &guardsize) == 0 && guardsize) { mprotect(m_threadStack, guardsize, PROT_READ | PROT_WRITE); } free(m_threadStack); m_threadStack = nullptr; } if (Exception* e = m_exception) { m_exception = 0; e->throwException(); } return true; }
int pth_attri_get (pth_attri_t *attri, pth_attr_types_t t, void *data) { if (attri != (pth_attri_t *)NULL) { switch (t) { /* pthread_attr_getdetachstate */ case PTH_ATTR_DETACHED: return pthread_attr_getdetachstate (&(attri->attr), (int *)data); /* pthread_attr_getdetachstate */ case PTH_ATTR_JOINABLE: return pthread_attr_getdetachstate (&(attri->attr), (int *)data); #ifndef LINUX /* pthread_attr_getstacksize */ case PTH_ATTR_STACKSZ: return pthread_attr_getstacksize (&(attri->attr), (size_t *)data); /* pthread_attr_getguardsize */ case PTH_ATTR_GUARDSZ: return pthread_attr_getguardsize (&(attri->attr), (size_t *)data); #endif /* !LINUX */ /* pthread_attr_getschedparam */ case PTH_ATTR_SCHEDPARAM: return pthread_attr_getschedparam (&(attri->attr), (struct sched_param *)data); /* pthread_attr_getinheritsched */ case PTH_ATTR_INSCHEDPARAM: return pthread_attr_getinheritsched (&(attri->attr), (int *)data); /* pthread_attr_getschedpolicy */ case PTH_ATTR_SCHEDPOLICY: return pthread_attr_getschedpolicy (&(attri->attr), (int *)data); /* pthread_attr_getscope */ case PTH_ATTR_SCOPE: return pthread_attr_getscope (&(attri->attr), (int *)data); default: return CAF_ERROR_SUB; } } return CAF_ERROR_SUB; }
static void display_stack_attr (pthread_attr_t *attr, char *prefix) { int s; size_t stack_size, guard_size, stack_size_check; void *stack_addr; s = pthread_attr_getguardsize(attr, &guard_size); if (s != 0) handle_error_en(s, "pthread_attr_getguardsize"); printf("%sGuard size = %d bytes\n", prefix, guard_size); s = pthread_attr_getstack(attr, &stack_addr, &stack_size); if (s != 0) handle_error_en(s, "pthread_attr_getstack"); printf("%sStack address = %p", prefix, stack_addr); if (stack_size > 0) printf(" (EOS = %p)", (char *) stack_addr + stack_size); printf("\n"); s = pthread_attr_getstacksize (attr, &stack_size_check); if (s != 0) handle_error_en(s, "pthread_attr_getstacksize"); assert (stack_size_check == stack_size); printf("%sStack size = 0x%x (%d) bytes\n", prefix, stack_size, stack_size); }
/* * Get the initial address and size of current thread's stack */ static int get_stack(void **addr, size_t *size) { #define CHECK_ERR(expr) \ {int err = (expr); if (err) return err;} #ifdef HAVE_PTHREAD_GETATTR_NP /* Linux */ pthread_attr_t attr; size_t guard = 0; STACK_GROW_DIR_DETECTION; CHECK_ERR(pthread_getattr_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); *size -= guard; pthread_attr_destroy(&attr); #elif defined HAVE_PTHREAD_ATTR_GET_NP /* FreeBSD, DragonFly BSD, NetBSD */ pthread_attr_t attr; CHECK_ERR(pthread_attr_init(&attr)); CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size)); pthread_attr_destroy(&attr); #elif (defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP) /* MacOS X */ pthread_t th = pthread_self(); *addr = pthread_get_stackaddr_np(th); *size = pthread_get_stacksize_np(th); #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP stack_t stk; # if defined HAVE_THR_STKSEGMENT /* Solaris */ CHECK_ERR(thr_stksegment(&stk)); # else /* OpenBSD */ CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk)); # endif *addr = stk.ss_sp; *size = stk.ss_size; #elif defined HAVE_PTHREAD_GETTHRDS_NP /* AIX */ pthread_t th = pthread_self(); struct __pthrdsinfo thinfo; char reg[256]; int regsiz=sizeof(reg); CHECK_ERR(pthread_getthrds_np(&th, PTHRDSINFO_QUERY_ALL, &thinfo, sizeof(thinfo), ®, ®siz)); *addr = thinfo.__pi_stackaddr; *size = thinfo.__pi_stacksize; STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size)); #else #error STACKADDR_AVAILABLE is defined but not implemented. #endif return 0; #undef CHECK_ERR }
static int do_test (void) { int result = 0; pthread_attr_t a; cpu_set_t c1, c2; int err = pthread_attr_init (&a); if (err) { error (0, err, "pthread_attr_init failed"); result = 1; } err = pthread_attr_getaffinity_np (&a, sizeof (c1), &c1); if (err && err != ENOSYS) { error (0, err, "pthread_attr_getaffinity_np failed"); result = 1; } err = pthread_attr_destroy (&a); if (err) { error (0, err, "pthread_attr_destroy failed"); result = 1; } err = pthread_getattr_np (pthread_self (), &a); if (err) { error (0, err, "pthread_getattr_np failed"); result = 1; } int detachstate; err = pthread_attr_getdetachstate (&a, &detachstate); if (err) { error (0, err, "pthread_attr_getdetachstate failed"); result = 1; } else if (detachstate != PTHREAD_CREATE_JOINABLE) { error (0, 0, "initial thread not joinable"); result = 1; } void *stackaddr; size_t stacksize; err = pthread_attr_getstack (&a, &stackaddr, &stacksize); if (err) { error (0, err, "pthread_attr_getstack failed"); result = 1; } else if ((void *) &a < stackaddr || (void *) &a >= stackaddr + stacksize) { error (0, 0, "pthread_attr_getstack returned range does not cover main's stack"); result = 1; } else printf ("initial thread stack %p-%p (0x%zx)\n", stackaddr, stackaddr + stacksize, stacksize); size_t guardsize; err = pthread_attr_getguardsize (&a, &guardsize); if (err) { error (0, err, "pthread_attr_getguardsize failed"); result = 1; } else if (guardsize != 0) { error (0, 0, "pthread_attr_getguardsize returned %zd != 0", guardsize); result = 1; } int scope; err = pthread_attr_getscope (&a, &scope); if (err) { error (0, err, "pthread_attr_getscope failed"); result = 1; } else if (scope != PTHREAD_SCOPE_SYSTEM) { error (0, 0, "pthread_attr_getscope returned %d != PTHREAD_SCOPE_SYSTEM", scope); result = 1; } int inheritsched; err = pthread_attr_getinheritsched (&a, &inheritsched); if (err) { error (0, err, "pthread_attr_getinheritsched failed"); result = 1; } else if (inheritsched != PTHREAD_INHERIT_SCHED) { error (0, 0, "pthread_attr_getinheritsched returned %d != PTHREAD_INHERIT_SCHED", inheritsched); result = 1; } err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1); if (err == 0) { err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2); if (err) { error (0, err, "pthread_attr_getaffinity_np failed"); result = 1; } else if (memcmp (&c1, &c2, sizeof (c1))) { error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np"); result = 1; } } err = pthread_attr_destroy (&a); if (err) { error (0, err, "pthread_attr_destroy failed"); result = 1; } pthread_t th; err = pthread_create (&th, NULL, tf, NULL); if (err) { error (0, err, "pthread_create #1 failed"); result = 1; } else { void *ret; err = pthread_join (th, &ret); if (err) { error (0, err, "pthread_join #1 failed"); result = 1; } else if (ret != NULL) result = 1; } err = pthread_attr_init (&a); if (err) { error (0, err, "pthread_attr_init failed"); result = 1; } DIAG_PUSH_NEEDS_COMMENT; #if __GNUC_PREREQ (7, 0) /* GCC 8 warns about aliasing of the restrict-qualified arguments passed &a. Since pthread_create does not dereference its fourth argument, this aliasing, which is deliberate in this test, cannot in fact cause problems. */ DIAG_IGNORE_NEEDS_COMMENT (8, "-Wrestrict"); #endif err = pthread_create (&th, &a, tf, &a); DIAG_POP_NEEDS_COMMENT; if (err) { error (0, err, "pthread_create #2 failed"); result = 1; } else { void *ret; err = pthread_join (th, &ret); if (err) { error (0, err, "pthread_join #2 failed"); result = 1; } else if (ret != NULL) result = 1; } err = pthread_attr_setguardsize (&a, 16 * sysconf (_SC_PAGESIZE)); if (err) { error (0, err, "pthread_attr_setguardsize failed"); result = 1; } DIAG_PUSH_NEEDS_COMMENT; #if __GNUC_PREREQ (7, 0) /* GCC 8 warns about aliasing of the restrict-qualified arguments passed &a. Since pthread_create does not dereference its fourth argument, this aliasing, which is deliberate in this test, cannot in fact cause problems. */ DIAG_IGNORE_NEEDS_COMMENT (8, "-Wrestrict"); #endif err = pthread_create (&th, &a, tf, &a); DIAG_POP_NEEDS_COMMENT; if (err) { error (0, err, "pthread_create #3 failed"); result = 1; } else { void *ret; err = pthread_join (th, &ret); if (err) { error (0, err, "pthread_join #3 failed"); result = 1; } else if (ret != NULL) result = 1; } err = pthread_attr_destroy (&a); if (err) { error (0, err, "pthread_attr_destroy failed"); result = 1; } return result; }
static void* GetActualGuardSizeFn(void* arg) { pthread_attr_t attributes; pthread_getattr_np(pthread_self(), &attributes); pthread_attr_getguardsize(&attributes, reinterpret_cast<size_t*>(arg)); return NULL; }
static int my_pthread_attr_getguardsize(pthread_attr_t const *__attr, size_t *guard_size) { pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; return pthread_attr_getguardsize(realattr, guard_size); }
static int do_test (void) { int result = 0; pthread_attr_t a; cpu_set_t c1, c2; int err = pthread_attr_init (&a); if (err) { error (0, err, "pthread_attr_init failed"); result = 1; } err = pthread_attr_getaffinity_np (&a, sizeof (c1), &c1); if (err && err != ENOSYS) { error (0, err, "pthread_attr_getaffinity_np failed"); result = 1; } err = pthread_attr_destroy (&a); if (err) { error (0, err, "pthread_attr_destroy failed"); result = 1; } err = pthread_getattr_np (pthread_self (), &a); if (err) { error (0, err, "pthread_getattr_np failed"); result = 1; } int detachstate; err = pthread_attr_getdetachstate (&a, &detachstate); if (err) { error (0, err, "pthread_attr_getdetachstate failed"); result = 1; } else if (detachstate != PTHREAD_CREATE_JOINABLE) { error (0, 0, "initial thread not joinable"); result = 1; } void *stackaddr; size_t stacksize; err = pthread_attr_getstack (&a, &stackaddr, &stacksize); if (err) { error (0, err, "pthread_attr_getstack failed"); result = 1; } else if ((void *) &a < stackaddr || (void *) &a >= stackaddr + stacksize) { error (0, 0, "pthread_attr_getstack returned range does not cover main's stack"); result = 1; } else printf ("initial thread stack %p-%p (0x%zx)\n", stackaddr, stackaddr + stacksize, stacksize); size_t guardsize; err = pthread_attr_getguardsize (&a, &guardsize); if (err) { error (0, err, "pthread_attr_getguardsize failed"); result = 1; } else if (guardsize != 0) { error (0, 0, "pthread_attr_getguardsize returned %zd != 0", guardsize); result = 1; } int scope; err = pthread_attr_getscope (&a, &scope); if (err) { error (0, err, "pthread_attr_getscope failed"); result = 1; } else if (scope != PTHREAD_SCOPE_SYSTEM) { error (0, 0, "pthread_attr_getscope returned %d != PTHREAD_SCOPE_SYSTEM", scope); result = 1; } int inheritsched; err = pthread_attr_getinheritsched (&a, &inheritsched); if (err) { error (0, err, "pthread_attr_getinheritsched failed"); result = 1; } else if (inheritsched != PTHREAD_INHERIT_SCHED) { error (0, 0, "pthread_attr_getinheritsched returned %d != PTHREAD_INHERIT_SCHED", inheritsched); result = 1; } err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1); if (err == 0) { err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2); if (err) { error (0, err, "pthread_attr_getaffinity_np failed"); result = 1; } else if (memcmp (&c1, &c2, sizeof (c1))) { error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np"); result = 1; } } err = pthread_attr_destroy (&a); if (err) { error (0, err, "pthread_attr_destroy failed"); result = 1; } pthread_t th; err = pthread_create (&th, NULL, tf, NULL); if (err) { error (0, err, "pthread_create #1 failed"); result = 1; } else { void *ret; err = pthread_join (th, &ret); if (err) { error (0, err, "pthread_join #1 failed"); result = 1; } else if (ret != NULL) result = 1; } err = pthread_attr_init (&a); if (err) { error (0, err, "pthread_attr_init failed"); result = 1; } err = pthread_create (&th, &a, tf, &a); if (err) { error (0, err, "pthread_create #2 failed"); result = 1; } else { void *ret; err = pthread_join (th, &ret); if (err) { error (0, err, "pthread_join #2 failed"); result = 1; } else if (ret != NULL) result = 1; } err = pthread_attr_setguardsize (&a, 16 * sysconf (_SC_PAGESIZE)); if (err) { error (0, err, "pthread_attr_setguardsize failed"); result = 1; } err = pthread_create (&th, &a, tf, &a); if (err) { error (0, err, "pthread_create #3 failed"); result = 1; } else { void *ret; err = pthread_join (th, &ret); if (err) { error (0, err, "pthread_join #3 failed"); result = 1; } else if (ret != NULL) result = 1; } err = pthread_attr_destroy (&a); if (err) { error (0, err, "pthread_attr_destroy failed"); result = 1; } return result; }
static void * tf (void *arg) { pthread_attr_t a, *ap, a2; int err; void *result = NULL; if (arg == NULL) { ap = &a2; err = pthread_attr_init (ap); if (err) { error (0, err, "pthread_attr_init failed"); return tf; } } else ap = (pthread_attr_t *) arg; err = pthread_getattr_np (pthread_self (), &a); if (err) { error (0, err, "pthread_getattr_np failed"); result = tf; } int detachstate1, detachstate2; err = pthread_attr_getdetachstate (&a, &detachstate1); if (err) { error (0, err, "pthread_attr_getdetachstate failed"); result = tf; } else { err = pthread_attr_getdetachstate (ap, &detachstate2); if (err) { error (0, err, "pthread_attr_getdetachstate failed"); result = tf; } else if (detachstate1 != detachstate2) { error (0, 0, "detachstate differs %d != %d", detachstate1, detachstate2); result = tf; } } void *stackaddr; size_t stacksize; err = pthread_attr_getstack (&a, &stackaddr, &stacksize); if (err) { error (0, err, "pthread_attr_getstack failed"); result = tf; } else if ((void *) &a < stackaddr || (void *) &a >= stackaddr + stacksize) { error (0, 0, "pthread_attr_getstack returned range does not cover thread's stack"); result = tf; } else printf ("thread stack %p-%p (0x%zx)\n", stackaddr, stackaddr + stacksize, stacksize); size_t guardsize1, guardsize2; err = pthread_attr_getguardsize (&a, &guardsize1); if (err) { error (0, err, "pthread_attr_getguardsize failed"); result = tf; } else { err = pthread_attr_getguardsize (ap, &guardsize2); if (err) { error (0, err, "pthread_attr_getguardsize failed"); result = tf; } else if (guardsize1 != guardsize2) { error (0, 0, "guardsize differs %zd != %zd", guardsize1, guardsize2); result = tf; } else printf ("thread guardsize %zd\n", guardsize1); } int scope1, scope2; err = pthread_attr_getscope (&a, &scope1); if (err) { error (0, err, "pthread_attr_getscope failed"); result = tf; } else { err = pthread_attr_getscope (ap, &scope2); if (err) { error (0, err, "pthread_attr_getscope failed"); result = tf; } else if (scope1 != scope2) { error (0, 0, "scope differs %d != %d", scope1, scope2); result = tf; } } int inheritsched1, inheritsched2; err = pthread_attr_getinheritsched (&a, &inheritsched1); if (err) { error (0, err, "pthread_attr_getinheritsched failed"); result = tf; } else { err = pthread_attr_getinheritsched (ap, &inheritsched2); if (err) { error (0, err, "pthread_attr_getinheritsched failed"); result = tf; } else if (inheritsched1 != inheritsched2) { error (0, 0, "inheritsched differs %d != %d", inheritsched1, inheritsched2); result = tf; } } cpu_set_t c1, c2; err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1); if (err == 0) { err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2); if (err) { error (0, err, "pthread_attr_getaffinity_np failed"); result = tf; } else if (memcmp (&c1, &c2, sizeof (c1))) { error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np"); result = tf; } } err = pthread_attr_destroy (&a); if (err) { error (0, err, "pthread_attr_destroy failed"); result = tf; } if (ap == &a2) { err = pthread_attr_destroy (ap); if (err) { error (0, err, "pthread_attr_destroy failed"); result = tf; } } return result; }
void *POSIX_Init( void *argument ) { int status; int scope; int inheritsched; int schedpolicy; size_t stacksize; #if HAVE_DECL_PTHREAD_ATTR_SETGUARDSIZE size_t guardsize; #endif void *stackaddr; int detachstate; struct sched_param schedparam; pthread_attr_t attr; pthread_attr_t destroyed_attr; TEST_BEGIN(); /* set the time of day, and print our buffer in multiple ways */ set_time( TM_FRIDAY, TM_MAY, 24, 96, 11, 5, 0 ); /* get id of this thread */ Init_id = pthread_self(); printf( "Init's ID is 0x%08" PRIxpthread_t "\n", Init_id ); /* exercise init and destroy */ puts( "Init - pthread_attr_init - EINVAL (NULL attr)" ); status = pthread_attr_init( NULL ); fatal_directive_check_status_only( status, EINVAL, "null attribute" ); puts( "Init - pthread_attr_init - SUCCESSFUL" ); status = pthread_attr_init( &attr ); posix_service_failed( status, "pthread_attr_init" ); puts( "Init - initialize and destroy an attribute - SUCCESSFUL" ); status = pthread_attr_init( &destroyed_attr ); posix_service_failed( status, "pthread_attr_init"); status = pthread_attr_destroy( &destroyed_attr ); posix_service_failed( status, "pthread_attr_destroy"); puts( "Init - pthread_attr_destroy - EINVAL (NULL attr)" ); status = pthread_attr_destroy( NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL attribute" ); puts( "Init - pthread_attr_destroy - EINVAL (not initialized)" ); status = pthread_attr_destroy( &destroyed_attr ); fatal_directive_check_status_only( status, EINVAL, "not initialized" ); /* check some errors in pthread_create */ puts( "Init - pthread_create - EINVAL (attr not initialized)" ); status = pthread_create( &Task_id, &destroyed_attr, Task_1, NULL ); fatal_directive_check_status_only( status, EINVAL, "attribute not initialized" ); /* junk stack address */ status = pthread_attr_setstackaddr( &attr, (void *)&schedparam ); posix_service_failed( status, "setstackaddr"); /* must go around pthread_attr_setstacksize to set a bad stack size */ attr.stacksize = 0; puts( "Init - pthread_create - EINVAL (stacksize too small)" ); status = pthread_create( &Task_id, &attr, Task_1, NULL ); fatal_directive_check_status_only( status, EINVAL, "stacksize too small" ); /* reset all the fields */ status = pthread_attr_init( &attr ); posix_service_failed( status, "pthread_attr_init"); #if HAVE_DECL_PTHREAD_ATTR_SETSTACKADDR attr.stacksize = rtems_configuration_get_work_space_size() * 10; puts( "Init - pthread_create - EAGAIN (stacksize too large)" ); status = pthread_create( &Task_id, &attr, Task_1, NULL ); fatal_directive_check_status_only( status, EAGAIN, "stacksize too large" ); #endif status = pthread_attr_init( &attr ); posix_service_failed( status, "pthread_attr_init"); /* must go around pthread_attr_set routines to set a bad value */ attr.inheritsched = -1; puts( "Init - pthread_create - EINVAL (invalid inherit scheduler)" ); status = pthread_create( &Task_id, &attr, Task_1, NULL ); fatal_directive_check_status_only( status, EINVAL, "invalid inherit scheduler" ); /* check out the error case for system scope not supported */ status = pthread_attr_init( &attr ); posix_service_failed( status, " pthread_attr_init"); /* must go around pthread_attr_set routines to set a bad value */ attr.contentionscope = PTHREAD_SCOPE_SYSTEM; puts( "Init - pthread_create - ENOTSUP (unsupported system contention scope)" ); status = pthread_create( &Task_id, &attr, Task_1, NULL ); fatal_directive_check_status_only( status, ENOTSUP, "unsupported system contention scope" ); status = pthread_attr_init( &attr ); posix_service_failed( status, "pthread_attr_init"); /* now check out pthread_create for inherit scheduler */ status = pthread_attr_setinheritsched( &attr, PTHREAD_INHERIT_SCHED ); posix_service_failed( status, "pthread_attr_setinheritsched"); puts( "Init - pthread_create - SUCCESSFUL (inherit scheduler)" ); status = pthread_create( &Task_id, &attr, Task_1, NULL ); posix_service_failed( status, "pthread_create"); status = pthread_join( Task_id, NULL ); posix_service_failed( status, " pthread_join"); /* switch to Task_1 */ /* exercise get and set scope */ empty_line(); status = pthread_attr_init( &attr ); posix_service_failed( status, "pthread_attr_init"); puts( "Init - pthread_attr_setscope - EINVAL (NULL attr)" ); status = pthread_attr_setscope( NULL, PTHREAD_SCOPE_PROCESS ); fatal_directive_check_status_only( status, EINVAL , "NULL attr" ); puts( "Init - pthread_attr_setscope - ENOTSUP" ); status = pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); fatal_directive_check_status_only( status, ENOTSUP, "PTHREAD_SCOPE_SYSTEM" ); puts( "Init - pthread_attr_setscope - EINVAL (not initialized attr)" ); status = pthread_attr_setscope( &destroyed_attr, PTHREAD_SCOPE_PROCESS ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_setscope - EINVAL (invalid scope)" ); status = pthread_attr_setscope( &attr, -1 ); fatal_directive_check_status_only( status, EINVAL, "invalid scope" ); puts( "Init - pthread_attr_setscope - SUCCESSFUL" ); status = pthread_attr_setscope( &attr, PTHREAD_SCOPE_PROCESS ); posix_service_failed( status, "pthread_attr_setscope"); puts( "Init - pthread_attr_getscope - EINVAL (NULL attr)" ); status = pthread_attr_getscope( NULL, &scope ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_getscope - EINVAL (NULL scope)" ); status = pthread_attr_getscope( &attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL scope" ); puts( "Init - pthread_attr_getscope - EINVAL (not initialized attr)" ); status = pthread_attr_getscope( &destroyed_attr, &scope ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_getscope - SUCCESSFUL" ); status = pthread_attr_getscope( &attr, &scope ); posix_service_failed( status, "pthread_attr_getscope"); printf( "Init - current scope attribute = %d\n", scope ); /* exercise get and set inherit scheduler */ empty_line(); puts( "Init - pthread_attr_setinheritsched - EINVAL (NULL attr)" ); status = pthread_attr_setinheritsched( NULL, PTHREAD_INHERIT_SCHED ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_setinheritsched - EINVAL (not initialized attr)" ); status = pthread_attr_setinheritsched( &destroyed_attr, PTHREAD_INHERIT_SCHED ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_setinheritsched - ENOTSUP (invalid inheritsched)" ); status = pthread_attr_setinheritsched( &attr, -1 ); fatal_directive_check_status_only( status, ENOTSUP, "invalid inheritsched" ); puts( "Init - pthread_attr_setinheritsched - SUCCESSFUL" ); status = pthread_attr_setinheritsched( &attr, PTHREAD_INHERIT_SCHED ); posix_service_failed( status, "pthread_attr_setinheritsched"); puts( "Init - pthread_attr_getinheritsched - EINVAL (NULL attr)" ); status = pthread_attr_getinheritsched( NULL, &inheritsched ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_getinheritsched - EINVAL (NULL inheritsched)" ); status = pthread_attr_getinheritsched( &attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL inheritsched" ); puts( "Init - pthread_attr_getinheritsched - EINVAL (not initialized attr)" ); status = pthread_attr_getinheritsched( &destroyed_attr, &inheritsched ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_getinheritsched - SUCCESSFUL" ); status = pthread_attr_getinheritsched( &attr, &inheritsched ); posix_service_failed( status, "pthread_attr_getinheritsched"); printf( "Init - current inherit scheduler attribute = %d\n", inheritsched ); /* exercise get and set inherit scheduler */ empty_line(); puts( "Init - pthread_attr_setschedpolicy - EINVAL (NULL attr)" ); status = pthread_attr_setschedpolicy( NULL, SCHED_FIFO ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_setschedpolicy - EINVAL (not initialized attr)" ); status = pthread_attr_setschedpolicy( &destroyed_attr, SCHED_OTHER ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_setschedpolicy - ENOTSUP (invalid schedpolicy)" ); status = pthread_attr_setschedpolicy( &attr, -1 ); fatal_directive_check_status_only( status, ENOTSUP, "invalid schedpolicy" ); puts( "Init - pthread_attr_setschedpolicy - SUCCESSFUL" ); status = pthread_attr_setschedpolicy( &attr, SCHED_RR ); posix_service_failed( status, "pthread_attr_setschedpolicy"); puts( "Init - pthread_attr_getschedpolicy - EINVAL (NULL attr)" ); status = pthread_attr_getschedpolicy( NULL, &schedpolicy ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_getschedpolicy - EINVAL (NULL schedpolicy)" ); status = pthread_attr_getschedpolicy( &attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL schedpolicy" ); puts( "Init - pthread_attr_getschedpolicy - EINVAL (not initialized attr)" ); status = pthread_attr_getschedpolicy( &destroyed_attr, &schedpolicy ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_getschedpolicy - SUCCESSFUL" ); status = pthread_attr_getschedpolicy( &attr, &schedpolicy ); posix_service_failed( status, "pthread_attr_getschedpolicy"); printf( "Init - current scheduler policy attribute = %d\n", schedpolicy ); /* exercise get and set stack size */ empty_line(); puts( "Init - pthread_attr_setstacksize - EINVAL (NULL attr)" ); status = pthread_attr_setstacksize( NULL, 0 ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_setstacksize - EINVAL (not initialized attr)" ); status = pthread_attr_setstacksize( &destroyed_attr, 0 ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_setstacksize - SUCCESSFUL (low stacksize)" ); status = pthread_attr_setstacksize( &attr, 0 ); posix_service_failed( status, "pthread_attr_setstacksize"); puts( "Init - pthread_attr_setstacksize - SUCCESSFUL (high stacksize)" ); status = pthread_attr_setstacksize( &attr, STACK_MINIMUM_SIZE * 2 ); posix_service_failed( status, ""); puts( "Init - pthread_attr_getstacksize - EINVAL (NULL attr)" ); status = pthread_attr_getstacksize( NULL, &stacksize ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_getstacksize - EINVAL (NULL stacksize)" ); status = pthread_attr_getstacksize( &attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL stacksize" ); puts( "Init - pthread_attr_getstacksize - EINVAL (not initialized attr)" ); status = pthread_attr_getstacksize( &destroyed_attr, &stacksize ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_getstacksize - SUCCESSFUL" ); status = pthread_attr_getstacksize( &attr, &stacksize ); posix_service_failed( status, "pthread_attr_getstacksize"); if ( stacksize == (STACK_MINIMUM_SIZE * 2) ) printf( "Init - current stack size attribute is OK\n" ); /* exercise get and set stack address */ empty_line(); puts( "Init - pthread_attr_setstackaddr - EINVAL (NULL attr)" ); status = pthread_attr_setstackaddr( NULL, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_setstackaddr - EINVAL (not initialized attr)" ); status = pthread_attr_setstackaddr( &destroyed_attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_setstackaddr - SUCCESSFUL" ); status = pthread_attr_setstackaddr( &attr, 0 ); posix_service_failed( status, ""); /* get stack addr */ puts( "Init - pthread_attr_getstackaddr - EINVAL (NULL attr)" ); status = pthread_attr_getstackaddr( NULL, &stackaddr ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_getstackaddr - EINVAL (NULL stackaddr)" ); status = pthread_attr_getstackaddr( &attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL stackaddr" ); puts( "Init - pthread_attr_getstackaddr - EINVAL (not initialized attr)" ); status = pthread_attr_getstackaddr( &destroyed_attr, &stackaddr ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_getstackaddr - SUCCESSFUL" ); status = pthread_attr_getstackaddr( &attr, &stackaddr ); posix_service_failed( status, "pthread_attr_getstackaddr"); printf( "Init - current stack address attribute = %p\n", stackaddr ); /* exercise get and set stack (as pair) */ empty_line(); #if HAVE_DECL_PTHREAD_ATTR_SETSTACK puts( "Init - pthread_attr_setstack- EINVAL (NULL attr)" ); status = pthread_attr_setstack( NULL, &stackaddr, 1024 ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_setstack- EINVAL (destroyed attr)" ); status = pthread_attr_setstack( &destroyed_attr, &stackaddr, 1024 ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_setstack- SUCCESSFUL (< min stack)" ); status = pthread_attr_setstack( &attr, stackaddr, 0 ); posix_service_failed( status, "OK"); puts( "Init - pthread_attr_setstack- SUCCESSFUL (big stack)" ); status = pthread_attr_setstack( &attr, stackaddr, STACK_MINIMUM_SIZE * 2 ); posix_service_failed( status, "OK"); #endif #if HAVE_DECL_PTHREAD_ATTR_GETSTACK puts( "Init - pthread_attr_getstack- EINVAL (NULL attr)" ); status = pthread_attr_getstack( NULL, &stackaddr, &stacksize ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_getstack- EINVAL (destroyed attr)" ); status = pthread_attr_getstack( &destroyed_attr, &stackaddr, &stacksize ); fatal_directive_check_status_only( status, EINVAL, "&destroyed attr" ); puts( "Init - pthread_attr_getstack- EINVAL (NULL stack)" ); status = pthread_attr_getstack( &attr, NULL, &stacksize ); fatal_directive_check_status_only( status, EINVAL, "&NULL stack" ); puts( "Init - pthread_attr_getstack- EINVAL (NULL stacksize)" ); status = pthread_attr_getstack( &attr, &stackaddr, NULL ); fatal_directive_check_status_only( status, EINVAL, "&NULL size" ); puts( "Init - pthread_attr_getstack- SUCCESSFUL" ); status = pthread_attr_getstack( &attr, &stackaddr, &stacksize ); posix_service_failed( status, "pthread_attr_getstack"); #endif /* exercise get and set detach state */ empty_line(); #if HAVE_DECL_PTHREAD_ATTR_SETGUARDSIZE puts( "Init - pthread_attr_setguardsize - EINVAL (NULL attr)" ); status = pthread_attr_setguardsize( NULL, 0 ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_setguardsize - EINVAL (not initialized attr)" ); status = pthread_attr_setguardsize( &destroyed_attr, 0 ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_setguardsize - SUCCESSFUL (low guardsize)" ); status = pthread_attr_setguardsize( &attr, 0 ); posix_service_failed( status, "pthread_attr_setguardsize"); puts( "Init - pthread_attr_setguardsize - SUCCESSFUL (high guardsize)" ); status = pthread_attr_setguardsize( &attr, STACK_MINIMUM_SIZE * 2 ); posix_service_failed( status, ""); #endif #if HAVE_DECL_PTHREAD_ATTR_GETGUARDSIZE puts( "Init - pthread_attr_getguardsize - EINVAL (NULL attr)" ); status = pthread_attr_getguardsize( NULL, &guardsize ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_getguardsize - EINVAL (NULL guardsize)" ); status = pthread_attr_getguardsize( &attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL guardsize" ); puts( "Init - pthread_attr_getguardsize - EINVAL (not initialized attr)" ); status = pthread_attr_getguardsize( &destroyed_attr, &guardsize ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_getguardsize - SUCCESSFUL" ); status = pthread_attr_getguardsize( &attr, &guardsize ); posix_service_failed( status, "pthread_attr_getguardsize"); #endif /* exercise get and set detach state */ empty_line(); puts( "Init - pthread_attr_setdetachstate - EINVAL (NULL attr)" ); status = pthread_attr_setdetachstate( NULL, PTHREAD_CREATE_DETACHED ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_setdetachstate - EINVAL (not initialized attr)" ); status = pthread_attr_setdetachstate( &destroyed_attr, PTHREAD_CREATE_JOINABLE ); fatal_directive_check_status_only( status, EINVAL, "not initialized att" ); puts( "Init - pthread_attr_setdetachstate - EINVAL (invalid detachstate)" ); status = pthread_attr_setdetachstate( &attr, -1 ); fatal_directive_check_status_only( status, EINVAL, "invalid detachstate" ); puts( "Init - pthread_attr_setdetachstate - SUCCESSFUL" ); status = pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); posix_service_failed( status, "pthread_attr_setdetachstate"); puts( "Init - pthread_attr_getdetachstate - EINVAL (NULL attr)" ); status = pthread_attr_getdetachstate( NULL, &detachstate ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_getdetachstate - EINVAL (NULL detatchstate)" ); status = pthread_attr_getdetachstate( &attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL detatchstate" ); puts( "Init - pthread_attr_getdetachstate - EINVAL (not initialized attr)" ); status = pthread_attr_getdetachstate( &destroyed_attr, &detachstate ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_getdetachstate - SUCCESSFUL" ); status = pthread_attr_getdetachstate( &attr, &detachstate ); posix_service_failed( status, "pthread_attr_getdetachstate"); printf( "Init - current detach state attribute = %d\n", detachstate ); /* exercise get and set scheduling parameters */ empty_line(); puts( "Init - pthread_attr_getschedparam - SUCCESSFUL" ); status = pthread_attr_getschedparam( &attr, &schedparam ); posix_service_failed( status, "pthread_attr_getschedparam"); print_schedparam( "Init - ", &schedparam ); puts( "Init - pthread_attr_setschedparam - EINVAL (NULL attr)" ); status = pthread_attr_setschedparam( NULL, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "NULL attr" ); puts( "Init - pthread_attr_setschedparam - EINVAL (not initialized attr)" ); status = pthread_attr_setschedparam( &destroyed_attr, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_setschedparam - EINVAL (NULL schedparam)" ); status = pthread_attr_setschedparam( &attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL schedparam" ); puts( "Init - pthread_attr_setschedparam - SUCCESSFUL" ); status = pthread_attr_setschedparam( &attr, &schedparam ); posix_service_failed( status, "pthread_attr_setschedparam"); puts( "Init - pthread_attr_getschedparam - EINVAL (NULL attr)" ); status = pthread_attr_getschedparam( NULL, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "pthread_attr_getschedparam" ); puts( "Init - pthread_attr_getschedparam - EINVAL (not initialized attr)" ); status = pthread_attr_getschedparam( &destroyed_attr, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "not initialized attr" ); puts( "Init - pthread_attr_getschedparam - EINVAL (NULL schedparam)" ); status = pthread_attr_getschedparam( &attr, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL schedparam" ); /* exercise pthread_getschedparam */ empty_line(); puts( "Init - pthread_getschedparam - EINVAL (NULL policy)" ); status = pthread_getschedparam( pthread_self(), NULL, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "NULL policy" ); puts( "Init - pthread_getschedparam - EINVAL (NULL schedparam)" ); status = pthread_getschedparam( pthread_self(), &schedpolicy, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL schedparam" ); puts( "Init - pthread_getschedparam - ESRCH (bad thread)" ); status = pthread_getschedparam( (pthread_t) -1, &schedpolicy, &schedparam ); fatal_directive_check_status_only( status, ESRCH, "bad thread" ); puts( "Init - pthread_getschedparam - SUCCESSFUL" ); status = pthread_getschedparam( pthread_self(), &schedpolicy, &schedparam ); posix_service_failed( status, "pthread_getschedparam"); printf( "Init - policy = %d\n", schedpolicy ); print_schedparam( "Init - ", &schedparam ); /* exercise pthread_setschedparam */ empty_line(); puts( "Init - pthread_setschedparam - EINVAL (NULL schedparam)" ); status = pthread_setschedparam( pthread_self(), SCHED_OTHER, NULL ); fatal_directive_check_status_only( status, EINVAL, "NULL schedparam" ); schedparam.sched_priority = -1; puts( "Init - pthread_setschedparam - EINVAL (invalid priority)" ); status = pthread_setschedparam( pthread_self(), SCHED_OTHER, NULL ); fatal_directive_check_status_only( status, EINVAL, "invalid priority" ); /* reset sched_param */ status = pthread_getschedparam( pthread_self(), &schedpolicy, &schedparam ); posix_service_failed( status, "pthread_getschedparam"); puts( "Init - pthread_setschedparam - EINVAL (invalid policy)" ); status = pthread_setschedparam( pthread_self(), -1, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "invalid policy" ); puts( "Init - pthread_setschedparam - ESRCH (invalid thread)" ); status = pthread_setschedparam( (pthread_t) -1, SCHED_OTHER, &schedparam ); fatal_directive_check_status_only( status, ESRCH, "invalid thread" ); /* now get sporadic server errors */ schedparam.sched_ss_repl_period.tv_sec = 0; schedparam.sched_ss_repl_period.tv_nsec = 0; schedparam.sched_ss_init_budget.tv_sec = 1; schedparam.sched_ss_init_budget.tv_nsec = 1; puts( "Init - pthread_setschedparam - EINVAL (replenish == 0)" ); status = pthread_setschedparam( pthread_self(), SCHED_SPORADIC, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "replenish == 0" ); schedparam.sched_ss_repl_period.tv_sec = 1; schedparam.sched_ss_repl_period.tv_nsec = 1; schedparam.sched_ss_init_budget.tv_sec = 0; schedparam.sched_ss_init_budget.tv_nsec = 0; puts( "Init - pthread_setschedparam - EINVAL (budget == 0)" ); status = pthread_setschedparam( pthread_self(), SCHED_SPORADIC, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "budget == 0" ); schedparam.sched_ss_repl_period.tv_sec = 1; schedparam.sched_ss_repl_period.tv_nsec = 0; schedparam.sched_ss_init_budget.tv_sec = 1; schedparam.sched_ss_init_budget.tv_nsec = 1; puts( "Init - pthread_setschedparam - EINVAL (replenish < budget)" ); status = pthread_setschedparam( pthread_self(), SCHED_SPORADIC, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "replenish < budget" ); schedparam.sched_ss_repl_period.tv_sec = 2; schedparam.sched_ss_repl_period.tv_nsec = 0; schedparam.sched_ss_init_budget.tv_sec = 1; schedparam.sched_ss_init_budget.tv_nsec = 0; schedparam.sched_ss_low_priority = -1; puts( "Init - pthread_setschedparam - EINVAL (invalid priority)" ); status = pthread_setschedparam( pthread_self(), SCHED_SPORADIC, &schedparam ); fatal_directive_check_status_only( status, EINVAL, "invalid priority" ); /* * Create a sporadic thread that doesn't need it's priority * boosted */ empty_line(); puts( "Init - pthread_attr_init - SUCCESSFUL" ); status = pthread_attr_init( &attr ); posix_service_failed( status, "pthread_attr_init" ); puts( "Init - pthread_attr_setinheritsched - EXPLICIT - SUCCESSFUL" ); status = pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); rtems_test_assert( !status ); schedparam.sched_ss_repl_period.tv_sec = 3; schedparam.sched_ss_repl_period.tv_nsec = 3; schedparam.sched_ss_init_budget.tv_sec = 1; schedparam.sched_ss_init_budget.tv_nsec = 1; schedparam.sched_priority = sched_get_priority_max( SCHED_FIFO ); schedparam.sched_ss_low_priority = sched_get_priority_max( SCHED_FIFO ) - 6; puts( "Init - pthread_attr_setschedpolicy - SUCCESSFUL" ); status = pthread_attr_setschedpolicy( &attr, SCHED_SPORADIC ); posix_service_failed( status, "pthread_attr_setschedparam"); puts( "Init - pthread_attr_setschedparam - SUCCESSFUL" ); status = pthread_attr_setschedparam( &attr, &schedparam ); posix_service_failed( status, "pthread_attr_setschedparam"); status = pthread_create( &Task2_id, &attr, Task_2, NULL ); rtems_test_assert( !status ); status = pthread_join( Task2_id, NULL ); posix_service_failed( status, " pthread_join"); TEST_END(); rtems_test_exit( 0 ); return NULL; /* just so the compiler thinks we returned something */ }
TEST(pthread, pthread_attr_getstack__main_thread) { // This test is only meaningful for the main thread, so make sure we're running on it! ASSERT_EQ(getpid(), syscall(__NR_gettid)); // Get the main thread's attributes. pthread_attr_t attributes; ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attributes)); // Check that we correctly report that the main thread has no guard page. size_t guard_size; ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size)); ASSERT_EQ(0U, guard_size); // The main thread has no guard page. // Get the stack base and the stack size (both ways). void* stack_base; size_t stack_size; ASSERT_EQ(0, pthread_attr_getstack(&attributes, &stack_base, &stack_size)); size_t stack_size2; ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size2)); // The two methods of asking for the stack size should agree. EXPECT_EQ(stack_size, stack_size2); #if defined(__BIONIC__) // What does /proc/self/maps' [stack] line say? void* maps_stack_hi = NULL; FILE* fp = fopen("/proc/self/maps", "r"); ASSERT_TRUE(fp != NULL); char line[BUFSIZ]; while (fgets(line, sizeof(line), fp) != NULL) { uintptr_t lo, hi; char name[10]; sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d %10s", &lo, &hi, name); if (strcmp(name, "[stack]") == 0) { maps_stack_hi = reinterpret_cast<void*>(hi); break; } } fclose(fp); // The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size. // Remember that the stack grows down (and is mapped in on demand), so the low address of the // region isn't very interesting. EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size); // The stack size should correspond to RLIMIT_STACK. rlimit rl; ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl)); uint64_t original_rlim_cur = rl.rlim_cur; if (rl.rlim_cur == RLIM_INFINITY) { rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB. } EXPECT_EQ(rl.rlim_cur, stack_size); auto guard = make_scope_guard([&rl, original_rlim_cur]() { rl.rlim_cur = original_rlim_cur; ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl)); }); // // What if RLIMIT_STACK is smaller than the stack's current extent? // rl.rlim_cur = rl.rlim_max = 1024; // 1KiB. We know the stack must be at least a page already. rl.rlim_max = RLIM_INFINITY; ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl)); ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attributes)); ASSERT_EQ(0, pthread_attr_getstack(&attributes, &stack_base, &stack_size)); ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size2)); EXPECT_EQ(stack_size, stack_size2); ASSERT_EQ(1024U, stack_size); // // What if RLIMIT_STACK isn't a whole number of pages? // rl.rlim_cur = rl.rlim_max = 6666; // Not a whole number of pages. rl.rlim_max = RLIM_INFINITY; ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl)); ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attributes)); ASSERT_EQ(0, pthread_attr_getstack(&attributes, &stack_base, &stack_size)); ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size2)); EXPECT_EQ(stack_size, stack_size2); ASSERT_EQ(6666U, stack_size); #endif }
static void current_stack_region(address *bottom, size_t *size) { pthread_attr_t attr; int res = pthread_getattr_np(pthread_self(), &attr); if (res != 0) { if (res == ENOMEM) { vm_exit_out_of_memory(0, "pthread_getattr_np"); } else { fatal(err_msg("pthread_getattr_np failed with errno = %d", res)); } } address stack_bottom; size_t stack_bytes; res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes); if (res != 0) { fatal(err_msg("pthread_attr_getstack failed with errno = %d", res)); } address stack_top = stack_bottom + stack_bytes; // The block of memory returned by pthread_attr_getstack() includes // guard pages where present. We need to trim these off. size_t page_bytes = os::Linux::page_size(); assert(((intptr_t) stack_bottom & (page_bytes - 1)) == 0, "unaligned stack"); size_t guard_bytes; res = pthread_attr_getguardsize(&attr, &guard_bytes); if (res != 0) { fatal(err_msg("pthread_attr_getguardsize failed with errno = %d", res)); } int guard_pages = align_size_up(guard_bytes, page_bytes) / page_bytes; assert(guard_bytes == guard_pages * page_bytes, "unaligned guard"); #ifdef IA64 // IA64 has two stacks sharing the same area of memory, a normal // stack growing downwards and a register stack growing upwards. // Guard pages, if present, are in the centre. This code splits // the stack in two even without guard pages, though in theory // there's nothing to stop us allocating more to the normal stack // or more to the register stack if one or the other were found // to grow faster. int total_pages = align_size_down(stack_bytes, page_bytes) / page_bytes; stack_bottom += (total_pages - guard_pages) / 2 * page_bytes; #endif // IA64 stack_bottom += guard_bytes; pthread_attr_destroy(&attr); // The initial thread has a growable stack, and the size reported // by pthread_attr_getstack is the maximum size it could possibly // be given what currently mapped. This can be huge, so we cap it. if (os::Linux::is_initial_thread()) { stack_bytes = stack_top - stack_bottom; if (stack_bytes > JavaThread::stack_size_at_create()) stack_bytes = JavaThread::stack_size_at_create(); stack_bottom = stack_top - stack_bytes; } assert(os::current_stack_pointer() >= stack_bottom, "should do"); assert(os::current_stack_pointer() < stack_top, "should do"); *bottom = stack_bottom; *size = stack_top - stack_bottom; }