2 |
|
* sheepthreads.c - Minimal pthreads implementation (libpthreads doesn't |
3 |
|
* like nonstandard stacks) |
4 |
|
* |
5 |
< |
* SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig |
5 |
> |
* SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig |
6 |
|
* |
7 |
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
* it under the terms of the GNU General Public License as published by |
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 |
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) |
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; |
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 |