File: mysemaphore.h

package info (click to toggle)
libnet-dns-native-perl 0.22-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, trixie
  • size: 588 kB
  • sloc: cpp: 589; ansic: 460; perl: 113; makefile: 5
file content (71 lines) | stat: -rw-r--r-- 1,551 bytes parent folder | download
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
typedef struct
{
	unsigned int count;
	unsigned long waiters_count;
	pthread_mutex_t lock;
	pthread_cond_t count_nonzero;
} my_sem_t;

int my_sem_init(my_sem_t *s, int shared, unsigned int initial_count) {
	int rc;
	rc = pthread_mutex_init(&s->lock, NULL);
	if (rc != 0) return rc;
	
	rc = pthread_cond_init(&s->count_nonzero, NULL);
	if (rc != 0) return rc;
	
	s->count = initial_count;
	s->waiters_count = 0;
	
	return 0;
}

int my_sem_wait(my_sem_t *s) {
	// Acquire mutex to enter critical section.
	pthread_mutex_lock(&s->lock);
	
	// Keep track of the number of waiters so that <sem_post> works correctly.
	s->waiters_count++;
	
	// Wait until the semaphore count is > 0, then atomically release
	// <lock> and wait for <count_nonzero> to be signaled. 
	while (s->count == 0)
		pthread_cond_wait(&s->count_nonzero, &s->lock);
	// <s->lock> is now held.
	
	// Decrement the waiters count.
	s->waiters_count--;
	
	// Decrement the semaphore's count.
	s->count--;
	
	// Release mutex to leave critical section.
	pthread_mutex_unlock(&s->lock);
	
	return 0;
}

int my_sem_post(my_sem_t *s) {
	pthread_mutex_lock(&s->lock);
	
	// Always allow one thread to continue if it is waiting.
	if (s->waiters_count > 0)
		pthread_cond_signal(&s->count_nonzero);
	
	// Increment the semaphore's count.
	s->count++;
	pthread_mutex_unlock(&s->lock);
	
	return 0;
}

int my_sem_destroy(my_sem_t *s) {
	int rc;
	rc = pthread_mutex_destroy(&s->lock);
	if (rc != 0) return rc;
	
	rc = pthread_cond_destroy(&s->count_nonzero);
	if (rc != 0) return rc;
	
	return 0;
}