xref: /haiku/src/build/libroot/sem.cpp (revision 90200dfec13f22e03b6a5572c51b8ba63c0c5bb0)
1 
2 #include <BeOSBuildCompatibility.h>
3 
4 #include <string.h>
5 
6 #include <OS.h>
7 #include <SupportDefs.h>
8 
9 // We assume that everything is single-threaded, so we don't need real
10 // semaphores. Simple fakes are sufficient.
11 
12 struct semaphore {
13 	char	name[B_OS_NAME_LENGTH];
14 	int32	count;
15 	bool	inUse;
16 };
17 
18 static const int kSemaphoreCount = 1024;
19 static semaphore sSemaphores[kSemaphoreCount];
20 
21 
22 static bool
23 check_sem(sem_id id)
24 {
25 	if (id < 0 || id >= kSemaphoreCount)
26 		return false;
27 	return sSemaphores[id].inUse;
28 }
29 
30 // create_sem
31 sem_id
32 create_sem(int32 count, const char *name)
33 {
34 	for (int i = 0; i < kSemaphoreCount; i++) {
35 		semaphore &sem = sSemaphores[i];
36 		if (!sem.inUse) {
37 			sem.inUse = true;
38 			sem.count = count;
39 			strlcpy(sem.name, name, sizeof(sem.name));
40 			return i;
41 		}
42 	}
43 
44 	return B_NO_MORE_SEMS;
45 }
46 
47 // delete_sem
48 status_t
49 delete_sem(sem_id id)
50 {
51 	if (!check_sem(id))
52 		return B_BAD_SEM_ID;
53 
54 	sSemaphores[id].inUse = false;
55 
56 	return B_OK;
57 }
58 
59 // acquire_sem
60 status_t
61 acquire_sem(sem_id id)
62 {
63 	return acquire_sem_etc(id, 1, 0, 0);
64 }
65 
66 // acquire_sem_etc
67 status_t
68 acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
69 {
70 	if (!check_sem(id))
71 		return B_BAD_SEM_ID;
72 
73 	if (count <= 0)
74 		return B_BAD_VALUE;
75 
76 	semaphore &sem = sSemaphores[id];
77 	if (sem.count >= count) {
78 		sem.count -= count;
79 		return B_OK;
80 	}
81 
82 	if (timeout < 0)
83 		timeout = 0;
84 
85 	bool noTimeout = false;
86 	if (flags & B_RELATIVE_TIMEOUT) {
87 		// relative timeout: get the absolute time when to time out
88 
89 		// special case: on timeout == 0 we return B_WOULD_BLOCK
90 		if (timeout == 0)
91 			return B_WOULD_BLOCK;
92 
93 		bigtime_t currentTime = system_time();
94 		if (timeout > B_INFINITE_TIMEOUT || currentTime >= B_INFINITE_TIMEOUT - timeout) {
95 			noTimeout = true;
96 		} else {
97 			timeout += currentTime;
98 		}
99 
100 	} else if (flags & B_ABSOLUTE_TIMEOUT) {
101 		// absolute timeout
102 	} else {
103 		// no timeout given
104 		noTimeout = true;
105 	}
106 
107 	// no timeout?
108 	if (noTimeout) {
109 		debugger("Would block on a semaphore without timeout in a "
110 			"single-threaded context!");
111 		return B_ERROR;
112 	}
113 
114 	// wait for the time out time
115 	status_t error = snooze_until(timeout, B_SYSTEM_TIMEBASE);
116 	if (error != B_OK)
117 		return error;
118 
119 	return B_TIMED_OUT;
120 }
121 
122 // release_sem
123 status_t
124 release_sem(sem_id id)
125 {
126 	return release_sem_etc(id, 1, 0);
127 }
128 
129 // release_sem_etc
130 status_t
131 release_sem_etc(sem_id id, int32 count, uint32 flags)
132 {
133 	if (!check_sem(id))
134 		return B_BAD_SEM_ID;
135 
136 	if (count <= 0)
137 		return B_BAD_VALUE;
138 
139 	semaphore &sem = sSemaphores[id];
140 	sem.count += count;
141 
142 	return B_OK;
143 }
144 
145 // atomic_add
146 int32
147 atomic_add(vint32 *value, int32 addValue)
148 {
149 	int32 oldValue = *value;
150 	value += addValue;
151 	return oldValue;
152 }
153