thread_os2.h 5.7 KB
Newer Older
Guido van Rossum's avatar
Guido van Rossum committed
1 2 3 4 5 6 7 8 9
/* This code implemented by cvale@netcom.com */

#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#include "os2.h"
#include "limits.h"

#include "process.h"

10 11 12 13
#if defined(PYCC_GCC)
#include <sys/builtin.h>
#include <sys/fmutex.h>
#else
14
long PyThread_get_thread_ident(void);
15
#endif
Guido van Rossum's avatar
Guido van Rossum committed
16

17
/* default thread stack size of 64kB */
18
#if !defined(THREAD_STACK_SIZE)
19
#define THREAD_STACK_SIZE       0x10000
20 21
#endif

22
#define OS2_STACKSIZE(x)        (x ? x : THREAD_STACK_SIZE)
23

Guido van Rossum's avatar
Guido van Rossum committed
24 25 26
/*
 * Initialization of the C package, should not be needed.
 */
27 28
static void
PyThread__init_thread(void)
Guido van Rossum's avatar
Guido van Rossum committed
29 30 31 32 33 34
{
}

/*
 * Thread support.
 */
35
long
36
PyThread_start_new_thread(void (*func)(void *), void *arg)
Guido van Rossum's avatar
Guido van Rossum committed
37
{
38
    int thread_id;
Guido van Rossum's avatar
Guido van Rossum committed
39

40 41 42 43
    thread_id = _beginthread(func,
                            NULL,
                            OS2_STACKSIZE(_pythread_stacksize),
                            arg);
Guido van Rossum's avatar
Guido van Rossum committed
44

45 46 47
    if (thread_id == -1) {
        dprintf(("_beginthread failed. return %ld\n", errno));
    }
Guido van Rossum's avatar
Guido van Rossum committed
48

49
    return thread_id;
Guido van Rossum's avatar
Guido van Rossum committed
50 51
}

52 53
long
PyThread_get_thread_ident(void)
Guido van Rossum's avatar
Guido van Rossum committed
54
{
55
#if !defined(PYCC_GCC)
56 57
    PPIB pib;
    PTIB tib;
58
#endif
Guido van Rossum's avatar
Guido van Rossum committed
59

60 61
    if (!initialized)
        PyThread_init_thread();
62

63
#if defined(PYCC_GCC)
64
    return _gettid();
65
#else
66 67
    DosGetInfoBlocks(&tib, &pib);
    return tib->tib_ptib2->tib2_ultid;
68
#endif
Guido van Rossum's avatar
Guido van Rossum committed
69 70
}

71 72
void
PyThread_exit_thread(void)
Guido van Rossum's avatar
Guido van Rossum committed
73
{
74 75 76 77 78
    dprintf(("%ld: PyThread_exit_thread called\n",
             PyThread_get_thread_ident()));
    if (!initialized)
        exit(0);
    _endthread();
Guido van Rossum's avatar
Guido van Rossum committed
79 80 81
}

/*
82
 * Lock support.  This is implemented with an event semaphore and critical
83
 * sections to make it behave more like a posix mutex than its OS/2
84
 * counterparts.
Guido van Rossum's avatar
Guido van Rossum committed
85
 */
86 87

typedef struct os2_lock_t {
88 89
    int is_set;
    HEV changed;
90 91
} *type_os2_lock;

92
PyThread_type_lock
93
PyThread_allocate_lock(void)
Guido van Rossum's avatar
Guido van Rossum committed
94
{
95
#if defined(PYCC_GCC)
96 97 98 99 100 101 102 103 104 105 106
    _fmutex *sem = malloc(sizeof(_fmutex));
    if (!initialized)
        PyThread_init_thread();
    dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
             PyThread_get_thread_ident(),
             (long)sem));
    if (_fmutex_create(sem, 0)) {
        free(sem);
        sem = NULL;
    }
    return (PyThread_type_lock)sem;
107
#else
108 109
    APIRET rc;
    type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
Guido van Rossum's avatar
Guido van Rossum committed
110

111 112 113
    dprintf(("PyThread_allocate_lock called\n"));
    if (!initialized)
        PyThread_init_thread();
Guido van Rossum's avatar
Guido van Rossum committed
114

115
    lock->is_set = 0;
Guido van Rossum's avatar
Guido van Rossum committed
116

117
    DosCreateEventSem(NULL, &lock->changed, 0, 0);
Guido van Rossum's avatar
Guido van Rossum committed
118

119 120 121
    dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
             PyThread_get_thread_ident(),
             lock->changed));
122

123
    return (PyThread_type_lock)lock;
124
#endif
Guido van Rossum's avatar
Guido van Rossum committed
125 126
}

127
void
128
PyThread_free_lock(PyThread_type_lock aLock)
Guido van Rossum's avatar
Guido van Rossum committed
129
{
130
#if !defined(PYCC_GCC)
131
    type_os2_lock lock = (type_os2_lock)aLock;
132 133
#endif

134 135
    dprintf(("%ld: PyThread_free_lock(%p) called\n",
             PyThread_get_thread_ident(),aLock));
Guido van Rossum's avatar
Guido van Rossum committed
136

137
#if defined(PYCC_GCC)
138 139 140 141
    if (aLock) {
        _fmutex_close((_fmutex *)aLock);
        free((_fmutex *)aLock);
    }
142
#else
143 144
    DosCloseEventSem(lock->changed);
    free(aLock);
145
#endif
Guido van Rossum's avatar
Guido van Rossum committed
146 147 148 149 150
}

/*
 * Return 1 on success if the lock was acquired
 *
151
 * and 0 if the lock was not acquired.
Guido van Rossum's avatar
Guido van Rossum committed
152
 */
153
int
154
PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
Guido van Rossum's avatar
Guido van Rossum committed
155
{
156
#if !defined(PYCC_GCC)
157 158 159 160 161
    int   done = 0;
    ULONG count;
    PID   pid = 0;
    TID   tid = 0;
    type_os2_lock lock = (type_os2_lock)aLock;
162
#endif
Guido van Rossum's avatar
Guido van Rossum committed
163

164 165 166 167
    dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
             PyThread_get_thread_ident(),
             aLock,
             waitflag));
Guido van Rossum's avatar
Guido van Rossum committed
168

169
#if defined(PYCC_GCC)
170 171 172 173
    /* always successful if the lock doesn't exist */
    if (aLock &&
        _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
        return 0;
174
#else
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
    while (!done) {
        /* if the lock is currently set, we have to wait for
         * the state to change
         */
        if (lock->is_set) {
            if (!waitflag)
                return 0;
            DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
        }

        /* enter a critical section and try to get the semaphore.  If
         * it is still locked, we will try again.
         */
        if (DosEnterCritSec())
            return 0;

        if (!lock->is_set) {
            lock->is_set = 1;
            DosResetEventSem(lock->changed, &count);
            done = 1;
        }

        DosExitCritSec();
    }
199
#endif
Guido van Rossum's avatar
Guido van Rossum committed
200

201
    return 1;
Guido van Rossum's avatar
Guido van Rossum committed
202 203
}

204 205
void
PyThread_release_lock(PyThread_type_lock aLock)
Guido van Rossum's avatar
Guido van Rossum committed
206
{
207
#if !defined(PYCC_GCC)
208
    type_os2_lock lock = (type_os2_lock)aLock;
209 210
#endif

211 212 213
    dprintf(("%ld: PyThread_release_lock(%p) called\n",
             PyThread_get_thread_ident(),
             aLock));
Guido van Rossum's avatar
Guido van Rossum committed
214

215
#if defined(PYCC_GCC)
216 217
    if (aLock)
        _fmutex_release((_fmutex *)aLock);
218
#else
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    if (!lock->is_set) {
        dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
                 PyThread_get_thread_ident(),
                 aLock,
                 GetLastError()));
        return;
    }

    if (DosEnterCritSec()) {
        dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
                 PyThread_get_thread_ident(),
                 aLock,
                 GetLastError()));
        return;
    }

    lock->is_set = 0;
    DosPostEventSem(lock->changed);

    DosExitCritSec();
239
#endif
Guido van Rossum's avatar
Guido van Rossum committed
240
}
241 242

/* minimum/maximum thread stack sizes supported */
243 244
#define THREAD_MIN_STACKSIZE    0x8000          /* 32kB */
#define THREAD_MAX_STACKSIZE    0x2000000       /* 32MB */
245 246 247 248 249 250 251

/* set the thread stack size.
 * Return 0 if size is valid, -1 otherwise.
 */
static int
_pythread_os2_set_stacksize(size_t size)
{
252 253 254 255 256 257 258 259 260 261 262 263 264
    /* set to default */
    if (size == 0) {
        _pythread_stacksize = 0;
        return 0;
    }

    /* valid range? */
    if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
        _pythread_stacksize = size;
        return 0;
    }

    return -1;
265 266
}

267
#define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x)