diff -urN pth-orig/pth.h.in pth/pth.h.in --- pth-orig/pth.h.in Sat Jan 1 20:15:05 2005 +++ pth/pth.h.in Wed Jan 12 10:13:29 2005 @@ -187,6 +187,7 @@ #define PTH_EVENT_COND _BIT(7) #define PTH_EVENT_TID _BIT(8) #define PTH_EVENT_FUNC _BIT(9) +#define PTH_EVENT_SEM _BIT(10) /* event occurange restrictions */ #define PTH_UNTIL_OCCURRED _BIT(11) @@ -197,6 +198,8 @@ #define PTH_UNTIL_TID_READY _BIT(16) #define PTH_UNTIL_TID_WAITING _BIT(17) #define PTH_UNTIL_TID_DEAD _BIT(18) +#define PTH_UNTIL_DECREMENT _BIT(19) +#define PTH_UNTIL_COUNT _BIT(23) /* event structure handling modes */ #define PTH_MODE_REUSE _BIT(20) @@ -264,6 +267,10 @@ #define PTH_COND_HANDLED _BIT(3) #define PTH_COND_INIT { PTH_COND_INITIALIZED, 0 } + /* semaphore variable values */ +#define PTH_SEM_INITIALIZED _BIT(0) +#define PTH_SEM_INIT { PTH_SEM_INITIALIZED, 0 } + /* barrier variable values */ #define PTH_BARRIER_INITIALIZED _BIT(0) #define PTH_BARRIER_INIT(threshold) { PTH_BARRIER_INITIALIZED, \ @@ -311,6 +318,13 @@ unsigned int cn_waiters; }; + /* the semaphore variable structure */ +typedef struct pth_sem_st pth_sem_t; +struct pth_sem_st { /* not hidden to avoid destructor */ + unsigned long sem_state; + unsigned int sem_count; +}; + /* the barrier variable structure */ typedef struct pth_barrier_st pth_barrier_t; struct pth_barrier_st { /* not hidden to avoid destructor */ @@ -501,6 +515,13 @@ extern int pth_cond_notify(pth_cond_t *, int); extern int pth_barrier_init(pth_barrier_t *, int); extern int pth_barrier_reach(pth_barrier_t *); +extern int pth_sem_init(pth_sem_t *); +extern int pth_sem_dec(pth_sem_t *); +extern int pth_sem_dec_value(pth_sem_t *, unsigned); +extern int pth_sem_inc(pth_sem_t *, int); +extern int pth_sem_inc_value(pth_sem_t *, unsigned, int); +extern int pth_sem_set_value(pth_sem_t *, unsigned); +extern int pth_sem_get_value(pth_sem_t *, unsigned *); /* user-space context functions */ extern int pth_uctx_create(pth_uctx_t *); diff -urN pth-orig/pth_event.c pth/pth_event.c --- pth-orig/pth_event.c Sat Jan 1 20:15:06 2005 +++ pth/pth_event.c Thu Jan 13 14:01:05 2005 @@ -51,6 +51,7 @@ struct { pth_cond_t *cond; } COND; struct { pth_t tid; } TID; struct { pth_event_func_t func; void *arg; pth_time_t tv; } FUNC; + struct { pth_sem_t *sem; unsigned count; } SEM; } ev_args; }; @@ -204,6 +205,20 @@ ev->ev_args.FUNC.arg = va_arg(ap, void *); ev->ev_args.FUNC.tv = va_arg(ap, pth_time_t); } + else if (spec & PTH_EVENT_SEM) { + /* semaphore variable */ + pth_sem_t *sem = va_arg(ap, pth_sem_t *); + if (spec & PTH_UNTIL_COUNT) + ev->ev_args.SEM.count = va_arg(ap, unsigned); + else + ev->ev_args.SEM.count = 1; + ev->ev_type = PTH_EVENT_SEM; + if (spec & PTH_UNTIL_DECREMENT) + ev->ev_goal = PTH_UNTIL_DECREMENT; + else + ev->ev_goal = PTH_UNTIL_OCCURRED; + ev->ev_args.SEM.sem = sem; + } else return pth_error((pth_event_t)NULL, EINVAL); @@ -277,6 +292,11 @@ *arg = ev->ev_args.FUNC.arg; *tv = ev->ev_args.FUNC.tv; } + else if (ev->ev_type & PTH_EVENT_SEM) { + /* condition variable */ + pth_sem_t **sem = va_arg(ap, pth_sem_t **); + *sem = ev->ev_args.SEM.sem; + } else return pth_error(FALSE, EINVAL); va_end(ap); diff -urN pth-orig/pth_sched.c pth/pth_sched.c --- pth-orig/pth_sched.c Sat Jan 1 20:15:06 2005 +++ pth/pth_sched.c Thu Jan 13 14:05:13 2005 @@ -540,6 +540,17 @@ } } } + /* Semaphore */ + else if (ev->ev_type == PTH_EVENT_SEM) { + if (ev->ev_args.SEM.sem->sem_state & PTH_SEM_INITIALIZED) { + if (ev->ev_args.SEM.sem->sem_count >= ev->ev_args.SEM.count) + { + this_occurred = TRUE; + if(ev->ev_goal & PTH_UNTIL_DECREMENT) + ev->ev_args.SEM.sem->sem_count -= ev->ev_args.SEM.count; + } + } + } /* Thread Termination */ else if (ev->ev_type == PTH_EVENT_TID) { if ( ( ev->ev_args.TID.tid == NULL diff -urN pth-orig/pth_sync.c pth/pth_sync.c --- pth-orig/pth_sync.c Sat Jan 1 20:15:06 2005 +++ pth/pth_sync.c Thu Jan 13 13:54:49 2005 @@ -380,3 +380,84 @@ return rv; } +/* +** Semaphore Variables +*/ + +int pth_sem_init(pth_sem_t *sem) +{ + if (sem == NULL) + return pth_error(FALSE, EINVAL); + sem->sem_state = PTH_SEM_INITIALIZED; + sem->sem_count = 0; + return TRUE; +} + +int pth_sem_dec(pth_sem_t * sem) +{ + return pth_sem_dec_value(sem, 1); +} + +int pth_sem_dec_value(pth_sem_t * sem, unsigned count) +{ + static pth_key_t ev_key = PTH_KEY_INIT; + pth_event_t ev; + /* consistency checks */ + if (sem == NULL) + return pth_error(FALSE, EINVAL); + if (!(sem->sem_state & PTH_SEM_INITIALIZED)) + return pth_error(FALSE, EDEADLK); + + ev = pth_event(PTH_EVENT_SEM|PTH_UNTIL_DECREMENT|PTH_UNTIL_COUNT|PTH_MODE_STATIC, &ev_key, sem,count); + pth_wait(ev); + return TRUE; +} + +int pth_sem_inc(pth_sem_t * sem, int yield) +{ + return pth_sem_inc_value(sem, 1, yield); +} + +int pth_sem_inc_value(pth_sem_t * sem, unsigned count, int yield) +{ + /* consistency checks */ + if (sem == NULL) + return pth_error(FALSE, EINVAL); + if (!(sem->sem_state & PTH_SEM_INITIALIZED)) + return pth_error(FALSE, EDEADLK); + + sem->sem_count+=count; + if(yield) + pth_yield(NULL); + return TRUE; +} + +int pth_sem_set_value(pth_sem_t * sem, unsigned value) +{ + /* consistency checks */ + if (sem == NULL) + return pth_error(FALSE, EINVAL); + if (!(sem->sem_state & PTH_SEM_INITIALIZED)) + return pth_error(FALSE, EDEADLK); + + sem->sem_count = value; + return TRUE; +} + +int pth_sem_get_value(pth_sem_t * sem, unsigned *value) +{ + /* consistency checks */ + if (sem == NULL) + return pth_error(FALSE, EINVAL); + if (!(sem->sem_state & PTH_SEM_INITIALIZED)) + return pth_error(FALSE, EDEADLK); + + if (value == NULL) + return pth_error(FALSE, EINVAL); + + *value = sem->sem_count; + return TRUE; +} + + +