ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/Linux/sheepthreads.c
(Generate patch)

Comparing SheepShaver/src/Unix/Linux/sheepthreads.c (file contents):
Revision 1.1 by cebix, 2002-02-04T16:58:13Z vs.
Revision 1.4 by gbeauche, 2004-01-04T16:27:50Z

# Line 51 | Line 51 | extern int test_and_set(int *var, int va
51   extern int __clone(int (*fn)(void *), void *, int, void *);
52  
53   /* struct sem_t */
54 + #define status __status
55 + #define spinlock __spinlock
56   #define sem_lock __sem_lock
57   #define sem_value __sem_value
58   #define sem_waiting __sem_waiting
59  
60 + /* Wait for "clone" children only (Linux 2.4+ specific) */
61 + #ifndef __WCLONE
62 + #define __WCLONE 0
63 + #endif
64 +
65  
66   /*
67   *  Return pthread ID of self
# Line 135 | Line 142 | int pthread_create(pthread_t *thread, co
142   int pthread_join(pthread_t thread, void **ret)
143   {
144          do {
145 <                if (waitpid(thread, NULL, 0) >= 0)
145 >                if (waitpid(thread, NULL, __WCLONE) >= 0);
146                          break;
147          } while (errno == EINTR);
148          if (ret)
# Line 168 | Line 175 | void pthread_testcancel(void)
175   *  Spinlocks
176   */
177  
178 + static int try_acquire_spinlock(int *lock)
179 + {
180 +        return test_and_set(lock, 1) == 0;
181 + }
182 +
183   static void acquire_spinlock(volatile int *lock)
184   {
185          do {
# Line 182 | Line 194 | static void release_spinlock(int *lock)
194  
195  
196   /*
197 + *  Initialize mutex
198 + */
199 +
200 + int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr)
201 + {
202 +        // pthread_init_lock
203 +        mutex->__m_lock.__status = 0;
204 +        mutex->__m_lock.__spinlock = 0;
205 +
206 +        mutex->__m_kind = mutex_attr ? mutex_attr->__mutexkind : PTHREAD_MUTEX_TIMED_NP;
207 +        mutex->__m_count = 0;
208 +        mutex->__m_owner = NULL;
209 +        return 0;
210 + }
211 +
212 +
213 + /*
214 + *  Destroy mutex
215 + */
216 +
217 + int pthread_mutex_destroy(pthread_mutex_t *mutex)
218 + {
219 +        switch (mutex->__m_kind) {
220 +        case PTHREAD_MUTEX_TIMED_NP:
221 +                return (mutex->__m_lock.__status != 0) ? EBUSY : 0;
222 +        default:
223 +                return EINVAL;
224 +        }
225 + }
226 +
227 +
228 + /*
229 + *  Lock mutex
230 + */
231 +
232 + int pthread_mutex_lock(pthread_mutex_t *mutex)
233 + {
234 +        switch (mutex->__m_kind) {
235 +        case PTHREAD_MUTEX_TIMED_NP:
236 +                acquire_spinlock(&mutex->__m_lock.__spinlock);
237 +                return 0;
238 +        default:
239 +                return EINVAL;
240 +        }
241 + }
242 +
243 +
244 + /*
245 + *  Try to lock mutex
246 + */
247 +
248 + int pthread_mutex_trylock(pthread_mutex_t *mutex)
249 + {
250 +        switch (mutex->__m_kind) {
251 +        case PTHREAD_MUTEX_TIMED_NP:
252 +                if (!try_acquire_spinlock(&mutex->__m_lock.__spinlock))
253 +                        return EBUSY;
254 +                return 0;
255 +        default:
256 +                return EINVAL;
257 +        }
258 + }
259 +
260 +
261 + /*
262 + *  Unlock mutex
263 + */
264 +
265 + int pthread_mutex_unlock(pthread_mutex_t *mutex)
266 + {
267 +        switch (mutex->__m_kind) {
268 +        case PTHREAD_MUTEX_TIMED_NP:
269 +                release_spinlock(&mutex->__m_lock.__spinlock);
270 +                return 0;
271 +        default:
272 +                return EINVAL;
273 +        }
274 + }
275 +
276 +
277 + /*
278 + *  Create mutex attribute
279 + */
280 +
281 + int pthread_mutexattr_init(pthread_mutexattr_t *attr)
282 + {
283 +        attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP;
284 +        return 0;
285 + }
286 +
287 +
288 + /*
289 + *  Destroy mutex attribute
290 + */
291 +
292 + int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
293 + {
294 +        return 0;
295 + }
296 +
297 +
298 + /*
299   *  Init semaphore
300   */
301  
# Line 216 | Line 330 | void null_handler(int sig)
330   int sem_wait(sem_t *sem)
331   {
332          acquire_spinlock(&sem->sem_lock.spinlock);
333 <        if (atomic_add((int *)&sem->sem_value, -1) >= 0) {
333 >        if (sem->sem_value > 0)
334 >                atomic_add((int *)&sem->sem_value, -1);
335 >        else {
336                  sigset_t mask;
337                  if (!sem->sem_lock.status) {
338                          struct sigaction sa;
# Line 243 | Line 359 | int sem_wait(sem_t *sem)
359   int sem_post(sem_t *sem)
360   {
361          acquire_spinlock(&sem->sem_lock.spinlock);
362 <        atomic_add((int *)&sem->sem_value, 1);
363 <        if (sem->sem_waiting)
362 >        if (sem->sem_waiting == NULL)
363 >                atomic_add((int *)&sem->sem_value, 1);
364 >        else
365                  kill((pid_t)sem->sem_waiting, sem->sem_lock.status);
366          release_spinlock(&sem->sem_lock.spinlock);
367          return 0;
368   }
369 +
370 +
371 + /*
372 + *  Simple producer/consumer test program
373 + */
374 +
375 + #ifdef TEST
376 + #include <stdio.h>
377 +
378 + static sem_t p_sem, c_sem;
379 + static int data = 0;
380 +
381 + static void *producer_func(void *arg)
382 + {
383 +        int i, n = (int)arg;
384 +        for (i = 0; i < n; i++) {
385 +                sem_wait(&p_sem);
386 +                data++;
387 +                sem_post(&c_sem);
388 +        }
389 +        return NULL;
390 + }
391 +
392 + static void *consumer_func(void *arg)
393 + {
394 +        int i, n = (int)arg;
395 +        for (i = 0; i < n; i++) {
396 +                sem_wait(&c_sem);
397 +                printf("data: %d\n", data);
398 +                sem_post(&p_sem);
399 +        }
400 +        sleep(1); // for testing pthread_join()
401 +        return NULL;
402 + }
403 +
404 + int main(void)
405 + {
406 +        pthread_t producer_thread, consumer_thread;
407 +        static const int N = 5;
408 +
409 +        if (sem_init(&c_sem, 0, 0) < 0)
410 +                return 1;
411 +        if (sem_init(&p_sem, 0, 1) < 0)
412 +                return 2;
413 +        if (pthread_create(&producer_thread, NULL, producer_func, (void *)N) != 0)
414 +                return 3;
415 +        if (pthread_create(&consumer_thread, NULL, consumer_func, (void *)N) != 0)
416 +                return 4;
417 +        pthread_join(producer_thread, NULL);
418 +        pthread_join(consumer_thread, NULL);
419 +        sem_destroy(&p_sem);
420 +        sem_destroy(&c_sem);
421 +        if (data != N)
422 +                return 5;
423 +        return 0;
424 + }
425 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines