win32: Garbage-collect pthreads_win32.[ch]

This commit is contained in:
Douglas Katzman 2020-09-01 05:31:47 -04:00
parent a603c8462e
commit 544548c21c
4 changed files with 0 additions and 783 deletions

View file

@ -8,90 +8,6 @@
#include <time.h>
#include <sys/time.h>
#ifdef PTHREAD_DEBUG_OUTPUT
#define pthshow(fmt,...) \
do { \
fprintf(stderr,fmt "\n", __VA_ARGS__); \
fflush(stderr); \
} while (0)
#define DEBUG_OWN(cs) do {(cs)->owner=pthread_self(); } while(0)
#define DEBUG_RELEASE(cs) do {(cs)->owner=0;} while(0)
#else
#define pthshow(fmt,...) do {} while (0)
#define DEBUG_OWN(cs) do {} while(0)
#define DEBUG_RELEASE(cs) do {} while(0)
#endif
struct freelist_cell {
struct freelist_cell * next;
void* data;
};
struct freelist {
void* (*create_fn)();
CRITICAL_SECTION lock;
struct freelist_cell * empty;
struct freelist_cell * full;
unsigned int count;
};
#define mutex_lock(x) EnterCriticalSection(x)
#define mutex_unlock(x) LeaveCriticalSection(x)
static void* freelist_get(struct freelist *fl)
{
void* result = NULL;
if (fl->full) {
mutex_lock(&fl->lock);
if (fl->full) {
struct freelist_cell *cell = fl->full;
fl->full = cell->next;
result = cell->data;
cell->next = fl->empty;
fl->empty = cell;
}
mutex_unlock(&fl->lock);
}
if (!result) {
result = fl->create_fn();
}
return result;
}
static void freelist_return(struct freelist *fl, void*data)
{
struct freelist_cell* cell = NULL;
if (fl->empty) {
mutex_lock(&fl->lock);
if (fl->empty) {
cell = fl->empty;
fl->empty = cell->next;
goto add_locked;
}
mutex_unlock(&fl->lock);
}
if (!cell) {
int i,n=32;
cell = malloc(sizeof(*cell)*n);
for (i=0; i<(n-1); ++i)
cell[i].next = &cell[i+1];
cell[i].next = NULL;
}
mutex_lock(&fl->lock);
++fl->count;
add_locked:
cell->data = data;
cell->next = fl->full;
fl->full = cell;
mutex_unlock(&fl->lock);
}
typedef unsigned char boolean;
/* TLS management internals */
DWORD thread_self_tls_index;
@ -168,43 +84,6 @@ int _sbcl_pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset)
return 0;
}
static CRITICAL_SECTION mutex_init_lock;
int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * attr)
{
*mutex = (struct _pthread_mutex_info*)malloc(sizeof(struct _pthread_mutex_info));
InitializeCriticalSection(&(*mutex)->cs);
(*mutex)->file = " (free) ";
return 0;
}
int pthread_mutexattr_init(pthread_mutexattr_t* attr)
{
return 0;
}
int pthread_mutexattr_destroy(pthread_mutexattr_t* attr)
{
return 0;
}
int pthread_mutexattr_settype(pthread_mutexattr_t* attr,int mutex_type)
{
return 0;
}
struct _pthread_mutex_info DEAD_MUTEX;
int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
if (*mutex != PTHREAD_MUTEX_INITIALIZER) {
pthread_np_assert_live_mutex(mutex,"destroy");
DeleteCriticalSection(&(*mutex)->cs);
free(*mutex);
*mutex = &DEAD_MUTEX;
}
return 0;
}
/* Add pending signal to (other) thread */
void pthread_np_add_pending_signal(pthread_t thread, int signum)
{
@ -244,452 +123,6 @@ sigset_t pthread_np_other_thread_sigpending(pthread_t thread)
0, 0);
}
/* Mutex implementation uses CRITICAL_SECTIONs. Somethings to keep in
mind: (1) uncontested locking is cheap; (2) long wait on a busy
lock causes exception, so it should never be attempted; (3) those
mutexes are recursive; (4) one thread locks, the other unlocks ->
the next one hangs. */
int pthread_mutex_lock(pthread_mutex_t *mutex)
{
pthread_np_assert_live_mutex(mutex,"lock");
if (*mutex == PTHREAD_MUTEX_INITIALIZER) {
mutex_lock(&mutex_init_lock);
if (*mutex == PTHREAD_MUTEX_INITIALIZER) {
pthread_mutex_init(mutex, NULL);
}
mutex_unlock(&mutex_init_lock);
}
EnterCriticalSection(&(*mutex)->cs);
DEBUG_OWN(*mutex);
return 0;
}
int pthread_mutex_trylock(pthread_mutex_t *mutex)
{
pthread_np_assert_live_mutex(mutex,"trylock");
if (*mutex == PTHREAD_MUTEX_INITIALIZER) {
mutex_lock(&mutex_init_lock);
if (*mutex == PTHREAD_MUTEX_INITIALIZER) {
pthread_mutex_init(mutex, NULL);
}
mutex_unlock(&mutex_init_lock);
}
if (TryEnterCriticalSection(&(*mutex)->cs)) {
DEBUG_OWN(*mutex);
return 0;
}
else
return EBUSY;
}
/* Versions of lock/trylock useful for debugging. Our header file
conditionally redefines lock/trylock to call them. */
int pthread_mutex_lock_annotate_np(pthread_mutex_t *mutex, const char* file, int line)
{
int contention = 0;
pthread_np_assert_live_mutex(mutex,"lock");
if (*mutex == PTHREAD_MUTEX_INITIALIZER) {
mutex_lock(&mutex_init_lock);
if (*mutex == PTHREAD_MUTEX_INITIALIZER) {
pthread_mutex_init(mutex, NULL);
pthshow("Mutex #x%p: automatic initialization; #x%p %s +%d",
mutex, *mutex,
file, line);
}
mutex_unlock(&mutex_init_lock);
}
if ((*mutex)->owner) {
pthshow("Mutex #x%p -> #x%p: contention; owned by #x%p, wanted by #x%p",
mutex, *mutex,
(*mutex)->owner,
pthread_self());
pthshow("Mutex #x%p -> #x%p: contention notes: old %s +%d, new %s +%d",
mutex, *mutex,
(*mutex)->file,(*mutex)->line, file, line);
contention = 1;
}
EnterCriticalSection(&(*mutex)->cs);
if (contention) {
pthshow("Mutex #x%p -> #x%p: contention end; left by #x%p, taken by #x%p",
mutex, *mutex,
(*mutex)->owner,
pthread_self());
pthshow("Mutex #x%p -> #x%p: contention notes: old %s +%d, new %s +%d",
mutex, *mutex,
(*mutex)->file,(*mutex)->line, file, line);
}
(*mutex)->owner = pthread_self();
(*mutex)->file = file;
(*mutex)->line = line;
return 0;
}
int pthread_mutex_trylock_annotate_np(pthread_mutex_t *mutex, const char* file, int line)
{
int contention = 0;
pthread_np_assert_live_mutex(mutex,"trylock");
if (*mutex == PTHREAD_MUTEX_INITIALIZER) {
mutex_lock(&mutex_init_lock);
if (*mutex == PTHREAD_MUTEX_INITIALIZER) {
pthread_mutex_init(mutex, NULL);
}
mutex_unlock(&mutex_init_lock);
}
if ((*mutex)->owner) {
pthshow("Mutex #x%p -> #x%p: tried contention; owned by #x%p, wanted by #x%p",
mutex, *mutex,
(*mutex)->owner,
pthread_self());
pthshow("Mutex #x%p -> #x%p: contention notes: old %s +%d, new %s +%d",
mutex, *mutex,
(*mutex)->file,(*mutex)->line, file, line);
contention = 1;
}
if (TryEnterCriticalSection(&(*mutex)->cs)) {
if (contention) {
pthshow("Mutex #x%p -> #x%p: contention end; left by #x%p, taken by #x%p",
mutex, *mutex,
(*mutex)->owner,
pthread_self());
pthshow("Mutex #x%p -> #x%p: contention notes: old %s +%d, new %s +%d",
mutex, *mutex,
(*mutex)->file,(*mutex)->line, file, line);
}
(*mutex)->owner = pthread_self();
(*mutex)->file = file;
(*mutex)->line = line;
return 0;
}
else
return EBUSY;
}
int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
/* Owner is for debugging only; NB if mutex is used recursively,
owner field will lie. */
pthread_np_assert_live_mutex(mutex,"unlock");
DEBUG_RELEASE(*mutex);
LeaveCriticalSection(&(*mutex)->cs);
return 0;
}
/* Condition variables implemented with events and wakeup queues. */
/* .info field in wakeup record is an "opportunistic" indicator that
wakeup has happened. On timeout from WaitForSingleObject, thread
doesn't know (1) whether to reset event, (2) whether to (try) to
find and unlink wakeup record. Let's let it know (of course,
it will know for sure only under cv_wakeup_lock). */
#define WAKEUP_WAITING_NOTIMEOUT 0
#define WAKEUP_WAITING_TIMEOUT 4
#define WAKEUP_HAPPENED 1
#define WAKEUP_BY_INTERRUPT 2
static void* event_create()
{
return (void*)CreateEvent(NULL,FALSE,FALSE,NULL);
}
static struct freelist event_freelist;
unsigned int pthread_free_event_pool_size()
{
return event_freelist.count;
}
static HANDLE fe_get_event()
{
return (HANDLE)freelist_get(&event_freelist);
}
static void fe_return_event(HANDLE handle)
{
freelist_return(&event_freelist, (void*)handle);
}
static HANDLE cv_default_event_get_fn()
{
pthread_thread *self = pthread_self();
HANDLE event = self->cv_event;
if (!event) {
event = CreateEvent(NULL, FALSE, FALSE, NULL);
self->cv_event = event;
} else {
/* ResetEvent(event); used to be here. Let's try without. It's
safe in pthread_cond_wait: if WaitForSingleObjectEx ever
returns, event is reset automatically, and the wakeup queue item
is removed by the signaller under wakeup_lock.
pthread_cond_timedwait should reset the event if
cv_wakeup_remove failed to find its wakeup record, otherwise
it's safe too. */
}
return event;
}
static void cv_default_event_return_fn(HANDLE event)
{
/* ResetEvent(event); could be here as well (and used to be).
Avoiding syscalls makes sense, however. */
}
static pthread_condattr_t cv_default_attr = {
0, /* alertable */
fe_get_event,
fe_return_event,
/* cv_default_event_get_fn, /\* get_fn *\/ */
/* cv_default_event_return_fn /\* return_fn *\/ */
};
int pthread_cond_init(pthread_cond_t * cv, const pthread_condattr_t * attr)
{
if (!attr)
attr = &cv_default_attr;
InitializeCriticalSection(&cv->wakeup_lock);
cv->first_wakeup = NULL;
cv->last_wakeup = NULL;
cv->alertable = attr->alertable;
cv->get_fn = attr->get_fn;
cv->return_fn = attr->return_fn;
return 0;
}
int pthread_condattr_init(pthread_condattr_t *attr)
{
*attr = cv_default_attr;
return 0;
}
int pthread_condattr_destroy(pthread_condattr_t *attr)
{
return 0;
}
int pthread_condattr_setevent_np(pthread_condattr_t *attr,
cv_event_get_fn get_fn, cv_event_return_fn ret_fn)
{
attr->get_fn = get_fn ? get_fn : fe_get_event;// cv_default_event_get_fn;
attr->return_fn = ret_fn ? ret_fn : fe_return_event; // cv_default_event_return_fn;
return 0;
}
int pthread_cond_destroy(pthread_cond_t *cv)
{
return 0;
}
int pthread_cond_broadcast(pthread_cond_t *cv)
{
int count = 0;
HANDLE postponed[128];
int npostponed = 0,i;
/* No strict requirements to memory visibility model, because of
mutex unlock around waiting. */
if (!cv->first_wakeup)
return 0;
mutex_lock(&cv->wakeup_lock);
while (cv->first_wakeup)
{
struct thread_wakeup * w = cv->first_wakeup;
HANDLE waitevent = w->event;
cv->first_wakeup = w->next;
w->info = WAKEUP_HAPPENED;
postponed[npostponed++] = waitevent;
if (/* w->info == WAKEUP_WAITING_TIMEOUT || */ npostponed ==
sizeof(postponed)/sizeof(postponed[0])) {
for (i=0; i<npostponed; ++i)
SetEvent(postponed[i]);
npostponed = 0;
}
++count;
}
cv->last_wakeup = NULL;
mutex_unlock(&cv->wakeup_lock);
for (i=0; i<npostponed; ++i)
SetEvent(postponed[i]);
return 0;
}
int pthread_cond_signal(pthread_cond_t *cv)
{
struct thread_wakeup * w;
/* No strict requirements to memory visibility model, because of
mutex unlock around waiting. */
if (!cv->first_wakeup)
return 0;
mutex_lock(&cv->wakeup_lock);
w = cv->first_wakeup;
if (w) {
HANDLE waitevent = w->event;
cv->first_wakeup = w->next;
if (!cv->first_wakeup)
cv->last_wakeup = NULL;
w->info = WAKEUP_HAPPENED;
SetEvent(waitevent);
}
mutex_unlock(&cv->wakeup_lock);
return 0;
}
/* Return value is used for futexes: 0=ok, 1 on unexpected word change. */
int cv_wakeup_add(struct pthread_cond_t* cv, struct thread_wakeup* w)
{
HANDLE event;
w->next = NULL;
mutex_lock(&cv->wakeup_lock);
if (w->uaddr) {
if (w->uval != *w->uaddr) {
mutex_unlock(&cv->wakeup_lock);
return 1;
}
pthread_self()->futex_wakeup = w;
}
event = cv->get_fn();
w->event = event;
if (cv->last_wakeup == w) {
fprintf(stderr, "cv->last_wakeup == w\n");
fflush(stderr);
ExitProcess(0);
}
if (cv->last_wakeup != NULL)
{
cv->last_wakeup->next = w;
cv->last_wakeup = w;
}
else
{
cv->first_wakeup = w;
cv->last_wakeup = w;
}
mutex_unlock(&cv->wakeup_lock);
return 0;
}
/* Return true if wakeup found, false if missing */
int cv_wakeup_remove(struct pthread_cond_t* cv, struct thread_wakeup* w)
{
int result = 0;
if (w->info == WAKEUP_HAPPENED || w->info == WAKEUP_BY_INTERRUPT)
goto finish;
mutex_lock(&cv->wakeup_lock);
{
if (w->info == WAKEUP_HAPPENED || w->info == WAKEUP_BY_INTERRUPT)
goto unlock;
if (cv->first_wakeup == w) {
cv->first_wakeup = w->next;
if (cv->last_wakeup == w)
cv->last_wakeup = NULL;
result = 1;
} else {
struct thread_wakeup * prev = cv->first_wakeup;
while (prev && prev->next != w)
prev = prev->next;
if (!prev) {
goto unlock;
}
prev->next = w->next;
if (cv->last_wakeup == w)
cv->last_wakeup = prev;
result = 1;
}
}
unlock:
mutex_unlock(&cv->wakeup_lock);
finish:
return result;
}
int pthread_cond_wait(pthread_cond_t * cv, pthread_mutex_t * cs)
{
struct thread_wakeup w;
w.uaddr = 0;
w.info = WAKEUP_WAITING_NOTIMEOUT;
cv_wakeup_add(cv, &w);
if (cv->last_wakeup->next == cv->last_wakeup) {
pthread_np_lose(5,"cv->last_wakeup->next == cv->last_wakeup\n");
}
if (cv->last_wakeup->next != NULL) {
pthread_np_lose(5,"cv->last_wakeup->next == cv->last_wakeup\n");
}
pthread_self()->waiting_cond = cv;
DEBUG_RELEASE(*cs);
pthread_mutex_unlock(cs);
do {
if (cv->alertable) {
while (WaitForSingleObjectEx(w.event, INFINITE, TRUE) == WAIT_IO_COMPLETION);
} else {
WaitForSingleObject(w.event, INFINITE);
}
} while (w.info == WAKEUP_WAITING_NOTIMEOUT);
pthread_self()->waiting_cond = NULL;
/* Event is signalled once, wakeup is dequeued by signaller. */
cv->return_fn(w.event);
pthread_mutex_lock(cs);
DEBUG_OWN(*cs);
return 0;
}
int pthread_cond_timedwait(pthread_cond_t * cv, pthread_mutex_t * cs,
const struct timespec * abstime)
{
DWORD rv;
struct thread_wakeup w;
pthread_t self = pthread_self();
w.info = WAKEUP_WAITING_TIMEOUT;
w.uaddr = 0;
cv_wakeup_add(cv, &w);
if (cv->last_wakeup->next == cv->last_wakeup) {
fprintf(stderr, "cv->last_wakeup->next == cv->last_wakeup\n");
ExitProcess(0);
}
self->waiting_cond = cv;
DEBUG_RELEASE(*cs);
/* barrier (release); waiting_cond globally visible */
pthread_mutex_unlock(cs);
{
struct timeval cur_tm;
long sec, msec;
gettimeofday(&cur_tm, NULL);
sec = abstime->tv_sec - cur_tm.tv_sec;
msec = sec * 1000 + abstime->tv_nsec / 1000000 - cur_tm.tv_usec / 1000;
if (msec < 0)
msec = 0;
do {
if (cv->alertable) {
while ((rv = WaitForSingleObjectEx(w.event, msec, TRUE))
== WAIT_IO_COMPLETION);
} else {
rv = WaitForSingleObject(w.event, msec);
}
} while (rv == WAIT_OBJECT_0 && w.info == WAKEUP_WAITING_TIMEOUT);
}
self->waiting_cond = NULL;
if (rv == WAIT_TIMEOUT) {
if (!cv_wakeup_remove(cv, &w)) {
/* Someone removed our wakeup record: though we got a timeout,
event was (will be) signalled before we are here.
Consume this wakeup. */
WaitForSingleObject(w.event, INFINITE);
}
}
cv->return_fn(w.event);
pthread_mutex_lock(cs);
DEBUG_OWN(*cs);
if (rv == WAIT_TIMEOUT)
return ETIMEDOUT;
else
return 0;
}
int sched_yield()
{
/* http://stackoverflow.com/questions/1383943/switchtothread-vs-sleep1
@ -703,7 +136,6 @@ int sched_yield()
void pthreads_win32_init()
{
thread_self_tls_index = TlsAlloc();
InitializeCriticalSection(&mutex_init_lock);
pthread_np_notice_thread();
}
@ -712,7 +144,6 @@ VOID CALLBACK pthreads_win32_unnotice(void* parameter, BOOLEAN timerOrWait)
{
pthread_t pth = parameter;
if (pth->cv_event) CloseHandle(pth->cv_event);
CloseHandle(pth->handle);
UnregisterWait(pth->wait_handle);
@ -780,77 +211,4 @@ int sigpending(sigset_t *set)
return 0;
}
void pthread_np_lose(int trace_depth, const char* fmt, ...)
{
va_list header;
void* frame;
int n = 0;
void** lastseh;
va_start(header,fmt);
vfprintf(stderr,fmt,header);
for (lastseh = *(void**)NtCurrentTeb();
lastseh && (lastseh!=(void*)0xFFFFFFFF);
lastseh = *lastseh);
fprintf(stderr, "Backtrace: %s (pthread %p)\n", header, pthread_self());
for (frame = __builtin_frame_address(0); frame; frame=*(void**)frame)
{
if ((n++)>trace_depth)
return;
fprintf(stderr, "[#%02d]: ebp = %p, ret = %p\n",n,
frame, ((void**)frame)[1]);
}
ExitProcess(0);
}
int
sem_init(sem_t *sem, int pshared_not_implemented, unsigned int value)
{
sem_t semh = CreateSemaphore(NULL, value, SEM_VALUE_MAX, NULL);
if (!semh)
return -1;
*sem = semh;
return 0;
}
int
sem_post(sem_t *sem)
{
return !ReleaseSemaphore(*sem, 1, NULL);
}
static int
sem_wait_timeout(sem_t *sem, DWORD ms)
{
switch (WaitForSingleObject(*sem, ms)) {
case WAIT_OBJECT_0:
return 0;
case WAIT_TIMEOUT:
/* errno = EAGAIN; */
return -1;
default:
/* errno = EINVAL; */
return -1;
}
}
int
sem_wait(sem_t *sem)
{
return sem_wait_timeout(sem, INFINITE);
}
int
sem_trywait(sem_t *sem)
{
return sem_wait_timeout(sem, 0);
}
int
sem_destroy(sem_t *sem)
{
return !CloseHandle(*sem);
}
#endif

View file

@ -50,23 +50,12 @@ typedef int sigset_t;
#define NSIG 32 /* maximum signal number + 1 */
#endif
/* To avoid overusing system TLS, pthread provides its own */
#define PTHREAD_KEYS_MAX 128
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
#define PTHREAD_STACK_MIN 0
void pthreads_win32_init();
/* 1 - Thread */
typedef struct pthread_thread* pthread_t;
typedef int pthread_attr_t; /* arbitrary */
typedef void (*pthread_cleanup_fn)(void* arg);
int pthread_equal(pthread_t thread1, pthread_t thread2);
int pthread_kill(pthread_t thread, int signum);
@ -85,58 +74,6 @@ extern DWORD thread_self_tls_index;
int _sbcl_pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
#endif
/* 2 - Mutex */
typedef struct _pthread_mutex_info {
char padding[64];
CRITICAL_SECTION cs;
pthread_t owner;
const char* file;
int line;
} __attribute__((aligned(128))) *pthread_mutex_t;
typedef int pthread_mutexattr_t;
#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)-1)
int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * attr);
int pthread_mutexattr_init(pthread_mutexattr_t*);
int pthread_mutexattr_destroy(pthread_mutexattr_t*);
int pthread_mutexattr_settype(pthread_mutexattr_t*, int);
#define PTHREAD_MUTEX_ERRORCHECK 0
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_lock_annotate_np(pthread_mutex_t *mutex, const char* file, int line);
int pthread_mutex_trylock_annotate_np(pthread_mutex_t *mutex, const char* file, int line);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
/* 3 - Condition variable */
typedef struct thread_wakeup {
HANDLE event;
struct thread_wakeup *next;
volatile intptr_t *uaddr;
intptr_t uval;
int info;
} thread_wakeup;
typedef HANDLE (*cv_event_get_fn)();
typedef void (*cv_event_return_fn)(HANDLE event);
typedef struct pthread_cond_t {
CRITICAL_SECTION wakeup_lock;
struct thread_wakeup *first_wakeup;
struct thread_wakeup *last_wakeup;
unsigned char alertable;
cv_event_get_fn get_fn;
cv_event_return_fn return_fn;
} pthread_cond_t;
typedef struct pthread_condattr_t {
unsigned char alertable;
cv_event_get_fn get_fn;
cv_event_return_fn return_fn;
} pthread_condattr_t;
#ifndef _TIMESPEC_DEFINED
typedef struct timespec {
time_t tv_sec;
@ -144,18 +81,6 @@ typedef struct timespec {
} timespec;
#endif
// not implemented: PTHREAD_COND_INITIALIZER
int pthread_condattr_init(pthread_condattr_t *attr);
int pthread_condattr_destroy(pthread_condattr_t *attr);
int pthread_condattr_setevent_np(pthread_condattr_t *attr,
cv_event_get_fn get_fn, cv_event_return_fn ret_fn);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, const struct timespec * abstime);
int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex);
/* some MinGWs seem to include it, others not: */
#ifndef ETIMEDOUT
# define ETIMEDOUT 123 //Something
@ -163,16 +88,9 @@ int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex);
int sched_yield();
void pthread_lock_structures();
void pthread_unlock_structures();
typedef void *(*pthread_fn)(void*);
typedef struct pthread_thread {
HANDLE handle;
struct thread *vm_thread;
pthread_cond_t *waiting_cond;
void *futex_wakeup;
sigset_t blocked_signal_set;
volatile sigset_t pending_signal_set;
@ -182,8 +100,6 @@ typedef struct pthread_thread {
/* Thread TEB base (mostly informative/debugging) */
void* teb;
HANDLE cv_event;
} pthread_thread;
typedef struct {
@ -219,28 +135,6 @@ int sigismember(const sigset_t *set, int signum);
typedef int sig_atomic_t;
/* Debugging */
void pthread_np_lose(int trace_depth, const char* fmt, ...);
extern struct _pthread_mutex_info DEAD_MUTEX;
static inline void pthread_np_assert_live_mutex(pthread_mutex_t* ptr,
const char *action)
{
if (*ptr == &DEAD_MUTEX) {
pthread_np_lose(5,"Trying to %s dead mutex %p\n",action,ptr);
}
}
typedef HANDLE sem_t;
#define SEM_VALUE_MAX (int) (~0U >>1)
int sem_init(sem_t *sem, int pshared_not_implemented, unsigned int value);
int sem_post(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_destroy(sem_t *sem);
#ifndef PTHREAD_INTERNALS
static inline int _sbcl_pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset)
{
@ -263,36 +157,5 @@ static inline int _sbcl_pthread_sigmask(int how, const sigset_t *set, sigset_t *
return 0;
}
#ifdef PTHREAD_DEBUG_OUTPUT
#define pthread_mutex_lock(mutex) \
pthread_mutex_lock_annotate_np(mutex, __FILE__, __LINE__ )
#define pthread_mutex_trylock(mutex) \
pthread_mutex_trylock_annotate_np(mutex, __FILE__ ,__LINE__)
#else
/* I'm not after inlinining _everything_, but those two things below are
(1) fast, (2) critical (3) short */
static inline int pthread_mutex_lock_np_inline(pthread_mutex_t *mutex)
{
pthread_np_assert_live_mutex(mutex,"lock");
if ((*mutex) == PTHREAD_MUTEX_INITIALIZER) {
return pthread_mutex_lock(mutex);
} else {
EnterCriticalSection(&(*mutex)->cs);
return 0;
}
}
static inline int pthread_mutex_unlock_np_inline(pthread_mutex_t *mutex)
{
pthread_np_assert_live_mutex(mutex,"unlock");
LeaveCriticalSection(&(*mutex)->cs);
return 0;
}
#define pthread_mutex_lock pthread_mutex_lock_np_inline
#define pthread_mutex_unlock pthread_mutex_unlock_np_inline
#endif /* !PTHREAD_DEBUG_OUTPUT */
#endif /* !PTHREAD_INTERNALS */
#endif /* WIN32_PTHREAD_INCLUDED */

View file

@ -456,7 +456,6 @@ unregister_thread(struct thread *th,
set_thread_self(self); \
struct thread* th = self->vm_thread
#define THREAD_TRAMPOLINE_EPILOGUE \
if (self->cv_event) CloseHandle(self->cv_event); \
free_thread_struct(th); \
HANDLE h = self->handle; \
free(self); \

View file

@ -30,9 +30,6 @@
#ifdef LISP_FEATURE_SB_THREAD
#include "pthreads_win32.h"
/* prevent inclusion of a mingw semaphore.h */
#define CANNOT_USE_POSIX_SEM_T
typedef sem_t os_sem_t;
#else
typedef void *siginfo_t;
typedef int sigset_t;