|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include <kernel/OS.h> |
|
7 |
|
8 #include "primpl.h" |
|
9 |
|
10 /* |
|
11 ** Create a new semaphore object. |
|
12 */ |
|
13 PR_IMPLEMENT(PRSemaphore*) |
|
14 PR_NewSem (PRUintn value) |
|
15 { |
|
16 PRSemaphore *semaphore; |
|
17 |
|
18 if (!_pr_initialized) _PR_ImplicitInitialization(); |
|
19 |
|
20 semaphore = PR_NEWZAP(PRSemaphore); |
|
21 if (NULL != semaphore) { |
|
22 if ((semaphore->sem = create_sem(value, "nspr_sem")) < B_NO_ERROR) |
|
23 return NULL; |
|
24 else |
|
25 return semaphore; |
|
26 } |
|
27 return NULL; |
|
28 } |
|
29 |
|
30 /* |
|
31 ** Destroy the given semaphore object. |
|
32 ** |
|
33 */ |
|
34 PR_IMPLEMENT(void) |
|
35 PR_DestroySem (PRSemaphore *sem) |
|
36 { |
|
37 status_t result; |
|
38 |
|
39 PR_ASSERT(sem != NULL); |
|
40 result = delete_sem(sem->sem); |
|
41 PR_ASSERT(result == B_NO_ERROR); |
|
42 PR_DELETE(sem); |
|
43 } |
|
44 |
|
45 /* |
|
46 ** Wait on a Semaphore. |
|
47 ** |
|
48 ** This routine allows a calling thread to wait or proceed depending upon |
|
49 ** the state of the semahore sem. The thread can proceed only if the |
|
50 ** counter value of the semaphore sem is currently greater than 0. If the |
|
51 ** value of semaphore sem is positive, it is decremented by one and the |
|
52 ** routine returns immediately allowing the calling thread to continue. If |
|
53 ** the value of semaphore sem is 0, the calling thread blocks awaiting the |
|
54 ** semaphore to be released by another thread. |
|
55 ** |
|
56 ** This routine can return PR_PENDING_INTERRUPT if the waiting thread |
|
57 ** has been interrupted. |
|
58 */ |
|
59 PR_IMPLEMENT(PRStatus) |
|
60 PR_WaitSem (PRSemaphore *sem) |
|
61 { |
|
62 PR_ASSERT(sem != NULL); |
|
63 if (acquire_sem(sem->sem) == B_NO_ERROR) |
|
64 return PR_SUCCESS; |
|
65 else |
|
66 return PR_FAILURE; |
|
67 } |
|
68 |
|
69 /* |
|
70 ** This routine increments the counter value of the semaphore. If other |
|
71 ** threads are blocked for the semaphore, then the scheduler will |
|
72 ** determine which ONE thread will be unblocked. |
|
73 */ |
|
74 PR_IMPLEMENT(void) |
|
75 PR_PostSem (PRSemaphore *sem) |
|
76 { |
|
77 status_t result; |
|
78 |
|
79 PR_ASSERT(sem != NULL); |
|
80 result = release_sem_etc(sem->sem, 1, B_DO_NOT_RESCHEDULE); |
|
81 PR_ASSERT(result == B_NO_ERROR); |
|
82 } |
|
83 |
|
84 /* |
|
85 ** Returns the value of the semaphore referenced by sem without affecting |
|
86 ** the state of the semaphore. The value represents the semaphore value |
|
87 ** at the time of the call, but may not be the actual value when the |
|
88 ** caller inspects it. |
|
89 */ |
|
90 PR_IMPLEMENT(PRUintn) |
|
91 PR_GetValueSem (PRSemaphore *sem) |
|
92 { |
|
93 sem_info info; |
|
94 |
|
95 PR_ASSERT(sem != NULL); |
|
96 get_sem_info(sem->sem, &info); |
|
97 return info.count; |
|
98 } |