Remove the dual-callback scheme for numeric and pointer thread IDs,
deprecate the original (numeric-only) scheme, and replace with the
CRYPTO_THREADID object. This hides the platform-specifics and should reduce
the possibility for programming errors (where failing to explicitly check
both thread ID forms could create subtle, platform-specific bugs).

Thanks to Bodo, for invaluable review and feedback.
diff --git a/crypto/err/err.c b/crypto/err/err.c
index f615cb4..69713a6 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -429,13 +429,13 @@
 
 static unsigned long err_state_hash(const ERR_STATE *a)
 	{
-	return (a->pid + (unsigned long)a->pidptr) * 13;
+	return CRYPTO_THREADID_hash(&a->tid) * 13;
 	}
 static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE)
 
 static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b)
 	{
-	return (a->pid != b->pid) || (a->pidptr != b->pidptr);
+	return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
 	}
 static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE)
 
@@ -980,40 +980,37 @@
 	return((p == NULL)?NULL:p->string);
 	}
 
-void ERR_remove_state(unsigned long pid)
+void ERR_remove_thread_state(const CRYPTO_THREADID *id)
 	{
 	ERR_STATE tmp;
-	void *pidptr;
 
-	err_fns_check();
-	if (pid != 0)
-		pidptr = &errno;
+	if (id)
+		CRYPTO_THREADID_cpy(&tmp.tid, id);
 	else
-		{
-		pid = CRYPTO_thread_id();
-		pidptr = CRYPTO_thread_idptr();
-		}
-	
-	tmp.pid=pid;
-	tmp.pidptr=pidptr;
+		CRYPTO_THREADID_current(&tmp.tid);
+	err_fns_check();
 	/* thread_del_item automatically destroys the LHASH if the number of
 	 * items reaches zero. */
 	ERRFN(thread_del_item)(&tmp);
 	}
 
+#ifndef OPENSSL_NO_DEPRECATED
+void ERR_remove_state(unsigned long pid)
+	{
+	ERR_remove_thread_state(NULL);
+	}
+#endif
+
 ERR_STATE *ERR_get_state(void)
 	{
 	static ERR_STATE fallback;
 	ERR_STATE *ret,tmp,*tmpp=NULL;
 	int i;
-	unsigned long pid;
-	void *pidptr;
+	CRYPTO_THREADID tid;
 
 	err_fns_check();
-	pid = CRYPTO_thread_id();
-	pidptr = CRYPTO_thread_idptr();
-	tmp.pid = pid;
-	tmp.pidptr = pidptr;
+	CRYPTO_THREADID_current(&tid);
+	CRYPTO_THREADID_cpy(&tmp.tid, &tid);
 	ret=ERRFN(thread_get_item)(&tmp);
 
 	/* ret == the error state, if NULL, make a new one */
@@ -1021,8 +1018,7 @@
 		{
 		ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
 		if (ret == NULL) return(&fallback);
-		ret->pid=pid;
-		ret->pidptr=pidptr;
+		CRYPTO_THREADID_cpy(&ret->tid, &tid);
 		ret->top=0;
 		ret->bottom=0;
 		for (i=0; i<ERR_NUM_ERRORS; i++)
diff --git a/crypto/err/err.h b/crypto/err/err.h
index 942f820..006351d 100644
--- a/crypto/err/err.h
+++ b/crypto/err/err.h
@@ -147,8 +147,7 @@
 #define ERR_NUM_ERRORS	16
 typedef struct err_state_st
 	{
-	unsigned long pid;
-	void *pidptr; /* new in OpenSSL 0.9.9 */
+	CRYPTO_THREADID tid;
 	int err_flags[ERR_NUM_ERRORS];
 	unsigned long err_buffer[ERR_NUM_ERRORS];
 	char *err_data[ERR_NUM_ERRORS];
@@ -351,7 +350,10 @@
 void ERR_load_crypto_strings(void);
 void ERR_free_strings(void);
 
+void ERR_remove_thread_state(const CRYPTO_THREADID *tid);
+#ifndef OPENSSL_NO_DEPRECATED
 void ERR_remove_state(unsigned long pid); /* if zero we look it up */
+#endif
 ERR_STATE *ERR_get_state(void);
 
 #ifndef OPENSSL_NO_LHASH
diff --git a/crypto/err/err_prn.c b/crypto/err/err_prn.c
index 2224a90..de32f33 100644
--- a/crypto/err/err_prn.c
+++ b/crypto/err/err_prn.c
@@ -72,8 +72,10 @@
 	const char *file,*data;
 	int line,flags;
 	unsigned long es;
+	CRYPTO_THREADID cur;
 
-	es=CRYPTO_thread_id();
+	CRYPTO_THREADID_current(&cur);
+	es=CRYPTO_THREADID_hash(&cur);
 	while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
 		{
 		ERR_error_string_n(l, buf, sizeof buf);