--- /dev/null	Mon Oct 15 13:28:40 2018
+++ new/usr/src/test/libc-tests/tests/threads/thread_name.c	Mon Oct 15 13:28:40 2018
@@ -0,0 +1,278 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Joyent, Inc.
+ */
+
+/*
+ * Some basic pthread name API tests.
+ */
+
+#include <sys/stat.h>
+#include <pthread.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <thread.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <err.h>
+
+
+/*ARGSUSED*/
+static void *
+thr(void *unused)
+{
+	(void) sleep(100);
+	return (NULL);
+}
+
+/*ARGSUSED*/
+int
+main(int argc, char *argv[])
+{
+	char name[PTHREAD_MAX_NAMELEN_NP];
+	pthread_attr_t attr;
+	char path[PATH_MAX];
+	pthread_t tid;
+	ssize_t n;
+	int test;
+	int rc;
+	int fd;
+
+	/* Default thread name is empty string. */
+	test = 1;
+
+	rc = pthread_getname_np(pthread_self(), name, sizeof (name));
+
+	if (rc != 0 || strcmp(name, "") != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* Can set name. */
+	test = 2;
+
+	(void) strlcpy(name, "main", sizeof (name));
+	rc = pthread_setname_np(pthread_self(), name);
+
+	if (rc != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_getname_np(pthread_self(), name, sizeof (name));
+
+	if (rc != 0 || strcmp(name, "main") != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* ERANGE check. */
+	test = 3;
+
+	rc = pthread_getname_np(pthread_self(), name, 2);
+
+	if (rc != ERANGE)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* EINVAL check. */
+	test = 4;
+
+	rc = pthread_getname_np(pthread_self(), NULL, sizeof (name));
+
+	if (rc != EINVAL)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* can clear thread name. */
+	test = 5;
+
+	rc = pthread_setname_np(pthread_self(), NULL);
+
+	if (rc != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_getname_np(pthread_self(), name, sizeof (name));
+
+	if (rc != 0 || strcmp(name, "") != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* non-existent thread check. */
+	test = 6;
+
+	rc = pthread_getname_np(808, name, sizeof (name));
+
+	if (rc != ESRCH)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_setname_np(808, "state");
+
+	if (rc != ESRCH)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* too long a name. */
+	test = 7;
+
+	rc = pthread_setname_np(pthread_self(),
+	    "12345678901234567890123456789012");
+
+	if (rc != ERANGE)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* can name another thread. */
+	test = 8;
+
+	rc = pthread_create(&tid, NULL, thr, NULL);
+
+	if (rc != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_setname_np(tid, "otherthread");
+
+	if (rc != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* attr tests. */
+	test = 9;
+
+	(void) pthread_attr_init(&attr);
+
+	rc = pthread_attr_setname_np(&attr,
+	    "12345678901234567890123456789012");
+
+	if (rc != ERANGE)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_attr_setname_np(&attr, "thread2");
+
+	if (rc != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_attr_getname_np(&attr, NULL, sizeof (name));
+
+	if (rc != EINVAL)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_attr_getname_np(&attr, name, 2);
+
+	if (rc != ERANGE)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* does the attr actually apply? */
+	test = 10;
+
+	rc = pthread_create(&tid, &attr, thr, NULL);
+
+	if (rc != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_getname_np(tid, name, sizeof (name));
+
+	if (rc != 0 || strcmp(name, "thread2") != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* proc read tests */
+	test = 11;
+
+	(void) snprintf(path, sizeof (path),
+	    "/proc/self/lwp/%d/lwpname", (int)tid);
+
+	fd = open(path, O_RDWR);
+
+	if (fd == -1)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+	n = read(fd, name, sizeof (name));
+
+	if (n != sizeof (name) || strcmp(name, "thread2") != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	if (lseek(fd, 0, SEEK_SET) != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+	n = read(fd, name, PTHREAD_MAX_NAMELEN_NP * 2);
+
+	if (n != sizeof (name) || strcmp(name, "thread2") != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	if (lseek(fd, 0, SEEK_SET) != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+	n = read(fd, name, 4);
+
+	if (n != 4 || strncmp(name, "thre", 4) != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* proc write tests */
+	test = 12;
+
+	if (lseek(fd, 0, SEEK_SET) != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+	n = write(fd, "1234567890123456789012345678901",
+	    PTHREAD_MAX_NAMELEN_NP);
+
+	if (n != PTHREAD_MAX_NAMELEN_NP)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+	if (lseek(fd, 0, SEEK_SET) != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+	n = write(fd, "foo", sizeof ("foo"));
+
+	if (n != sizeof ("foo"))
+		errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+	if (lseek(fd, 0, SEEK_SET) != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, errno);
+
+	n = read(fd, name, sizeof (name));
+
+	if (n != sizeof (name) || strcmp(name, "foo") != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	(void) close(fd);
+
+	/* thr_* API. */
+	test = 13;
+
+	rc = thr_setname(thr_self(), "main");
+
+	if (rc != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = thr_getname(thr_self(), name, sizeof (name));
+
+	if (rc != 0 || strcmp(name, "main") != 0)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	/* badness */
+	test = 14;
+
+	rc = thr_setname(thr_self(), "\033]0;messeduptitle\a");
+
+	if (rc != EINVAL)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = thr_setname(thr_self(), "ab\177\177\n");
+
+	if (rc != EINVAL)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_attr_setname_np(&attr, "\033]0;messeduptitle\a");
+
+	if (rc != EINVAL)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	rc = pthread_attr_setname_np(&attr, "ab\177\177\n");
+
+	if (rc != EINVAL)
+		errx(EXIT_FAILURE, "test %d failed with %d", test, rc);
+
+	return (EXIT_SUCCESS);
+}
