Skip to content

Commit

Permalink
Add support for naming a thread, using an API compatible with Tru64 U…
Browse files Browse the repository at this point in the history
…nix:

* pthread_attr_getname_np()
* pthread_attr_setname_np()
* pthread_getname_np()
* pthread_setname_np()

In addition to being query'able by the application (for log messages, etc.),
it is intended that these names can show up in the debugger.

Reviewed by nathanw.
  • Loading branch information
thorpej committed Feb 26, 2003
1 parent f008143 commit 917ff11
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 10 deletions.
176 changes: 171 additions & 5 deletions lib/libpthread/pthread.c
@@ -1,4 +1,4 @@
/* $NetBSD: pthread.c,v 1.10 2003/02/22 00:53:29 nathanw Exp $ */
/* $NetBSD: pthread.c,v 1.11 2003/02/26 22:02:48 thorpej Exp $ */

/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
Expand Down Expand Up @@ -102,6 +102,12 @@ void *pthread__static_lib_binder[] = {
&pthread__nanosleeping
};

/* Private data for pthread_attr_t */
struct pthread_attr_private {
char ptap_name[PTHREAD_MAX_NAMELEN_NP];
void *ptap_namearg;
};

/*
* This needs to be started by the library loading code, before main()
* gets to run, for various things that use the state of the initial thread
Expand Down Expand Up @@ -206,6 +212,7 @@ pthread__initthread(pthread_t self, pthread_t t)
pthread_lockinit(&t->pt_join_lock);
PTQ_INIT(&t->pt_cleanup_stack);
memset(&t->pt_specific, 0, sizeof(int) * PTHREAD_KEYS_MAX);
t->pt_name = NULL;
#ifdef PTHREAD__DEBUG
t->blocks = 0;
t->preempts = 0;
Expand All @@ -220,6 +227,8 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
{
pthread_t self, newthread;
pthread_attr_t nattr;
struct pthread_attr_private *p;
char *name;
int ret;

PTHREADD_ADD(PTHREADD_CREATE);
Expand All @@ -241,6 +250,14 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
else
return EINVAL;

/* Fetch misc. attributes from the attr structure. */
if ((p = nattr.pta_private) != NULL) {
if (p->ptap_name[0] != '\0') {
if ((name = strdup(p->ptap_name)) == NULL)
return ENOMEM;
} else
name = NULL;
}

self = pthread__self();

Expand All @@ -262,8 +279,11 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
newthread->pt_flags = nattr.pta_flags;
newthread->pt_sigmask = self->pt_sigmask;

/* 3. Set up misc. attributes. */
newthread->pt_name = name;

/*
* 3. Set up context.
* 4. Set up context.
*
* The pt_uc pointer points to a location safely below the
* stack start; this is arranged by pthread__stackalloc().
Expand All @@ -274,14 +294,14 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
makecontext(newthread->pt_uc, pthread__create_tramp, 2,
startfunc, arg);

/* 4. Add to list of all threads. */
/* 5. Add to list of all threads. */
pthread_spinlock(self, &pthread__allqueue_lock);
PTQ_INSERT_HEAD(&pthread__allqueue, newthread, pt_allq);
nthreads++;
pthread_spinunlock(self, &pthread__allqueue_lock);

SDPRINTF(("(pthread_create %p) Created new thread %p.\n", self, newthread));
/* 5. Put on run queue. */
/* 6. Put on run queue. */
pthread__sched(self, newthread);

*thread = newthread;
Expand Down Expand Up @@ -348,6 +368,7 @@ pthread_exit(void *retval)
{
pthread_t self;
struct pt_clean_t *cleanup;
char *name;
int nt;

self = pthread__self();
Expand All @@ -371,8 +392,13 @@ pthread_exit(void *retval)

pthread_spinlock(self, &self->pt_join_lock);
if (self->pt_flags & PT_FLAG_DETACHED) {
name = self->pt_name;
self->pt_name = NULL;
pthread_spinunlock(self, &self->pt_join_lock);

if (name != NULL)
free(name);

pthread_spinlock(self, &pthread__allqueue_lock);
PTQ_REMOVE(&pthread__allqueue, self, pt_allq);
nthreads--;
Expand All @@ -390,6 +416,7 @@ pthread_exit(void *retval)
PTQ_INSERT_HEAD(&pthread__deadqueue, self, pt_allq);
pthread__block(self, &pthread__deadqueue_lock);
} else {
/* Note: name will be freed by the joiner. */
pthread_spinlock(self, &pthread__allqueue_lock);
nthreads--;
nt = nthreads;
Expand Down Expand Up @@ -417,6 +444,7 @@ int
pthread_join(pthread_t thread, void **valptr)
{
pthread_t self;
char *name;
int num;

self = pthread__self();
Expand Down Expand Up @@ -475,6 +503,8 @@ pthread_join(pthread_t thread, void **valptr)

/* All ours. */
thread->pt_state = PT_STATE_DEAD;
name = thread->pt_name;
thread->pt_name = NULL;
pthread_spinunlock(self, &thread->pt_join_lock);

if (valptr != NULL)
Expand All @@ -491,6 +521,9 @@ pthread_join(pthread_t thread, void **valptr)
PTQ_INSERT_HEAD(&pthread__deadqueue, thread, pt_allq);
pthread_spinunlock(self, &pthread__deadqueue_lock);

if (name != NULL)
free(name);

return 0;
}

Expand Down Expand Up @@ -535,21 +568,110 @@ pthread_detach(pthread_t thread)
}


int
pthread_getname_np(pthread_t thread, char *name, size_t len)
{
pthread_t self;

self = pthread__self();

if (pthread__find(self, thread) != 0)
return ESRCH;

if (thread->pt_magic != PT_MAGIC)
return EINVAL;

pthread_spinlock(self, &thread->pt_join_lock);
if (thread->pt_name == NULL)
name[0] = '\0';
else
strlcpy(name, thread->pt_name, len);
pthread_spinunlock(self, &thread->pt_join_lock);

return 0;
}


int
pthread_setname_np(pthread_t thread, const char *name, void *arg)
{
pthread_t self = pthread_self();
char *oldname, *cp, newname[PTHREAD_MAX_NAMELEN_NP];
int namelen;

if (pthread__find(self, thread) != 0)
return ESRCH;

if (thread->pt_magic != PT_MAGIC)
return EINVAL;

namelen = snprintf(newname, sizeof(newname), name, arg);
if (namelen >= PTHREAD_MAX_NAMELEN_NP)
return EINVAL;

cp = strdup(newname);
if (cp == NULL)
return ENOMEM;

pthread_spinlock(self, &thread->pt_join_lock);

if (thread->pt_state == PT_STATE_DEAD) {
pthread_spinunlock(self, &thread->pt_join_lock);
free(cp);
return EINVAL;
}

oldname = thread->pt_name;
thread->pt_name = cp;

pthread_spinunlock(self, &thread->pt_join_lock);

if (oldname != NULL)
free(oldname);

return 0;
}


static struct pthread_attr_private *
pthread__attr_init_private(pthread_attr_t *attr)
{
struct pthread_attr_private *p;

if ((p = attr->pta_private) != NULL)
return p;

p = malloc(sizeof(*p));
if (p != NULL) {
memset(p, 0, sizeof(*p));
attr->pta_private = p;
}
return p;
}


int
pthread_attr_init(pthread_attr_t *attr)
{

attr->pta_magic = PT_ATTR_MAGIC;
attr->pta_flags = 0;
attr->pta_private = NULL;

return 0;
}


int
/*ARGSUSED*/
pthread_attr_destroy(pthread_attr_t *attr)
{
struct pthread_attr_private *p;

if ((attr == NULL) || (attr->pta_magic != PT_ATTR_MAGIC))
return EINVAL;

if ((p = attr->pta_private) != NULL)
free(p);

return 0;
}
Expand Down Expand Up @@ -624,6 +746,50 @@ pthread_attr_getschedparam(const pthread_attr_t *attr,
}


int
pthread_attr_getname_np(const pthread_attr_t *attr, char *name, size_t len,
void **argp)
{
struct pthread_attr_private *p;

if ((attr == NULL) || (attr->pta_magic != PT_ATTR_MAGIC))
return EINVAL;

if ((p = attr->pta_private) == NULL) {
name[0] = '\0';
if (argp != NULL)
*argp = NULL;
} else {
strlcpy(name, p->ptap_name, len);
if (argp != NULL)
*argp = p->ptap_namearg;
}

return 0;
}


int
pthread_attr_setname_np(pthread_attr_t *attr, const char *name, void *arg)
{
struct pthread_attr_private *p;
int namelen;

p = pthread__attr_init_private(attr);
if (p == NULL)
return ENOMEM;

namelen = snprintf(p->ptap_name, PTHREAD_MAX_NAMELEN_NP, name, arg);
if (namelen >= PTHREAD_MAX_NAMELEN_NP) {
p->ptap_name[0] = '\0';
return EINVAL;
}
p->ptap_namearg = arg;

return 0;
}


/*
* XXX There should be a way for applications to use the efficent
* inline version, but there are opacity/namespace issues.
Expand Down
13 changes: 12 additions & 1 deletion lib/libpthread/pthread.h
@@ -1,4 +1,4 @@
/* $NetBSD: pthread.h,v 1.8 2003/02/13 02:50:48 nathanw Exp $ */
/* $NetBSD: pthread.h,v 1.9 2003/02/26 22:02:48 thorpej Exp $ */

/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
Expand Down Expand Up @@ -69,6 +69,9 @@ int pthread_attr_setschedparam(pthread_attr_t *,
const struct sched_param *);
int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
int pthread_attr_setdetachstate(pthread_attr_t *, int);
int pthread_attr_getname_np(const pthread_attr_t *, char *,
size_t, void **);
int pthread_attr_setname_np(pthread_attr_t *, const char *, void *);

int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
int pthread_mutex_destroy(pthread_mutex_t *);
Expand Down Expand Up @@ -102,6 +105,9 @@ int pthread_setcancelstate(int, int *);
int pthread_setcanceltype(int, int *);
void pthread_testcancel(void);

int pthread_getname_np(pthread_t, char *, size_t);
int pthread_setname_np(pthread_t, const char *, void *);

struct pthread_cleanup_store {
void *pad[4];
};
Expand Down Expand Up @@ -176,6 +182,11 @@ __END_DECLS
#define PTHREAD_STACK_MIN 4096 /* XXX Pulled out of my butt */
#define PTHREAD_THREADS_MAX 64 /* Min. required */

/*
* Maximum length of a thread's name, including the terminating NUL.
*/
#define PTHREAD_MAX_NAMELEN_NP 32

/*
* Mutex attributes.
*/
Expand Down
7 changes: 5 additions & 2 deletions lib/libpthread/pthread_int.h
@@ -1,4 +1,4 @@
/* $NetBSD: pthread_int.h,v 1.8 2003/02/15 21:18:59 jdolecek Exp $ */
/* $NetBSD: pthread_int.h,v 1.9 2003/02/26 22:02:48 thorpej Exp $ */

/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
Expand Down Expand Up @@ -112,10 +112,13 @@ struct pthread_st {
/* Stack of cancellation cleanup handlers and their arguments */
PTQ_HEAD(, pt_clean_t) pt_cleanup_stack;

/* Thread's name, set by the application. */
char* pt_name;

/* Other threads trying to pthread_join() us. */
struct pthread_queue_t pt_joiners;
/* Lock for above, and for changing pt_state to ZOMBIE or DEAD,
* and for setting the DETACHED flag
* and for setting the DETACHED flag. Also protects pt_name.
*/
pthread_spin_t pt_join_lock;

Expand Down
4 changes: 2 additions & 2 deletions lib/libpthread/shlib_version
@@ -1,5 +1,5 @@
# $NetBSD: shlib_version,v 1.3 2003/01/20 20:10:20 christos Exp $
# $NetBSD: shlib_version,v 1.4 2003/02/26 22:02:48 thorpej Exp $
# Remember to update distrib/sets/lists/base/shl.* when changing
#
major=0
minor=1
minor=2

0 comments on commit 917ff11

Please sign in to comment.