static int native_thread_init_stack(rb_thread_t *th) { rb_thread_id_t curr = pthread_self(); if (pthread_equal(curr, native_main_thread.id)) { th->machine_stack_start = native_main_thread.stack_start; th->machine_stack_maxsize = native_main_thread.stack_maxsize; } else { #ifdef HAVE_PTHREAD_GETATTR_NP pthread_attr_t attr; void *start; CHECK_ERR(pthread_getattr_np(curr, &attr)); # if defined HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, &start, &th->machine_stack_maxsize)); # elif defined HAVE_PTHREAD_ATTR_GETSTACKSIZE && defined HAVE_PTHREAD_ATTR_GETSTACKADDR CHECK_ERR(pthread_attr_getstackaddr(&attr, &start)); CHECK_ERR(pthread_attr_getstacksize(&attr, &th->machine_stack_maxsize)); # endif th->machine_stack_start = start; #else rb_raise(rb_eNotImpError, "ruby engine can initialize only in the main thread"); #endif } #ifdef __ia64 th->machine_register_stack_start = native_main_thread.register_stack_start; th->machine_stack_maxsize /= 2; th->machine_register_stack_maxsize = th->machine_stack_maxsize; #endif return 0; }
static void current_stack_region(address* bottom, size_t* size) { if (os::Linux::is_initial_thread()) { // initial thread needs special handling because pthread_getattr_np() // may return bogus value. *bottom = os::Linux::initial_thread_stack_bottom(); *size = os::Linux::initial_thread_stack_size(); } else { pthread_attr_t attr; int rslt = pthread_getattr_np(pthread_self(), &attr); // JVM needs to know exact stack location, abort if it fails if (rslt != 0) { if (rslt == ENOMEM) { vm_exit_out_of_memory(0, "pthread_getattr_np"); } else { fatal(err_msg("pthread_getattr_np failed with errno = %d", rslt)); } } if (pthread_attr_getstack(&attr, (void**)bottom, size) != 0) { fatal("Can not locate current stack attributes!"); } pthread_attr_destroy(&attr); } assert(os::current_stack_pointer() >= *bottom && os::current_stack_pointer() < *bottom + *size, "just checking"); }
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 void* run_( void* arg ) { pthread_mutex_t* mutex = (pthread_mutex_t*)arg; pthread_attr_t attr; void* stack_addr; size_t stack_size; pthread_getattr_np(pthread_self(), &attr); pthread_attr_getstack(&attr, &stack_addr, &stack_size); pthread_mutex_lock(mutex); printf("--- pthread ---\n"); printf("thread id: [0x%08x]\n", (unsigned int)pthread_self()); printf("stack addr: [%p]\n", stack_addr); printf("stack size: [0x%08x]\n", stack_size); printf("&arg: [%p]\n", &arg); printf("\n"); raise(SIGINT); raise(SIGINT); pthread_mutex_unlock(mutex); return NULL; }
static void get_stack(void **stack_addr, size_t *stack_size) { pthread_attr_t attr; pthread_getattr_np(pthread_self(), &attr); pthread_attr_getstack(&attr, stack_addr, stack_size); pthread_attr_destroy(&attr); }
//return 0: success, -1 fail __LIBC_HIDDEN__ int malloc_get_stack(size_t* pthread_stack_start, size_t* pthread_stack_end) { pid_t pid = getpid(); if (gettid() == pid) { if (pid != malloc_pid) { malloc_pid = pid; malloc_main_thread_stack_start = 0; // reset for new process malloc_main_thread_stack_size = 0; } if (!malloc_main_thread_stack_start) { if (malloc_get_main_thread_stack(pid)) { return -1; } } *pthread_stack_start = malloc_main_thread_stack_start; *pthread_stack_end = malloc_main_thread_stack_start - malloc_main_thread_stack_size; } else { pthread_attr_t attr; pthread_getattr_np(pthread_self(), &attr); *pthread_stack_start = (size_t)attr.stack_base + attr.stack_size; *pthread_stack_end = (size_t)attr.stack_base; } return 0; }
size_t get_stack_size(int main) { if (main) { // Retrieve stack size of the main thread. struct rlimit curr; if (getrlimit(RLIMIT_STACK, &curr) != 0) { throw_get_stack_size_failed(); } return curr.rlim_cur; } else { #if defined(LEAN_MULTI_THREAD) pthread_attr_t attr; memset (&attr, 0, sizeof(attr)); if (pthread_getattr_np(pthread_self(), &attr) != 0) { throw_get_stack_size_failed(); } void * ptr; size_t result; if (pthread_attr_getstack (&attr, &ptr, &result) != 0) { throw_get_stack_size_failed(); } if (pthread_attr_destroy(&attr) != 0) { throw_get_stack_size_failed(); } return result; #else return 0; #endif } }
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); }
int Stack_Size_Check::svc (void) { size_t my_size = 0; #ifdef __USE_GNU pthread_attr_t my_attrs; pthread_getattr_np (pthread_self (), &my_attrs); pthread_attr_getstacksize (&my_attrs, &my_size); pthread_attr_destroy (&my_attrs); #else // No known way to do this yet... feel free to fill this in. my_size = this->stack_size_; #endif /* __USE_GNU */ // The Posix docs say that the size set for the threads stack will be the // *minimum* size allocated (the actual size may be bigger because of // a) pagesize rounding, b) guardsize addition) so we can really only // check if we have gotten *at least* what we asked for. if (my_size < this->stack_size_) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("%t: My stack size attr %B; expected %B\n"), my_size, this->stack_size_)); this->failed_ = true; } else ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%t: My stack size attr %B; correct.\n"), my_size)); return 0; }
void TestThreadStackSize_getstacksize() { const size_t c_stacksize = 320000; // set up a thread with a stack size of 'c_stacksize' SCXCoreLib::SCXHandle<SCXCoreLib::SCXThreadParam> p(new SCXCoreLib::SCXThreadParam()); SCXCoreLib::SCXThreadAttr threadAttr; CPPUNIT_ASSERT_NO_THROW(threadAttr.SetStackSize(c_stacksize)); SCXCoreLib::SCXThread* thread = new SCXCoreLib::SCXThread(SCXThreadTest::SimpleThreadBodyTerminate, p, &threadAttr); // Let's make sure the stack size is what we set it to be. // SCXThreadId is just a typedef of pthread_t on SCX_UNIX. SCXCoreLib::SCXThreadId pt = thread->GetThreadID(); pthread_attr_t attr; int errorval = pthread_getattr_np(pt, &attr); CPPUNIT_ASSERT_EQUAL_MESSAGE("pthread_getattr_np failed", 0, errorval); size_t actualsize; errorval = pthread_attr_getstacksize(&attr, &actualsize); CPPUNIT_ASSERT_EQUAL_MESSAGE("pthread_attr_getstacksize failed", 0, errorval); // according to pthread_attr_setstacksize's man page, the allocated stack size should be // greater than or equal to the requested stack size std::stringstream ss; ss << "Actual stack size (" << actualsize << ") should be greater than or equal to requested size (" << c_stacksize << ")"; CPPUNIT_ASSERT_MESSAGE(ss.str(), actualsize >= c_stacksize); // clean up the thread thread->RequestTerminate(); thread->Wait(); delete thread; }
void system_get_stack(pthread_t thread, void **base, size_t *size) { dbg_assert(base && size); pthread_attr_t attr; dbg_check( pthread_getattr_np(thread, &attr) ); dbg_check( pthread_attr_getstack(&attr, base, size) ); }
static void AssertDetached(pthread_t t, bool is_detached) { pthread_attr_t attr; ASSERT_EQ(0, pthread_getattr_np(t, &attr)); int detach_state; ASSERT_EQ(0, pthread_attr_getdetachstate(&attr, &detach_state)); pthread_attr_destroy(&attr); ASSERT_EQ(is_detached, (detach_state == PTHREAD_CREATE_DETACHED)); }
int my_pthread_getattr_np(pthread_t __th, pthread_attr_t *__attr) { assert(__attr != NULL); pthread_attr_t *realattr = (pthread_attr_t *) *(int *) __attr; assert(realattr != NULL); return pthread_getattr_np(__th,realattr); }
static int my_pthread_getattr_np(pthread_t thid, pthread_attr_t *__attr) { pthread_attr_t *realattr; realattr = malloc(sizeof(pthread_attr_t)); *((unsigned int *)__attr) = (unsigned int) realattr; return pthread_getattr_np(thid, realattr); }
size_t MachineThreads::Thread::getRegisters(MachineThreads::Thread::Registers& registers) { Thread::Registers::PlatformRegisters& regs = registers.regs; #if OS(DARWIN) #if CPU(X86) unsigned user_count = sizeof(regs)/sizeof(int); thread_state_flavor_t flavor = i386_THREAD_STATE; #elif CPU(X86_64) unsigned user_count = x86_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = x86_THREAD_STATE64; #elif CPU(PPC) unsigned user_count = PPC_THREAD_STATE_COUNT; thread_state_flavor_t flavor = PPC_THREAD_STATE; #elif CPU(PPC64) unsigned user_count = PPC_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = PPC_THREAD_STATE64; #elif CPU(ARM) unsigned user_count = ARM_THREAD_STATE_COUNT; thread_state_flavor_t flavor = ARM_THREAD_STATE; #elif CPU(ARM64) unsigned user_count = ARM_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = ARM_THREAD_STATE64; #else #error Unknown Architecture #endif kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)®s, &user_count); if (result != KERN_SUCCESS) { WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result); CRASH(); } return user_count * sizeof(uintptr_t); // end OS(DARWIN) #elif OS(WINDOWS) regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; GetThreadContext(platformThreadHandle, ®s); return sizeof(CONTEXT); #elif USE(PTHREADS) pthread_attr_init(®s); #if HAVE(PTHREAD_NP_H) || OS(NETBSD) #if !OS(OPENBSD) // e.g. on FreeBSD 5.4, [email protected] pthread_attr_get_np(platformThread, ®s); #endif #else // FIXME: this function is non-portable; other POSIX systems may have different np alternatives pthread_getattr_np(platformThread, ®s); #endif return 0; #else #error Need a way to get thread registers on this platform #endif }
void* thread(void* param) { pthread_attr_t attr; printf("\n In thread\n" ); pthread_getattr_np(pthread_self(), &attr); read_stack_attributes(&attr); read_detachstate_attribute(&attr); read_guard_attribute(&attr); read_schedpolicy_attribute(&attr); return 0; }
static void pthread_attr_getstack_18908062_helper(void*) { char local_variable; pthread_attr_t attributes; pthread_getattr_np(pthread_self(), &attributes); void* stack_base; size_t stack_size; pthread_attr_getstack(&attributes, &stack_base, &stack_size); // Test whether &local_variable is in [stack_base, stack_base + stack_size). ASSERT_LE(reinterpret_cast<char*>(stack_base), &local_variable); ASSERT_LT(&local_variable, reinterpret_cast<char*>(stack_base) + stack_size); }
void mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) { pthread_attr_t attr; *staddr = NULL; *stsize = (size_t)-1; pthread_getattr_np (pthread_self (), &attr); pthread_attr_getstack (&attr, (void**)staddr, stsize); pthread_attr_destroy (&attr); }
void print_it () { int rc; pthread_attr_t foo; size_t size; rc = pthread_getattr_np (pthread_self(), & foo); assert (rc == 0); rc = pthread_attr_getstacksize(&foo, &size); assert (rc == 0); printf ("stacksize=%u\n", size); rc = pthread_attr_destroy (&foo); assert (rc == 0); }
STATUS taskGetInfo(TASK_ID task_id, TASK_DESC *desc) { int vfirst, vlast, ret; struct wind_task *task; struct WIND_TCB *tcb; pthread_attr_t attr; size_t stacksize; void *stackbase; task = get_wind_task(task_id); if (task == NULL) { errno = S_objLib_OBJ_ID_ERROR; return ERROR; } tcb = task->tcb; desc->td_tid = task_id; desc->td_priority = wind_task_get_priority(task); desc->td_status = get_task_status(task); desc->td_flags = tcb->flags; strncpy(desc->td_name, task->name, sizeof(desc->td_name)); desc->td_entry = tcb->entry; desc->td_errorStatus = *task->thobj.errno_pointer; ret = pthread_getattr_np(task->thobj.tid, &attr); put_wind_task(task); /* * If the target does not support pthread_getattr_np(), we are * out of luck for determining the stack information. We just * zero it. */ if (ret) { /* No idea, buddy. */ desc->td_stacksize = 0; desc->td_pStackBase = NULL; } else { pthread_attr_getstack(&attr, &stackbase, &stacksize); desc->td_stacksize = stacksize; desc->td_pStackBase = stackbase; if (&vfirst < &vlast) /* Stack grows upward. */ desc->td_pStackEnd = (caddr_t)stackbase + stacksize; else /* Stack grows downward. */ desc->td_pStackEnd = (caddr_t)stackbase - stacksize; } return OK; }
void *nativeStackBase() { #if defined(__UCLIBC__) || defined(__EMSCRIPTEN__) return NULL; #else pthread_attr_t attr; void *addr; size_t size; pthread_getattr_np(pthread_self(), &attr); pthread_attr_getstack(&attr, &addr, &size); return addr+size; #endif }
static void display_thread_attr(pthread_t thread, char *prefix) { int s; pthread_attr_t attr; s = pthread_getattr_np(thread, &attr); if (s != 0) handle_error_en(s, "pthread_getattr_np"); display_stack_attr (&attr, prefix); s = pthread_attr_destroy(&attr); if (s != 0) handle_error_en(s, "pthread_attr_destroy"); }
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 }
void mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) { pthread_attr_t attr; guint8 *current = (guint8*)&attr; *staddr = NULL; *stsize = (size_t)-1; pthread_getattr_np (pthread_self (), &attr); pthread_attr_getstack (&attr, (void**)staddr, stsize); pthread_attr_destroy (&attr); if (*staddr && ((current <= *staddr) || (current > *staddr + *stsize))) slow_get_thread_bounds (current, staddr, stsize); }
static int get_stack_attr(void *low, void *high) { /* GNU Pthread specific */ pthread_attr_t attr; uintptr_t stackaddr; size_t stacksize; if (pthread_getattr_np(pthread_self(), &attr)) { return 1; } if (pthread_attr_getstack(&attr, (void *)&stackaddr, &stacksize)) { return 1; } *(uintptr_t *)low = stackaddr; *(uintptr_t *)high = stackaddr + stacksize; return 0; }
void * GetNativeStackBaseImpl() { pthread_t thread = pthread_self(); # if defined(XP_MACOSX) || defined(DARWIN) return pthread_get_stackaddr_np(thread); # else pthread_attr_t sattr; pthread_attr_init(&sattr); # if defined(__OpenBSD__) stack_t ss; # elif defined(PTHREAD_NP_H) || defined(_PTHREAD_NP_H_) || defined(NETBSD) /* e.g. on FreeBSD 4.8 or newer, [email protected] */ pthread_attr_get_np(thread, &sattr); # else /* * FIXME: this function is non-portable; * other POSIX systems may have different np alternatives */ pthread_getattr_np(thread, &sattr); # endif void *stackBase = 0; size_t stackSize = 0; # ifdef DEBUG int rc = # endif # if defined(__OpenBSD__) pthread_stackseg_np(pthread_self(), &ss); stackBase = (void*)((size_t) ss.ss_sp - ss.ss_size); stackSize = ss.ss_size; # else pthread_attr_getstack(&sattr, &stackBase, &stackSize); # endif JS_ASSERT(!rc); JS_ASSERT(stackBase); pthread_attr_destroy(&sattr); # if JS_STACK_GROWTH_DIRECTION > 0 return stackBase; # else return static_cast<char*>(stackBase) + stackSize; # endif # endif }
static void *thread_start (void *arg) { int s; pthread_attr_t gattr; /* pthread_getattr_np() is a non-standard GNU extension that retrieves the attributes of the thread specified in its first argument */ s = pthread_getattr_np (pthread_self (), &gattr); if (s != 0) handle_error_en (s, "pthread_getattr_np"); printf ("Thread attributes:\n"); display_pthread_attr (&gattr, "\t"); exit (EXIT_SUCCESS); /* Terminate all threads */ }
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 Thread * NewThread(void) { Thread *thrPtr; static unsigned int nextuid = 0; pthread_t tid; #if defined(HAVE_PTHREAD_GETATTR_NP) static char *func = "NewThread"; pthread_attr_t attr; int err; #endif thrPtr = ns_calloc(1, sizeof(Thread)); Ns_MutexLock(&uidlock); thrPtr->uid = nextuid++; Ns_MutexUnlock(&uidlock); tid = pthread_self(); #if defined(HAVE_PTHREAD_GETATTR_NP) err = pthread_getattr_np(tid, &attr); if (err != 0) { NsThreadFatal(func, "pthread_getattr_np", err); } err = pthread_attr_getstackaddr(&attr, &thrPtr->stackaddr); if (err != 0) { NsThreadFatal(func, "pthread_attr_getstackaddr", err); } err = pthread_attr_getstacksize(&attr, &thrPtr->stacksize); if (err != 0) { NsThreadFatal(func, "pthread_attr_getstacksize", err); } thrPtr->stacksize -= guardsize; err = pthread_attr_destroy(&attr); if (err != 0) { NsThreadFatal(func, "pthread_attr_destroy", err); } #elif defined(HAVE_PTHREAD_GET_STACKADDR_NP) thrPtr->stackaddr = pthread_get_stackaddr_np(tid); thrPtr->stacksize = pthread_get_stacksize_np(tid) - guardsize; #endif return thrPtr; }
void* startRoutine(void *data) { int state=0; pthread_t tid = pthread_self(); displayThreadId(tid); printf("\n Running startRoutine()...: %d ************", start++); //sleep(SLEEPTIME_SMALL); pthread_attr_t myattr; pthread_getattr_np(pthread_self(), &myattr); pthread_attr_getdetachstate(&myattr, &state); if(state == PTHREAD_CREATE_JOINABLE) { printf("\n Joinable thread ! state=%d", state); } printf("\n Leaving startRoutine()... : %d************\n",end++); return 0; }