source: trunk/source/lisp-kernel/Threads.h @ 11184

Last change on this file since 11184 was 11184, checked in by gb, 12 years ago

#include <sys/syscall.h> on Linux. use gettid() (which is only
available via syscall) for get_current_native_thread_id() on Linux.
(These thread IDs are what're used by GDB's 'info threads' command;
they're pid's from the linux kernel's perspective, but threads within
a process all see the same value returned by getpid() in modern Linux.)
Fall back to getpid() if the syscall isn't defined, but I'm not sure
that we can run on something so old that the syscall wouldn't be defined.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.9 KB
Line 
1/*
2   Copyright (C) 1994-2001 Digitool, Inc
3   This file is part of OpenMCL. 
4
5   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
6   License , known as the LLGPL and distributed with OpenMCL as the
7   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
8   which is distributed with OpenMCL as the file "LGPL".  Where these
9   conflict, the preamble takes precedence. 
10
11   OpenMCL is referenced in the preamble as the "LIBRARY."
12
13   The LLGPL is also available online at
14   http://opensource.franz.com/preamble.html
15*/
16
17#include <stdlib.h>
18#ifndef WINDOWS
19#include <unistd.h>
20#include <sys/mman.h>
21#endif
22#undef __argv
23#include <stdio.h>
24#ifndef WINDOWS
25#include <pthread.h>
26#endif
27#ifdef WINDOWS
28#include <process.h>
29#endif
30#include <errno.h>
31#include <limits.h>
32
33#ifdef SOLARIS
34#include <sys/syscall.h>
35#include <sys/lwp.h>
36#endif
37
38#ifdef LINUX
39#include <sys/syscall.h>
40#endif
41
42#undef USE_MACH_SEMAPHORES
43#define USE_POSIX_SEMAPHORES
44#undef USE_WINDOWS_SEMAPHORES
45
46#ifdef DARWIN
47#define USE_MACH_SEMAPHORES 1
48#undef  USE_POSIX_SEMAPHORES
49#endif
50#ifdef WINDOWS
51#define USE_WINDOWS_SEMAPHORES 1
52#undef USE_POSIX_SEMAPHORES
53#ifdef WIN_32
54struct timespec {
55  int tv_sec;
56  int tv_nsec;
57};
58#endif
59#endif
60
61#ifdef USE_POSIX_SEMAPHORES
62#include <semaphore.h>
63#endif
64
65
66#ifdef USE_MACH_SEMAPHORES
67/* We have to use Mach semaphores, even if we're otherwise
68   using POSIX signals, etc. */
69#include <mach/task.h>
70#include <mach/semaphore.h>
71#endif
72
73#include <limits.h>
74
75#ifdef FREEBSD
76#include <pthread_np.h>
77#endif
78
79#ifndef WINDOWS
80#include <sched.h>
81#endif
82
83#include "lisp.h"
84#include "lisp_globals.h"
85#include "gc.h"
86
87#ifdef USE_FUTEX
88#ifndef FUTEX_WAIT
89#define FUTEX_WAIT (0)
90#endif
91#ifndef FUTEX_WAKE
92#define FUTEX_WAKE (1)
93#endif
94#include <sys/syscall.h>
95#endif
96
97#ifndef WINDOWS
98#include <syslog.h>
99#endif
100
101Boolean extern threads_initialized;
102Boolean extern log_tcr_info;
103
104#define LOCK_SPINLOCK(x,tcr) get_spin_lock(&(x),tcr)
105#define RELEASE_SPINLOCK(x) (x)=0
106
107#define TCR_TO_TSD(tcr) ((void *)((natural)(tcr)+TCR_BIAS))
108#define TCR_FROM_TSD(tsd) ((TCR *)((natural)(tsd)-TCR_BIAS))
109
110#ifdef USE_WINDOWS_SEMAPHORES
111
112typedef void * SEMAPHORE;
113#define SEM_WAIT(s) WaitForSingleObject(s,INFINITE)
114#define SEM_RAISE(s) ReleaseSemaphore(s, 1L, NULL)
115#define SEM_BROADCAST(s, count) do {while(count) {SEM_RAISE(s);(count)--;}}while(0)
116#define SEM_TIMEDWAIT(s,t) WaitOnSingleObject(s,t)
117
118#endif
119#ifdef USE_POSIX_SEMAPHORES
120typedef sem_t * SEMAPHORE;
121#define SEM_WAIT(s) sem_wait((SEMAPHORE)s)
122#define SEM_RAISE(s) sem_post((SEMAPHORE)s)
123#define SEM_BROADCAST(s, count) do {while(count) {SEM_RAISE(s);(count)--;}}while(0)
124#define SEM_TIMEDWAIT(s,t) sem_timedwait((SEMAPHORE)s,(struct timespec *)t)
125#endif
126
127#ifdef USE_MACH_SEMAPHORES
128typedef semaphore_t SEMAPHORE;
129#define SEM_WAIT(s) semaphore_wait((SEMAPHORE)(natural)s)
130#define SEM_RAISE(s) semaphore_signal((SEMAPHORE)(natural)s)
131#define SEM_BROADCAST(s,count)semaphore_signal_all((SEMAPHORE)(natural)s)
132#define SEM_TIMEDWAIT(s,t) semaphore_timedwait((SEMAPHORE)(natural)s,t)
133#endif
134
135void sem_wait_forever(SEMAPHORE s);
136
137#ifdef USE_POSIX_SEMAPHORES
138#define SEM_WAIT_FOREVER(s) sem_wait_forever((SEMAPHORE)s)
139#endif
140
141#ifdef USE_MACH_SEMAPHORES
142#define SEM_WAIT_FOREVER(s) sem_wait_forever((SEMAPHORE)(natural)s)
143#endif
144
145#ifdef USE_WINDOWS_SEMAPHORES
146#define SEM_WAIT_FOREVER(s) sem_wait_forever((SEMAPHORE)s)
147#endif
148
149typedef struct
150{
151  signed_natural avail;
152  TCR* owner;
153  signed_natural  count;
154  void* signal;
155  signed_natural waiting;
156  void *malloced_ptr;
157  signed_natural spinlock;
158} _recursive_lock, *RECURSIVE_LOCK;
159
160
161int lock_recursive_lock(RECURSIVE_LOCK, TCR *);
162int unlock_recursive_lock(RECURSIVE_LOCK, TCR *);
163RECURSIVE_LOCK new_recursive_lock(void);
164void destroy_recursive_lock(RECURSIVE_LOCK);
165int recursive_lock_trylock(RECURSIVE_LOCK, TCR *, int *);
166
167#define LOCK(m, t) lock_recursive_lock((RECURSIVE_LOCK)ptr_from_lispobj(m), (TCR *)t)
168#define UNLOCK(m, t) unlock_recursive_lock((RECURSIVE_LOCK)ptr_from_lispobj(m), (TCR *)t)
169
170/* Hmm.  This doesn't look like the MacOS Thread Manager ... */
171LispObj current_thread_osid(void);
172void *current_native_thread_id(void);
173void *new_semaphore(int);
174void destroy_semaphore(void**);
175void tsd_set(LispObj, void *);
176void *tsd_get(LispObj);
177TCR *new_tcr(natural, natural);
178TCR *initial_thread_tcr;
179
180#define DEFAULT_THREAD_STACK_SIZE ((size_t) -1)
181#define MINIMAL_THREAD_STACK_SIZE ((size_t) 0)
182
183
184LispObj create_system_thread(size_t stack_size, 
185                             void* stackaddr,
186#ifdef WINDOWS
187                             unsigned CALLBACK (*start_routine)(void *)
188#else
189                             void* (*start_routine)(void *)
190#endif
191                             ,
192                             void* param);
193
194TCR *get_tcr(Boolean);
195TCR *get_interrupt_tcr(Boolean);
196Boolean suspend_tcr(TCR *);
197Boolean resume_tcr(TCR *);
198
199typedef struct
200{
201  signed_natural spin; /* need spin lock to change fields */
202  signed_natural state; /* 0 = free, positive if writer, negative if readers; */
203  natural blocked_writers;
204  natural blocked_readers;
205  TCR  *writer;
206#ifdef USE_FUTEX
207  natural reader_signal;
208  natural writer_signal;
209#else
210  void * reader_signal;
211  void * writer_signal;
212#endif
213  void *malloced_ptr;
214} rwlock;
215
216
217rwlock * rwlock_new(void);
218void rwlock_destroy(rwlock *);
219int rwlock_rlock(rwlock *, TCR *, struct timespec *);
220int rwlock_wlock(rwlock *, TCR *, struct timespec *);
221int rwlock_try_wlock(rwlock *, TCR *);
222int rwlock_try_rlock(rwlock *, TCR *);
223int rwlock_unlock(rwlock *, TCR *);
224
225
226natural
227atomic_and(natural*, natural);
228
229natural
230atomic_ior(natural*, natural);
231
232#define SET_TCR_FLAG(t,bit) atomic_ior(&(t->flags),(1L<<bit))
233#define CLR_TCR_FLAG(t,bit) atomic_and(&(t->flags),~(1L<<bit))
234
235
236#if defined(SIGRTMIN) && !defined(SOLARIS)
237#define SIG_SUSPEND_THREAD (SIGRTMIN+6)
238#else
239#define SIG_SUSPEND_THREAD SIGUSR2
240#endif
241
242extern int thread_suspend_signal, thread_resume_signal;
243
244void *
245allocate_stack(natural);
246
247void
248suspend_resume_handler(int, siginfo_t *, ExceptionInformation *);
249
250/* Maybe later
251Boolean
252rwlock_try_rlock(rwlock *);
253
254Boolean
255rwlock_try_wlock(rwlock *);
256*/
Note: See TracBrowser for help on using the repository browser.