summaryrefslogtreecommitdiff
path: root/minix/lib/libddekit/src/semaphore.c
blob: e51cd14d9d33bfaaaf1f8b9c660e3a3a3040e00b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "common.h"
#include <ddekit/condvar.h>
#include <ddekit/lock.h>
#include <ddekit/memory.h>
#include <ddekit/panic.h>
#include <ddekit/semaphore.h>

#ifdef DDEBUG_LEVEL_SEMAPHORE
#undef DDEBUG
#define DDEBUG DDEBUG_LEVEL_SEMAPHORE
#endif

#include "debug.h"
#include "thread.h"

struct ddekit_sem {
	unsigned count;
	ddekit_thread_t *wait_queue;
};

#define SEM_DEBUG(p)                                                  \
    do {                                                              \
		DDEBUG_MSG_VERBOSE("%s, %p, %d\n",__func__, sem, sem->count); \
	} while(0)                                                        

/*****************************************************************************
 *     ddekit_sem_init                                                       *
 *************************+**************************************************/
ddekit_sem_t *ddekit_sem_init(int value)
{  
	ddekit_sem_t *sem;
	
	sem = (ddekit_sem_t *) ddekit_simple_malloc(sizeof(ddekit_sem_t));
	
	sem->count = value;
	sem->wait_queue = NULL;
	
	SEM_DEBUG(p);
	return sem; 
}

/*****************************************************************************
 *     ddekit_sem_deinit                                                     *
 ****************************************************************************/
void ddekit_sem_deinit(ddekit_sem_t *sem)
{
	SEM_DEBUG(p);
	ddekit_simple_free(sem);	
}

/*****************************************************************************
 *     ddekit_sem_down                                                       *
 ****************************************************************************/
void ddekit_sem_down(ddekit_sem_t *sem)
{
	SEM_DEBUG(p);
	if(sem->count == 0) {
		if(sem->wait_queue == NULL) {
			sem->wait_queue = ddekit_thread_myself();
		} else {
			ddekit_thread_t *pos = sem->wait_queue;
			while(pos->next != NULL) {
				pos = pos->next;
			}
			pos->next = ddekit_thread_myself();
		}
		_ddekit_thread_schedule();
	} else {
		sem->count--;
	}
}

/*****************************************************************************
 *     ddekit_sem_down_try                                                   *
 ****************************************************************************/
int ddekit_sem_down_try(ddekit_sem_t *sem)
{
	if(sem->count == 0) {
		return -1;
	}
	sem->count--;
	return 0;
}

/*****************************************************************************
 *     ddekit_sem_up                                                         *
 ****************************************************************************/
void ddekit_sem_up(ddekit_sem_t *sem)
{   
	SEM_DEBUG(p);
	if (sem->wait_queue == NULL) {
		sem->count++;
		return;
	} else {
		ddekit_thread_t *waiter = sem->wait_queue;
		sem->wait_queue = waiter->next;
		waiter->next = NULL;
		_ddekit_thread_enqueue(waiter);
		ddekit_thread_schedule();
	}
}

/****************************************************************************
 *     ddekit_sem_down_timed                                                *
 ***************************************************************************/
int ddekit_sem_down_timed(ddekit_sem_t *sem, int timo )
{
	ddekit_panic("not implemented!");
	return 0;
}