Group folders
This commit is contained in:
parent
fcca47f043
commit
68a39a090c
9 changed files with 133 additions and 0 deletions
112
src/PREEMPTIVE/sem.c
Executable file
112
src/PREEMPTIVE/sem.c
Executable file
|
@ -0,0 +1,112 @@
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* file: sem.c *
|
||||||
|
* *
|
||||||
|
* Module implementing semaphores. *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#include "sem.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
pthread_mutex_t sem_mutex; /* protect sem module from race conditions */
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* INTERFACE: sem_create() *
|
||||||
|
* *
|
||||||
|
* Make and return a semaphore (i.e. return a pointer to a Sem struct). *
|
||||||
|
************************************************************************/
|
||||||
|
Sem *sem_create(int val)
|
||||||
|
{
|
||||||
|
Sem *s;
|
||||||
|
static int firstcall = 1;
|
||||||
|
|
||||||
|
/* We, perhaps naively, assume that sem_create() will not be
|
||||||
|
* called concurrently!
|
||||||
|
*/
|
||||||
|
if (firstcall) {
|
||||||
|
firstcall = 0;
|
||||||
|
pthread_mutex_init(&sem_mutex, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val < 0) return (Sem *)0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&sem_mutex);
|
||||||
|
|
||||||
|
if ((s = (Sem *)malloc(sizeof(Sem))) == (Sem *)0) {
|
||||||
|
return (Sem *)0;
|
||||||
|
}
|
||||||
|
s->val = val;
|
||||||
|
pthread_cond_init(&s->cond, NULL);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&sem_mutex);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* INTERFACE: sem_destroy() *
|
||||||
|
* *
|
||||||
|
* Destroy a semaphore. *
|
||||||
|
* Forbid destruction (return -1) if the semaphore has waiting threads. *
|
||||||
|
* Otherwise return 1 for success. *
|
||||||
|
************************************************************************/
|
||||||
|
int
|
||||||
|
sem_destroy(Sem *s)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&sem_mutex);
|
||||||
|
|
||||||
|
if (s->val < 0) {
|
||||||
|
/* Mustn't destroy a semaphore with waiting threads
|
||||||
|
* on it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&sem_mutex);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pthread_cond_destroy(&s->cond);
|
||||||
|
free((void *)s);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&sem_mutex);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* INTERFACE: sem_P() *
|
||||||
|
* *
|
||||||
|
* Do a P on a semaphore(!) *
|
||||||
|
************************************************************************/
|
||||||
|
void
|
||||||
|
sem_P(Sem *s)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&sem_mutex);
|
||||||
|
|
||||||
|
if (--s->val < 0) {
|
||||||
|
/* wait on the semaphore's condition */
|
||||||
|
pthread_cond_wait(&s->cond, &sem_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&sem_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* INTERFACE: sem_V() *
|
||||||
|
* *
|
||||||
|
* Do a V on a semaphore. *
|
||||||
|
************************************************************************/
|
||||||
|
void
|
||||||
|
sem_V(Sem *s)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&sem_mutex);
|
||||||
|
|
||||||
|
if (++s->val <= 0) {
|
||||||
|
/* assert the semaphore's condition */
|
||||||
|
pthread_cond_signal(&s->cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&sem_mutex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end file: sem.c */
|
21
src/PREEMPTIVE/sem.h
Executable file
21
src/PREEMPTIVE/sem.h
Executable file
|
@ -0,0 +1,21 @@
|
||||||
|
/* file: sem.h -- definitions for semaphores. */
|
||||||
|
|
||||||
|
#ifndef SEM_DEFINED
|
||||||
|
#define SEM_DEFINED
|
||||||
|
|
||||||
|
/* Include public interface. */
|
||||||
|
#include "../thread.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
typedef struct semtype {
|
||||||
|
int val;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
} Sem;
|
||||||
|
|
||||||
|
Sem *create_sem(int val);
|
||||||
|
int destroy_sem(Sem *s);
|
||||||
|
void sem_P(Sem *s);
|
||||||
|
void sem_V(Sem *s);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/* end file: sem.h */
|
Reference in a new issue