summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2016-04-02 19:56:54 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2016-04-02 19:56:54 +0000
commit4bd70a202ef4f88bc788d55769964a6928490376 (patch)
tree2f0aade3c8c54e06f43f27652bfa5ddb5167ac77 /lib
parenta55e1169da61fa81974081006c42e49a98442ad9 (diff)
Wrap <pthread.h> and <pthread_np.h> to eliminate PLT entries for internal
references. Use _thread_pagesize for the semaphore mmap size instead of calling getpagesize() each time. ok beck@
Diffstat (limited to 'lib')
-rw-r--r--lib/librthread/Makefile7
-rw-r--r--lib/librthread/namespace.h43
-rw-r--r--lib/librthread/pthread.h125
-rw-r--r--lib/librthread/pthread_np.h29
-rw-r--r--lib/librthread/rthread.c5
-rw-r--r--lib/librthread/rthread_attr.c3
-rw-r--r--lib/librthread/rthread_rwlock.c3
-rw-r--r--lib/librthread/rthread_sem.c6
-rw-r--r--lib/librthread/rthread_sync.c10
-rw-r--r--lib/librthread/rthread_tls.c5
10 files changed, 226 insertions, 10 deletions
diff --git a/lib/librthread/Makefile b/lib/librthread/Makefile
index c4fae147425..28d35a0052b 100644
--- a/lib/librthread/Makefile
+++ b/lib/librthread/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.40 2015/05/19 20:50:06 guenther Exp $
+# $OpenBSD: Makefile,v 1.41 2016/04/02 19:56:53 guenther Exp $
LIB=pthread
LIBCSRCDIR= ${.CURDIR}/../libc
@@ -6,7 +6,8 @@ LIBCSRCDIR= ${.CURDIR}/../libc
CFLAGS+=-Wall -g -Werror -Wshadow
CFLAGS+=-Wmissing-prototypes -Wstrict-prototypes
CFLAGS+=-Wsign-compare
-CFLAGS+=-I${LIBCSRCDIR}/arch/${MACHINE_CPU} -I${LIBCSRCDIR}/include
+CFLAGS+=-I${.CURDIR} -include namespace.h \
+ -I${LIBCSRCDIR}/arch/${MACHINE_CPU} -I${LIBCSRCDIR}/include
CDIAGFLAGS=
LDADD = -Wl,-znodelete,-zinitfirst,-znodlopen
@@ -47,3 +48,5 @@ SRCDIR= ${.CURDIR}/../libpthread
.include "${SRCDIR}/include/Makefile.inc"
.include "${SRCDIR}/man/Makefile.inc"
.include <bsd.lib.mk>
+
+${OBJS} ${GOBJS} ${POBJS} ${SOBJS} ${DOBJS}: ${.CURDIR}/namespace.h
diff --git a/lib/librthread/namespace.h b/lib/librthread/namespace.h
new file mode 100644
index 00000000000..4d3c4596816
--- /dev/null
+++ b/lib/librthread/namespace.h
@@ -0,0 +1,43 @@
+/* $OpenBSD: namespace.h,v 1.1 2016/04/02 19:56:53 guenther Exp $ */
+
+#ifndef _LIBPTHREAD_NAMESPACE_H_
+#define _LIBPTHREAD_NAMESPACE_H_
+
+/*
+ * Copyright (c) 2016 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h> /* for __dso_hidden and __strong_alias */
+
+#ifndef PIC
+# define WEAK_IN_STATIC_ALIAS(x,y) __weak_alias(x,y)
+# define WEAK_IN_STATIC __attribute__((weak))
+#else
+# define WEAK_IN_STATIC_ALIAS(x,y) __strong_alias(x,y)
+# define WEAK_IN_STATIC /* nothing */
+#endif
+
+#define HIDDEN(x) _libpthread_##x
+#define HIDDEN_STRING(x) "_libpthread_" __STRING(x)
+
+#define PROTO_NORMAL(x) __dso_hidden typeof(x) x asm(HIDDEN_STRING(x))
+#define PROTO_STD_DEPRECATED(x) typeof(x) x __attribute__((deprecated))
+#define PROTO_DEPRECATED(x) PROTO_STD_DEPRECATED(x) WEAK_IN_STATIC
+
+#define DEF_STD(x) __strong_alias(x, HIDDEN(x))
+#define DEF_NONSTD(x) WEAK_IN_STATIC_ALIAS(x, HIDDEN(x))
+
+#endif /* _LIBPTHREAD_NAMESPACE_H_ */
+
diff --git a/lib/librthread/pthread.h b/lib/librthread/pthread.h
new file mode 100644
index 00000000000..539f4ad82aa
--- /dev/null
+++ b/lib/librthread/pthread.h
@@ -0,0 +1,125 @@
+/* $OpenBSD: pthread.h,v 1.1 2016/04/02 19:56:53 guenther Exp $ */
+/*
+ * Copyright (c) 2016 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBPTHREAD_PTHREAD_H_
+#define _LIBPTHREAD_PTHREAD_H_
+
+#include_next <pthread.h>
+
+PROTO_STD_DEPRECATED(pthread_attr_destroy);
+PROTO_STD_DEPRECATED(pthread_attr_getdetachstate);
+PROTO_STD_DEPRECATED(pthread_attr_getguardsize);
+PROTO_STD_DEPRECATED(pthread_attr_getinheritsched);
+PROTO_STD_DEPRECATED(pthread_attr_getschedparam);
+PROTO_STD_DEPRECATED(pthread_attr_getschedpolicy);
+PROTO_STD_DEPRECATED(pthread_attr_getscope);
+PROTO_STD_DEPRECATED(pthread_attr_getstack);
+PROTO_STD_DEPRECATED(pthread_attr_getstacksize);
+PROTO_STD_DEPRECATED(pthread_attr_init);
+PROTO_STD_DEPRECATED(pthread_attr_setdetachstate);
+PROTO_STD_DEPRECATED(pthread_attr_setguardsize);
+PROTO_STD_DEPRECATED(pthread_attr_setinheritsched);
+PROTO_STD_DEPRECATED(pthread_attr_setschedparam);
+PROTO_STD_DEPRECATED(pthread_attr_setschedpolicy);
+PROTO_STD_DEPRECATED(pthread_attr_setscope);
+PROTO_STD_DEPRECATED(pthread_attr_setstack);
+PROTO_STD_DEPRECATED(pthread_attr_setstacksize);
+PROTO_STD_DEPRECATED(pthread_barrier_destroy);
+PROTO_STD_DEPRECATED(pthread_barrier_init);
+PROTO_STD_DEPRECATED(pthread_barrier_wait);
+PROTO_STD_DEPRECATED(pthread_barrierattr_destroy);
+PROTO_STD_DEPRECATED(pthread_barrierattr_getpshared);
+PROTO_STD_DEPRECATED(pthread_barrierattr_init);
+PROTO_STD_DEPRECATED(pthread_barrierattr_setpshared);
+PROTO_STD_DEPRECATED(pthread_cancel);
+PROTO_STD_DEPRECATED(pthread_cleanup_pop);
+PROTO_STD_DEPRECATED(pthread_cleanup_push);
+PROTO_NORMAL(pthread_cond_broadcast);
+PROTO_NORMAL(pthread_cond_destroy);
+PROTO_NORMAL(pthread_cond_init);
+PROTO_STD_DEPRECATED(pthread_cond_signal);
+PROTO_STD_DEPRECATED(pthread_cond_timedwait);
+PROTO_NORMAL(pthread_cond_wait);
+PROTO_STD_DEPRECATED(pthread_condattr_destroy);
+PROTO_STD_DEPRECATED(pthread_condattr_getclock);
+PROTO_STD_DEPRECATED(pthread_condattr_init);
+PROTO_STD_DEPRECATED(pthread_condattr_setclock);
+PROTO_STD_DEPRECATED(pthread_create);
+PROTO_STD_DEPRECATED(pthread_detach);
+PROTO_STD_DEPRECATED(pthread_equal);
+PROTO_NORMAL(pthread_exit);
+PROTO_STD_DEPRECATED(pthread_getconcurrency);
+PROTO_STD_DEPRECATED(pthread_getcpuclockid);
+PROTO_STD_DEPRECATED(pthread_getschedparam);
+PROTO_NORMAL(pthread_getspecific);
+PROTO_STD_DEPRECATED(pthread_join);
+PROTO_NORMAL(pthread_key_create);
+PROTO_STD_DEPRECATED(pthread_key_delete);
+PROTO_STD_DEPRECATED(pthread_kill);
+PROTO_NORMAL(pthread_mutex_destroy);
+PROTO_STD_DEPRECATED(pthread_mutex_getprioceiling);
+PROTO_NORMAL(pthread_mutex_init);
+PROTO_NORMAL(pthread_mutex_lock);
+PROTO_STD_DEPRECATED(pthread_mutex_setprioceiling);
+PROTO_STD_DEPRECATED(pthread_mutex_timedlock);
+PROTO_STD_DEPRECATED(pthread_mutex_trylock);
+PROTO_NORMAL(pthread_mutex_unlock);
+PROTO_STD_DEPRECATED(pthread_mutexattr_destroy);
+PROTO_STD_DEPRECATED(pthread_mutexattr_getprioceiling);
+PROTO_STD_DEPRECATED(pthread_mutexattr_getprotocol);
+PROTO_STD_DEPRECATED(pthread_mutexattr_gettype);
+PROTO_STD_DEPRECATED(pthread_mutexattr_init);
+PROTO_STD_DEPRECATED(pthread_mutexattr_setprioceiling);
+PROTO_STD_DEPRECATED(pthread_mutexattr_setprotocol);
+PROTO_STD_DEPRECATED(pthread_mutexattr_settype);
+PROTO_STD_DEPRECATED(pthread_once);
+PROTO_STD_DEPRECATED(pthread_rwlock_destroy);
+PROTO_NORMAL(pthread_rwlock_init);
+PROTO_STD_DEPRECATED(pthread_rwlock_rdlock);
+PROTO_STD_DEPRECATED(pthread_rwlock_timedrdlock);
+PROTO_STD_DEPRECATED(pthread_rwlock_timedwrlock);
+PROTO_STD_DEPRECATED(pthread_rwlock_tryrdlock);
+PROTO_STD_DEPRECATED(pthread_rwlock_trywrlock);
+PROTO_STD_DEPRECATED(pthread_rwlock_unlock);
+PROTO_STD_DEPRECATED(pthread_rwlock_wrlock);
+PROTO_STD_DEPRECATED(pthread_rwlockattr_destroy);
+PROTO_STD_DEPRECATED(pthread_rwlockattr_getpshared);
+PROTO_STD_DEPRECATED(pthread_rwlockattr_init);
+PROTO_STD_DEPRECATED(pthread_rwlockattr_setpshared);
+PROTO_NORMAL(pthread_self);
+PROTO_NORMAL(pthread_setcancelstate);
+PROTO_STD_DEPRECATED(pthread_setcanceltype);
+PROTO_STD_DEPRECATED(pthread_setconcurrency);
+PROTO_STD_DEPRECATED(pthread_setschedparam);
+PROTO_NORMAL(pthread_setspecific);
+PROTO_STD_DEPRECATED(pthread_spin_destroy);
+PROTO_STD_DEPRECATED(pthread_spin_init);
+PROTO_STD_DEPRECATED(pthread_spin_lock);
+PROTO_STD_DEPRECATED(pthread_spin_trylock);
+PROTO_STD_DEPRECATED(pthread_spin_unlock);
+PROTO_STD_DEPRECATED(pthread_testcancel);
+
+/*
+ * Obsolete, non-portable
+ */
+PROTO_DEPRECATED(pthread_setprio);
+PROTO_DEPRECATED(pthread_getprio);
+PROTO_DEPRECATED(pthread_attr_getstackaddr);
+PROTO_NORMAL(pthread_attr_setstackaddr);
+PROTO_DEPRECATED(pthread_yield);
+
+#endif /* !_LIBPTHREAD_PTHREAD_H_ */
diff --git a/lib/librthread/pthread_np.h b/lib/librthread/pthread_np.h
new file mode 100644
index 00000000000..1f110fc0186
--- /dev/null
+++ b/lib/librthread/pthread_np.h
@@ -0,0 +1,29 @@
+/* $OpenBSD: pthread_np.h,v 1.1 2016/04/02 19:56:53 guenther Exp $ */
+/*
+ * Copyright (c) 2016 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBPTHREAD_PTHREAD_NP_H_
+#define _LIBPTHREAD_PTHREAD_NP_H_
+
+#include_next <pthread_np.h>
+
+PROTO_DEPRECATED(pthread_main_np);
+PROTO_DEPRECATED(pthread_mutexattr_getkind_np);
+PROTO_DEPRECATED(pthread_mutexattr_setkind_np);
+PROTO_DEPRECATED(pthread_set_name_np);
+PROTO_DEPRECATED(pthread_stackseg_np);
+
+#endif /* !_LIBPTHREAD_PTHREAD_NP_H_ */
diff --git a/lib/librthread/rthread.c b/lib/librthread/rthread.c
index 1a70da97a0c..a622214d2fe 100644
--- a/lib/librthread/rthread.c
+++ b/lib/librthread/rthread.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread.c,v 1.89 2016/04/02 19:00:51 guenther Exp $ */
+/* $OpenBSD: rthread.c,v 1.90 2016/04/02 19:56:53 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -272,6 +272,7 @@ pthread_self(void)
return (TCB_THREAD());
}
+DEF_STD(pthread_self);
static void
_rthread_reaper(void)
@@ -338,6 +339,7 @@ pthread_exit(void *retval)
__threxit(&thread->tid);
for(;;);
}
+DEF_STD(pthread_exit);
int
pthread_join(pthread_t thread, void **retval)
@@ -539,6 +541,7 @@ pthread_setcancelstate(int state, int *oldstatep)
return (0);
}
+DEF_STD(pthread_setcancelstate);
int
pthread_setcanceltype(int type, int *oldtypep)
diff --git a/lib/librthread/rthread_attr.c b/lib/librthread/rthread_attr.c
index 9959e1c49ec..b4c0f8b3a2c 100644
--- a/lib/librthread/rthread_attr.c
+++ b/lib/librthread/rthread_attr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_attr.c,v 1.20 2014/08/09 03:29:35 guenther Exp $ */
+/* $OpenBSD: rthread_attr.c,v 1.21 2016/04/02 19:56:53 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -170,6 +170,7 @@ pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr)
return (0);
}
+DEF_NONSTD(pthread_attr_setstackaddr);
int
pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope)
diff --git a/lib/librthread/rthread_rwlock.c b/lib/librthread/rthread_rwlock.c
index 03ad648ebd8..007196bbbb6 100644
--- a/lib/librthread/rthread_rwlock.c
+++ b/lib/librthread/rthread_rwlock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_rwlock.c,v 1.5 2015/11/01 03:52:17 guenther Exp $ */
+/* $OpenBSD: rthread_rwlock.c,v 1.6 2016/04/02 19:56:53 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* Copyright (c) 2012 Philip Guenther <guenther@openbsd.org>
@@ -49,6 +49,7 @@ pthread_rwlock_init(pthread_rwlock_t *lockp,
return (0);
}
+DEF_STD(pthread_rwlock_init);
int
pthread_rwlock_destroy(pthread_rwlock_t *lockp)
diff --git a/lib/librthread/rthread_sem.c b/lib/librthread/rthread_sem.c
index bf9be17d484..e7a8e4e0733 100644
--- a/lib/librthread/rthread_sem.c
+++ b/lib/librthread/rthread_sem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_sem.c,v 1.21 2015/12/10 13:02:24 tedu Exp $ */
+/* $OpenBSD: rthread_sem.c,v 1.22 2016/04/02 19:56:53 guenther Exp $ */
/*
* Copyright (c) 2004,2005,2013 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -46,7 +46,7 @@
* Size of memory to be mmap()'ed by named semaphores.
* Should be >= SEM_PATH_SIZE and page-aligned.
*/
-#define SEM_MMAP_SIZE getpagesize()
+#define SEM_MMAP_SIZE _thread_pagesize
/*
* Internal implementation of semaphores
@@ -347,7 +347,7 @@ sem_open(const char *name, int oflag, ...)
errno = EPERM;
return (SEM_FAILED);
}
- if (sb.st_size != SEM_MMAP_SIZE) {
+ if (sb.st_size != (off_t)SEM_MMAP_SIZE) {
if (!(oflag & O_CREAT)) {
close(fd);
errno = EINVAL;
diff --git a/lib/librthread/rthread_sync.c b/lib/librthread/rthread_sync.c
index 72e664b431e..137bc926014 100644
--- a/lib/librthread/rthread_sync.c
+++ b/lib/librthread/rthread_sync.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_sync.c,v 1.39 2013/06/01 23:06:26 tedu Exp $ */
+/* $OpenBSD: rthread_sync.c,v 1.40 2016/04/02 19:56:53 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* Copyright (c) 2012 Philip Guenther <guenther@openbsd.org>
@@ -58,6 +58,7 @@ pthread_mutex_init(pthread_mutex_t *mutexp, const pthread_mutexattr_t *attr)
return (0);
}
+DEF_STD(pthread_mutex_init);
int
pthread_mutex_destroy(pthread_mutex_t *mutexp)
@@ -79,6 +80,7 @@ pthread_mutex_destroy(pthread_mutex_t *mutexp)
}
return (0);
}
+DEF_STD(pthread_mutex_destroy);
static int
_rthread_mutex_lock(pthread_mutex_t *mutexp, int trywait,
@@ -170,6 +172,7 @@ pthread_mutex_lock(pthread_mutex_t *p)
{
return (_rthread_mutex_lock(p, 0, NULL));
}
+DEF_STD(pthread_mutex_lock);
int
pthread_mutex_trylock(pthread_mutex_t *p)
@@ -234,6 +237,7 @@ pthread_mutex_unlock(pthread_mutex_t *mutexp)
return (0);
}
+DEF_STD(pthread_mutex_unlock);
/*
* condition variables
@@ -256,6 +260,7 @@ pthread_cond_init(pthread_cond_t *condp, const pthread_condattr_t *attr)
return (0);
}
+DEF_STD(pthread_cond_init);
int
pthread_cond_destroy(pthread_cond_t *condp)
@@ -277,6 +282,7 @@ pthread_cond_destroy(pthread_cond_t *condp)
return (0);
}
+DEF_STD(pthread_cond_destroy);
int
pthread_cond_timedwait(pthread_cond_t *condp, pthread_mutex_t *mutexp,
@@ -563,6 +569,7 @@ pthread_cond_wait(pthread_cond_t *condp, pthread_mutex_t *mutexp)
return (0);
}
+DEF_STD(pthread_cond_wait);
int
@@ -677,3 +684,4 @@ pthread_cond_broadcast(pthread_cond_t *condp)
return (0);
}
+DEF_STD(pthread_cond_broadcast);
diff --git a/lib/librthread/rthread_tls.c b/lib/librthread/rthread_tls.c
index c16b0dd243a..80a75f8f088 100644
--- a/lib/librthread/rthread_tls.c
+++ b/lib/librthread/rthread_tls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_tls.c,v 1.16 2013/11/02 22:37:17 tedu Exp $ */
+/* $OpenBSD: rthread_tls.c,v 1.17 2016/04/02 19:56:53 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -57,6 +57,7 @@ pthread_key_create(pthread_key_t *key, void (*destructor)(void*))
return (0);
}
+DEF_STD(pthread_key_create);
int
pthread_key_delete(pthread_key_t key)
@@ -135,6 +136,7 @@ pthread_getspecific(pthread_key_t key)
return (rs->data);
}
+DEF_STD(pthread_getspecific);
int
pthread_setspecific(pthread_key_t key, const void *data)
@@ -151,6 +153,7 @@ pthread_setspecific(pthread_key_t key, const void *data)
return (0);
}
+DEF_STD(pthread_setspecific);
void
_rthread_tls_destructors(pthread_t thread)